[m-dev.] For Review: Bytecode compiler

Levi Cameron l.cameron2 at ugrad.unimelb.edu.au
Thu Jan 25 18:48:12 AEDT 2001


Estimated hours taken: 4

Changed code generator to output bytecode stubs if needed

bytecode/code_gen.m:
	Changed code generator to output bytecode call stub if
	procedure contains no foreign code

bytecode/hlds_util.m:
	Added predicates to determine if a goal tree contains
	any foreign code.

bytecode/llds_out.m:
	Added a #include to modules generating bytecode

Levi
l.cameron2 at ugrad.unimelb.edu.au

Index: code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.92
diff -u -r1.92 code_gen.m
--- code_gen.m	2001/01/18 01:18:40	1.92
+++ code_gen.m	2001/01/24 00:55:52
@@ -228,7 +228,28 @@
 			bool		% Is this the frame of a model_non
 					% proc defined via pragma C code?
 		).
 %---------------------------------------------------------------------------%
 
 generate_proc_code(PredInfo, ProcInfo, ProcId, PredId, ModuleInfo,
@@ -348,10 +369,33 @@
 		ContainsReconstruction = does_not_contain_reconstruction
 	),
 
-		% Construct a c_procedure structure with all the information.
 	code_info__get_label_counter(LabelCounter, CodeInfo, _),
-	Proc = c_procedure(Name, Arity, proc(PredId, ProcId), Instructions,
-		ProcLabel, LabelCounter, ContainsReconstruction).
+
+	globals__lookup_bool_option(Globals, generate_bytecode, GenBytecode),
+	(
+		% XXX: There is a mass of calls above that the bytecode
+		% doesn't need; work out which is and isn't needed and put
+		% inside the else case below
+		GenBytecode = yes,
+		\+ code_util__compiler_generated(PredInfo),
+		\+ (Name = "main", Arity = 2),
+		goal_has_foreign(Goal) = no
+	->
+
+		EmptyLabelCounter = counter__init(0),
+		code_gen__bytecode_stub(ModuleInfo, PredId, ProcId,
+			BytecodeInstructions),
+		Proc = c_procedure(Name, Arity, proc(PredId, ProcId),
+			BytecodeInstructions, ProcLabel, EmptyLabelCounter,
+			ContainsReconstruction)
+	;	
+		Proc = c_procedure(Name, Arity, proc(PredId, ProcId),
+			Instructions, ProcLabel, LabelCounter,
+			ContainsReconstruction)
+	).
 
 :- pred maybe_add_tabling_pointer_var(module_info::in,
 	pred_id::in, proc_id::in, proc_info::in, proc_label::in,
@@ -1211,5 +1255,69 @@
 		Instrn = Instrn0
 	),
 	code_gen__add_saved_succip(Instrns0, StackLoc, Instrns).
+
+%---------------------------------------------------------------------------%
+
+:- pred code_gen__bytecode_stub(module_info::in, pred_id::in, proc_id::in,
+	list(instruction)::out) is det.
+
+code_gen__bytecode_stub(ModuleInfo, PredId, ProcId, BytecodeInstructions) :-
+	
+%	module_info_name(ModuleInfo, ModuleSymName),
+	module_info_pred_info(ModuleInfo, PredId, PredInfo),
+	pred_info_module(PredInfo, ModuleSymName),
+
+	prog_out__sym_name_to_string(ModuleSymName, "__", ModuleName),
+	
+	code_util__make_local_entry_label(ModuleInfo, PredId,
+		ProcId, no, Entry),
+
+	pred_info_name(PredInfo, PredName),
+	proc_id_to_int(ProcId, ProcNum),
+	string__int_to_string(ProcNum, ProcStr),
+	pred_info_arity(PredInfo, Arity),
+	int_to_string(Arity, ArityStr),
+	pred_info_get_is_pred_or_func(PredInfo, PredOrFunc),
+
+	CallStructName = "bytecode_call__" ++
+		(PredOrFunc = function -> "fn__" ; "") ++
+		ModuleName ++ "__" ++ PredName ++ "_" ++ ArityStr ++ "_" ++
+		ProcStr,
+
+	append_list([
+		"\t\tstatic MB_Call ", CallStructName, " = {\n",
+		"\t\t\t(MB_Word) NULL,\n",
+		"\t\t\t""", ModuleName, """,\n",
+		"\t\t\t""", PredName, """,\n",
+		"\t\t\t", ProcStr, ",\n",
+		"\t\t\t", ArityStr, ",\n",
+		"\t\t\t", (PredOrFunc = function -> "TRUE" ; "FALSE"), "\n",
+		"\t\t};\n"
+		], CallStruct),
+
+	append_list([
+		"\t\tMB_Word* return_adr;\n",
+		"\t\tMR_save_registers();\n",
+		"\t\treturn_adr = MB_bytecode_call_entry(",
+			"&",CallStructName,");\n",
+		"\t\tMR_restore_registers();\n",
+		"\t\tMR_GOTO(return_adr);\n"
+		], BytecodeCall),
+
+		
+	BytecodeInstructions = [
+		label(Entry) - "Procedure entry point",
+
+		pragma_c(
+		[],
+		[
+		pragma_c_raw_code("\t{\n"),
+		pragma_c_raw_code(CallStruct),
+		pragma_c_raw_code(BytecodeCall),
+		pragma_c_raw_code("\t}\n")
+		],
+		may_call_mercury, no, no, no, no
+		) - "Entry stub"
+	].
 
 %---------------------------------------------------------------------------%
Index: hlds_goal.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.83
diff -u -r1.83 hlds_goal.m
--- hlds_goal.m	2001/01/16 15:44:21	1.83
+++ hlds_goal.m	2001/01/22 05:59:06
@@ -800,6 +800,12 @@
 :- pred negate_goal(hlds_goal, hlds_goal_info, hlds_goal).
 :- mode negate_goal(in, in, out) is det.
 
+	% Return yes if goal(s) contain any foreign code
+:- func goal_has_foreign(hlds_goal) = bool.
+:- mode goal_has_foreign(in) = out is det.
+:- func goal_have_foreign(list(hlds_goal)) = bool.
+:- mode goal_have_foreign(in) = out is det.
+
 	% A goal is atomic iff it doesn't contain any sub-goals
 	% (except possibly goals inside lambda expressions --
 	% but lambda expressions will get transformed into separate
@@ -1460,6 +1466,7 @@
 		NegatedGoal = not(Goal) - GoalInfo
 	).
 
+
 :- pred all_negated(list(hlds_goal), list(hlds_goal)).
 :- mode all_negated(in, out) is semidet.
 
@@ -1470,6 +1477,71 @@
 	all_negated(NegatedConj, Goals1),
 	all_negated(NegatedGoals, Goals2),
 	list__append(Goals1, Goals2, Goals).
+
+%-----------------------------------------------------------------------------%
+% Returns yes if a goal (or subgoal contained within) contains any foreign
+% code
+goal_has_foreign(Goal) = HasForeign :-
+	Goal = GoalExpr - _,
+	(
+		GoalExpr = conj(Goals),
+		HasForeign = goal_have_foreign(Goals)
+	;
+		GoalExpr = call(_, _, _, _, _, _),
+		HasForeign = no
+	;
+		GoalExpr = generic_call(_, _, _, _),
+		HasForeign = no
+	;
+		GoalExpr = switch(_, _, _, _),
+		HasForeign = no
+	;
+		GoalExpr = unify(_, _, _, _, _),
+		HasForeign = no
+	;
+		GoalExpr = disj(Goals, _),
+		HasForeign = goal_have_foreign(Goals)
+	;
+		GoalExpr = not(Goal2),
+		HasForeign = goal_has_foreign(Goal2)
+	;
+		GoalExpr = some(_, _, Goal2),
+		HasForeign = goal_has_foreign(Goal2)
+	;
+		GoalExpr = if_then_else(_, Goal2, Goal3, Goal4, _),
+		HasForeign =
+		(	goal_has_foreign(Goal2) = yes 
+		->	yes
+		;	goal_has_foreign(Goal3) = yes
+		->	yes
+		;	goal_has_foreign(Goal4) = yes
+		->	yes
+		;	no
+		)
+	;
+		GoalExpr = pragma_foreign_code(_, _, _, _, _, _, _),
+		HasForeign = yes
+	;
+		GoalExpr = par_conj(Goals, _),
+		HasForeign = goal_have_foreign(Goals)
+	;
+		GoalExpr = bi_implication(Goal2, Goal3),
+		HasForeign =
+		(	goal_has_foreign(Goal2) = yes
+		->	yes
+		;	goal_has_foreign(Goal3) = yes
+		->	yes
+		;	no
+		)
+	).
+
+goal_have_foreign([]) = no.
+goal_have_foreign([X | Xs]) =
+	(	goal_has_foreign(X) = yes
+	->	yes
+	;	goal_have_foreign(Xs)
+	).
+
 
 %-----------------------------------------------------------------------------%
 
Index: llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.171
diff -u -r1.171 llds_out.m
--- llds_out.m	2001/01/20 15:42:43	1.171
+++ llds_out.m	2001/01/24 03:04:59
@@ -418,6 +418,12 @@
 		io__write_string("#include ""mercury_trace_base.h""\n")
 	;
 		io__write_string("#include ""mercury_imp.h""\n")
+	),
+	globals__io_lookup_bool_option(generate_bytecode, GenBytecode),
+	(	{ GenBytecode = yes },
+		io__write_string("#include ""mb_interface.h""\n")
+	;	{ GenBytecode = no },
+		io__write_string("")
 	).
 
 output_c_file_intro_and_grade(SourceFileName, Version) -->
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list