diff --git a/compiler/code_info.m b/compiler/code_info.m index 5455d3ed5..5f071126f 100644 --- a/compiler/code_info.m +++ b/compiler/code_info.m @@ -1913,18 +1913,19 @@ prepare_for_semi_commit(AddTrailOps, SemiCommitInfo, Code, !CI) :- % inside MR_commit_{mark,cut}. Components = [ foreign_proc_raw_code(cannot_branch_away, - affects_liveness, live_lvals_info(set.init), + proc_affects_liveness, live_lvals_info(set.init), "\t\tMR_save_transient_registers();\n"), foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), + proc_does_not_affect_liveness, live_lvals_info(set.init), "\t\tMR_commit_mark();\n"), foreign_proc_raw_code(cannot_branch_away, - affects_liveness, live_lvals_info(set.init), + proc_affects_liveness, live_lvals_info(set.init), "\t\tMR_restore_transient_registers();\n") ], + MD = proc_may_duplicate, MarkCode = node([ llds_instr(foreign_proc_code([], Components, - proc_will_not_call_mercury, no, no, no, no, no, yes), "") + proc_will_not_call_mercury, no, no, no, no, no, MD), "") ]) ; UseMinimalModelStackCopyCut = no, @@ -1995,12 +1996,13 @@ generate_semi_commit(SemiCommitInfo, Code, !CI) :- % See the comment in prepare_for_semi_commit above. Components = [ foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), + proc_does_not_affect_liveness, live_lvals_info(set.init), "\t\tMR_commit_cut();\n") ], + MD = proc_may_duplicate, CutCode = node([ llds_instr(foreign_proc_code([], Components, - proc_will_not_call_mercury, no, no, no, no, no, yes), + proc_will_not_call_mercury, no, no, no, no, no, MD), "commit for temp frame hijack") ]) ; diff --git a/compiler/hlds_pred.m b/compiler/hlds_pred.m index 41a674ba9..301afd2d0 100644 --- a/compiler/hlds_pred.m +++ b/compiler/hlds_pred.m @@ -315,17 +315,17 @@ % The user requests that this be predicate should % be inlined, even if it exceeds the usual size limits. % Used for pragma(inline). - % Mutually exclusive with user_marked_no_inline. + % Mutually exclusive with marker_user_marked_no_inline. ; marker_user_marked_no_inline % The user requests that this be predicate should % not be inlined. Used for pragma(no_inline). - % Mutually exclusive with user_marked_inline. + % Mutually exclusive with marker_user_marked_inline. ; marker_heuristic_inline % The compiler (meaning probably inlining.m) requests % that this predicate be inlined. Does not override - % user_marked_no_inline. + % marker_user_marked_no_inline. ; marker_class_method % Requests that this predicate be transformed into diff --git a/compiler/inlining.m b/compiler/inlining.m index f8c86ecdd..5ea7a0b84 100644 --- a/compiler/inlining.m +++ b/compiler/inlining.m @@ -937,8 +937,7 @@ can_inline_proc_2(PredId, ProcId, BuiltinState, HighLevelCode, % whole procedures not code fragments. proc_info_get_eval_method(ProcInfo, eval_normal), - % Don't inline anything we have been specifically requested - % not to inline. + % Don't inline anything we have been specifically requested not to inline. \+ pred_info_requested_no_inlining(PredInfo), % Don't inline any procedure whose complexity we are trying to determine, @@ -965,18 +964,33 @@ can_inline_proc_2(PredId, ProcId, BuiltinState, HighLevelCode, ( Detism = detism_non ; Detism = detism_multi ) ), - % Only inline foreign_code if it is appropriate for - % the target language. module_info_get_globals(ModuleInfo, Globals), globals.get_target(Globals, Target), ( + CalledGoal = hlds_goal(call_foreign_proc(ForeignAttributes, + _, _, _, _, _, _), _) + -> + % Only inline foreign_code if it is appropriate for the target + % language. ( - CalledGoal = hlds_goal(call_foreign_proc(ForeignAttributes, - _, _, _, _, _, _), _), ForeignLanguage = get_foreign_language(ForeignAttributes) + => + ok_to_inline_language(ForeignLanguage, Target) + ), + + % Don't inline foreign_code if it is has been marked with the attribute + % that requests the code not be duplicated. + ( + MaybeMayDuplicate = get_may_duplicate(ForeignAttributes) + => + ( + MaybeMayDuplicate = no + ; + MaybeMayDuplicate = yes(proc_may_duplicate) + ) ) - => - ok_to_inline_language(ForeignLanguage, Target) + ; + true ), ( diff --git a/compiler/ite_gen.m b/compiler/ite_gen.m index 34b8bb32a..195a16e70 100644 --- a/compiler/ite_gen.m +++ b/compiler/ite_gen.m @@ -444,31 +444,32 @@ make_pneg_context_wrappers(Globals, GoalInfo, PNegCondCode, PNegThenCode, ), PNegCondComponents = [ - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - live_lvals_info(set.init), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, live_lvals_info(set.init), wrap_transient("\t\tMR_pneg_enter_cond();\n")) ], PNegThenComponents = [ - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - live_lvals_info(set.init), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, live_lvals_info(set.init), wrap_transient("\t\tMR_pneg_enter_then();\n")) ], PNegElseComponents = [ - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - live_lvals_info(set.init), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, live_lvals_info(set.init), wrap_transient("\t\tMR_pneg_enter_else(" ++ CtxtStr ++ ");\n")) ], + MD = proc_may_duplicate, PNegCondCode = node([ llds_instr(foreign_proc_code([], PNegCondComponents, - proc_will_not_call_mercury, no, no, no, no, yes, yes), "") + proc_will_not_call_mercury, no, no, no, no, yes, MD), "") ]), PNegThenCode = node([ llds_instr(foreign_proc_code([], PNegThenComponents, - proc_will_not_call_mercury, no, no, no, no, yes, yes), "") + proc_will_not_call_mercury, no, no, no, no, yes, MD), "") ]), PNegElseCode = node([ llds_instr(foreign_proc_code([], PNegElseComponents, - proc_will_not_call_mercury, no, no, no, no, yes, yes), "") + proc_will_not_call_mercury, no, no, no, no, yes, MD), "") ]) ; PNegCondCode = empty, diff --git a/compiler/jumpopt.m b/compiler/jumpopt.m index e3c161e9b..06e1e3538 100644 --- a/compiler/jumpopt.m +++ b/compiler/jumpopt.m @@ -67,6 +67,7 @@ :- import_module libs.compiler_util. :- import_module ll_backend.code_util. :- import_module ll_backend.opt_util. +:- import_module parse_tree.prog_data. :- import_module map. :- import_module maybe. @@ -873,7 +874,7 @@ instr_may_be_duplicated(Instr) = InstrMayBeDuplicated :- % When debugging is enabled, size is in any case more important % than the last bit of speed. InstrMayBeDuplicated = no - ; Instr ^ fproc_maybe_dupl = no -> + ; Instr ^ fproc_maybe_dupl = proc_may_not_duplicate -> InstrMayBeDuplicated = no ; InstrMayBeDuplicated = yes diff --git a/compiler/livemap.m b/compiler/livemap.m index d47467b53..f07f810d9 100644 --- a/compiler/livemap.m +++ b/compiler/livemap.m @@ -312,10 +312,10 @@ build_livemap_foreign_proc_components([Component | Components], ; Component = foreign_proc_user_code(_, AffectsLiveness, Code), ( - AffectsLiveness = affects_liveness, + AffectsLiveness = proc_affects_liveness, !:ContainsBadUserCode = yes ; - AffectsLiveness = default_affects_liveness, + AffectsLiveness = proc_default_affects_liveness, ( Code = "" -> true ; @@ -324,7 +324,7 @@ build_livemap_foreign_proc_components([Component | Components], !:ContainsBadUserCode = yes ) ; - AffectsLiveness = does_not_affect_liveness + AffectsLiveness = proc_does_not_affect_liveness ) ; Component = foreign_proc_raw_code(_Context, AffectsLiveness, @@ -339,16 +339,16 @@ build_livemap_foreign_proc_components([Component | Components], build_livemap_foreign_proc_components(Components, !Livevals, !ContainsBadUserCode). -:- pred build_live_lval_info(affects_liveness::in, c_code_live_lvals::in, +:- pred build_live_lval_info(proc_affects_liveness::in, c_code_live_lvals::in, string::in, lvalset::in, lvalset::out, bool::in, bool::out) is det. build_live_lval_info(AffectsLiveness, LiveLvalInfo, Code, !Livevals, !ContainsBadUserCode) :- ( - AffectsLiveness = affects_liveness, + AffectsLiveness = proc_affects_liveness, !:ContainsBadUserCode = yes ; - AffectsLiveness = default_affects_liveness, + AffectsLiveness = proc_default_affects_liveness, ( Code = "" -> true ; @@ -357,7 +357,7 @@ build_live_lval_info(AffectsLiveness, LiveLvalInfo, Code, !:ContainsBadUserCode = yes ) ; - AffectsLiveness = does_not_affect_liveness, + AffectsLiveness = proc_does_not_affect_liveness, ( LiveLvalInfo = no_live_lvals_info, !:ContainsBadUserCode = yes diff --git a/compiler/llds.m b/compiler/llds.m index 405e94940..d417bbcc1 100644 --- a/compiler/llds.m +++ b/compiler/llds.m @@ -303,7 +303,7 @@ % (rval+1)th label in the list. e.g. computed_goto(2, [A, B, C, D]) % will branch to label C. - ; arbitrary_c_code(affects_liveness, c_code_live_lvals, string) + ; arbitrary_c_code(proc_affects_liveness, c_code_live_lvals, string) % Do whatever is specified by the string, which can be any piece % of C code that does not have any non-local flow of control. @@ -435,7 +435,7 @@ fproc_fix_onlylayout :: maybe(label), fproc_nofix :: maybe(label), fproc_stack_slot_ref :: bool, - fproc_maybe_dupl :: bool + fproc_maybe_dupl :: proc_may_duplicate ) % The first argument says what local variable declarations % are required for the following components, which in turn @@ -583,9 +583,9 @@ :- type foreign_proc_component ---> foreign_proc_inputs(list(foreign_proc_input)) ; foreign_proc_outputs(list(foreign_proc_output)) - ; foreign_proc_user_code(maybe(prog_context), affects_liveness, + ; foreign_proc_user_code(maybe(prog_context), proc_affects_liveness, string) - ; foreign_proc_raw_code(can_branch_away, affects_liveness, + ; foreign_proc_raw_code(can_branch_away, proc_affects_liveness, c_code_live_lvals, string) ; foreign_proc_fail_to(label) ; foreign_proc_noop. diff --git a/compiler/opt_debug.m b/compiler/opt_debug.m index 76942f3f8..68b7006ff 100644 --- a/compiler/opt_debug.m +++ b/compiler/opt_debug.m @@ -605,14 +605,14 @@ dump_proclabel(ProcLabel) = Str :- PredModuleName = sym_name_mangle(PredModule), ExtraModule = PredModuleName ++ "_" ), - Str = ExtraModule ++ sym_name_mangle(Module) ++ "_" ++ PredName ++ "_" - ++ int_to_string(Arity) ++ "_" ++ int_to_string(Mode) + Str = ExtraModule ++ sym_name_mangle(Module) ++ "__" ++ PredName + ++ "_" ++ int_to_string(Arity) ++ "_" ++ int_to_string(Mode) ; ProcLabel = special_proc_label(Module, SpecialPredId, TypeModule, TypeName, TypeArity, Mode), TypeCtor = type_ctor(qualified(TypeModule, TypeName), TypeArity), - Str = sym_name_mangle(Module) ++ "_" + Str = sym_name_mangle(Module) ++ "__" ++ special_pred_name(SpecialPredId, TypeCtor) ++ "_" ++ qualify_name(sym_name_mangle(TypeModule), TypeName) ++ "_" ++ int_to_string(TypeArity) ++ "_" ++ int_to_string(Mode) @@ -802,7 +802,7 @@ dump_instr(ProcLabel, PrintComments, Instr) = Str :- ++ dump_maybe_label("fix onlylayout:", MaybeProcLabel, MFOL) ++ dump_maybe_label("nofix:", MaybeProcLabel, MNF) ++ dump_bool_msg("stack slot ref:", SSR) - ++ dump_bool_msg("may duplicate:", MD) + ++ dump_may_duplicate(MD) ++ "\n" ++ ")" ). @@ -822,6 +822,11 @@ dump_maybe_label(Msg, MaybeProcLabel, yes(Label)) = dump_bool_msg(Msg, no) = Msg ++ " no\n". dump_bool_msg(Msg, yes) = Msg ++ " yes\n". +:- func dump_may_duplicate(proc_may_duplicate) = string. + +dump_may_duplicate(proc_may_duplicate) = "may_duplicate". +dump_may_duplicate(proc_may_not_duplicate) = "may_not_duplicate". + :- func dump_may_use_atomic(may_use_atomic_alloc) = string. dump_may_use_atomic(may_use_atomic_alloc) = "may_use_atomic_alloc". @@ -855,18 +860,28 @@ dump_component(MaybeProcLabel, foreign_proc_inputs(Inputs)) = dump_component(MaybeProcLabel, foreign_proc_outputs(Outputs)) = dump_output_components(MaybeProcLabel, Outputs). dump_component(_, foreign_proc_user_code(_, AL, Code)) = - dump_affects_liveness(AL) ++ "\n" ++ Code ++ "\n". + ( Code = "" -> + "empty user_code: " ++ dump_affects_liveness(AL) ++ "\n" + ; + "user_code: " ++ dump_affects_liveness(AL) ++ "\n" ++ Code ++ "\n" + ). dump_component(_, foreign_proc_raw_code(_, AL, _, Code)) = - dump_affects_liveness(AL) ++ "\n" ++ Code ++ "\n". + ( Code = "" -> + "empty raw_code: " ++ dump_affects_liveness(AL) ++ "\n" + ; + "raw_code:\n" ++ dump_affects_liveness(AL) ++ "\n" ++ Code ++ "\n" + ). dump_component(MaybeProcLabel, foreign_proc_fail_to(Label)) = "fail to " ++ dump_label(MaybeProcLabel, Label) ++ "\n". dump_component(_, foreign_proc_noop) = "". -:- func dump_affects_liveness(affects_liveness) = string. +:- func dump_affects_liveness(proc_affects_liveness) = string. -dump_affects_liveness(affects_liveness) = "affects_liveness". -dump_affects_liveness(does_not_affect_liveness) = "does_not_affect_liveness". -dump_affects_liveness(default_affects_liveness) = "default_affects_liveness". +dump_affects_liveness(proc_affects_liveness) = "affects_liveness". +dump_affects_liveness(proc_does_not_affect_liveness) = + "does_not_affect_liveness". +dump_affects_liveness(proc_default_affects_liveness) = + "default_affects_liveness". :- func dump_input_components(maybe(proc_label), list(foreign_proc_input)) = string. diff --git a/compiler/opt_util.m b/compiler/opt_util.m index b37dc0b7c..a603cffb1 100644 --- a/compiler/opt_util.m +++ b/compiler/opt_util.m @@ -1476,7 +1476,56 @@ count_temps_instr(init_sync_term(Lval, _), !R, !F) :- count_temps_instr(fork(_), !R, !F). count_temps_instr(join_and_continue(Lval, _), !R, !F) :- count_temps_lval(Lval, !R, !F). -count_temps_instr(foreign_proc_code(_, _, _, _, _, _, _, _, _), !R, !F). +count_temps_instr(foreign_proc_code(_, Comps, _, _, _, _, _, _, _), !R, !F) :- + count_temps_components(Comps, !R, !F). + +:- pred count_temps_components(list(foreign_proc_component)::in, + int::in, int::out, int::in, int::out) is det. + +count_temps_components([], !R, !F). +count_temps_components([Comp | Comps], !R, !F) :- + count_temps_component(Comp, !R, !F), + count_temps_components(Comps, !R, !F). + +:- pred count_temps_component(foreign_proc_component::in, + int::in, int::out, int::in, int::out) is det. + +count_temps_component(Comp, !R, !F) :- + ( + Comp = foreign_proc_inputs(Inputs), + count_temps_inputs(Inputs, !R, !F) + ; + Comp = foreign_proc_outputs(Outputs), + count_temps_outputs(Outputs, !R, !F) + ; + Comp = foreign_proc_user_code(_, _, _) + ; + Comp = foreign_proc_raw_code(_, _, _, _) + ; + Comp = foreign_proc_fail_to(_) + ; + Comp = foreign_proc_noop + ). + +:- pred count_temps_inputs(list(foreign_proc_input)::in, + int::in, int::out, int::in, int::out) is det. + +count_temps_inputs([], !R, !F). +count_temps_inputs([Input | Inputs], !R, !F) :- + Input = foreign_proc_input(_VarName, _VarType, _IsDummy, _OrigType, + ArgRval, _MaybeForeignType, _BoxPolicy), + count_temps_rval(ArgRval, !R, !F), + count_temps_inputs(Inputs, !R, !F). + +:- pred count_temps_outputs(list(foreign_proc_output)::in, + int::in, int::out, int::in, int::out) is det. + +count_temps_outputs([], !R, !F). +count_temps_outputs([Output | Outputs], !R, !F) :- + Output = foreign_proc_output(DestLval, _VarType, _IsDummy, _OrigType, + _VarName, _MaybeForeignType, _BoxPolicy), + count_temps_lval(DestLval, !R, !F), + count_temps_outputs(Outputs, !R, !F). :- pred count_temps_lval(lval::in, int::in, int::out, int::in, int::out) is det. diff --git a/compiler/pragma_c_gen.m b/compiler/pragma_c_gen.m index 3d5f4fe08..a82a2b54d 100644 --- a/compiler/pragma_c_gen.m +++ b/compiler/pragma_c_gen.m @@ -530,11 +530,11 @@ generate_ordinary_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, ( MayCallMercury = proc_will_not_call_mercury, SaveRegsComp = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), "") + proc_does_not_affect_liveness, live_lvals_info(set.init), "") ; MayCallMercury = proc_may_call_mercury, SaveRegsComp = foreign_proc_raw_code(cannot_branch_away, - affects_liveness, live_lvals_info(set.init), + proc_affects_liveness, live_lvals_info(set.init), "\tMR_save_registers();\n") ), @@ -542,9 +542,9 @@ generate_ordinary_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, ( ThreadSafe = proc_thread_safe, ObtainLock = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), ""), + proc_does_not_affect_liveness, live_lvals_info(set.init), ""), ReleaseLock = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), "") + proc_does_not_affect_liveness, live_lvals_info(set.init), "") ; ThreadSafe = proc_not_thread_safe, module_info_pred_info(ModuleInfo, PredId, PredInfo), @@ -553,16 +553,18 @@ generate_ordinary_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, ObtainLockStr = "\tMR_OBTAIN_GLOBAL_LOCK(""" ++ MangledName ++ """);\n", ObtainLock = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), ObtainLockStr), + proc_does_not_affect_liveness, live_lvals_info(set.init), + ObtainLockStr), ReleaseLockStr = "\tMR_RELEASE_GLOBAL_LOCK(""" ++ MangledName ++ """);\n", ReleaseLock = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), ReleaseLockStr) + proc_does_not_affect_liveness, live_lvals_info(set.init), + ReleaseLockStr) ), % - C_Code_Comp = foreign_proc_user_code(Context, default_affects_liveness, - C_Code), + AffectsLiveness = get_affects_liveness(Attributes), + C_Code_Comp = foreign_proc_user_code(Context, AffectsLiveness, C_Code), % goal_info_get_determinism(GoalInfo, Detism), @@ -576,22 +578,22 @@ generate_ordinary_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, MaybeFailLabel = yes(FailLabel) ), DefSuccessComp = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), + proc_does_not_affect_liveness, live_lvals_info(set.init), "\tMR_bool " ++ foreign_proc_succ_ind_name ++ ";\n" ++ "#undef SUCCESS_INDICATOR\n" ++ "#define SUCCESS_INDICATOR " ++ foreign_proc_succ_ind_name ++ "\n"), UndefSuccessComp = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), + proc_does_not_affect_liveness, live_lvals_info(set.init), "#undef SUCCESS_INDICATOR\n" ++ "#define SUCCESS_INDICATOR MR_r1\n") ; CheckSuccess_Comp = foreign_proc_noop, MaybeFailLabel = no, DefSuccessComp = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), ""), + proc_does_not_affect_liveness, live_lvals_info(set.init), ""), UndefSuccessComp = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), "") + proc_does_not_affect_liveness, live_lvals_info(set.init), "") ), % #ifndef MR_CONSERVATIVE_GC @@ -603,7 +605,7 @@ generate_ordinary_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, ; MayCallMercury = proc_may_call_mercury, RestoreRegsComp = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), + proc_does_not_affect_liveness, live_lvals_info(set.init), "#ifndef MR_CONSERVATIVE_GC\n\t" ++ "MR_restore_registers();\n#endif\n") ), @@ -635,12 +637,18 @@ generate_ordinary_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, SaveRegsComp, ObtainLock, C_Code_Comp, ReleaseLock, CheckSuccess_Comp, RestoreRegsComp, OutputComp, UndefSuccessComp, ProcLabelHashUndef], + MaybeMayDupl = get_may_duplicate(Attributes), ( - ExtraArgs = [], - MaybeDupl = yes + MaybeMayDupl = yes(MayDupl) ; - ExtraArgs = [_ | _], - MaybeDupl = no + MaybeMayDupl = no, + ( + ExtraArgs = [], + MayDupl = proc_may_duplicate + ; + ExtraArgs = [_ | _], + MayDupl = proc_may_not_duplicate + ) ), ExtraAttributes = get_extra_attributes(Attributes), ( list.member(refers_to_llds_stack, ExtraAttributes) -> @@ -650,7 +658,7 @@ generate_ordinary_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, ), PragmaCCode = node([ llds_instr(foreign_proc_code(Decls, Components, MayCallMercury, - no, no, no, MaybeFailLabel, RefersToLLDSSTack, MaybeDupl), + no, no, no, MaybeFailLabel, RefersToLLDSSTack, MayDupl), "foreign_proc inclusion") ]), % @@ -691,11 +699,11 @@ generate_ordinary_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, make_proc_label_hash_define(ModuleInfo, PredId, ProcId, ProcLabelHashDef, ProcLabelHashUndef) :- ProcLabelHashDef = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), + proc_does_not_affect_liveness, live_lvals_info(set.init), "#define\tMR_PROC_LABEL\t" ++ make_proc_label_string(ModuleInfo, PredId, ProcId) ++ "\n"), ProcLabelHashUndef = foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), + proc_does_not_affect_liveness, live_lvals_info(set.init), "#undef\tMR_PROC_LABEL\n"). :- func make_proc_label_string(module_info, pred_id, proc_id) = string. @@ -730,6 +738,7 @@ generate_nondet_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, "inappropriate code model for nondet foreign_proc"), % Extract the may_call_mercury attribute. MayCallMercury = get_may_call_mercury(Attributes), + AffectsLiveness = get_affects_liveness(Attributes), % Generate #define MR_PROC_LABEL /* see note (5) */ % and #undef MR_PROC_LABEL. @@ -854,6 +863,7 @@ generate_nondet_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, Undef2 = "#undef\tSUCCEED_LAST\n", Undef3 = "#undef\tFAIL\n", + MD = proc_may_not_duplicate, ( % Use the form that duplicates the common code if the programmer % asked for it, or if the code is small enough for its duplication @@ -886,90 +896,102 @@ generate_nondet_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, CallComponents = [ foreign_proc_inputs(InputDescs), foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, no_live_lvals_info, InitSaveStruct), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SaveRegs), + proc_does_not_affect_liveness, no_live_lvals_info, + InitSaveStruct), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SaveRegs), ProcLabelDefine, - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, CallDef1), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, CallDef2), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, CallDef3), - foreign_proc_user_code(FirstContext, default_affects_liveness, - First), - foreign_proc_user_code(SharedContext, default_affects_liveness, - Shared), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, CallSuccessLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RestoreRegs), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, CallDef1), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, CallDef2), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, CallDef3), + foreign_proc_user_code(FirstContext, AffectsLiveness, First), + foreign_proc_user_code(SharedContext, AffectsLiveness, Shared), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + CallSuccessLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RestoreRegs), foreign_proc_outputs(OutputDescs), - foreign_proc_raw_code(can_branch_away, does_not_affect_liveness, - no_live_lvals_info, Succeed), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, CallLastSuccessLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RestoreRegs), + foreign_proc_raw_code(can_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + Succeed), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + CallLastSuccessLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RestoreRegs), foreign_proc_outputs(OutputDescs), - foreign_proc_raw_code(can_branch_away, does_not_affect_liveness, - no_live_lvals_info, SucceedDiscard), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef1), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef2), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef3), + foreign_proc_raw_code(can_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SucceedDiscard), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef1), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef2), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef3), ProcLabelUndef ], CallBlockCode = node([ llds_instr(foreign_proc_code(CallDecls, CallComponents, - MayCallMercury, no, no, no, no, yes, no), + MayCallMercury, no, no, no, no, yes, MD), "Call and shared foreign_proc inclusion") ]), RetryDecls = [SaveStructDecl | OutDecls], RetryComponents = [ - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, InitSaveStruct), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SaveRegs), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + InitSaveStruct), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SaveRegs), ProcLabelDefine, - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RetryDef1), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RetryDef2), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RetryDef3), - foreign_proc_user_code(LaterContext, default_affects_liveness, - Later), - foreign_proc_user_code(SharedContext, default_affects_liveness, - Shared), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RetrySuccessLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RestoreRegs), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, RetryDef1), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, RetryDef2), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, RetryDef3), + foreign_proc_user_code(LaterContext, AffectsLiveness, Later), + foreign_proc_user_code(SharedContext, AffectsLiveness, Shared), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RetrySuccessLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RestoreRegs), foreign_proc_outputs(OutputDescs), - foreign_proc_raw_code(can_branch_away, does_not_affect_liveness, - no_live_lvals_info, Succeed), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RetryLastSuccessLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RestoreRegs), + foreign_proc_raw_code(can_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + Succeed), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RetryLastSuccessLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RestoreRegs), foreign_proc_outputs(OutputDescs), - foreign_proc_raw_code(can_branch_away, does_not_affect_liveness, - no_live_lvals_info, SucceedDiscard), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef1), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef2), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef3), + foreign_proc_raw_code(can_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SucceedDiscard), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef1), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef2), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef3), ProcLabelUndef ], RetryBlockCode = node([ llds_instr(foreign_proc_code(RetryDecls, RetryComponents, - MayCallMercury, no, no, no, no, yes, no), + MayCallMercury, no, no, no, no, yes, MD), "Retry and shared foreign_proc inclusion") ]), @@ -1001,134 +1023,161 @@ generate_nondet_foreign_proc_code(CodeModel, Attributes, PredId, ProcId, CallDecls = [SaveStructDecl | Decls], CallComponents = [ foreign_proc_inputs(InputDescs), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, InitSaveStruct), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SaveRegs), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + InitSaveStruct), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SaveRegs), ProcLabelDefine, - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, CallDef1), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, CallDef2), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, CallDef3), - foreign_proc_user_code(FirstContext, default_affects_liveness, - First), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, GotoSharedLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, CallSuccessLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RestoreRegs), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, CallDef1), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, CallDef2), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, CallDef3), + foreign_proc_user_code(FirstContext, AffectsLiveness, First), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + GotoSharedLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + CallSuccessLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RestoreRegs), foreign_proc_outputs(OutputDescs), - foreign_proc_raw_code(can_branch_away, does_not_affect_liveness, - no_live_lvals_info, Succeed), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, CallLastSuccessLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RestoreRegs), + foreign_proc_raw_code(can_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + Succeed), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + CallLastSuccessLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RestoreRegs), foreign_proc_outputs(OutputDescs), - foreign_proc_raw_code(can_branch_away, does_not_affect_liveness, - no_live_lvals_info, SucceedDiscard), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef1), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef2), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef3), + foreign_proc_raw_code(can_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SucceedDiscard), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef1), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef2), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef3), ProcLabelUndef ], CallBlockCode = node([ llds_instr(foreign_proc_code(CallDecls, CallComponents, - MayCallMercury, yes(SharedLabel), no, no, no, yes, no), + MayCallMercury, yes(SharedLabel), no, no, no, yes, MD), "Call foreign_proc inclusion") ]), RetryDecls = [SaveStructDecl | OutDecls], RetryComponents = [ - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, InitSaveStruct), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SaveRegs), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + InitSaveStruct), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SaveRegs), ProcLabelDefine, - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RetryDef1), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RetryDef2), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RetryDef3), - foreign_proc_user_code(LaterContext, default_affects_liveness, - Later), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, GotoSharedLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RetrySuccessLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RestoreRegs), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, RetryDef1), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, RetryDef2), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, RetryDef3), + foreign_proc_user_code(LaterContext, AffectsLiveness, Later), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + GotoSharedLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RetrySuccessLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RestoreRegs), foreign_proc_outputs(OutputDescs), - foreign_proc_raw_code(can_branch_away, does_not_affect_liveness, - no_live_lvals_info, Succeed), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RetryLastSuccessLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RestoreRegs), + foreign_proc_raw_code(can_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + Succeed), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RetryLastSuccessLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RestoreRegs), foreign_proc_outputs(OutputDescs), - foreign_proc_raw_code(can_branch_away, does_not_affect_liveness, - no_live_lvals_info, SucceedDiscard), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef1), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef2), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef3), + foreign_proc_raw_code(can_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SucceedDiscard), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef1), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef2), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef3), ProcLabelUndef ], RetryBlockCode = node([ llds_instr(foreign_proc_code(RetryDecls, RetryComponents, - MayCallMercury, yes(SharedLabel), no, no, no, yes, no), + MayCallMercury, yes(SharedLabel), no, no, no, yes, MD), "Retry foreign_proc inclusion") ]), SharedDecls = [SaveStructDecl | OutDecls], SharedComponents = [ - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, InitSaveStruct), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SaveRegs), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + InitSaveStruct), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SaveRegs), ProcLabelDefine, - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SharedDef1), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SharedDef2), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SharedDef3), - foreign_proc_user_code(SharedContext, default_affects_liveness, + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SharedDef1), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SharedDef2), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SharedDef3), + foreign_proc_user_code(SharedContext, AffectsLiveness, Shared), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SharedSuccessLabel), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, RestoreRegs), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SharedSuccessLabel), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RestoreRegs), foreign_proc_outputs(OutputDescs), - foreign_proc_raw_code(can_branch_away, does_not_affect_liveness, - no_live_lvals_info, Succeed), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SharedLastSuccessLabel), - foreign_proc_raw_code(can_branch_away, does_not_affect_liveness, - no_live_lvals_info, RestoreRegs), + foreign_proc_raw_code(can_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + Succeed), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SharedLastSuccessLabel), + foreign_proc_raw_code(can_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + RestoreRegs), foreign_proc_outputs(OutputDescs), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, SucceedDiscard), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef1), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef2), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, Undef3), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, + SucceedDiscard), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef1), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef2), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, Undef3), ProcLabelUndef ], SharedBlockCode = node([ llds_instr(foreign_proc_code(SharedDecls, SharedComponents, - MayCallMercury, no, no, no, no, yes, no), + MayCallMercury, no, no, no, no, yes, MD), "Shared foreign_proc inclusion") ]), diff --git a/compiler/proc_gen.m b/compiler/proc_gen.m index 69180385a..0325e1f13 100644 --- a/compiler/proc_gen.m +++ b/compiler/proc_gen.m @@ -913,13 +913,15 @@ generate_entry(CI, CodeModel, Goal, OutsideResumePoint, FrameInfo, string.format("#define\tMR_ORDINARY_SLOTS\t%d\n", [i(TotalSlots)], DefineStr), DefineComponents = [foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), DefineStr)], + proc_does_not_affect_liveness, live_lvals_info(set.init), + DefineStr)], NondetFrameInfo = ordinary_frame(PushMsg, TotalSlots, yes(Struct)), + MD = proc_may_not_duplicate, AllocCode = node([ llds_instr(mkframe(NondetFrameInfo, yes(OutsideResumeAddress)), "Allocate stack frame"), llds_instr(foreign_proc_code([], DefineComponents, - proc_will_not_call_mercury, no, no, no, no, no, no), "") + proc_will_not_call_mercury, no, no, no, no, no, MD), "") ]), NondetPragma = yes ; @@ -1007,10 +1009,12 @@ generate_exit(CodeModel, FrameInfo, TraceSlotInfo, ProcContext, NondetPragma = yes, UndefStr = "#undef\tMR_ORDINARY_SLOTS\n", UndefComponents = [foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), UndefStr)], + proc_does_not_affect_liveness, live_lvals_info(set.init), + UndefStr)], + MD = proc_may_not_duplicate, UndefCode = node([ llds_instr(foreign_proc_code([], UndefComponents, - proc_will_not_call_mercury, no, no, no, no, no, no), "") + proc_will_not_call_mercury, no, no, no, no, no, MD), "") ]), RestoreDeallocCode = empty, % always empty for nondet code ExitCode = tree_list([StartComment, UndefCode, EndComment]) @@ -1169,12 +1173,13 @@ generate_exit(CodeModel, FrameInfo, TraceSlotInfo, ProcContext, ReturnMacroName = "MR_tbl_mmos_return_answer", ReturnCodeStr = "\t" ++ ReturnMacroName ++ "(" ++ DebugStr ++ ", " ++ GeneratorLocnStr ++ ");\n", - Component = foreign_proc_user_code(no, does_not_affect_liveness, - ReturnCodeStr), + Component = foreign_proc_user_code(no, + proc_does_not_affect_liveness, ReturnCodeStr), + MD = proc_may_not_duplicate, SuccessCode = node([ llds_instr(livevals(LiveLvals), ""), llds_instr(foreign_proc_code([], [Component], - proc_may_call_mercury, no, no, no, no, no, no), "") + proc_may_call_mercury, no, no, no, no, no, MD), "") ]) ; MaybeSpecialReturn = no, @@ -1268,20 +1273,22 @@ bytecode_stub(ModuleInfo, PredId, ProcId, BytecodeInstructions) :- ], BytecodeCall), BytecodeInstructionsComponents = [ - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - live_lvals_info(set.init), "\t{\n"), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - live_lvals_info(set.init), CallStruct), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - no_live_lvals_info, BytecodeCall), - foreign_proc_raw_code(cannot_branch_away, does_not_affect_liveness, - live_lvals_info(set.init), "\t}\n") + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, live_lvals_info(set.init), "\t{\n"), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, live_lvals_info(set.init), + CallStruct), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, no_live_lvals_info, BytecodeCall), + foreign_proc_raw_code(cannot_branch_away, + proc_does_not_affect_liveness, live_lvals_info(set.init), "\t}\n") ], + MD = proc_may_not_duplicate, BytecodeInstructions = [ llds_instr(label(EntryLabel), "Procedure entry point"), llds_instr(foreign_proc_code([], BytecodeInstructionsComponents, - proc_may_call_mercury, no, no, no, no, no, no), "Entry stub") + proc_may_call_mercury, no, no, no, no, no, MD), "Entry stub") ]. %---------------------------------------------------------------------------% diff --git a/compiler/prog_data.m b/compiler/prog_data.m index 30c3dc24d..1d3d875bb 100644 --- a/compiler/prog_data.m +++ b/compiler/prog_data.m @@ -686,8 +686,6 @@ :- func default_attributes(foreign_language) = pragma_foreign_proc_attributes. :- func get_may_call_mercury(pragma_foreign_proc_attributes) = proc_may_call_mercury. -:- func get_affects_liveness(pragma_foreign_proc_attributes) = - affects_liveness. :- func get_thread_safe(pragma_foreign_proc_attributes) = proc_thread_safe. :- func get_purity(pragma_foreign_proc_attributes) = purity. :- func get_terminates(pragma_foreign_proc_attributes) = proc_terminates. @@ -705,11 +703,15 @@ proc_may_modify_trail. :- func get_may_call_mm_tabled(pragma_foreign_proc_attributes) = may_call_mm_tabled. -:- func get_allocates_memory(pragma_foreign_proc_attributes) = - allocates_memory. -:- func get_registers_roots(pragma_foreign_proc_attributes) = - registers_roots. :- func get_box_policy(pragma_foreign_proc_attributes) = box_policy. +:- func get_affects_liveness(pragma_foreign_proc_attributes) = + proc_affects_liveness. +:- func get_allocates_memory(pragma_foreign_proc_attributes) = + proc_allocates_memory. +:- func get_registers_roots(pragma_foreign_proc_attributes) = + proc_registers_roots. +:- func get_may_duplicate(pragma_foreign_proc_attributes) = + maybe(proc_may_duplicate). :- func get_extra_attributes(pragma_foreign_proc_attributes) = pragma_foreign_proc_extra_attributes. @@ -717,10 +719,6 @@ pragma_foreign_proc_attributes::in, pragma_foreign_proc_attributes::out) is det. -:- pred set_affects_liveness(affects_liveness::in, - pragma_foreign_proc_attributes::in, - pragma_foreign_proc_attributes::out) is det. - :- pred set_thread_safe(proc_thread_safe::in, pragma_foreign_proc_attributes::in, pragma_foreign_proc_attributes::out) is det. @@ -765,18 +763,26 @@ pragma_foreign_proc_attributes::in, pragma_foreign_proc_attributes::out) is det. -:- pred set_allocates_memory(allocates_memory::in, - pragma_foreign_proc_attributes::in, - pragma_foreign_proc_attributes::out) is det. - -:- pred set_registers_roots(registers_roots::in, - pragma_foreign_proc_attributes::in, - pragma_foreign_proc_attributes::out) is det. - :- pred set_box_policy(box_policy::in, pragma_foreign_proc_attributes::in, pragma_foreign_proc_attributes::out) is det. +:- pred set_affects_liveness(proc_affects_liveness::in, + pragma_foreign_proc_attributes::in, + pragma_foreign_proc_attributes::out) is det. + +:- pred set_allocates_memory(proc_allocates_memory::in, + pragma_foreign_proc_attributes::in, + pragma_foreign_proc_attributes::out) is det. + +:- pred set_registers_roots(proc_registers_roots::in, + pragma_foreign_proc_attributes::in, + pragma_foreign_proc_attributes::out) is det. + +:- pred set_may_duplicate(maybe(proc_may_duplicate)::in, + pragma_foreign_proc_attributes::in, + pragma_foreign_proc_attributes::out) is det. + :- pred add_extra_attribute(pragma_foreign_proc_extra_attribute::in, pragma_foreign_proc_attributes::in, pragma_foreign_proc_attributes::out) is det. @@ -834,22 +840,26 @@ ---> native_if_possible ; always_boxed. -:- type affects_liveness - ---> affects_liveness - ; does_not_affect_liveness - ; default_affects_liveness. +:- type proc_affects_liveness + ---> proc_affects_liveness + ; proc_does_not_affect_liveness + ; proc_default_affects_liveness. -:- type allocates_memory - ---> does_not_allocate_memory - ; allocates_bounded_memory - ; allocates_unbounded_memory - ; default_allocates_memory. +:- type proc_allocates_memory + ---> proc_does_not_allocate_memory + ; proc_allocates_bounded_memory + ; proc_allocates_unbounded_memory + ; proc_default_allocates_memory. -:- type registers_roots - ---> registers_roots - ; does_not_register_roots - ; does_not_have_roots - ; default_registers_roots. +:- type proc_registers_roots + ---> proc_registers_roots + ; proc_does_not_register_roots + ; proc_does_not_have_roots + ; proc_default_registers_roots. + +:- type proc_may_duplicate + ---> proc_may_duplicate + ; proc_may_not_duplicate. % This type specifies the termination property of a procedure % defined using pragma c_code or pragma foreign_proc. @@ -1704,9 +1714,10 @@ default_memo_table_attributes = attr_may_modify_trail :: proc_may_modify_trail, attr_may_call_mm_tabled :: may_call_mm_tabled, attr_box_policy :: box_policy, - attr_affects_liveness :: affects_liveness, - attr_allocates_memory :: allocates_memory, - attr_registers_roots :: registers_roots, + attr_affects_liveness :: proc_affects_liveness, + attr_allocates_memory :: proc_allocates_memory, + attr_registers_roots :: proc_registers_roots, + attr_may_duplicate :: maybe(proc_may_duplicate), attr_extra_attributes :: list(pragma_foreign_proc_extra_attribute) ). @@ -1716,8 +1727,9 @@ default_attributes(Language) = proc_not_tabled_for_io, purity_impure, depends_on_mercury_calls, no_user_annotated_sharing, default_exception_behaviour, no, no, proc_may_modify_trail, default_calls_mm_tabled, - native_if_possible, default_affects_liveness, - default_allocates_memory, default_registers_roots, []). + native_if_possible, proc_default_affects_liveness, + proc_default_allocates_memory, proc_default_registers_roots, + no, []). get_may_call_mercury(Attrs) = Attrs ^ attr_may_call_mercury. get_thread_safe(Attrs) = Attrs ^ attr_thread_safe. @@ -1735,6 +1747,7 @@ get_box_policy(Attrs) = Attrs ^ attr_box_policy. get_affects_liveness(Attrs) = Attrs ^ attr_affects_liveness. get_allocates_memory(Attrs) = Attrs ^ attr_allocates_memory. get_registers_roots(Attrs) = Attrs ^ attr_registers_roots. +get_may_duplicate(Attrs) = Attrs ^ attr_may_duplicate. get_extra_attributes(Attrs) = Attrs ^ attr_extra_attributes. set_may_call_mercury(MayCallMercury, Attrs0, Attrs) :- @@ -1769,6 +1782,8 @@ set_allocates_memory(AllocatesMemory, Attrs0, Attrs) :- Attrs = Attrs0 ^ attr_allocates_memory := AllocatesMemory. set_registers_roots(RegistersRoots, Attrs0, Attrs) :- Attrs = Attrs0 ^ attr_registers_roots := RegistersRoots. +set_may_duplicate(MayDuplicate, Attrs0, Attrs) :- + Attrs = Attrs0 ^ attr_may_duplicate := MayDuplicate. attributes_to_strings(Attrs) = StringList :- % We ignore Lang because it isn't an attribute that you can put @@ -1778,7 +1793,7 @@ attributes_to_strings(Attrs) = StringList :- Purity, Terminates, _UserSharing, Exceptions, _LegacyBehaviour, OrdinaryDespiteDetism, MayModifyTrail, MayCallMM_Tabled, BoxPolicy, AffectsLiveness, AllocatesMemory, RegistersRoots, - ExtraAttributes), + MaybeMayDuplicate, ExtraAttributes), ( MayCallMercury = proc_may_call_mercury, MayCallMercuryStr = "may_call_mercury" @@ -1868,47 +1883,60 @@ attributes_to_strings(Attrs) = StringList :- BoxPolicyStrList = ["always_boxed"] ), ( - AffectsLiveness = affects_liveness, + AffectsLiveness = proc_affects_liveness, AffectsLivenessStrList = ["affects_liveness"] ; - AffectsLiveness = does_not_affect_liveness, + AffectsLiveness = proc_does_not_affect_liveness, AffectsLivenessStrList = ["doesnt_affect_liveness"] ; - AffectsLiveness = default_affects_liveness, + AffectsLiveness = proc_default_affects_liveness, AffectsLivenessStrList = [] ), ( - AllocatesMemory = does_not_allocate_memory, + AllocatesMemory = proc_does_not_allocate_memory, AllocatesMemoryStrList =["doesnt_allocate_memory"] ; - AllocatesMemory = allocates_bounded_memory, + AllocatesMemory = proc_allocates_bounded_memory, AllocatesMemoryStrList = ["allocates_bounded_memory"] ; - AllocatesMemory = allocates_unbounded_memory, + AllocatesMemory = proc_allocates_unbounded_memory, AllocatesMemoryStrList = ["allocates_unbounded_memory"] ; - AllocatesMemory = default_allocates_memory, + AllocatesMemory = proc_default_allocates_memory, AllocatesMemoryStrList = [] ), ( - RegistersRoots = registers_roots, + RegistersRoots = proc_registers_roots, RegistersRootsStrList = ["registers_roots"] ; - RegistersRoots = does_not_register_roots, + RegistersRoots = proc_does_not_register_roots, RegistersRootsStrList =["doesnt_register_roots"] ; - RegistersRoots = does_not_have_roots, + RegistersRoots = proc_does_not_have_roots, RegistersRootsStrList = ["doesnt_have_roots"] ; - RegistersRoots = default_registers_roots, + RegistersRoots = proc_default_registers_roots, RegistersRootsStrList = [] ), + ( + MaybeMayDuplicate = yes(MayDuplicate), + ( + MayDuplicate = proc_may_duplicate, + MayDuplicateStrList = ["may_duplicate"] + ; + MayDuplicate = proc_may_not_duplicate, + MayDuplicateStrList = ["may_not_duplicate"] + ) + ; + MaybeMayDuplicate = no, + MayDuplicateStrList = [] + ), StringList = [MayCallMercuryStr, ThreadSafeStr, TabledForIOStr | PurityStrList] ++ TerminatesStrList ++ ExceptionsStrList ++ OrdinaryDespiteDetismStrList ++ MayModifyTrailStrList ++ MayCallMM_TabledStrList ++ BoxPolicyStrList ++ - AffectsLivenessStrList ++ - AllocatesMemoryStrList ++ RegistersRootsStrList ++ + AffectsLivenessStrList ++ AllocatesMemoryStrList ++ + RegistersRootsStrList ++ MayDuplicateStrList ++ list.map(extra_attribute_to_string, ExtraAttributes). add_extra_attribute(NewAttribute, Attributes0, diff --git a/compiler/prog_io_pragma.m b/compiler/prog_io_pragma.m index 50aea9b34..2eded1d5b 100644 --- a/compiler/prog_io_pragma.m +++ b/compiler/prog_io_pragma.m @@ -1495,9 +1495,10 @@ parse_pragma_keyword(ExpectedKeyword, Term, StringArg, StartContext) :- ; coll_may_modify_trail(proc_may_modify_trail) ; coll_may_call_mm_tabled(may_call_mm_tabled) ; coll_box_policy(box_policy) - ; coll_affects_liveness(affects_liveness) - ; coll_allocates_memory(allocates_memory) - ; coll_registers_roots(registers_roots). + ; coll_affects_liveness(proc_affects_liveness) + ; coll_allocates_memory(proc_allocates_memory) + ; coll_registers_roots(proc_registers_roots) + ; coll_may_duplicate(proc_may_duplicate). :- pred parse_pragma_foreign_proc_attributes_term(foreign_language::in, string::in, varset::in, term::in, @@ -1543,20 +1544,22 @@ parse_pragma_foreign_proc_attributes_term(ForeignLanguage, Pragma, Varset, coll_may_call_mercury(proc_will_not_call_mercury) - coll_may_call_mm_tabled(may_call_mm_tabled), coll_box_policy(native_if_possible) - coll_box_policy(always_boxed), - coll_affects_liveness(affects_liveness) - - coll_affects_liveness(does_not_affect_liveness), - coll_allocates_memory(does_not_allocate_memory) - - coll_allocates_memory(allocates_bounded_memory), - coll_allocates_memory(does_not_allocate_memory) - - coll_allocates_memory(allocates_unbounded_memory), - coll_allocates_memory(allocates_bounded_memory) - - coll_allocates_memory(allocates_unbounded_memory), - coll_registers_roots(does_not_register_roots) - - coll_registers_roots(registers_roots), - coll_registers_roots(does_not_register_roots) - - coll_registers_roots(does_not_have_roots), - coll_registers_roots(registers_roots) - - coll_registers_roots(does_not_have_roots) + coll_affects_liveness(proc_affects_liveness) - + coll_affects_liveness(proc_does_not_affect_liveness), + coll_allocates_memory(proc_does_not_allocate_memory) - + coll_allocates_memory(proc_allocates_bounded_memory), + coll_allocates_memory(proc_does_not_allocate_memory) - + coll_allocates_memory(proc_allocates_unbounded_memory), + coll_allocates_memory(proc_allocates_bounded_memory) - + coll_allocates_memory(proc_allocates_unbounded_memory), + coll_registers_roots(proc_does_not_register_roots) - + coll_registers_roots(proc_registers_roots), + coll_registers_roots(proc_does_not_register_roots) - + coll_registers_roots(proc_does_not_have_roots), + coll_registers_roots(proc_registers_roots) - + coll_registers_roots(proc_does_not_have_roots), + coll_may_duplicate(proc_may_duplicate) - + coll_may_duplicate(proc_may_not_duplicate) ], ( parse_pragma_foreign_proc_attributes_term0(Varset, Term, AttrList) -> ( @@ -1619,6 +1622,8 @@ process_attribute(coll_allocates_memory(AllocatesMemory), !Attrs) :- set_allocates_memory(AllocatesMemory, !Attrs). process_attribute(coll_registers_roots(RegistersRoots), !Attrs) :- set_registers_roots(RegistersRoots, !Attrs). +process_attribute(coll_may_duplicate(MayDuplicate), !Attrs) :- + set_may_duplicate(yes(MayDuplicate), !Attrs). % Check whether all the required attributes have been set for % a particular language @@ -1699,6 +1704,8 @@ parse_single_pragma_foreign_proc_attribute(Varset, Term, Flag) :- Flag = coll_allocates_memory(AllocatesMemory) ; parse_registers_roots(Term, RegistersRoots) -> Flag = coll_registers_roots(RegistersRoots) + ; parse_may_duplicate(Term, MayDuplicate) -> + Flag = coll_may_duplicate(MayDuplicate) ; fail ). @@ -1746,21 +1753,21 @@ parse_box_policy(term.functor(term.atom("native_if_possible"), [], _), parse_box_policy(term.functor(term.atom("always_boxed"), [], _), always_boxed). -:- pred parse_affects_liveness(term::in, affects_liveness::out) is semidet. +:- pred parse_affects_liveness(term::in, proc_affects_liveness::out) is semidet. parse_affects_liveness(Term, AffectsLiveness) :- Term = term.functor(term.atom(Functor), [], _), ( Functor = "affects_liveness", - AffectsLiveness = affects_liveness + AffectsLiveness = proc_affects_liveness ; ( Functor = "doesnt_affect_liveness" ; Functor = "does_not_affect_liveness" ), - AffectsLiveness = does_not_affect_liveness + AffectsLiveness = proc_does_not_affect_liveness ). -:- pred parse_allocates_memory(term::in, allocates_memory::out) is semidet. +:- pred parse_allocates_memory(term::in, proc_allocates_memory::out) is semidet. parse_allocates_memory(Term, AllocatesMemory) :- Term = term.functor(term.atom(Functor), [], _), @@ -1768,32 +1775,44 @@ parse_allocates_memory(Term, AllocatesMemory) :- ( Functor = "doesnt_allocate_memory" ; Functor = "does_not_allocate_memory" ), - AllocatesMemory = does_not_allocate_memory + AllocatesMemory = proc_does_not_allocate_memory ; Functor = "allocates_bounded_memory", - AllocatesMemory = allocates_bounded_memory + AllocatesMemory = proc_allocates_bounded_memory ; Functor = "allocates_unbounded_memory", - AllocatesMemory = allocates_unbounded_memory + AllocatesMemory = proc_allocates_unbounded_memory ). -:- pred parse_registers_roots(term::in, registers_roots::out) is semidet. +:- pred parse_registers_roots(term::in, proc_registers_roots::out) is semidet. parse_registers_roots(Term, RegistersRoots) :- Term = term.functor(term.atom(Functor), [], _), ( Functor = "registers_roots", - RegistersRoots = registers_roots + RegistersRoots = proc_registers_roots ; ( Functor = "doesnt_register_roots" ; Functor = "does_not_register_roots" ), - RegistersRoots = does_not_register_roots + RegistersRoots = proc_does_not_register_roots ; ( Functor = "doesnt_have_roots" ; Functor = "does_not_have_roots" ), - RegistersRoots = does_not_have_roots + RegistersRoots = proc_does_not_have_roots + ). + +:- pred parse_may_duplicate(term::in, proc_may_duplicate::out) is semidet. + +parse_may_duplicate(Term, RegistersRoots) :- + Term = term.functor(term.atom(Functor), [], _), + ( + Functor = "may_duplicate", + RegistersRoots = proc_may_duplicate + ; + Functor = "may_not_duplicate", + RegistersRoots = proc_may_not_duplicate ). :- pred parse_tabled_for_io(term::in, proc_tabled_for_io::out) is semidet. diff --git a/compiler/simplify.m b/compiler/simplify.m index 5d4df4ed6..921185633 100644 --- a/compiler/simplify.m +++ b/compiler/simplify.m @@ -386,7 +386,7 @@ simplify_proc(Simplifications, PredId, ProcId, !ModuleInfo, !ProcInfo, !IO) :- turn_off_common_struct_threshold = 1000. simplify_proc_return_msgs(Simplifications0, PredId, ProcId, !ModuleInfo, - !ProcInfo, ErrorSpecs, !IO) :- + !ProcInfo, !:ErrorSpecs, !IO) :- proc_info_get_vartypes(!.ProcInfo, VarTypes0), NumVars = map.count(VarTypes0), ( NumVars > turn_off_common_struct_threshold -> @@ -436,7 +436,7 @@ simplify_proc_return_msgs(Simplifications0, PredId, ProcId, !ModuleInfo, proc_info_set_has_user_event(HasUserEvent, !ProcInfo), simplify_info_get_module_info(Info, !:ModuleInfo), - simplify_info_get_error_specs(Info, ErrorSpecs0), + simplify_info_get_error_specs(Info, !:ErrorSpecs), ( Info ^ format_calls = yes, ( @@ -450,12 +450,56 @@ simplify_proc_return_msgs(Simplifications0, PredId, ProcId, !ModuleInfo, % build the format strings or values, which means that the new version % in Goal may not contain the information find_format_call_errors needs % to avoid spurious messages about unknown format strings or values. - find_format_call_errors(!.ModuleInfo, Goal0, ErrorSpecs0, ErrorSpecs1) + find_format_call_errors(!.ModuleInfo, Goal0, !ErrorSpecs) ; % Either there are no calls to check or we would ignore the added % messages anyway. - ErrorSpecs1 = ErrorSpecs0 + true ), + + Goal = hlds_goal(GoalExpr, GoalInfo), + ( + GoalExpr = call_foreign_proc(Attributes, _, _, _, _, _, _), + MaybeMayDuplicate = get_may_duplicate(Attributes), + MaybeMayDuplicate = yes(MayDuplicate) + -> + ( + MayDuplicate = proc_may_duplicate, + ( check_marker(Markers, marker_user_marked_no_inline) -> + goal_info_get_context(GoalInfo, Context), + Pieces = [words("Error: the `may_duplicate' attribute"), + words("on the foreign_proc"), + words("contradicts the `no_inline' pragma"), + words("on the predicate.")], + Msg = simple_msg(Context, [always(Pieces)]), + Severity = severity_error, + Spec = error_spec(Severity, phase_simplify(report_in_any_mode), + [Msg]), + !:ErrorSpecs = [Spec | !.ErrorSpecs] + ; + true + ) + ; + MayDuplicate = proc_may_not_duplicate, + ( check_marker(Markers, marker_user_marked_inline) -> + goal_info_get_context(GoalInfo, Context), + Pieces = [words("Error: the `may_not_duplicate' attribute"), + words("on the foreign_proc"), + words("contradicts the `inline' pragma"), + words("on the predicate.")], + Msg = simple_msg(Context, [always(Pieces)]), + Severity = severity_error, + Spec = error_spec(Severity, phase_simplify(report_in_any_mode), + [Msg]), + !:ErrorSpecs = [Spec | !.ErrorSpecs] + ; + true + ) + ) + ; + true + ), + pred_info_get_import_status(PredInfo, Status), IsDefinedHere = status_defined_in_this_module(Status), ( @@ -463,10 +507,9 @@ simplify_proc_return_msgs(Simplifications0, PredId, ProcId, !ModuleInfo, % Don't generate any warnings or even errors if the predicate isn't % defined here; any such messages will be generated when we compile % the module the predicate comes from. - ErrorSpecs = [] + !:ErrorSpecs = [] ; - IsDefinedHere = yes, - ErrorSpecs = ErrorSpecs1 + IsDefinedHere = yes ). simplify_process_clause_body_goal(Goal0, Goal, !Info, !IO) :- diff --git a/compiler/table_gen.m b/compiler/table_gen.m index 315bbdd5c..5b7137f91 100644 --- a/compiler/table_gen.m +++ b/compiler/table_gen.m @@ -664,15 +664,15 @@ create_new_loop_goal(Detism, OrigGoal, Statistics, PredId, ProcId, "(" ++ DebugArgStr ++ ", " ++ cur_table_node_name ++ ");\n", table_generate_foreign_proc(MarkInactivePredName, detism_det, - tabling_c_attributes, [TableTipArg], [], + tabling_c_attributes_dupl, [TableTipArg], [], MarkInactiveCode, purity_impure, [], ModuleInfo, Context, MarkInactiveGoal), table_generate_foreign_proc(MarkInactiveFailPredName, detism_failure, - tabling_c_attributes, [TableTipArg], [], + tabling_c_attributes_dupl, [TableTipArg], [], MarkInactiveFailCode, purity_impure, [], ModuleInfo, Context, MarkInactiveFailGoal), table_generate_foreign_proc(MarkActiveFailPredName, detism_failure, - tabling_c_attributes, [TableTipArg], [], + tabling_c_attributes_dupl, [TableTipArg], [], MarkActiveFailCode, purity_impure, [], ModuleInfo, Context, MarkActiveFailGoal), @@ -947,7 +947,7 @@ create_new_memo_goal(Detism, OrigGoal, Statistics, _MaybeSizeLimit, MarkAsFailedCode = MarkAsFailedMacroName ++ "(" ++ DebugArgStr ++ ", " ++ cur_table_node_name ++ ");", table_generate_foreign_proc(MarkAsFailedPredName, detism_failure, - tabling_c_attributes, [TableTipArg], [], + tabling_c_attributes_dupl, [TableTipArg], [], MarkAsFailedCode, purity_impure, [], ModuleInfo, Context, ElseGoal), InactiveGoalExpr = if_then_else([], RenamedOrigGoal, @@ -1038,15 +1038,15 @@ create_new_memo_non_goal(Detism, OrigGoal, Statistics, _MaybeSizeLimit, "(" ++ DebugArgStr ++ ", " ++ RecordVarName ++ ");\n", table_generate_foreign_proc(MarkIncompletePredName, detism_det, - tabling_c_attributes, [RecordArg], [], + tabling_c_attributes_dupl, [RecordArg], [], MarkIncompleteCode, purity_impure, [], ModuleInfo, Context, MarkIncompleteGoal), table_generate_foreign_proc(MarkActivePredName, detism_failure, - tabling_c_attributes, [RecordArg], [], + tabling_c_attributes_dupl, [RecordArg], [], MarkActiveCode, purity_impure, [], ModuleInfo, Context, MarkActiveGoal), table_generate_foreign_proc(MarkCompletePredName, detism_failure, - tabling_c_attributes, [RecordArg], [], + tabling_c_attributes_dupl, [RecordArg], [], MarkCompleteCode, purity_impure, [], ModuleInfo, Context, MarkCompleteGoal), @@ -1665,9 +1665,9 @@ do_own_stack_transform(Detism, OrigGoal, Statistics, PredId, ProcId, native_if_possible), RestoreAllPredName = "table_mmos_restore_answers", table_generate_foreign_proc(RestoreAllPredName, detism_det, - tabling_c_attributes, [AnswerBlockArg], RestoreArgs, RestoreCodeStr, - purity_semipure, RestoreInstMapDeltaSrc, ModuleInfo, Context, - RestoreGoal), + tabling_c_attributes_no_dupl, [AnswerBlockArg], + RestoreArgs, RestoreCodeStr, purity_semipure, RestoreInstMapDeltaSrc, + ModuleInfo, Context, RestoreGoal), GoalExpr = conj(plain_conj, LookupSetupGoals ++ [GetNextAnswerGoal, RestoreGoal]), @@ -1742,7 +1742,7 @@ do_own_stack_create_generator(PredId, ProcId, !.PredInfo, !.ProcInfo, PickupGeneratorArg = foreign_arg(GeneratorVar, yes(generator_name - out_mode), generator_type, native_if_possible), table_generate_foreign_proc("table_mmos_pickup_inputs", detism_det, - tabling_c_attributes, [PickupGeneratorArg], PickupForeignArgs, + tabling_c_attributes_no_dupl, [PickupGeneratorArg], PickupForeignArgs, PickupGeneratorCode ++ PickupVarCode, purity_impure, PickupInstMapDeltaSrc, ModuleInfo0, Context, PickupGoal), @@ -1768,7 +1768,7 @@ do_own_stack_create_generator(PredId, ProcId, !.PredInfo, !.ProcInfo, CompletionArg = foreign_arg(GeneratorVar, yes(generator_name - in_mode), generator_type, native_if_possible), table_generate_foreign_proc("table_mmos_completion", detism_failure, - tabling_c_attributes, [CompletionArg], [], + tabling_c_attributes_no_dupl, [CompletionArg], [], CompletionCode, purity_impure, [], ModuleInfo0, Context, CompletionGoal), @@ -1997,7 +1997,8 @@ generate_simple_call_table_lookup_goal(StatusType, PredName, LookupCodeStr ++ CallTableTipAssignStr ++ MainPredCodeStr, - table_generate_foreign_proc(PredName, detism_det, tabling_c_attributes, + table_generate_foreign_proc(PredName, detism_det, + tabling_c_attributes_no_dupl, Args, LookupForeignArgs, CodeStr, purity_impure, ground_vars(BoundVars), ModuleInfo, Context, SetupGoal0), attach_call_table_tip(SetupGoal0, SetupGoal), @@ -2054,7 +2055,7 @@ generate_memo_non_call_table_lookup_goal(NumberedVars, PredId, ProcId, cur_table_node_name ++ ", " ++ RecordVarName ++ ", " ++ StatusVarName ++ ");\n", table_generate_foreign_proc(SetupPredName, detism_det, - tabling_c_attributes, Args, LookupForeignArgs, + tabling_c_attributes_no_dupl, Args, LookupForeignArgs, LookupDeclCodeStr ++ PredCodeStr, purity_impure, ground_vars(BoundVars), ModuleInfo, Context, SetupGoal0), attach_call_table_tip(SetupGoal0, SetupGoal), @@ -2110,8 +2111,9 @@ generate_mm_call_table_lookup_goal(NumberedVars, PredId, ProcId, CodeStr = LookupDeclStr ++ LookupCodeStr ++ SetupCodeStr, ModuleInfo = !.TableInfo ^ table_module_info, table_generate_foreign_proc(SetupPredName, detism_det, - tabling_c_attributes, Args, LookupForeignArgs, CodeStr, purity_impure, - ground_vars(BoundVars), ModuleInfo, Context, SetupGoal0), + tabling_c_attributes_no_dupl, Args, LookupForeignArgs, CodeStr, + purity_impure, ground_vars(BoundVars), ModuleInfo, Context, + SetupGoal0), attach_call_table_tip(SetupGoal0, SetupGoal), LookupSetupGoals = LookupPrefixGoals ++ [SetupGoal], @@ -2421,7 +2423,7 @@ generate_memo_save_goal(NumberedSaveVars, TableTipVar, BlockSize, BlockSize, CreateMacroName, Context, !VarSet, !VarTypes, !TableInfo, SaveArgs, SavePrefixGoals, SaveDeclCode, SaveCode), table_generate_foreign_proc(CreatePredName, detism_det, - tabling_c_attributes, [TableArg], SaveArgs, + tabling_c_attributes_dupl, [TableArg], SaveArgs, SaveDeclCode ++ SaveCode, purity_impure, [], ModuleInfo, Context, SaveGoal), Goals = SavePrefixGoals ++ [SaveGoal] @@ -2432,7 +2434,7 @@ generate_memo_save_goal(NumberedSaveVars, TableTipVar, BlockSize, MarkAsSucceededCode = MarkAsSucceededMacroName ++ "(" ++ DebugArgStr ++ ", " ++ cur_table_node_name ++ ");", table_generate_foreign_proc(MarkAsSucceededPredName, detism_det, - tabling_c_attributes, [TableArg], [], + tabling_c_attributes_dupl, [TableArg], [], MarkAsSucceededCode, purity_impure, [], ModuleInfo, Context, SaveGoal), Goals = [SaveGoal] @@ -2490,7 +2492,7 @@ generate_memo_non_save_goals(NumberedSaveVars, PredId, ProcId, "\tif (" ++ SuccName ++ ") {\n" ++ CreateSaveCode ++ "\t}\n" ++ AssignSuccessCodeStr, table_generate_foreign_proc(DuplCheckPredName, detism_semi, - tabling_c_attributes, [RecordArg], LookupForeignArgs, CodeStr, + tabling_c_attributes_dupl, [RecordArg], LookupForeignArgs, CodeStr, purity_impure, [], ModuleInfo, Context, DuplicateCheckSaveGoal), Goals = LookupPrefixGoals ++ [DuplicateCheckSaveGoal]. @@ -2545,7 +2547,7 @@ generate_mm_save_goals(NumberedSaveVars, SubgoalVar, PredId, ProcId, BlockSize, GetCodeStr ++ LookupCodeStr ++ DuplCheckCodeStr ++ CondSaveStr ++ AssignSuccessCodeStr, table_generate_foreign_proc(DuplCheckPredName, detism_semi, - tabling_c_attributes, Args, LookupForeignArgs, + tabling_c_attributes_dupl, Args, LookupForeignArgs, CodeStr, purity_impure, [], ModuleInfo, Context, DuplicateCheckSaveGoal), Goals = LookupPrefixGoals ++ [DuplicateCheckSaveGoal]. @@ -2630,7 +2632,7 @@ generate_own_stack_save_return_goal(NumberedOutputVars, GeneratorVar, DuplCheckCodeStr ++ CondSaveCodeStr ++ AssignSuccessCodeStr, ModuleInfo = !.TableInfo ^ table_module_info, table_generate_foreign_proc(DuplCheckPredName, detism_semi, - tabling_c_attributes, Args, LookupForeignArgs, + tabling_c_attributes_dupl, Args, LookupForeignArgs, CodeStr, purity_impure, [], ModuleInfo, Context, DuplicateCheckSaveGoal), Goals = LookupPrefixGoals ++ SavePrefixGoals ++ @@ -2729,7 +2731,7 @@ generate_memo_restore_goal(NumberedOutputVars, OrigInstMapDelta, TipVar, answer_block_name ++ ");\n" ++ RestoreCodeStr, table_generate_foreign_proc(GetPredName, detism_det, - tabling_c_attributes, Args, RestoreArgs, + tabling_c_attributes_dupl, Args, RestoreArgs, DeclCodeStr ++ GetRestoreCodeStr, purity_semipure, RestoreInstMapDeltaSrc, ModuleInfo, Context, ShortcutGoal), Goal = ShortcutGoal @@ -2770,9 +2772,10 @@ generate_memo_non_restore_goal(Detism, NumberedOutputVars, OrigInstMapDelta, answer_block_type, native_if_possible), Args = [Arg], PredName = "table_memo_non_return_all_shortcut", - table_generate_foreign_proc(PredName, detism_det, tabling_c_attributes, - Args, RestoreArgs, RestoreCodeStr, purity_semipure, - RestoreInstMapDeltaSrc, ModuleInfo, Context, ShortcutGoal), + table_generate_foreign_proc(PredName, detism_det, + tabling_c_attributes_no_dupl, Args, RestoreArgs, RestoreCodeStr, + purity_semipure, RestoreInstMapDeltaSrc, ModuleInfo, Context, + ShortcutGoal), GoalExpr = conj(plain_conj, [ReturnAnswerBlocksGoal, ShortcutGoal]), set.list_to_set([RecordVar | OutputVars], NonLocals), @@ -2844,7 +2847,7 @@ generate_mm_restore_or_suspend_goal(PredName, Detism, Purity, Args = [Arg], ReturnAllPredName = "table_mm_return_all_shortcut", table_generate_foreign_proc(ReturnAllPredName, detism_det, - tabling_c_attributes, Args, RestoreArgs, RestoreCodeStr, + tabling_c_attributes_no_dupl, Args, RestoreArgs, RestoreCodeStr, purity_semipure, RestoreInstMapDeltaSrc, ModuleInfo, Context, ReturnAllGoal), GoalExpr = conj(plain_conj, [ReturnAnswerBlocksGoal, ReturnAllGoal]), @@ -3524,11 +3527,20 @@ var_is_io_state(VarTypes, Var) :- %-----------------------------------------------------------------------------% -:- func tabling_c_attributes = pragma_foreign_proc_attributes. +:- func tabling_c_attributes_dupl = pragma_foreign_proc_attributes. -tabling_c_attributes = Attrs :- +tabling_c_attributes_dupl = Attrs :- Attrs0 = default_attributes(lang_c), - set_may_call_mercury(proc_will_not_call_mercury, Attrs0, Attrs). + set_may_call_mercury(proc_will_not_call_mercury, Attrs0, Attrs1), + set_affects_liveness(proc_does_not_affect_liveness, Attrs1, Attrs2), + set_may_duplicate(yes(proc_may_duplicate), Attrs2, Attrs). + +:- func tabling_c_attributes_no_dupl = pragma_foreign_proc_attributes. + +tabling_c_attributes_no_dupl = Attrs :- + Attrs0 = default_attributes(lang_c), + set_may_call_mercury(proc_will_not_call_mercury, Attrs0, Attrs1), + set_affects_liveness(proc_does_not_affect_liveness, Attrs1, Attrs). :- func make_generator_c_attributes = pragma_foreign_proc_attributes. diff --git a/compiler/trace_gen.m b/compiler/trace_gen.m index 77f847317..6fcfa6cf7 100644 --- a/compiler/trace_gen.m +++ b/compiler/trace_gen.m @@ -625,10 +625,11 @@ generate_slot_fill_code(CI, TraceInfo, TraceCode) :- TraceStmt1 = FillSlotsUptoTrail ), TraceComponents1 = [foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), TraceStmt1)], + proc_does_not_affect_liveness, live_lvals_info(set.init), TraceStmt1)], + MD = proc_may_not_duplicate, TraceCode1 = node([ llds_instr(foreign_proc_code([], TraceComponents1, - proc_will_not_call_mercury, no, no, MaybeLayoutLabel, no, yes, no), + proc_will_not_call_mercury, no, no, MaybeLayoutLabel, no, yes, MD), "") ]), ( @@ -645,10 +646,11 @@ generate_slot_fill_code(CI, TraceInfo, TraceCode) :- stackref_to_string(CallTableLval, CallTableLvalStr), TraceStmt3 = "\t\t" ++ CallTableLvalStr ++ " = 0;\n", TraceComponents3 = [foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(set.init), TraceStmt3)], + proc_does_not_affect_liveness, live_lvals_info(set.init), + TraceStmt3)], TraceCode3 = node([ llds_instr(foreign_proc_code([], TraceComponents3, - proc_will_not_call_mercury, no, no, no, no, yes, no), "") + proc_will_not_call_mercury, no, no, no, no, yes, MD), "") ]) ; MaybeCallTableLval = no, @@ -673,7 +675,7 @@ trace_prepare_for_call(CI, TraceCode) :- ), ResetStmt = MacroStr ++ "(" ++ CallDepthStr ++ ");\n", TraceCode = node([ - llds_instr(arbitrary_c_code(does_not_affect_liveness, + llds_instr(arbitrary_c_code(proc_does_not_affect_liveness, live_lvals_info(set.init), ResetStmt), "") ]) ; @@ -922,7 +924,9 @@ generate_event_code(Port, PortInfo, MaybeTraceInfo, Context, HideEvent, true ), TraceComponents = [foreign_proc_raw_code(cannot_branch_away, - does_not_affect_liveness, live_lvals_info(LiveLvalSet), TraceStmt)], + proc_does_not_affect_liveness, live_lvals_info(LiveLvalSet), + TraceStmt)], + MD = proc_may_not_duplicate, TraceCode = node([ llds_instr(label(Label), @@ -933,7 +937,7 @@ generate_event_code(Port, PortInfo, MaybeTraceInfo, Context, HideEvent, % pair is preceded by another label, and this way we can % eliminate this other label. llds_instr(foreign_proc_code([], TraceComponents, - proc_may_call_mercury, no, no, yes(Label), no, yes, no), "") + proc_may_call_mercury, no, no, yes(Label), no, yes, MD), "") ]), Code = tree(ProduceCode, TraceCode). diff --git a/compiler/use_local_vars.m b/compiler/use_local_vars.m index cd7d55ba1..e88bacef3 100644 --- a/compiler/use_local_vars.m +++ b/compiler/use_local_vars.m @@ -89,6 +89,7 @@ :- import_module ll_backend.livemap. :- import_module ll_backend.opt_debug. :- import_module ll_backend.opt_util. +:- import_module parse_tree.prog_data. :- import_module int. :- import_module map. @@ -151,7 +152,7 @@ use_local_vars_block(MaybeLiveMap, NumRealRRegs, AccessThreshold, Label, use_local_vars_instrs(!RestInstrs, !TempCounter, NumRealRRegs, AccessThreshold, MaybeLiveMap, MaybeFallThrough) :- - opt_assign(!RestInstrs, !TempCounter, NumRealRRegs, MaybeLiveMap, + opt_assign(!RestInstrs, !TempCounter, NumRealRRegs, [], MaybeLiveMap, MaybeFallThrough), ( AccessThreshold >= 1 -> opt_access(!RestInstrs, !TempCounter, NumRealRRegs, @@ -163,18 +164,30 @@ use_local_vars_instrs(!RestInstrs, !TempCounter, %-----------------------------------------------------------------------------% :- pred opt_assign(list(instruction)::in, list(instruction)::out, - counter::in, counter::out, int::in, maybe(livemap)::in, maybe(label)::in) - is det. + counter::in, counter::out, int::in, list(lval)::in, + maybe(livemap)::in, maybe(label)::in) is det. -opt_assign([], [], !TempCounter, _, _, _). +opt_assign([], [], !TempCounter, _, _, _, _). opt_assign([Instr0 | TailInstrs0], Instrs, !TempCounter, NumRealRRegs, - MaybeLiveMap, MaybeFallThrough) :- + !.AvoidLvals, MaybeLiveMap, MaybeFallThrough) :- Instr0 = llds_instr(Uinstr0, _Comment0), ( - ( Uinstr0 = assign(ToLval, _FromRval) - ; Uinstr0 = incr_hp(ToLval, _MaybeTag, _SizeRval, _MO, _Type, _Atomic) - ), - base_lval_worth_replacing(NumRealRRegs, ToLval) + ( + ( + Uinstr0 = assign(ToLval, _FromRval) + ; + Uinstr0 = incr_hp(ToLval, _MaybeTag, _SizeRval, _MO, _Type, + _Atomic) + ), + base_lval_worth_replacing(NumRealRRegs, ToLval), + MaybeMore = no + ; + Uinstr0 = foreign_proc_code(_D, Comps, _MCM, _FNL, _FL, _FOL, _NF, + _S, _MD), + opt_assign_find_output_in_components(Comps, NumRealRRegs, + !.AvoidLvals, ToLval), + MaybeMore = yes + ) -> ( ToLval = reg(_, _), @@ -189,9 +202,18 @@ opt_assign([Instr0 | TailInstrs0], Instrs, !TempCounter, NumRealRRegs, list.map_foldl( exprn_aux.substitute_lval_in_instr(ToLval, NewLval), TailInstrs0, TailInstrs1, 0, _), - opt_assign(TailInstrs1, TailInstrs, !TempCounter, NumRealRRegs, - MaybeLiveMap, MaybeFallThrough), - Instrs = [Instr | TailInstrs] + ( + MaybeMore = no, + opt_assign(TailInstrs1, TailInstrs, !TempCounter, NumRealRRegs, + [], MaybeLiveMap, MaybeFallThrough), + Instrs = [Instr | TailInstrs] + ; + MaybeMore = yes, + !:AvoidLvals = [ToLval | !.AvoidLvals], + Instrs1 = [Instr | TailInstrs1], + opt_assign(Instrs1, Instrs, !TempCounter, NumRealRRegs, + !.AvoidLvals, MaybeLiveMap, MaybeFallThrough) + ) ; counter.allocate(TempNum, !TempCounter), NewLval = temp(reg_r, TempNum), @@ -201,20 +223,71 @@ opt_assign([Instr0 | TailInstrs0], Instrs, !TempCounter, NumRealRRegs, -> substitute_lval_in_defn(ToLval, NewLval, Instr0, Instr), CopyInstr = llds_instr(assign(ToLval, lval(NewLval)), ""), - opt_assign(TailInstrs1, TailInstrs, !TempCounter, NumRealRRegs, - MaybeLiveMap, MaybeFallThrough), - Instrs = [Instr, CopyInstr | TailInstrs] + ( + MaybeMore = no, + opt_assign(TailInstrs1, TailInstrs, !TempCounter, NumRealRRegs, + [], MaybeLiveMap, MaybeFallThrough), + Instrs = [Instr, CopyInstr | TailInstrs] + ; + MaybeMore = yes, + !:AvoidLvals = [ToLval | !.AvoidLvals], + Instrs1 = [Instr, CopyInstr | TailInstrs1], + opt_assign(Instrs1, Instrs, !TempCounter, NumRealRRegs, + !.AvoidLvals, MaybeLiveMap, MaybeFallThrough) + ) ; - opt_assign(TailInstrs0, TailInstrs, !TempCounter, NumRealRRegs, - MaybeLiveMap, MaybeFallThrough), - Instrs = [Instr0 | TailInstrs] + ( + MaybeMore = no, + opt_assign(TailInstrs0, TailInstrs, !TempCounter, NumRealRRegs, + [], MaybeLiveMap, MaybeFallThrough), + Instrs = [Instr0 | TailInstrs] + ; + MaybeMore = yes, + !:AvoidLvals = [ToLval | !.AvoidLvals], + Instrs1 = [Instr0 | TailInstrs0], + opt_assign(Instrs1, Instrs, !TempCounter, NumRealRRegs, + !.AvoidLvals, MaybeLiveMap, MaybeFallThrough) + ) ) ; opt_assign(TailInstrs0, TailInstrs, !TempCounter, NumRealRRegs, - MaybeLiveMap, MaybeFallThrough), + [], MaybeLiveMap, MaybeFallThrough), Instrs = [Instr0 | TailInstrs] ). +:- pred opt_assign_find_output_in_components(list(foreign_proc_component)::in, + int::in, list(lval)::in, lval::out) is semidet. + +opt_assign_find_output_in_components([Comp | Comps], NumRealRRegs, AvoidLvals, + ToLval) :- + ( + Comp = foreign_proc_outputs(Outputs), + opt_assign_find_output_in_outputs(Outputs, NumRealRRegs, AvoidLvals, + ToLvalPrime) + -> + ToLval = ToLvalPrime + ; + opt_assign_find_output_in_components(Comps, NumRealRRegs, AvoidLvals, + ToLval) + ). + +:- pred opt_assign_find_output_in_outputs(list(foreign_proc_output)::in, + int::in, list(lval)::in, lval::out) is semidet. + +opt_assign_find_output_in_outputs([Output | Outputs], NumRealRRegs, AvoidLvals, + ToLval) :- + Output = foreign_proc_output(Dest, _Type, _IsDummy, _VarName, + _OrigType, _MaybeForeignType, _BoxPolicy), + ( + base_lval_worth_replacing(NumRealRRegs, Dest), + not list.member(Dest, AvoidLvals) + -> + ToLval = Dest + ; + opt_assign_find_output_in_outputs(Outputs, NumRealRRegs, AvoidLvals, + ToLval) + ). + %-----------------------------------------------------------------------------% :- type maybe_compulsory_lvals @@ -409,12 +482,55 @@ substitute_lval_in_defn(OldLval, NewLval, Instr0, Instr) :- expect(unify(ToLval, OldLval), this_file, "substitute_lval_in_defn: mismatch in incr_hp"), Uinstr = incr_hp(NewLval, MaybeTag, SizeRval, MO, Type, MayUseAtomic) + ; Uinstr0 = foreign_proc_code(D, Comps0, MCM, FNL, FL, FOL, NF, S, MD) -> + substitute_lval_in_defn_components(OldLval, NewLval, Comps0, Comps, + 0, NumSubsts), + expect(unify(NumSubsts, 1), + this_file, + "substitute_lval_in_defn: mismatch in foreign_proc_code"), + Uinstr = foreign_proc_code(D, Comps, MCM, FNL, FL, FOL, NF, S, MD) ; unexpected(this_file, "substitute_lval_in_defn: unexpected instruction") ), Instr = llds_instr(Uinstr, Comment). +:- pred substitute_lval_in_defn_components(lval::in, lval::in, + list(foreign_proc_component)::in, list(foreign_proc_component)::out, + int::in, int::out) is det. + +substitute_lval_in_defn_components(_OldLval, _NewLval, [], [], !NumSubsts). +substitute_lval_in_defn_components(OldLval, NewLval, + [Comp0 | Comps0], [Comp | Comps], !NumSubsts) :- + ( Comp0 = foreign_proc_outputs(Outputs0) -> + substitute_lval_in_defn_outputs(OldLval, NewLval, + Outputs0, Outputs, !NumSubsts), + Comp = foreign_proc_outputs(Outputs) + ; + Comp = Comp0 + ), + substitute_lval_in_defn_components(OldLval, NewLval, Comps0, Comps, + !NumSubsts). + +:- pred substitute_lval_in_defn_outputs(lval::in, lval::in, + list(foreign_proc_output)::in, list(foreign_proc_output)::out, + int::in, int::out) is det. + +substitute_lval_in_defn_outputs(_OldLval, _NewLval, [], [], !NumSubsts). +substitute_lval_in_defn_outputs(OldLval, NewLval, + [Output0 | Outputs0], [Output | Outputs], !NumSubsts) :- + Output0 = foreign_proc_output(Dest0, Type, IsDummy, VarName, + OrigType, MaybeForeignType, BoxPolicy), + ( Dest0 = OldLval -> + Output = foreign_proc_output(NewLval, Type, IsDummy, VarName, + OrigType, MaybeForeignType, BoxPolicy), + !:NumSubsts = !.NumSubsts + 1 + ; + Output = Output0 + ), + substitute_lval_in_defn_outputs(OldLval, NewLval, Outputs0, Outputs, + !NumSubsts). + % Substitute NewLval for OldLval in an instruction sequence % until we come an instruction that may define OldLval. % We don't worry about instructions that define a variable that @@ -457,88 +573,171 @@ substitute_lval_in_instr_until_defn(OldLval, NewLval, substitute_lval_in_instr_until_defn_2(OldLval, NewLval, !Instr, !Instrs, !N) :- !.Instr = llds_instr(Uinstr0, _), ( - Uinstr0 = comment(_), - substitute_lval_in_instr_until_defn(OldLval, NewLval, !Instrs, !N) - ; - Uinstr0 = livevals(_) - ; Uinstr0 = block(_, _, _), unexpected(this_file, "substitute_lval_in_instr_until_defn: found block") ; Uinstr0 = assign(Lval, _), - ( Lval = OldLval -> + ( assignment_updates_oldlval(Lval, OldLval) = yes -> + % XXX we should still substitute on the rhs % If we alter any lval that occurs in OldLval, we must stop - % the substitutions. At the moment, the only lval OldLval - % contains is itself. + % the substitutions. true ; exprn_aux.substitute_lval_in_instr(OldLval, NewLval, !Instr, !N), substitute_lval_in_instr_until_defn(OldLval, NewLval, !Instrs, !N) ) ; - Uinstr0 = llcall(_, _, _, _, _, _) + Uinstr0 = incr_hp(Lval, _, _, _, _, _), + ( assignment_updates_oldlval(Lval, OldLval) = yes -> + % If we alter any lval that occurs in OldLval, we must stop + % the substitutions. + true + ; + exprn_aux.substitute_lval_in_instr(OldLval, NewLval, !Instr, !N), + substitute_lval_in_instr_until_defn(OldLval, NewLval, !Instrs, !N) + ) ; - Uinstr0 = mkframe(_, _) + Uinstr0 = foreign_proc_code(_, Components, _, _, _, _, _, _, _), + AffectsLiveness = components_affect_liveness(Components), + ( + AffectsLiveness = no, + ( components_update_oldlval(Components, OldLval) = yes -> + % If we alter any lval that occurs in OldLval, we must stop + % the substitutions. + true + ; + exprn_aux.substitute_lval_in_instr(OldLval, NewLval, + !Instr, !N), + substitute_lval_in_instr_until_defn(OldLval, NewLval, + !Instrs, !N) + ) + ; + AffectsLiveness = yes + ) ; - Uinstr0 = label(_) + Uinstr0 = comment(_), + substitute_lval_in_instr_until_defn(OldLval, NewLval, !Instrs, !N) ; - Uinstr0 = goto(_) + Uinstr0 = if_val(_, _), + exprn_aux.substitute_lval_in_instr(OldLval, NewLval, !Instr, !N), + substitute_lval_in_instr_until_defn(OldLval, NewLval, !Instrs, !N) ; Uinstr0 = computed_goto(_, _), exprn_aux.substitute_lval_in_instr(OldLval, NewLval, !Instr, !N) ; - Uinstr0 = if_val(_, _), - exprn_aux.substitute_lval_in_instr(OldLval, NewLval, !Instr, !N) + ( Uinstr0 = label(_) + ; Uinstr0 = livevals(_) + ; Uinstr0 = llcall(_, _, _, _, _, _) + ; Uinstr0 = mkframe(_, _) + ; Uinstr0 = goto(_) + ; Uinstr0 = save_maxfr(_) + ; Uinstr0 = restore_maxfr(_) + ; Uinstr0 = mark_hp(_) + ; Uinstr0 = restore_hp(_) + ; Uinstr0 = free_heap(_) + ; Uinstr0 = store_ticket(_) + ; Uinstr0 = reset_ticket(_, _) + ; Uinstr0 = discard_ticket + ; Uinstr0 = prune_ticket + ; Uinstr0 = mark_ticket_stack(_) + ; Uinstr0 = prune_tickets_to(_) + ; Uinstr0 = incr_sp(_, _, _) + ; Uinstr0 = decr_sp(_) + ; Uinstr0 = decr_sp_and_return(_) + ; Uinstr0 = init_sync_term(_, _) + ; Uinstr0 = fork(_) + ; Uinstr0 = join_and_continue(_, _) + ; Uinstr0 = arbitrary_c_code(_, _, _) + ) + ). + +:- func assignment_updates_oldlval(lval, lval) = bool. + +assignment_updates_oldlval(Lval, OldLval) = + ( Lval = OldLval -> + % If we alter any lval that occurs in OldLval, we must stop the + % substitutions. At the moment, the only lval OldLval can contain + % is itself. + yes ; - Uinstr0 = save_maxfr(_) + no + ). + +:- func components_update_oldlval(list(foreign_proc_component), lval) = bool. + +components_update_oldlval([], _Lval) = no. +components_update_oldlval([Component | Components], Lval) = + ( component_updates_oldlval(Component, Lval) = yes -> + yes ; - Uinstr0 = restore_maxfr(_) - ; - Uinstr0 = incr_hp(Lval, _, _, _, _, _), - ( Lval = OldLval -> - % If we alter any lval that occurs in OldLval, we must stop - % the substitutions. At the moment, the only lval OldLval - % contains is itself. - true + components_update_oldlval(Components, Lval) + ). + +:- func component_updates_oldlval(foreign_proc_component, lval) = bool. + +component_updates_oldlval(Component, Lval) = Updates :- + ( + Component = foreign_proc_outputs(Outputs), + ( + some [Output] ( + list.member(Output, Outputs), + Output ^ out_arg_dest = Lval + ) + -> + Updates = yes ; - exprn_aux.substitute_lval_in_instr(OldLval, NewLval, !Instr, !N), - substitute_lval_in_instr_until_defn(OldLval, NewLval, !Instrs, !N) + Updates = no ) ; - Uinstr0 = mark_hp(_) + ( Component = foreign_proc_inputs(_) + ; Component = foreign_proc_fail_to(_) + ; Component = foreign_proc_noop + ; Component = foreign_proc_user_code(_, _, _) + ; Component = foreign_proc_raw_code(_, _, _, _) + ), + Updates = no + ). + +:- func components_affect_liveness(list(foreign_proc_component)) + = bool. + +components_affect_liveness([]) = no. +components_affect_liveness([Component | Components]) = + ( component_affects_liveness(Component) = yes -> + yes ; - Uinstr0 = restore_hp(_) + components_affect_liveness(Components) + ). + +:- func component_affects_liveness(foreign_proc_component) = bool. + +component_affects_liveness(Component) = Affects :- + ( + ( Component = foreign_proc_inputs(_) + ; Component = foreign_proc_outputs(_) + ; Component = foreign_proc_fail_to(_) + ; Component = foreign_proc_noop + ), + Affects = no ; - Uinstr0 = free_heap(_) - ; - Uinstr0 = store_ticket(_) - ; - Uinstr0 = reset_ticket(_, _) - ; - Uinstr0 = discard_ticket - ; - Uinstr0 = prune_ticket - ; - Uinstr0 = mark_ticket_stack(_) - ; - Uinstr0 = prune_tickets_to(_) - ; - Uinstr0 = incr_sp(_, _, _) - ; - Uinstr0 = decr_sp(_) - ; - Uinstr0 = decr_sp_and_return(_) - ; - Uinstr0 = init_sync_term(_, _) - ; - Uinstr0 = fork(_) - ; - Uinstr0 = join_and_continue(_, _) - ; - Uinstr0 = arbitrary_c_code(_, _, _) - ; - Uinstr0 = foreign_proc_code(_, _, _, _, _, _, _, _, _) + ( Component = foreign_proc_user_code(_, AffectsLiveness, Code) + ; Component = foreign_proc_raw_code(_, AffectsLiveness, _, Code) + ), + ( + AffectsLiveness = proc_affects_liveness, + Affects = yes + ; + AffectsLiveness = proc_does_not_affect_liveness, + Affects = no + ; + AffectsLiveness = proc_default_affects_liveness, + ( Code = "" -> + Affects = no + ; + Affects = yes + ) + ) ). %-----------------------------------------------------------------------------% diff --git a/configure.in b/configure.in index ae0903b8b..f56cf990c 100644 --- a/configure.in +++ b/configure.in @@ -279,7 +279,8 @@ if test "$BOOTSTRAP_MC" != ""; then :- pragma foreign_proc("C", return_rtti_version(Version::out), [[may_call_mercury, promise_pure, terminates, - ordinary_despite_detism, will_not_modify_trail]], " + does_not_affect_liveness, will_not_modify_trail]], + " Version = MR_RTTI_VERSION; "). @@ -2186,12 +2187,13 @@ fi AC_CACHE_VAL(mercury_cv_gcc_labels, AC_TRY_RUN([ - extern void exit(int); - void *entry_foo_1; - void *entry_bar_1; - void *succip; - int global; - void *dummy_identity_function(void *); + extern void exit(int); + void *entry_foo_1; + void *entry_bar_1; + void *succip; + int global; + void *dummy_identity_function(void *); + foo() { entry_foo_1 = && foo_1; goto *dummy_identity_function(&&return_label); diff --git a/doc/reference_manual.texi b/doc/reference_manual.texi index 853c6e607..6e976b7d5 100644 --- a/doc/reference_manual.texi +++ b/doc/reference_manual.texi @@ -6399,6 +6399,16 @@ In the absence of either attribute, the compiler assumes @samp{affects_liveness}, unless the code of the foreign_proc in question is empty. +@item @samp{may_duplicate/may_not_duplicate} +This attribute tells the compiler +whether it is allowed to duplicate the foreign code fragment +through optimizations such as inlining. +The @samp{may_duplicate} attribute says that it may; +The @samp{may_not_duplicate} attribute says that it may not. +In the absence of either attribute, +the compiler is allowed make its own judgement in the matter, +based on factors such as the size of the code fragment. + @c @item @c @samp{does_not_allocate_memory/allocates_bounded_memory/allocates_unbounded_memory} @c This attribute declares whether a foreign procedure diff --git a/library/array.m b/library/array.m index cbd6c67d8..1140cd4c1 100644 --- a/library/array.m +++ b/library/array.m @@ -1,15 +1,15 @@ %-----------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et %-----------------------------------------------------------------------------% -% Copyright (C) 1993-1995, 1997-2006 The University of Melbourne. +% Copyright (C) 1993-1995, 1997-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %-----------------------------------------------------------------------------% -% +% % File: array.m. % Main authors: fjh, bromage. % Stability: medium-low. -% +% % This module provides dynamically-sized one-dimensional arrays. % Array indices start at zero. % @@ -54,7 +54,7 @@ % A0I = A0 ^ elem(I), % A1 = A0 ^ elem(I) := X, % Y = f(A1, A0I) -% +% %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% @@ -490,7 +490,8 @@ array.compare_elements(N, Size, Array1, Array2, Result) :- :- pragma foreign_proc("C", bounds_checks, - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " #ifdef ML_OMIT_ARRAY_BOUNDS_CHECKS SUCCESS_INDICATOR = MR_FALSE; @@ -578,7 +579,8 @@ array.init(Size, Item, Array) :- :- pragma foreign_proc("C", array.init_2(Size::in, Item::in, Array::array_uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " ML_alloc_array(Array, Size + 1, MR_PROC_LABEL); ML_init_array(Array, Size, Item); @@ -586,7 +588,8 @@ array.init(Size, Item, Array) :- :- pragma foreign_proc("C", array.make_empty_array(Array::array_uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " ML_alloc_array(Array, 1, MR_PROC_LABEL); ML_init_array(Array, 0, 0); @@ -638,14 +641,16 @@ array.init(Size, Item, Array) :- :- pragma foreign_proc("C", array.min(Array::array_ui, Min::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " /* Array not used */ Min = 0; "). :- pragma foreign_proc("C", array.min(Array::in, Min::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " /* Array not used */ Min = 0; @@ -683,13 +688,15 @@ array.init(Size, Item, Array) :- :- pragma foreign_proc("C", array.max(Array::array_ui, Max::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Max = Array->size - 1; "). :- pragma foreign_proc("C", array.max(Array::in, Max::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Max = Array->size - 1; "). @@ -743,13 +750,15 @@ array.bounds(Array, Min, Max) :- :- pragma foreign_proc("C", array.size(Array::array_ui, Max::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Max = Array->size; "). :- pragma foreign_proc("C", array.size(Array::in, Max::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Max = Array->size; "). @@ -842,13 +851,15 @@ array.lookup(Array, Index, Item) :- :- pragma foreign_proc("C", array.unsafe_lookup(Array::array_ui, Index::in, Item::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Item = Array->elements[Index]; "). :- pragma foreign_proc("C", array.unsafe_lookup(Array::in, Index::in, Item::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Item = Array->elements[Index]; "). @@ -893,7 +904,8 @@ array.set(Array0, Index, Item, Array) :- :- pragma foreign_proc("C", array.unsafe_set(Array0::array_di, Index::in, Item::in, Array::array_uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Array0->elements[Index] = Item; /* destructive update! */ Array = Array0; @@ -968,7 +980,8 @@ ML_resize_array(MR_ArrayPtr array, MR_ArrayPtr old_array, :- pragma foreign_proc("C", array.resize(Array0::array_di, Size::in, Item::in, Array::array_uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " if ((Array0)->size == Size) { Array = Array0; @@ -1083,7 +1096,8 @@ array.shrink(Array0, Size, Array) :- :- pragma foreign_proc("C", array.shrink_2(Array0::array_di, Size::in, Array::array_uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " ML_alloc_array(Array, Size + 1, MR_PROC_LABEL); ML_shrink_array(Array, Array0, Size); @@ -1147,7 +1161,8 @@ ML_copy_array(MR_ArrayPtr array, MR_ConstArrayPtr old_array) :- pragma foreign_proc("C", array.copy(Array0::array_ui, Array::array_uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " ML_alloc_array(Array, Array0->size + 1, MR_PROC_LABEL); ML_copy_array(Array, (MR_ConstArrayPtr) Array0); @@ -1155,7 +1170,8 @@ ML_copy_array(MR_ArrayPtr array, MR_ConstArrayPtr old_array) :- pragma foreign_proc("C", array.copy(Array0::in, Array::array_uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " ML_alloc_array(Array, Array0->size + 1, MR_PROC_LABEL); ML_copy_array(Array, (MR_ConstArrayPtr) Array0); diff --git a/library/builtin.m b/library/builtin.m index 0cc192ec5..edb12f250 100644 --- a/library/builtin.m +++ b/library/builtin.m @@ -1,7 +1,7 @@ %---------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 %---------------------------------------------------------------------------% -% Copyright (C) 1994-2006 The University of Melbourne. +% Copyright (C) 1994-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %---------------------------------------------------------------------------% @@ -458,13 +458,15 @@ get_one_solution(CCPred) = OutVal :- :- pragma foreign_proc("C", cc_cast(X :: (pred(out) is cc_multi)) = (Y :: out(pred(out) is det)), - [will_not_call_mercury, thread_safe, will_not_modify_trail], + [will_not_call_mercury, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Y = X; "). :- pragma foreign_proc("C", cc_cast(X :: (pred(out) is cc_nondet)) = (Y :: out(pred(out) is semidet)), - [will_not_call_mercury, thread_safe, will_not_modify_trail], + [will_not_call_mercury, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Y = X; "). @@ -509,7 +511,8 @@ get_one_solution_io(Pred, X, !IO) :- :- pragma foreign_proc("C", cc_cast_io(X :: (pred(out, di, uo) is cc_multi)) = (Y :: out(pred(out, di, uo) is det)), - [will_not_call_mercury, thread_safe, will_not_modify_trail], + [will_not_call_mercury, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Y = X; "). @@ -778,7 +781,8 @@ deep_copy(java.lang.Object original) { :- pragma foreign_proc("C", copy(Value::ui, Copy::uo), - [will_not_call_mercury, thread_safe, promise_pure, will_not_modify_trail], + [will_not_call_mercury, thread_safe, promise_pure, will_not_modify_trail, + does_not_affect_liveness], " MR_save_transient_registers(); Copy = MR_deep_copy(Value, (MR_TypeInfo) TypeInfo_for_T, NULL, NULL); @@ -787,7 +791,8 @@ deep_copy(java.lang.Object original) { :- pragma foreign_proc("C", copy(Value::in, Copy::uo), - [will_not_call_mercury, thread_safe, promise_pure, will_not_modify_trail], + [will_not_call_mercury, thread_safe, promise_pure, will_not_modify_trail, + does_not_affect_liveness], " MR_save_transient_registers(); Copy = MR_deep_copy(Value, (MR_TypeInfo) TypeInfo_for_T, NULL, NULL); @@ -1005,13 +1010,13 @@ namespace mercury.builtin { :- pragma foreign_proc("C", semidet_succeed, - [will_not_call_mercury, thread_safe, promise_pure], + [will_not_call_mercury, thread_safe, promise_pure, does_not_affect_liveness], " SUCCESS_INDICATOR = MR_TRUE; "). :- pragma foreign_proc("C", semidet_fail, - [will_not_call_mercury, thread_safe, promise_pure], + [will_not_call_mercury, thread_safe, promise_pure, does_not_affect_liveness], " SUCCESS_INDICATOR = MR_FALSE; "). @@ -1056,13 +1061,13 @@ semidet_false :- semidet_fail. :- pragma foreign_proc("C", cc_multi_equal(X::in, Y::out), - [will_not_call_mercury, thread_safe, promise_pure], + [will_not_call_mercury, thread_safe, promise_pure, does_not_affect_liveness], " Y = X; "). :- pragma foreign_proc("C", cc_multi_equal(X::di, Y::uo), - [will_not_call_mercury, thread_safe, promise_pure], + [will_not_call_mercury, thread_safe, promise_pure, does_not_affect_liveness], " Y = X; "). diff --git a/library/char.m b/library/char.m index 21d06920d..db97030fc 100644 --- a/library/char.m +++ b/library/char.m @@ -1,24 +1,24 @@ %---------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 %---------------------------------------------------------------------------% -% Copyright (C) 1994-2006 The University of Melbourne. +% Copyright (C) 1994-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %-----------------------------------------------------------------------------% -% +% % File: char.m. % Main author: fjh. % Stability: high. -% +% % This module defines some predicates that manipulate characters. -% +% % The set of characters which are supported and the mapping from % characters to integer values are both implementation-dependent. -% +% % Originally we used `character' rather than `char' for the type name % because `char' was used by NU-Prolog to mean something different. % But now we use `char' and the use of `character' is discouraged. -% +% %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% @@ -450,21 +450,24 @@ char.det_from_int(Int) = Char :- :- pragma foreign_proc("C", char.to_int(Character::in, Int::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Int = (MR_UnsignedChar) Character; "). :- pragma foreign_proc("C", char.to_int(Character::in, Int::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " SUCCESS_INDICATOR = ((MR_UnsignedChar) Character == Int); "). :- pragma foreign_proc("C", char.to_int(Character::out, Int::in), - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, + does_not_affect_liveness], " /* ** If the integer doesn't fit into a char, then the assignment @@ -527,7 +530,8 @@ char.min_char_value(0). :- pragma foreign_proc("C", char.max_char_value(Max::out), - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, + does_not_affect_liveness], " Max = UCHAR_MAX; "). diff --git a/library/dir.m b/library/dir.m index 9fde88943..1419d3b59 100644 --- a/library/dir.m +++ b/library/dir.m @@ -1,7 +1,7 @@ %---------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 %---------------------------------------------------------------------------% -% Copyright (C) 1994-1995,1997,1999-2000,2002-2006 The University of Melbourne. +% Copyright (C) 1994-1995,1997,1999-2000,2002-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %---------------------------------------------------------------------------% @@ -907,7 +907,8 @@ can_implement_make_directory :- semidet_fail. :- pragma foreign_proc("C", can_implement_make_directory, - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " #if defined(MR_WIN32) SUCCESS_INDICATOR = MR_TRUE; @@ -942,7 +943,7 @@ dir.make_single_directory(DirName, Result, !IO) :- dir.make_single_directory_2(ErrorIfExists::in, DirName::in, Result::out, IO0::di, IO::uo), [may_call_mercury, promise_pure, tabled_for_io, thread_safe, - terminates, will_not_modify_trail], + terminates, will_not_modify_trail, does_not_affect_liveness], "{ #if defined(MR_WIN32) if (CreateDirectory(DirName, NULL)) { @@ -1315,7 +1316,8 @@ check_for_symlink_loop(SymLinkParent, DirName, LoopRes, !ParentIds, !IO) :- can_implement_dir_foldl :- semidet_fail. :- pragma foreign_proc("C", can_implement_dir_foldl, - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " #if defined(MR_HAVE_OPENDIR) && defined(MR_HAVE_READDIR) && \\ defined(MR_HAVE_CLOSEDIR) @@ -1352,7 +1354,7 @@ dir.open(DirName, Res, !IO) :- :- pragma foreign_proc("C", dir.open_2(DirName::in, Result::out, IO0::di, IO::uo), [may_call_mercury, promise_pure, tabled_for_io, thread_safe, - terminates, will_not_modify_trail], + terminates, will_not_modify_trail, does_not_affect_liveness], "{ #if defined(MR_WIN32) WIN32_FIND_DATA file_data; @@ -1521,7 +1523,7 @@ copy_c_string(_) = _ :- :- pragma foreign_proc("C", copy_c_string(Ptr::in) = (Str::out), [will_not_call_mercury, promise_pure, thread_safe, - will_not_modify_trail], + will_not_modify_trail, does_not_affect_liveness], " MR_make_aligned_string_copy(Str, (char *) Ptr); "). @@ -1558,7 +1560,7 @@ dir.close(Dir, Res, !IO) :- :- pragma foreign_proc("C", dir.close_2(Dir::in, Status::out, Error::out, IO0::di, IO::uo), [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, - will_not_modify_trail], + will_not_modify_trail, does_not_affect_liveness], "{ IO = IO0; #if defined(MR_WIN32) @@ -1625,7 +1627,7 @@ dir.read_entry(Dir, Res, !IO) :- dir.read_entry_2(Dir::in, Status::out, Error::out, FileName::out, IO0::di, IO::uo), [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, - will_not_modify_trail], + will_not_modify_trail, does_not_affect_liveness], "{ #if defined(MR_WIN32) WIN32_FIND_DATA file_data; diff --git a/library/float.m b/library/float.m index 71b819da6..8aece201b 100644 --- a/library/float.m +++ b/library/float.m @@ -1,7 +1,7 @@ %---------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 %---------------------------------------------------------------------------% -% Copyright (C) 1994-1998,2001-2006 The University of Melbourne. +% Copyright (C) 1994-1998,2001-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %---------------------------------------------------------------------------% @@ -256,7 +256,8 @@ X / Y = Z :- :- pragma foreign_proc("C", float_domain_checks, - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " #ifdef ML_OMIT_MATH_DOMAIN_CHECKS SUCCESS_INDICATOR = MR_FALSE; @@ -293,7 +294,8 @@ X / Y = Z :- :- pragma foreign_proc("C", float(IntVal::in) = (FloatVal::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " FloatVal = IntVal; "). @@ -314,7 +316,8 @@ X / Y = Z :- :- pragma foreign_proc("C", float.ceiling_to_int(X :: in) = (Ceil :: out), - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, + does_not_affect_liveness], " Ceil = (MR_Integer) ceil(X); "). @@ -340,7 +343,8 @@ X / Y = Z :- :- pragma foreign_proc("C", float.floor_to_int(X :: in) = (Floor :: out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Floor = (MR_Integer) floor(X); "). @@ -366,7 +370,8 @@ X / Y = Z :- :- pragma foreign_proc("C", float.round_to_int(X :: in) = (Round :: out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Round = (MR_Integer) floor(X + 0.5); "). @@ -392,7 +397,8 @@ X / Y = Z :- :- pragma foreign_proc("C", float.truncate_to_int(X :: in) = (Trunc :: out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Trunc = (MR_Integer) X; "). @@ -499,7 +505,8 @@ float.multiply_by_pow(Scale0, Base, Exp) = Result :- % non-negative, as this condition is not guaranteed by either API. :- pragma foreign_proc("C", float.hash(F::in) = (H::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " H = MR_hash_float(F); "). @@ -535,7 +542,8 @@ is_nan_or_inf(Float) :- :- pragma foreign_proc("C", is_nan(Flt::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " SUCCESS_INDICATOR = MR_is_nan(Flt); "). @@ -556,7 +564,8 @@ is_nan_or_inf(Float) :- :- pragma foreign_proc("C", is_inf(Flt::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " SUCCESS_INDICATOR = MR_is_inf(Flt); "). @@ -615,7 +624,8 @@ is_nan_or_inf(Float) :- :- pragma foreign_proc("C", float.max = (Max::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Max = ML_FLOAT_MAX; "). @@ -634,7 +644,8 @@ is_nan_or_inf(Float) :- :- pragma foreign_proc("C", float.min = (Min::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Min = ML_FLOAT_MIN; "). @@ -655,7 +666,8 @@ float.min = 2.2250738585072014e-308. :- pragma foreign_proc("C", float.epsilon = (Eps::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Eps = ML_FLOAT_EPSILON; "). @@ -677,7 +689,8 @@ float.epsilon = 2.2204460492503131e-16. :- pragma foreign_proc("C", float.radix = (Radix::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Radix = ML_FLOAT_RADIX; "). @@ -695,7 +708,8 @@ float.radix = 2. :- pragma foreign_proc("C", float.mantissa_digits = (MantDig::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " MantDig = ML_FLOAT_MANT_DIG; "). @@ -711,7 +725,8 @@ float.mantissa_digits = 53. :- pragma foreign_proc("C", float.min_exponent = (MinExp::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " MinExp = ML_FLOAT_MIN_EXP; "). @@ -727,7 +742,8 @@ float.min_exponent = -1021. :- pragma foreign_proc("C", float.max_exponent = (MaxExp::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " MaxExp = ML_FLOAT_MAX_EXP; "). diff --git a/library/int.m b/library/int.m index 3e80e582a..5a11c9c67 100644 --- a/library/int.m +++ b/library/int.m @@ -1,15 +1,15 @@ %-----------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 %-----------------------------------------------------------------------------% -% Copyright (C) 1994-2006 The University of Melbourne. +% Copyright (C) 1994-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %-----------------------------------------------------------------------------% -% +% % File: int.m. % Main authors: conway, fjh. % Stability: medium. -% +% % Predicates and functions for dealing with machine-size integer numbers. % % The behaviour of a computation for which overflow occurs is undefined. @@ -17,7 +17,7 @@ % module do not check for overflow, and the results you get are those % delivered by the C compiler. However, future implementations % might check for overflow.) -% +% %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% @@ -433,7 +433,8 @@ X rem Y = Rem :- :- pragma foreign_proc("C", int_domain_checks, - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " #ifdef ML_OMIT_MATH_DOMAIN_CHECKS SUCCESS_INDICATOR = MR_FALSE; @@ -611,7 +612,8 @@ is(X, X). :- pragma foreign_proc("C", int.max_int(Max::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " if (sizeof(MR_Integer) == sizeof(int)) { Max = INT_MAX; @@ -624,7 +626,8 @@ is(X, X). :- pragma foreign_proc("C", int.min_int(Min::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " if (sizeof(MR_Integer) == sizeof(int)) { Min = INT_MIN; @@ -637,28 +640,32 @@ is(X, X). :- pragma foreign_proc("C", int.bits_per_int(Bits::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Bits = ML_BITS_PER_INT; "). :- pragma foreign_proc("C", int.quot_bits_per_int(Int::in) = (Div::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Div = Int / ML_BITS_PER_INT; "). :- pragma foreign_proc("C", int.times_bits_per_int(Int::in) = (Result::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Result = Int * ML_BITS_PER_INT; "). :- pragma foreign_proc("C", int.rem_bits_per_int(Int::in) = (Rem::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Rem = Int % ML_BITS_PER_INT; "). diff --git a/library/io.m b/library/io.m index f34870dfd..4d795eecf 100644 --- a/library/io.m +++ b/library/io.m @@ -1881,7 +1881,8 @@ io.read_line_as_string(input_stream(Stream), Result, !IO) :- :- pragma foreign_proc("C", io.read_line_as_string_2(Stream::in, _Bool::in, Res :: out, RetString::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " #define ML_IO_READ_LINE_GROW(n) ((n) * 3 / 2) #define ML_IO_BYTES_TO_WORDS(n) (((n) + sizeof(MR_Word) - 1) / sizeof(MR_Word)) @@ -2149,7 +2150,8 @@ io.output_clear_err(output_stream(Stream), !IO) :- :- pragma foreign_proc("C", io.clear_err(Stream::in, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " if (MR_IS_FILE_STREAM(*Stream)) { clearerr(MR_file(*Stream)); @@ -2197,7 +2199,8 @@ io.check_err(Stream, Res, !IO) :- :- pragma foreign_proc("C", ferror(Stream::in, RetVal::out, RetStr::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " if (MR_IS_FILE_STREAM(*Stream)) { RetVal = ferror(MR_file(*Stream)); @@ -2236,7 +2239,8 @@ io.make_err_msg(Msg0, Msg, !IO) :- :- pragma foreign_proc("C", io.get_system_error(Error::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ Error = errno; MR_update_io(IO0, IO); @@ -2261,7 +2265,8 @@ io.make_err_msg(Msg0, Msg, !IO) :- :- pragma foreign_proc("C", make_err_msg(Error::in, Msg0::in, Msg::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " ML_maybe_make_err_msg(MR_TRUE, Error, Msg0, MR_PROC_LABEL, Msg); MR_update_io(IO0, IO); @@ -2289,7 +2294,8 @@ have_win32 :- semidet_fail. :- pragma foreign_proc("C", have_win32, - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, + does_not_affect_liveness], " #ifdef MR_WIN32 SUCCESS_INDICATOR = MR_TRUE; @@ -2302,7 +2308,8 @@ have_cygwin :- semidet_fail. :- pragma foreign_proc("C", have_cygwin, - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, + does_not_affect_liveness], " #ifdef __CYGWIN__ SUCCESS_INDICATOR = MR_TRUE; @@ -2333,7 +2340,8 @@ make_win32_err_msg(_, _, "", !IO) :- :- pragma foreign_proc("C", make_win32_err_msg(Error::in, Msg0::in, Msg::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " ML_maybe_make_win32_err_msg(MR_TRUE, Error, Msg0, MR_PROC_LABEL, Msg); MR_update_io(IO0, IO); @@ -2379,7 +2387,8 @@ io.output_stream_file_size(output_stream(Stream), Size, !IO) :- :- pragma foreign_proc("C", io.stream_file_size(Stream::in, Size::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " #if defined(MR_HAVE_FSTAT) && \ (defined(MR_HAVE_FILENO) || defined(fileno)) && defined(S_ISREG) @@ -2431,7 +2440,8 @@ io.file_modification_time(File, Result, !IO) :- :- pragma foreign_proc("C", io.file_modification_time_2(FileName::in, Status::out, Msg::out, Time::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " #ifdef MR_HAVE_STAT struct stat s; @@ -2508,7 +2518,8 @@ file_type_implemented :- semidet_fail. :- pragma foreign_proc("C", file_type_implemented, - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, + does_not_affect_liveness], " #ifdef MR_HAVE_STAT SUCCESS_INDICATOR = MR_TRUE; @@ -2534,7 +2545,8 @@ file_type_implemented :- semidet_fail. :- pragma foreign_proc("C", io.file_type_2(FollowSymLinks::in, FileName::in, Result::out, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " #ifdef MR_HAVE_STAT struct stat s; @@ -2776,9 +2788,10 @@ io.check_file_accessibility(FileName, AccessTypes, Result, !IO) :- io.res::out, io::di, io::uo) is det. :- pragma foreign_proc("C", - io.check_file_accessibility_2(FileName::in, AccessTypes::in, - Result::out, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + io.check_file_accessibility_2(FileName::in, AccessTypes::in, Result::out, + IO0::di, IO::uo), + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " #if defined(MR_HAVE_ACCESS) #ifdef F_OK @@ -3114,7 +3127,7 @@ compare_file_id(Result, FileId1, FileId2) :- :- pragma foreign_proc("C", compare_file_id_2(Res::out, FileId1::in, FileId2::in), - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, does_not_affect_liveness], " int device_cmp; int inode_cmp; @@ -3172,7 +3185,8 @@ io.file_id(FileName, Result, !IO) :- :- pragma foreign_proc("C", io.file_id_2(FileName::in, Status::out, Msg::out, FileId::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ #ifdef MR_HAVE_STAT struct stat s; @@ -3210,7 +3224,8 @@ io.file_id(FileName, Result, !IO) :- have_file_ids :- semidet_fail. :- pragma foreign_proc("C", have_file_ids, - [promise_pure, will_not_call_mercury, thread_safe, will_not_modify_trail], + [promise_pure, will_not_call_mercury, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " #if defined(MR_BROKEN_STAT_ST_INO) || !defined(MR_HAVE_STAT) /* Win32 returns junk in the st_ino field of `struct stat'. */ @@ -3243,7 +3258,8 @@ have_file_ids :- semidet_fail. :- pragma foreign_proc("C", io.alloc_buffer(Size::in, Buffer::buffer_uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ MR_Word buf; MR_offset_incr_hp_atomic_msg(buf, 0, @@ -3262,7 +3278,8 @@ io.alloc_buffer(Size, buffer(Array)) :- :- pragma foreign_proc("C", io.resize_buffer(OldSize::in, NewSize::in, Buffer0::buffer_di, Buffer::buffer_uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ MR_CHECK_EXPR_TYPE(Buffer0, MR_Char *); MR_CHECK_EXPR_TYPE(Buffer, MR_Char *); @@ -3303,7 +3320,8 @@ io.resize_buffer(_OldSize, NewSize, buffer(Array0), buffer(Array)) :- :- pragma foreign_proc("C", io.buffer_to_string(Buffer::buffer_di, Len::in, Str::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ Str = Buffer; Str[Len] = '\\0'; @@ -3318,7 +3336,8 @@ io.buffer_to_string(buffer(Array), Len, from_char_list(List)) :- :- pragma foreign_proc("C", io.read_into_buffer(Stream::in, Buffer0::buffer_di, Buffer::buffer_uo, Pos0::in, Pos::out, Size::in, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ int items_read; @@ -3690,7 +3709,7 @@ should_reduce_stack_usage(yes). :- pragma foreign_proc("C", should_reduce_stack_usage(ShouldReduce::out), - [will_not_call_mercury, promise_pure], + [will_not_call_mercury, promise_pure, does_not_affect_liveness], " #ifdef MR_EXEC_TRACE ShouldReduce = MR_TRUE; @@ -4219,7 +4238,8 @@ source_name(stderr) = "". :- pragma foreign_proc("C", io.get_stream_db(StreamDb::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " StreamDb = ML_io_stream_db; MR_update_io(IO0, IO); @@ -4229,7 +4249,8 @@ source_name(stderr) = "". :- pragma foreign_proc("C", io.set_stream_db(StreamDb::in, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " ML_io_stream_db = StreamDb; MR_update_io(IO0, IO); @@ -4311,7 +4332,8 @@ io.maybe_delete_stream_info(Stream, !IO) :- :- pragma foreign_proc("C", io.may_delete_stream_info(MayDelete::out, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " MayDelete = !MR_debug_ever_enabled; IO = IO0; @@ -4364,7 +4386,8 @@ io.update_globals(UpdatePred, !IO) :- :- pred io.lock_globals(io::di, io::uo) is det. :- pragma foreign_proc("C", io.lock_globals(IO0::di, IO::uo), - [promise_pure, will_not_call_mercury, thread_safe, tabled_for_io], + [promise_pure, will_not_call_mercury, thread_safe, tabled_for_io, + does_not_affect_liveness], " #ifdef MR_THREAD_SAFE MR_LOCK(&ML_io_user_globals_lock, \"io.lock_globals/2\"); @@ -4380,7 +4403,8 @@ lock_globals(!IO). :- pred io.unlock_globals(io::di, io::uo) is det. :- pragma foreign_proc("C", io.unlock_globals(IO0::di, IO::uo), - [promise_pure, will_not_call_mercury, thread_safe, tabled_for_io], + [promise_pure, will_not_call_mercury, thread_safe, tabled_for_io, + does_not_affect_liveness], " #ifdef MR_THREAD_SAFE MR_UNLOCK(&ML_io_user_globals_lock, \"io.unlock_globals/2\"); @@ -4396,7 +4420,8 @@ unlock_globals(!IO). :- impure pred io.unlock_globals is det. :- pragma foreign_proc("C", io.unlock_globals, - [will_not_call_mercury, thread_safe], + [will_not_call_mercury, thread_safe, + does_not_affect_liveness], " #ifdef MR_THREAD_SAFE MR_UNLOCK(&ML_io_user_globals_lock, \"io.unlock_globals/2\"); @@ -4415,7 +4440,8 @@ io.unlock_globals :- :- pred io.unsafe_get_globals(univ::uo, io::di, io::uo) is det. :- pragma foreign_proc("C", io.unsafe_get_globals(Globals::uo, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " Globals = ML_io_user_globals; MR_update_io(IO0, IO); @@ -4424,7 +4450,8 @@ io.unlock_globals :- :- pred io.unsafe_set_globals(univ::di, io::di, io::uo) is det. :- pragma foreign_proc("C", io.unsafe_set_globals(Globals::di, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " /* XXX need to globalize the memory */ ML_io_user_globals = Globals; @@ -4467,7 +4494,7 @@ io.progname_base(DefaultName, PrognameBase, !IO) :- :- pragma foreign_proc("C", io.get_stream_id(Stream::in) = (Id::out), - [will_not_call_mercury, promise_pure], + [will_not_call_mercury, promise_pure, does_not_affect_liveness], " #ifndef MR_NATIVE_GC /* @@ -4590,7 +4617,8 @@ io.finalize_state(!IO). :- pragma foreign_proc("C", io.gc_init(StreamDbType::in, UserGlobalsType::in, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " /* for Windows DLLs, we need to call GC_INIT() from each DLL */ #ifdef MR_CONSERVATIVE_GC @@ -6063,7 +6091,8 @@ io.read_char_code(input_stream(Stream), CharCode, !IO) :- :- pragma foreign_proc("C", io.read_char_code_2(Stream::in, CharCode::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " CharCode = mercury_getc(Stream); MR_update_io(IO0, IO); @@ -6076,7 +6105,8 @@ io.read_byte_val(input_stream(Stream), ByteVal, !IO) :- is det. :- pragma foreign_proc("C", io.read_byte_val_2(Stream::in, ByteVal::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " ByteVal = mercury_getc(Stream); MR_update_io(IO0, IO); @@ -6085,11 +6115,11 @@ io.read_byte_val(input_stream(Stream), ByteVal, !IO) :- io.putback_char(input_stream(Stream), Character, !IO) :- io.putback_char_2(Stream, Character, !IO). -:- pred io.putback_char_2(io.stream::in, char::in, io::di, io::uo) - is det. +:- pred io.putback_char_2(io.stream::in, char::in, io::di, io::uo) is det. :- pragma foreign_proc("C", io.putback_char_2(Stream::in, Character::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, terminates], + [may_call_mercury, promise_pure, tabled_for_io, terminates, + does_not_affect_liveness], " MercuryFilePtr mf = Stream; if (Character == '\\n') { @@ -6108,7 +6138,8 @@ io.putback_byte(binary_input_stream(Stream), Character, !IO) :- :- pred io.putback_byte_2(io.stream::in, int::in, io::di, io::uo) is det. :- pragma foreign_proc("C", io.putback_byte_2(Stream::in, Character::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, terminates], + [may_call_mercury, promise_pure, tabled_for_io, terminates, + does_not_affect_liveness], " MercuryFilePtr mf = Stream; /* XXX should work even if ungetc() fails */ @@ -6194,7 +6225,8 @@ io.putback_byte(binary_input_stream(Stream), Character, !IO) :- :- pragma foreign_proc("C", io.write_string(Message::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " mercury_print_string(mercury_current_text_output, Message); MR_update_io(IO0, IO); @@ -6202,7 +6234,8 @@ io.putback_byte(binary_input_stream(Stream), Character, !IO) :- :- pragma foreign_proc("C", io.write_char(Character::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " if (MR_PUTCH(*mercury_current_text_output, Character) < 0) { mercury_output_error(mercury_current_text_output); @@ -6215,7 +6248,8 @@ io.putback_byte(binary_input_stream(Stream), Character, !IO) :- :- pragma foreign_proc("C", io.write_int(Val::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " if (ML_fprintf(mercury_current_text_output, ""%ld"", (long) Val) < 0) { mercury_output_error(mercury_current_text_output); @@ -6225,7 +6259,8 @@ io.putback_byte(binary_input_stream(Stream), Character, !IO) :- :- pragma foreign_proc("C", io.write_float(Val::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " char buf[MR_SPRINTF_FLOAT_BUF_SIZE]; MR_sprintf_float(buf, Val); @@ -6237,7 +6272,8 @@ io.putback_byte(binary_input_stream(Stream), Character, !IO) :- :- pragma foreign_proc("C", io.write_byte(Byte::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " /* call putc with a strictly non-negative byte-sized integer */ if (MR_PUTCH(*mercury_current_binary_output, @@ -6250,7 +6286,8 @@ io.putback_byte(binary_input_stream(Stream), Character, !IO) :- :- pragma foreign_proc("C", io.write_bytes(Message::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], "{ mercury_print_binary_string(mercury_current_binary_output, Message); MR_update_io(IO0, IO); @@ -6258,7 +6295,8 @@ io.putback_byte(binary_input_stream(Stream), Character, !IO) :- :- pragma foreign_proc("C", io.flush_output(IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " if (MR_FLUSH(*mercury_current_text_output) < 0) { mercury_output_error(mercury_current_text_output); @@ -6268,8 +6306,8 @@ io.putback_byte(binary_input_stream(Stream), Character, !IO) :- :- pragma foreign_proc("C", io.flush_binary_output(IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, - terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " if (MR_FLUSH(*mercury_current_binary_output) < 0) { mercury_output_error(mercury_current_binary_output); @@ -6444,7 +6482,8 @@ io.seek_binary_output(binary_output_stream(Stream), Whence, Offset, !IO) :- :- pragma foreign_proc("C", io.seek_binary_2(Stream::in, Flag::in, Off::in, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " static const int seek_flags[] = { SEEK_SET, SEEK_CUR, SEEK_END }; @@ -6472,7 +6511,8 @@ io.binary_output_stream_offset(binary_output_stream(Stream), Offset, !IO) :- io::di, io::uo) is det. :- pragma foreign_proc("C", io.binary_stream_offset_2(Stream::in, Offset::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " /* XXX should check for failure */ /* XXX should check if the stream is tellable */ @@ -6496,7 +6536,8 @@ io.write_string(output_stream(Stream), Message, !IO) :- :- pred io.write_string_2(io.stream::in, string::in, io::di, io::uo) is det. :- pragma foreign_proc("C", io.write_string_2(Stream::in, Message::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " mercury_print_string(Stream, Message); MR_update_io(IO0, IO); @@ -6508,7 +6549,8 @@ io.write_char(output_stream(Stream), Character, !IO) :- :- pred io.write_char_2(io.stream::in, char::in, io::di, io::uo) is det. :- pragma foreign_proc("C", io.write_char_2(Stream::in, Character::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " if (MR_PUTCH(*Stream, Character) < 0) { mercury_output_error(Stream); @@ -6525,7 +6567,8 @@ io.write_int(output_stream(Stream), Val, !IO) :- :- pred io.write_int_2(io.stream::in, int::in, io::di, io::uo) is det. :- pragma foreign_proc("C", io.write_int_2(Stream::in, Val::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " if (ML_fprintf(Stream, ""%ld"", (long) Val) < 0) { mercury_output_error(Stream); @@ -6539,7 +6582,8 @@ io.write_float(output_stream(Stream), Val, !IO) :- :- pred io.write_float_2(io.stream::in, float::in, io::di, io::uo) is det. :- pragma foreign_proc("C", io.write_float_2(Stream::in, Val::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " char buf[MR_SPRINTF_FLOAT_BUF_SIZE]; MR_sprintf_float(buf, Val); @@ -6555,7 +6599,8 @@ io.write_byte(binary_output_stream(Stream), Byte, !IO) :- :- pred io.write_byte_2(io.stream::in, int::in, io::di, io::uo) is det. :- pragma foreign_proc("C", io.write_byte_2(Stream::in, Byte::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " /* call putc with a strictly non-negative byte-sized integer */ if (MR_PUTCH(*Stream, (int) ((unsigned char) Byte)) < 0) { @@ -6570,7 +6615,8 @@ io.write_bytes(binary_output_stream(Stream), Message, !IO) :- :- pred io.write_bytes_2(io.stream::in, string::in, io::di, io::uo) is det. :- pragma foreign_proc("C", io.write_bytes_2(Stream::in, Message::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " mercury_print_binary_string(Stream, Message); MR_update_io(IO0, IO); @@ -6582,7 +6628,8 @@ io.flush_output(output_stream(Stream), !IO) :- :- pred io.flush_output_2(io.stream::in, io::di, io::uo) is det. :- pragma foreign_proc("C", io.flush_output_2(Stream::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " if (MR_FLUSH(*Stream) < 0) { mercury_output_error(Stream); @@ -6596,7 +6643,8 @@ io.flush_binary_output(binary_output_stream(Stream), !IO) :- :- pred io.flush_binary_output_2(io.stream::in, io::di, io::uo) is det. :- pragma foreign_proc("C", io.flush_binary_output_2(Stream::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " if (MR_FLUSH(*Stream) < 0) { mercury_output_error(Stream); @@ -6765,7 +6813,7 @@ io.stdin_stream = input_stream(io.stdin_stream_2). :- func io.stdin_stream_2 = io.stream. :- pragma foreign_proc("C", io.stdin_stream_2 = (Stream::out), - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, does_not_affect_liveness], " Stream = &mercury_stdin; "). @@ -6776,7 +6824,8 @@ io.stdin_stream(input_stream(Stream), !IO) :- :- pred io.stdin_stream_2(io.stream::out, io::di, io::uo) is det. :- pragma foreign_proc("C", io.stdin_stream_2(Stream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " Stream = &mercury_stdin; MR_update_io(IO0, IO); @@ -6787,7 +6836,7 @@ io.stdout_stream = output_stream(io.stdout_stream_2). :- func io.stdout_stream_2 = io.stream. :- pragma foreign_proc("C", io.stdout_stream_2 = (Stream::out), - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, does_not_affect_liveness], " Stream = &mercury_stdout; "). @@ -6809,7 +6858,7 @@ io.stderr_stream = output_stream(io.stderr_stream_2). :- func io.stderr_stream_2 = io.stream. :- pragma foreign_proc("C", io.stderr_stream_2 = (Stream::out), - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, does_not_affect_liveness], " Stream = &mercury_stderr; "). @@ -6820,7 +6869,8 @@ io.stderr_stream(output_stream(Stream), !IO) :- :- pred io.stderr_stream_2(io.stream::out, io::di, io::uo) is det. :- pragma foreign_proc("C", io.stderr_stream_2(Stream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " Stream = &mercury_stderr; MR_update_io(IO0, IO); @@ -6832,7 +6882,8 @@ io.stdin_binary_stream(binary_input_stream(Stream), !IO) :- :- pred io.stdin_binary_stream_2(io.stream::out, io::di, io::uo) is det. :- pragma foreign_proc("C", io.stdin_binary_stream_2(Stream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " Stream = &mercury_stdin_binary; MR_update_io(IO0, IO); @@ -6844,7 +6895,8 @@ io.stdout_binary_stream(binary_output_stream(Stream), !IO) :- :- pred io.stdout_binary_stream_2(io.stream::out, io::di, io::uo) is det. :- pragma foreign_proc("C", io.stdout_binary_stream_2(Stream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " Stream = &mercury_stdout_binary; MR_update_io(IO0, IO); @@ -6856,7 +6908,8 @@ io.input_stream(input_stream(Stream), !IO) :- :- pred io.input_stream_2(io.stream::out, io::di, io::uo) is det. :- pragma foreign_proc("C", io.input_stream_2(Stream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " Stream = mercury_current_text_input; MR_update_io(IO0, IO); @@ -6868,7 +6921,8 @@ io.output_stream(output_stream(Stream), !IO) :- :- pred io.output_stream_2(io.stream::out, io::di, io::uo) is det. :- pragma foreign_proc("C", io.output_stream_2(Stream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " Stream = mercury_current_text_output; MR_update_io(IO0, IO); @@ -6880,7 +6934,8 @@ io.binary_input_stream(binary_input_stream(Stream), !IO) :- :- pred io.binary_input_stream_2(io.stream::out, io::di, io::uo) is det. :- pragma foreign_proc("C", io.binary_input_stream_2(Stream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " Stream = mercury_current_binary_input; MR_update_io(IO0, IO); @@ -6892,7 +6947,8 @@ io.binary_output_stream(binary_output_stream(Stream), !IO) :- :- pred io.binary_output_stream_2(io.stream::out, io::di, io::uo) is det. :- pragma foreign_proc("C", io.binary_output_stream_2(Stream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " Stream = mercury_current_binary_output; MR_update_io(IO0, IO); @@ -6900,7 +6956,8 @@ io.binary_output_stream(binary_output_stream(Stream), !IO) :- :- pragma foreign_proc("C", io.get_line_number(LineNum::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " LineNum = MR_line_number(*mercury_current_text_input); MR_update_io(IO0, IO); @@ -6913,7 +6970,8 @@ io.get_line_number(input_stream(Stream), LineNum, !IO) :- is det. :- pragma foreign_proc("C", io.get_line_number_2(Stream::in, LineNum::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " LineNum = MR_line_number(*Stream); MR_update_io(IO0, IO); @@ -6921,7 +6979,8 @@ io.get_line_number(input_stream(Stream), LineNum, !IO) :- :- pragma foreign_proc("C", io.set_line_number(LineNum::in, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " MR_line_number(*mercury_current_text_input) = LineNum; MR_update_io(IO0, IO); @@ -6935,7 +6994,8 @@ io.set_line_number(input_stream(Stream), LineNum, !IO) :- :- pragma foreign_proc("C", io.set_line_number_2(Stream::in, LineNum::in, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " MR_line_number(*Stream) = LineNum; MR_update_io(IO0, IO); @@ -6943,7 +7003,8 @@ io.set_line_number(input_stream(Stream), LineNum, !IO) :- :- pragma foreign_proc("C", io.get_output_line_number(LineNum::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " LineNum = MR_line_number(*mercury_current_text_output); MR_update_io(IO0, IO); @@ -6957,7 +7018,8 @@ io.get_output_line_number(output_stream(Stream), LineNum, !IO) :- :- pragma foreign_proc("C", io.get_output_line_number_2(Stream::in, LineNum::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " LineNum = MR_line_number(*Stream); MR_update_io(IO0, IO); @@ -6965,7 +7027,8 @@ io.get_output_line_number(output_stream(Stream), LineNum, !IO) :- :- pragma foreign_proc("C", io.set_output_line_number(LineNum::in, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " MR_line_number(*mercury_current_text_output) = LineNum; MR_update_io(IO0, IO); @@ -6978,7 +7041,8 @@ io.set_output_line_number(output_stream(Stream), LineNum, !IO) :- io::di, io::uo) is det. :- pragma foreign_proc("C", io.set_output_line_number_2(Stream::in, LineNum::in, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " MR_line_number(*Stream) = LineNum; MR_update_io(IO0, IO); @@ -6991,7 +7055,8 @@ io.set_input_stream(input_stream(NewStream), input_stream(OutStream), !IO) :- io::di, io::uo) is det. :- pragma foreign_proc("C", io.set_input_stream_2(NewStream::in, OutStream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " OutStream = mercury_current_text_input; mercury_current_text_input = NewStream; @@ -7007,7 +7072,8 @@ io.set_output_stream(output_stream(NewStream), output_stream(OutStream), :- pragma foreign_proc("C", io.set_output_stream_2(NewStream::in, OutStream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " OutStream = mercury_current_text_output; mercury_current_text_output = NewStream; @@ -7023,7 +7089,8 @@ io.set_binary_input_stream(binary_input_stream(NewStream), :- pragma foreign_proc("C", io.set_binary_input_stream_2(NewStream::in, OutStream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " OutStream = mercury_current_binary_input; mercury_current_binary_input = NewStream; @@ -7039,7 +7106,8 @@ io.set_binary_output_stream(binary_output_stream(NewStream), :- pragma foreign_proc("C", io.set_binary_output_stream_2(NewStream::in, OutStream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " OutStream = mercury_current_binary_output; mercury_current_binary_output = NewStream; @@ -7376,7 +7444,8 @@ io.set_binary_output_stream(binary_output_stream(NewStream), :- pragma foreign_proc("C", io.do_open_text(FileName::in, Mode::in, ResultCode::out, StreamId::out, Stream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " Stream = mercury_open(FileName, Mode); ResultCode = (Stream != NULL ? 0 : -1); @@ -7387,7 +7456,8 @@ io.set_binary_output_stream(binary_output_stream(NewStream), :- pragma foreign_proc("C", io.do_open_binary(FileName::in, Mode::in, ResultCode::out, StreamId::out, Stream::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " Stream = mercury_open(FileName, Mode); ResultCode = (Stream != NULL ? 0 : -1); @@ -7495,7 +7565,8 @@ io.close_binary_output(binary_output_stream(Stream), !IO) :- :- pragma foreign_proc("C", io.close_stream(Stream::in, IO0::di, IO::uo), - [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates], + [may_call_mercury, promise_pure, tabled_for_io, thread_safe, terminates, + does_not_affect_liveness], " mercury_close(Stream); MR_update_io(IO0, IO); @@ -7519,7 +7590,8 @@ io.close_binary_output(binary_output_stream(Stream), !IO) :- :- pragma foreign_proc("C", io.progname(DefaultProgname::in, PrognameOut::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], " if (MR_progname) { MR_make_aligned_string(PrognameOut, MR_progname); @@ -7531,7 +7603,8 @@ io.close_binary_output(binary_output_stream(Stream), !IO) :- :- pragma foreign_proc("C", io.command_line_arguments(Args::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ int i; @@ -7547,7 +7620,8 @@ io.close_binary_output(binary_output_stream(Stream), !IO) :- :- pragma foreign_proc("C", io.get_exit_status(ExitStatus::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " ExitStatus = mercury_exit_status; MR_update_io(IO0, IO); @@ -7555,7 +7629,8 @@ io.close_binary_output(binary_output_stream(Stream), !IO) :- :- pragma foreign_proc("C", io.set_exit_status(ExitStatus::in, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " mercury_exit_status = ExitStatus; MR_update_io(IO0, IO); @@ -7564,7 +7639,8 @@ io.close_binary_output(binary_output_stream(Stream), !IO) :- :- pragma foreign_proc("C", io.call_system_code(Command::in, Status::out, Msg::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io], + [will_not_call_mercury, promise_pure, tabled_for_io, + does_not_affect_liveness], " Status = system(Command); if (Status == -1) { @@ -7614,7 +7690,7 @@ io.handle_system_command_exit_code(Status0::in) = (Status::out) :- :- pragma foreign_proc("C", io.handle_system_command_exit_code(Status0::in) = (Status::out), - [will_not_call_mercury, thread_safe, promise_pure], + [will_not_call_mercury, thread_safe, promise_pure, does_not_affect_liveness], " #if defined (WIFEXITED) && defined (WEXITSTATUS) && \ defined (WIFSIGNALED) && defined (WTERMSIG) @@ -7816,7 +7892,7 @@ command_line_argument(_, "") :- :- pragma foreign_proc("C", io.getenv(Var::in, Value::out), - [will_not_call_mercury, tabled_for_io], + [will_not_call_mercury, tabled_for_io, does_not_affect_liveness], "{ Value = getenv(Var); SUCCESS_INDICATOR = (Value != 0); @@ -7864,7 +7940,7 @@ io.setenv(Var, Value) :- :- pragma foreign_proc("C", io.putenv(VarAndValue::in), - [will_not_call_mercury, tabled_for_io], + [will_not_call_mercury, tabled_for_io, does_not_affect_liveness], " SUCCESS_INDICATOR = (putenv(VarAndValue) == 0); "). @@ -7968,7 +8044,8 @@ io.make_temp(Dir, Prefix, Name, !IO) :- :- pragma foreign_proc("C", io.do_make_temp(Dir::in, Prefix::in, Sep::in, FileName::out, Error::out, ErrorMessage::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ /* ** Constructs a temporary name by concatenating Dir, `/', the first 5 chars @@ -8256,7 +8333,8 @@ io.remove_file(FileName, Result, !IO) :- :- pragma foreign_proc("C", io.remove_file_2(FileName::in, RetVal::out, RetStr::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ RetVal = remove(FileName); ML_maybe_make_err_msg(RetVal != 0, errno, ""remove failed: "", @@ -8320,7 +8398,8 @@ io.rename_file(OldFileName, NewFileName, Result, IO0, IO) :- :- pragma foreign_proc("C", io.rename_file_2(OldFileName::in, NewFileName::in, RetVal::out, RetStr::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ RetVal = rename(OldFileName, NewFileName); ML_maybe_make_err_msg(RetVal != 0, errno, ""rename failed: "", @@ -8379,7 +8458,8 @@ io.have_symlinks :- semidet_fail. :- pragma foreign_proc("C", io.have_symlinks, - [will_not_call_mercury, promise_pure, thread_safe], + [will_not_call_mercury, promise_pure, thread_safe, + does_not_affect_liveness], " #if defined(MR_HAVE_SYMLINK) && defined(MR_HAVE_READLINK) SUCCESS_INDICATOR = MR_TRUE; @@ -8408,7 +8488,8 @@ io.make_symlink(FileName, LinkFileName, Result, !IO) :- :- pragma foreign_proc("C", io.make_symlink_2(FileName::in, LinkFileName::in, Status::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ #ifdef MR_HAVE_SYMLINK Status = (symlink(FileName, LinkFileName) == 0); @@ -8438,7 +8519,8 @@ io.read_symlink(FileName, Result, !IO) :- :- pragma foreign_proc("C", io.read_symlink_2(FileName::in, TargetFileName::out, Status::out, Error::out, IO0::di, IO::uo), - [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe], + [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe, + does_not_affect_liveness], "{ #ifdef MR_HAVE_READLINK #ifndef PATH_MAX diff --git a/library/lexer.m b/library/lexer.m index f10053978..3e5788b65 100644 --- a/library/lexer.m +++ b/library/lexer.m @@ -1,7 +1,7 @@ %---------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 %---------------------------------------------------------------------------% -% Copyright (C) 1993-2000, 2003-2006 The University of Melbourne. +% Copyright (C) 1993-2000, 2003-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %---------------------------------------------------------------------------% @@ -1172,7 +1172,8 @@ unicode_encoding_int_to_encoding(1, utf16). :- pragma foreign_proc("C", backend_unicode_encoding_int = (EncodingInt::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " EncodingInt = 0; "). diff --git a/library/math.m b/library/math.m index c48d35893..39ea69b5a 100644 --- a/library/math.m +++ b/library/math.m @@ -5,11 +5,11 @@ % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %---------------------------------------------------------------------------% -% +% % File: math.m. % Main author: bromage. % Stability: high. -% +% % Higher mathematical operations. (The basics are in float.m.) % % By default, domain errors are currently handled by throwing an exception. @@ -36,7 +36,7 @@ % predicate the error occurred, as well as giving you a stack trace if % that is enabled; with the checks disabled you only have the information % that the floating-point exception signal handler gives you. -% +% %---------------------------------------------------------------------------% %---------------------------------------------------------------------------% @@ -262,7 +262,8 @@ :- pragma foreign_proc("C", math_domain_checks, - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " #ifdef ML_OMIT_MATH_DOMAIN_CHECKS SUCCESS_INDICATOR = MR_FALSE; @@ -295,7 +296,8 @@ % Pythagoras' number :- pragma foreign_proc("C", math.pi = (Pi::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Pi = ML_FLOAT_PI; "). @@ -321,7 +323,8 @@ math.pi = 3.1415926535897932384626433832795029. % Base of natural logarithms :- pragma foreign_proc("C", math.e = (E::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " E = ML_FLOAT_E; "). @@ -346,7 +349,8 @@ math.e = 2.7182818284590452353602874713526625. :- pragma foreign_proc("C", math.ceiling(Num::in) = (Ceil::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Ceil = ceil(Num); "). @@ -365,7 +369,8 @@ math.e = 2.7182818284590452353602874713526625. :- pragma foreign_proc("C", math.floor(Num::in) = (Floor::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Floor = floor(Num); "). @@ -384,7 +389,8 @@ math.e = 2.7182818284590452353602874713526625. :- pragma foreign_proc("C", math.round(Num::in) = (Rounded::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Rounded = floor(Num+0.5); "). @@ -417,7 +423,8 @@ math.sqrt(X) = SquareRoot :- :- pragma foreign_proc("C", math.sqrt_2(X::in) = (SquareRoot::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " SquareRoot = sqrt(X); "). @@ -488,7 +495,8 @@ math.pow(X, Y) = Res :- :- pragma foreign_proc("C", math.pow_2(X::in, Y::in) = (Res::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Res = pow(X, Y); "). @@ -509,7 +517,8 @@ math.pow(X, Y) = Res :- :- pragma foreign_proc("C", math.exp(X::in) = (Exp::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Exp = exp(X); "). @@ -537,7 +546,8 @@ math.ln(X) = Log :- :- pragma foreign_proc("C", math.ln_2(X::in) = (Log::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Log = log(X); "). @@ -565,7 +575,8 @@ math.log10(X) = Log :- :- pragma foreign_proc("C", math.log10_2(X::in) = (Log10::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Log10 = log10(X); "). @@ -589,7 +600,8 @@ math.log2(X) = Log :- :- pragma foreign_proc("C", math.log2_2(X::in) = (Log2::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Log2 = log(X) / ML_FLOAT_LN2; "). @@ -624,7 +636,8 @@ math.log(B, X) = Log :- :- pragma foreign_proc("C", math.log_2(B::in, X::in) = (Log::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Log = log(X) / log(B); "). @@ -639,7 +652,8 @@ math.log_2(B, X) = math.ln_2(X) / math.ln_2(B). :- pragma foreign_proc("C", math.sin(X::in) = (Sin::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Sin = sin(X); "). @@ -658,7 +672,8 @@ math.log_2(B, X) = math.ln_2(X) / math.ln_2(B). :- pragma foreign_proc("C", math.cos(X::in) = (Cos::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Cos = cos(X); "). @@ -677,7 +692,8 @@ math.log_2(B, X) = math.ln_2(X) / math.ln_2(B). :- pragma foreign_proc("C", math.tan(X::in) = (Tan::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Tan = tan(X); "). @@ -710,7 +726,8 @@ math.asin(X) = ASin :- :- pragma foreign_proc("C", math.asin_2(X::in) = (ASin::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " ASin = asin(X); "). @@ -743,7 +760,8 @@ math.acos(X) = ACos :- :- pragma foreign_proc("C", math.acos_2(X::in) = (ACos::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " ACos = acos(X); "). @@ -763,7 +781,8 @@ math.acos(X) = ACos :- :- pragma foreign_proc("C", math.atan(X::in) = (ATan::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " ATan = atan(X); "). @@ -782,7 +801,8 @@ math.acos(X) = ACos :- :- pragma foreign_proc("C", math.atan2(Y::in, X::in) = (ATan2::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " ATan2 = atan2(Y, X); "). @@ -801,7 +821,8 @@ math.acos(X) = ACos :- :- pragma foreign_proc("C", math.sinh(X::in) = (Sinh::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Sinh = sinh(X); "). @@ -817,7 +838,8 @@ math.sinh(X) = Sinh :- :- pragma foreign_proc("C", math.cosh(X::in) = (Cosh::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Cosh = cosh(X); "). @@ -833,7 +855,8 @@ math.cosh(X) = Cosh :- :- pragma foreign_proc("C", math.tanh(X::in) = (Tanh::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Tanh = tanh(X); "). diff --git a/library/private_builtin.m b/library/private_builtin.m index 872aacfa8..c6e6d0ecf 100644 --- a/library/private_builtin.m +++ b/library/private_builtin.m @@ -1,7 +1,7 @@ %---------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 %---------------------------------------------------------------------------% -% Copyright (C) 1994-2006 The University of Melbourne. +% Copyright (C) 1994-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %---------------------------------------------------------------------------% @@ -173,7 +173,8 @@ builtin_compare_string(R, S1, S2) :- :- pragma foreign_proc("C", builtin_strcmp(Res::out, S1::in, S2::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Res = strcmp(S1, S2); "). @@ -552,7 +553,8 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", type_info_from_typeclass_info(TypeClassInfo::in, Index::in, TypeInfo::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " TypeInfo = MR_typeclass_info_param_type_info(TypeClassInfo, Index); "). @@ -560,7 +562,8 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", unconstrained_type_info_from_typeclass_info(TypeClassInfo::in, Index::in, TypeInfo::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " TypeInfo = MR_typeclass_info_instance_tvar_type_info(TypeClassInfo, Index); "). @@ -568,7 +571,8 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", superclass_from_typeclass_info(TypeClassInfo0::in, Index::in, TypeClassInfo::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " TypeClassInfo = MR_typeclass_info_superclass_info(TypeClassInfo0, Index); @@ -577,7 +581,8 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", instance_constraint_from_typeclass_info(TypeClassInfo0::in, Index::in, TypeClassInfo::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " TypeClassInfo = MR_typeclass_info_arg_typeclass_info(TypeClassInfo0, Index); @@ -701,7 +706,7 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", reset_ticket_undo(Ticket::in), - [will_not_call_mercury, thread_safe], + [will_not_call_mercury, thread_safe, does_not_affect_liveness], " #ifdef MR_USE_TRAIL MR_reset_ticket(Ticket, MR_undo); @@ -710,7 +715,7 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", reset_ticket_commit(Ticket::in), - [will_not_call_mercury, thread_safe], + [will_not_call_mercury, thread_safe, does_not_affect_liveness], " #ifdef MR_USE_TRAIL MR_reset_ticket(Ticket, MR_commit); @@ -719,7 +724,7 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", reset_ticket_solve(Ticket::in), - [will_not_call_mercury, thread_safe], + [will_not_call_mercury, thread_safe, does_not_affect_liveness], " #ifdef MR_USE_TRAIL MR_reset_ticket(Ticket, MR_solve); @@ -728,7 +733,7 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", discard_ticket, - [will_not_call_mercury, thread_safe], + [will_not_call_mercury, thread_safe, does_not_affect_liveness], " #ifdef MR_USE_TRAIL MR_discard_ticket(); @@ -737,7 +742,7 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", prune_ticket, - [will_not_call_mercury, thread_safe], + [will_not_call_mercury, thread_safe, does_not_affect_liveness], " #ifdef MR_USE_TRAIL MR_prune_ticket(); @@ -746,7 +751,7 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", mark_ticket_stack(TicketCounter::out), - [will_not_call_mercury, thread_safe], + [will_not_call_mercury, thread_safe, does_not_affect_liveness], " #ifdef MR_USE_TRAIL MR_mark_ticket_stack(TicketCounter); @@ -757,7 +762,7 @@ special__Compare____base_typeclass_info_1_0( :- pragma foreign_proc("C", prune_tickets_to(TicketCounter::in), - [will_not_call_mercury, thread_safe], + [will_not_call_mercury, thread_safe, does_not_affect_liveness], " #ifdef MR_USE_TRAIL MR_prune_tickets_to(TicketCounter); @@ -993,7 +998,7 @@ trailed_nondet_pragma_foreign_code :- [will_not_call_mercury, thread_safe, will_not_modify_trail], " #ifdef MR_NATIVE_GC - *(MR_Word *)Pointer = + * (MR_Word *) Pointer = MR_agc_deep_copy(* (MR_Word *) Pointer, (MR_TypeInfo) TypeInfo_for_T, MR_ENGINE(MR_eng_heap_zone2->MR_zone_min), MR_ENGINE(MR_eng_heap_zone2->MR_zone_hardmax)); @@ -1012,7 +1017,8 @@ trailed_nondet_pragma_foreign_code :- :- pragma foreign_proc("C", mark_hp(SavedHeapPointer::out), - [will_not_call_mercury, thread_safe, will_not_modify_trail], + [will_not_call_mercury, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " #ifndef MR_CONSERVATIVE_GC MR_mark_hp(SavedHeapPointer); @@ -1024,7 +1030,8 @@ trailed_nondet_pragma_foreign_code :- :- pragma foreign_proc("C", restore_hp(SavedHeapPointer::in), - [will_not_call_mercury, thread_safe, will_not_modify_trail], + [will_not_call_mercury, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " #ifndef MR_CONSERVATIVE_GC MR_restore_hp(SavedHeapPointer); @@ -1550,7 +1557,8 @@ no_clauses(PredName) :- :- pragma foreign_proc("C", trace_evaluate_runtime_condition, - [will_not_call_mercury, thread_safe, promise_semipure], + [will_not_call_mercury, thread_safe, promise_semipure, + does_not_affect_liveness], " /* All uses of this predicate should override the body. */ MR_fatal_error(""trace_evaluate_runtime_condition called""); diff --git a/library/string.m b/library/string.m index 852613425..453d446b0 100644 --- a/library/string.m +++ b/library/string.m @@ -1,7 +1,7 @@ %---------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 %---------------------------------------------------------------------------% -% Copyright (C) 1993-2006 The University of Melbourne. +% Copyright (C) 1993-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %---------------------------------------------------------------------------% @@ -976,6 +976,9 @@ string.prefix(String::in, Prefix::in) :- PreLen = length(Prefix), PreLen =< Len, prefix_2_iii(String, Prefix, PreLen - 1). +string.prefix(String::in, Prefix::out) :- + Len = length(String), + prefix_2_ioii(String, Prefix, 0, Len). :- pred prefix_2_iii(string::in, string::in, int::in) is semidet. @@ -987,10 +990,6 @@ prefix_2_iii(String, Prefix, I) :- true ). -string.prefix(String::in, Prefix::out) :- - Len = length(String), - prefix_2_ioii(String, Prefix, 0, Len). - :- pred prefix_2_ioii(string::in, string::out, int::in, int::in) is multi. prefix_2_ioii(String, Prefix, PreLen, _Len) :- @@ -1007,6 +1006,9 @@ string.suffix(String::in, Suffix::in) :- PreLen = length(Suffix), PreLen =< Len, suffix_2_iiii(String, Suffix, 0, Len - PreLen, PreLen). +string.suffix(String::in, Suffix::out) :- + Len = length(String), + suffix_2_ioii(String, Suffix, 0, Len). :- pred suffix_2_iiii(string::in, string::in, int::in, int::in, int::in) is semidet. @@ -1020,10 +1022,6 @@ suffix_2_iiii(String, Suffix, I, Offset, Len) :- true ). -string.suffix(String::in, Suffix::out) :- - Len = length(String), - suffix_2_ioii(String, Suffix, 0, Len). - :- pred suffix_2_ioii(string::in, string::out, int::in, int::in) is multi. suffix_2_ioii(String, Suffix, SufLen, Len) :- @@ -1169,7 +1167,8 @@ string.int_to_base_string_group_2(NegN, Base, Curr, Period, Sep, Str) :- :- pragma foreign_proc("C", string.to_char_list(Str::in, CharList::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_ConstString p = Str + strlen(Str); CharList = MR_list_empty_msg(MR_PROC_LABEL); @@ -1182,7 +1181,8 @@ string.int_to_base_string_group_2(NegN, Base, Curr, Period, Sep, Str) :- :- pragma foreign_proc("C", string.to_char_list(Str::uo, CharList::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ /* mode (uo, in) is det */ MR_Word char_list_ptr; @@ -1250,7 +1250,8 @@ string.to_char_list_2(Str, Index, CharList) :- :- pragma foreign_proc("C", string.from_rev_char_list(Chars::in, Str::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_Word list_ptr; MR_Word size, len; @@ -1391,7 +1392,8 @@ string.append_list(Lists, string.append_list(Lists)). % the amount of garbage created. :- pragma foreign_proc("C", string.append_list(Strs::in) = (Str::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_Word list = Strs; MR_Word tmp; @@ -1423,7 +1425,8 @@ string.append_list(Lists, string.append_list(Lists)). % garbage created. :- pragma foreign_proc("C", string.join_list(Sep::in, Strs::in) = (Str::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_Word list; MR_Word tmp; @@ -1521,7 +1524,8 @@ string.sub_string_search(WholeString, Pattern, Index) :- :- pragma foreign_proc("C", sub_string_search_start(WholeString::in, Pattern::in, BeginAt::in, Index::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ char *match; match = strstr(WholeString + BeginAt, Pattern); @@ -2008,7 +2012,8 @@ make_format(Flags, MaybeWidth, MaybePrec, LengthMod, Spec) = :- pred using_sprintf is semidet. :- pragma foreign_proc("C", using_sprintf, - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " SUCCESS_INDICATOR = MR_TRUE; "). @@ -2085,7 +2090,8 @@ make_format_dotnet(_Flags, MaybeWidth, MaybePrec, _LengthMod, Spec0) = String :- :- pragma foreign_proc("C", int_length_modifer = (LengthModifier::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_make_aligned_string(LengthModifier, MR_INTEGER_LENGTH_MODIFIER); }"). @@ -2103,7 +2109,8 @@ int_length_modifer = _ :- :- pragma foreign_proc("C", native_format_float(FormatStr::in, Val::in) = (Str::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_save_transient_hp(); Str = MR_make_string(MR_PROC_LABEL, FormatStr, (double) Val); @@ -2122,7 +2129,8 @@ native_format_float(_, _) = _ :- :- pragma foreign_proc("C", native_format_int(FormatStr::in, Val::in) = (Str::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_save_transient_hp(); Str = MR_make_string(MR_PROC_LABEL, FormatStr, Val); @@ -2141,7 +2149,8 @@ native_format_int(_, _) = _ :- :- pragma foreign_proc("C", native_format_string(FormatStr::in, Val::in) = (Str::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_save_transient_hp(); Str = MR_make_string(MR_PROC_LABEL, FormatStr, Val); @@ -2160,7 +2169,8 @@ native_format_string(_, _) = _ :- :- pragma foreign_proc("C", native_format_char(FormatStr::in, Val::in) = (Str::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_save_transient_hp(); Str = MR_make_string(MR_PROC_LABEL, FormatStr, Val); @@ -3001,7 +3011,8 @@ string.from_float(Flt) = string.float_to_string(Flt). :- pragma foreign_proc("C", string.float_to_string(Flt::in, Str::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ /* ** For efficiency reasons we duplicate the C implementation @@ -3060,7 +3071,8 @@ max_precision = min_precision + 2. :- pragma foreign_proc("C", string.lowlevel_float_to_string(Flt::in, Str::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ /* ** Note any changes here will require the same changes in @@ -3099,7 +3111,8 @@ string.det_to_float(FloatString) = :- pragma foreign_proc("C", string.to_float(FloatString::in, FloatVal::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ /* ** The %c checks for any erroneous characters appearing after the float; @@ -3189,7 +3202,8 @@ string.det_to_float(FloatString) = % shouldn't be considered to be part of the string itself. :- pragma foreign_proc("C", string.contains_char(Str::in, Ch::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " SUCCESS_INDICATOR = (strchr(Str, Ch) != NULL) && Ch != '\\0'; "). @@ -3237,7 +3251,8 @@ string.index(Str, Index, Char) :- % We should consider making this routine a compiler built-in. :- pragma foreign_proc("C", string.index_check(Index::in, Length::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " /* ** We do not test for negative values of Index because (a) MR_Unsigned @@ -3262,7 +3277,8 @@ string.index_check(Index, Length) :- :- pragma foreign_proc("C", string.unsafe_index(Str::in, Index::in, Ch::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Ch = Str[Index]; "). @@ -3323,7 +3339,8 @@ String ^ unsafe_elem(Index) = unsafe_index(String, Index). :- pragma foreign_proc("C", string.set_char(Ch::in, Index::in, Str0::in, Str::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " size_t len = strlen(Str0); if ((MR_Unsigned) Index >= len) { @@ -3355,7 +3372,7 @@ string.set_char(Ch, Index, Str0, Str) :- % :- pragma foreign_proc("C", % string.set_char(Ch::in, Index::in, Str0::di, Str::uo), -% [will_not_call_mercury, promise_pure, thread_safe], +% [will_not_call_mercury, promise_pure, thread_safe, does_not_affect_liveness], % " % if ((MR_Unsigned) Index >= strlen(Str0)) { % SUCCESS_INDICATOR = MR_FALSE; @@ -3384,7 +3401,8 @@ string.set_char(Ch, Index, Str0, Str) :- :- pragma foreign_proc("C", string.unsafe_set_char(Ch::in, Index::in, Str0::in, Str::out), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " size_t len = strlen(Str0); MR_allocate_aligned_string_msg(Str, len, MR_PROC_LABEL); @@ -3408,7 +3426,7 @@ string.set_char(Ch, Index, Str0, Str) :- % :- pragma foreign_proc("C", % string.unsafe_set_char(Ch::in, Index::in, Str0::di, Str::uo), -% [will_not_call_mercury, promise_pure, thread_safe], +% [will_not_call_mercury, promise_pure, thread_safe, does_not_affect_liveness], % " % Str = Str0; % MR_set_char(Str, Index, Ch); @@ -3430,9 +3448,12 @@ string.set_char(Ch, Index, Str0, Str) :- /*-----------------------------------------------------------------------*/ +:- pragma promise_equivalent_clauses(string.length/2). + :- pragma foreign_proc("C", string.length(Str::in, Length::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Length = strlen(Str); "). @@ -3451,7 +3472,8 @@ string.set_char(Ch, Index, Str0, Str) :- :- pragma foreign_proc("C", string.length(Str::ui, Length::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " Length = strlen(Str); "). @@ -3467,8 +3489,6 @@ string.set_char(Ch, Index, Str0, Str) :- Length = Str.length(); "). -:- pragma promise_equivalent_clauses(string.length/2). - string.length(Str0, Len) :- % XXX This copy is only necessary because of the ui. copy(Str0, Str), @@ -3500,7 +3520,8 @@ string.append(S1::out, S2::out, S3::in) :- :- pragma foreign_proc("C", string.append_iii(S1::in, S2::in, S3::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ size_t len_1 = strlen(S1); SUCCESS_INDICATOR = ( @@ -3523,7 +3544,8 @@ string.append_iii(X, Y, Z) :- :- pragma foreign_proc("C", string.append_ioi(S1::in, S2::uo, S3::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ size_t len_1, len_2, len_3; @@ -3561,7 +3583,8 @@ string.append_ioi(X, Y, Z) :- :- pragma foreign_proc("C", string.append_iio(S1::in, S2::in, S3::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ size_t len_1, len_2; len_1 = strlen(S1); @@ -3606,7 +3629,8 @@ string.append_ooi_2(NextS1Len, S3Len, S1, S2, S3) :- :- pragma foreign_proc("C", string.append_ooi_3(S1Len::in, S3Len::in, S1::out, S2::out, S3::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_allocate_aligned_string_msg(S1, S1Len, MR_PROC_LABEL); MR_memcpy(S1, S3, S1Len); @@ -3659,7 +3683,8 @@ strchars(I, End, Str) = :- pragma foreign_proc("C", string.substring(Str::in, Start::in, Count::in, SubString::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_Integer len; MR_Word tmp; @@ -3679,7 +3704,8 @@ strchars(I, End, Str) = :- pragma foreign_proc("C", string.unsafe_substring(Str::in, Start::in, Count::in, SubString::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_Integer len; @@ -3702,7 +3728,8 @@ strchars(I, End, Str) = :- pragma foreign_proc("C", string.split(Str::in, Count::in, Left::uo, Right::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ MR_Integer len; MR_Word tmp; @@ -3771,7 +3798,8 @@ string.split(Str, Count, Left, Right) :- :- pragma foreign_proc("C", string.first_char(Str::in, First::in, Rest::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " SUCCESS_INDICATOR = ( Str[0] == First && @@ -3801,7 +3829,8 @@ string.split(Str, Count, Left, Right) :- :- pragma foreign_proc("C", string.first_char(Str::in, First::uo, Rest::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], " First = Str[0]; SUCCESS_INDICATOR = (First != '\\0' && strcmp(Str + 1, Rest) == 0); @@ -3834,7 +3863,8 @@ string.split(Str, Count, Left, Right) :- :- pragma foreign_proc("C", string.first_char(Str::in, First::in, Rest::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ if (Str[0] != First || First == '\\0') { SUCCESS_INDICATOR = MR_FALSE; @@ -3879,7 +3909,8 @@ string.split(Str, Count, Left, Right) :- :- pragma foreign_proc("C", string.first_char(Str::in, First::uo, Rest::uo), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ First = Str[0]; if (First == '\\0') { @@ -3924,7 +3955,8 @@ string.split(Str, Count, Left, Right) :- :- pragma foreign_proc("C", string.first_char(Str::uo, First::in, Rest::in), - [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail], + [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail, + does_not_affect_liveness], "{ size_t len = strlen(Rest) + 1; MR_allocate_aligned_string_msg(Str, len, MR_PROC_LABEL); diff --git a/library/table_builtin.m b/library/table_builtin.m index 809713245..d55e2bbe9 100644 --- a/library/table_builtin.m +++ b/library/table_builtin.m @@ -1,7 +1,7 @@ %---------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 %---------------------------------------------------------------------------% -% Copyright (C) 1998-2006 The University of Melbourne. +% Copyright (C) 1998-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. %---------------------------------------------------------------------------% @@ -241,7 +241,7 @@ get_tabling_stats(Info, Statistics, !IO) :- AnswerTableLookups::out, AnswerTableNotDupl::out, PrevAnswerTableLookups::out, PrevAnswerTableNotDupl::out, _IO0::di, _IO::uo), - [will_not_call_mercury, promise_pure], + [will_not_call_mercury, promise_pure, does_not_affect_liveness], " AnswerTable = ( Info->MR_pt_has_answer_table ? 1 : 0 ); Inputs = Info->MR_pt_num_inputs; @@ -333,7 +333,7 @@ get_all_output_step_stats(Info, CurSlot, !CurStepStats, !PrevStepStats, !IO) :- PrevNumInsertProbes::out, PrevNumLookupProbes::out, PrevNumResizes::out, PrevNumResizesOld::out, PrevNumResizesNew::out, _IO0::di, _IO::uo), - [will_not_call_mercury, promise_pure], + [will_not_call_mercury, promise_pure, does_not_affect_liveness], " MR_TableStepStats *cur; MR_TableStepStats *prev; @@ -379,7 +379,7 @@ get_all_output_step_stats(Info, CurSlot, !CurStepStats, !PrevStepStats, !IO) :- PrevNumInsertProbes::out, PrevNumLookupProbes::out, PrevNumResizes::out, PrevNumResizesOld::out, PrevNumResizesNew::out, _IO0::di, _IO::uo), - [will_not_call_mercury, promise_pure], + [will_not_call_mercury, promise_pure, does_not_affect_liveness], " MR_TableStepStats *cur; MR_TableStepStats *prev; @@ -413,7 +413,7 @@ get_all_output_step_stats(Info, CurSlot, !CurStepStats, !PrevStepStats, !IO) :- :- pragma foreign_proc("C", copy_current_stats_to_prev(Info::in, _IO0::di, _IO::uo), - [will_not_call_mercury, promise_pure], + [will_not_call_mercury, promise_pure, does_not_affect_liveness], " int i; MR_TableStepStats *cur; @@ -483,35 +483,35 @@ get_all_output_step_stats(Info, CurSlot, !CurStepStats, !PrevStepStats, !IO) :- :- pragma foreign_proc("C", table_loop_setup(T::in, Status::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_loop_setup(MR_TABLE_DEBUG_BOOL, MR_FALSE, T, Status); "). :- pragma foreign_proc("C", table_loop_setup_shortcut(T0::in, T::out, Status::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_loop_setup_shortcut(T0, T, Status); "). :- pragma foreign_proc("C", table_loop_mark_as_inactive(T::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_loop_mark_as_inactive(MR_TABLE_DEBUG_BOOL, T); "). :- pragma foreign_proc("C", table_loop_mark_as_inactive_and_fail(T::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_loop_mark_as_inactive_and_fail(MR_TABLE_DEBUG_BOOL, T); "). :- pragma foreign_proc("C", table_loop_mark_as_active_and_fail(T::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_loop_mark_as_active_and_fail(MR_TABLE_DEBUG_BOOL, T); "). @@ -676,77 +676,77 @@ table_loop_mark_as_active_and_fail(_) :- :- pragma foreign_proc("C", table_memo_det_setup(T::in, Status::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_det_setup(MR_TABLE_DEBUG_BOOL, MR_FALSE, T, Status); "). :- pragma foreign_proc("C", table_memo_det_setup_shortcut(T0::in, T::out, Status::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_det_setup_shortcut(T0, T, Status); "). :- pragma foreign_proc("C", table_memo_semi_setup(T::in, Status::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_semi_setup(MR_TABLE_DEBUG_BOOL, MR_FALSE, T, Status); "). :- pragma foreign_proc("C", table_memo_semi_setup_shortcut(T0::in, T::out, Status::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_semi_setup_shortcut(T0, T, Status); "). :- pragma foreign_proc("C", table_memo_non_setup(T0::in, Record::out, Status::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_non_setup(MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, Record, Status); "). :- pragma foreign_proc("C", table_memo_mark_as_failed(T::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_mark_as_failed(MR_TABLE_DEBUG_BOOL, T); "). :- pragma foreign_proc("C", table_memo_mark_as_succeeded(T::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_mark_as_succeeded(MR_TABLE_DEBUG_BOOL, T); "). :- pragma foreign_proc("C", table_memo_mark_as_incomplete(R::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_mark_as_incomplete(MR_TABLE_DEBUG_BOOL, R); "). :- pragma foreign_proc("C", table_memo_mark_as_active_and_fail(R::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_mark_as_active_and_fail(MR_TABLE_DEBUG_BOOL, R); "). :- pragma foreign_proc("C", table_memo_mark_as_complete_and_fail(R::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_mark_as_complete_and_fail(MR_TABLE_DEBUG_BOOL, R); "). :- pragma foreign_proc("C", table_memo_create_answer_block(T::in, Size::in, AnswerBlock::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_create_answer_block(MR_TABLE_DEBUG_BOOL, T, Size, AnswerBlock); @@ -754,35 +754,35 @@ table_loop_mark_as_active_and_fail(_) :- :- pragma foreign_proc("C", table_memo_fill_answer_block_shortcut(T::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_fill_answer_block_shortcut(T); "). :- pragma foreign_proc("C", table_memo_get_answer_block(T::in, AnswerBlock::out), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_memo_get_answer_block(MR_TABLE_DEBUG_BOOL, T, AnswerBlock); "). :- pragma foreign_proc("C", table_memo_get_answer_block_shortcut(T::in), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_memo_get_answer_block_shortcut(T); "). :- pragma foreign_proc("C", table_memo_non_get_answer_table(R::in, AT::out), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_memo_non_get_answer_table(MR_TABLE_DEBUG_BOOL, R, AT); "). :- pragma foreign_proc("C", table_memo_non_answer_is_not_duplicate(T::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_non_answer_is_not_duplicate(MR_TABLE_DEBUG_BOOL, T, SUCCESS_INDICATOR); @@ -790,7 +790,7 @@ table_loop_mark_as_active_and_fail(_) :- :- pragma foreign_proc("C", table_memo_non_answer_is_not_duplicate_shortcut(R::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_non_answer_is_not_duplicate_shortcut(R, SUCCESS_INDICATOR); @@ -798,14 +798,14 @@ table_loop_mark_as_active_and_fail(_) :- :- pragma foreign_proc("C", table_memo_non_create_answer_block_shortcut(R::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_memo_non_create_answer_block_shortcut(R::in); "). :- pragma foreign_proc("C", table_memo_non_return_all_shortcut(R::in), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_memo_non_return_all_shortcut(R); "). @@ -1032,7 +1032,7 @@ table_memo_non_create_answer_block_shortcut(_) :- :- pragma foreign_proc("C", table_io_in_range(T::out, Counter::out, Start::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_io_in_range(MR_TABLE_DEBUG_BOOL, T, Counter, Start, SUCCESS_INDICATOR); @@ -1040,7 +1040,7 @@ table_memo_non_create_answer_block_shortcut(_) :- :- pragma foreign_proc("C", table_io_has_occurred(T::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_io_has_occurred(MR_TABLE_DEBUG_BOOL, T, SUCCESS_INDICATOR); "). @@ -1049,14 +1049,14 @@ table_io_copy_io_state(IO, IO). :- pragma foreign_proc("C", table_io_left_bracket_unitized_goal(TraceEnabled::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_io_left_bracket_unitized_goal(TraceEnabled); "). :- pragma foreign_proc("C", table_io_right_bracket_unitized_goal(TraceEnabled::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_io_right_bracket_unitized_goal(TraceEnabled); "). @@ -1182,7 +1182,7 @@ table_io_right_bracket_unitized_goal(_TraceEnabled) :- :- pragma foreign_proc("C", table_mm_setup(T::in, Subgoal::out, Status::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_mm_setup(MR_TABLE_DEBUG_BOOL, MR_FALSE, T, Subgoal, Status); "). @@ -1197,21 +1197,21 @@ table_io_right_bracket_unitized_goal(_TraceEnabled) :- :- pragma foreign_proc("C", table_mm_return_all_shortcut(AnswerBlock::in), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_mm_return_all_shortcut(AnswerBlock); "). :- pragma foreign_proc("C", table_mm_get_answer_table(Subgoal::in, AnswerTable::out), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_mm_get_answer_table(MR_TABLE_DEBUG_BOOL, Subgoal, AnswerTable); "). :- pragma foreign_proc("C", table_mm_answer_is_not_duplicate(TrieNode::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_mm_answer_is_not_duplicate(MR_TABLE_DEBUG_BOOL, TrieNode, SUCCESS_INDICATOR); @@ -1219,7 +1219,7 @@ table_io_right_bracket_unitized_goal(_TraceEnabled) :- :- pragma foreign_proc("C", table_mm_answer_is_not_duplicate_shortcut(Subgoal::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " /* ** The body of this predicate doesn't matter, because it will never be @@ -1232,7 +1232,7 @@ table_io_right_bracket_unitized_goal(_TraceEnabled) :- :- pragma foreign_proc("C", table_mm_create_answer_block(Subgoal::in, Size::in, AnswerBlock::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_mm_create_answer_block(MR_TABLE_DEBUG_BOOL, Subgoal, Size, AnswerBlock); @@ -1240,7 +1240,7 @@ table_io_right_bracket_unitized_goal(_TraceEnabled) :- :- pragma foreign_proc("C", table_mm_fill_answer_block_shortcut(Subgoal::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_mm_fill_answer_block_shortcut(Subgoal); "). @@ -1351,12 +1351,6 @@ table_mm_fill_answer_block_shortcut(_) :- :- impure pred table_mmos_create_answer_block(ml_generator::in, int::in, ml_answer_block::out) is det. - % Return the base of the answer table trie for the subgoal of the - % given generator. - % -:- semipure pred table_mmos_get_answer_table(ml_generator::in, - ml_trie_node::out) is det. - % Return the given answer to the consumer(s) that requested it. % :- impure pred table_mmos_return_answer(ml_generator::in, ml_answer_block::in) @@ -1389,7 +1383,7 @@ table_mm_fill_answer_block_shortcut(_) :- :- pragma foreign_proc("C", table_mmos_save_inputs, - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " /* ** The body of this predicate doesn't matter, because it will never be @@ -1401,7 +1395,7 @@ table_mm_fill_answer_block_shortcut(_) :- :- pragma foreign_proc("C", table_mmos_setup_consumer(T::in, GeneratorPred::in, Consumer::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " /* ** The body of this predicate doesn't matter, because it will never be @@ -1414,7 +1408,7 @@ table_mm_fill_answer_block_shortcut(_) :- :- pragma foreign_proc("C", table_mmos_answer_is_not_duplicate(T::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " /* ** The body of this predicate doesn't matter, because it will never be @@ -1427,7 +1421,7 @@ table_mm_fill_answer_block_shortcut(_) :- :- pragma foreign_proc("C", table_mmos_answer_is_not_duplicate_shortcut(G::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " /* ** The body of this predicate doesn't matter, because it will never be @@ -1443,7 +1437,7 @@ table_mm_fill_answer_block_shortcut(_) :- :- pragma foreign_proc("C", table_mmos_restore_answers(AnswerBlock::in), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " /* ** The body of this predicate doesn't matter, because it will never be @@ -1454,18 +1448,9 @@ table_mm_fill_answer_block_shortcut(_) :- MR_fatal_error(""table_mmos_restore_answers: direct call""); "). -:- pragma foreign_proc("C", - table_mmos_get_answer_table(Generator::in, TrieNode::out), - [will_not_call_mercury, promise_semipure], -" - /* - MR_tbl_mmos_get_answer_table(Generator, TrieNode); - */ -"). - :- pragma foreign_proc("C", table_mmos_pickup_inputs(Generator::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " /* ** The body of this predicate doesn't matter, because it will never be @@ -1479,7 +1464,7 @@ table_mm_fill_answer_block_shortcut(_) :- :- pragma foreign_proc("C", table_mmos_create_answer_block(Generator::in, BlockSize::in, AnswerBlock::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " /* MR_tbl_mmos_create_answer_block(Generator, BlockSize, AnswerBlock); @@ -1488,7 +1473,7 @@ table_mm_fill_answer_block_shortcut(_) :- :- pragma foreign_proc("C", table_mmos_return_answer(Generator::in, AnswerBlock::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " /* MR_tbl_mmos_return_answer(Generator, AnswerBlock); @@ -1497,7 +1482,7 @@ table_mm_fill_answer_block_shortcut(_) :- :- pragma foreign_proc("C", table_mmos_completion(Generator::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " /* MR_tbl_mmos_completion(Generator); @@ -1512,11 +1497,6 @@ table_mmos_setup_consumer(_, _, Consumer) :- % Required only to avoid warnings; never executed. pretend_to_generate_value(Consumer). -table_mmos_get_answer_table(_, TrieNode) :- - semipure private_builtin.semip, - % Required only to avoid warnings; never executed. - pretend_to_generate_value(TrieNode). - table_mmos_create_answer_block(_, _, AnswerBlock) :- impure private_builtin.imp, % Required only to avoid warnings; never executed. @@ -1714,14 +1694,14 @@ MR_DECLARE_TYPE_CTOR_INFO_STRUCT(MR_TYPE_CTOR_INFO_NAME(io, state, 0)); :- pragma foreign_proc("C", table_lookup_insert_int(T0::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_int(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, V, T); "). :- pragma foreign_proc("C", table_lookup_insert_start_int(T0::in, S::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_start_int(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, S, V, T); @@ -1729,28 +1709,28 @@ MR_DECLARE_TYPE_CTOR_INFO_STRUCT(MR_TYPE_CTOR_INFO_NAME(io, state, 0)); :- pragma foreign_proc("C", table_lookup_insert_char(T0::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_char(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, V, T); "). :- pragma foreign_proc("C", table_lookup_insert_string(T0::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_string(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, V, T); "). :- pragma foreign_proc("C", table_lookup_insert_float(T0::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_float(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, V, T); "). :- pragma foreign_proc("C", table_lookup_insert_enum(T0::in, R::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_enum(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, R, V, T); @@ -1758,7 +1738,7 @@ MR_DECLARE_TYPE_CTOR_INFO_STRUCT(MR_TYPE_CTOR_INFO_NAME(io, state, 0)); :- pragma foreign_proc("C", table_lookup_insert_user(T0::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_user(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, TypeInfo_for_T, V, T); @@ -1766,7 +1746,7 @@ MR_DECLARE_TYPE_CTOR_INFO_STRUCT(MR_TYPE_CTOR_INFO_NAME(io, state, 0)); :- pragma foreign_proc("C", table_lookup_insert_user_fast_loose(T0::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_user_addr(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, TypeInfo_for_T, V, T); @@ -1774,7 +1754,7 @@ MR_DECLARE_TYPE_CTOR_INFO_STRUCT(MR_TYPE_CTOR_INFO_NAME(io, state, 0)); :- pragma foreign_proc("C", table_lookup_insert_poly(T0::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_poly(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, TypeInfo_for_T, V, T); @@ -1782,7 +1762,7 @@ MR_DECLARE_TYPE_CTOR_INFO_STRUCT(MR_TYPE_CTOR_INFO_NAME(io, state, 0)); :- pragma foreign_proc("C", table_lookup_insert_poly_fast_loose(T0::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_poly_addr(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, TypeInfo_for_T, V, T); @@ -1790,14 +1770,14 @@ MR_DECLARE_TYPE_CTOR_INFO_STRUCT(MR_TYPE_CTOR_INFO_NAME(io, state, 0)); :- pragma foreign_proc("C", table_lookup_insert_typeinfo(T0::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_typeinfo(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, V, T); "). :- pragma foreign_proc("C", table_lookup_insert_typeclassinfo(T0::in, V::in, T::out), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_lookup_insert_typeclassinfo(NULL, MR_TABLE_DEBUG_BOOL, MR_FALSE, T0, V, T); @@ -1807,42 +1787,42 @@ MR_DECLARE_TYPE_CTOR_INFO_STRUCT(MR_TYPE_CTOR_INFO_NAME(io, state, 0)); :- pragma foreign_proc("C", table_save_int_answer(AB::in, Offset::in, V::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_save_int_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). :- pragma foreign_proc("C", table_save_char_answer(AB::in, Offset::in, V::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_save_char_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). :- pragma foreign_proc("C", table_save_string_answer(AB::in, Offset::in, V::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_save_string_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). :- pragma foreign_proc("C", table_save_float_answer(AB::in, Offset::in, V::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_save_float_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). :- pragma foreign_proc("C", table_save_io_state_answer(AB::in, Offset::in, V::ui), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_save_io_state_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). :- pragma foreign_proc("C", table_save_any_answer(AB::in, Offset::in, V::in), - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_tbl_save_any_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, TypeInfo_for_T, V); @@ -1850,42 +1830,42 @@ MR_DECLARE_TYPE_CTOR_INFO_STRUCT(MR_TYPE_CTOR_INFO_NAME(io, state, 0)); :- pragma foreign_proc("C", table_restore_int_answer(AB::in, Offset::in, V::out), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_restore_int_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). :- pragma foreign_proc("C", table_restore_char_answer(AB::in, Offset::in, V::out), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_restore_char_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). :- pragma foreign_proc("C", table_restore_string_answer(AB::in, Offset::in, V::out), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_restore_string_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). :- pragma foreign_proc("C", table_restore_float_answer(AB::in, Offset::in, V::out), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_restore_float_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). :- pragma foreign_proc("C", table_restore_io_state_answer(AB::in, Offset::in, V::uo), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_restore_io_state_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). :- pragma foreign_proc("C", table_restore_any_answer(AB::in, Offset::in, V::out), - [will_not_call_mercury, promise_semipure], + [will_not_call_mercury, promise_semipure, does_not_affect_liveness], " MR_tbl_restore_any_answer(MR_TABLE_DEBUG_BOOL, AB, Offset, V); "). @@ -1895,7 +1875,7 @@ table_error(Message) :- :- pragma foreign_proc("C", table_report_statistics, - [will_not_call_mercury], + [will_not_call_mercury, does_not_affect_liveness], " MR_table_report_statistics(stderr); "). diff --git a/library/version_array.m b/library/version_array.m index afcd1d4ec..2c08d754c 100644 --- a/library/version_array.m +++ b/library/version_array.m @@ -1,7 +1,7 @@ %-----------------------------------------------------------------------------% % vim: ts=4 sw=4 et tw=0 wm=0 ft=mercury %-----------------------------------------------------------------------------% -% Copyright (C) 2004-2006 The University of Melbourne. +% Copyright (C) 2004-2007 The University of Melbourne. % This file may only be copied under the terms of the GNU Library General % Public License - see the file COPYING.LIB in the Mercury distribution. % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 @@ -282,7 +282,8 @@ cmp_version_array_2(I, VAa, VAb, R) :- :- pragma foreign_proc("C", version_array.empty = (VA::out), - [will_not_call_mercury, promise_pure, will_not_modify_trail], + [will_not_call_mercury, promise_pure, will_not_modify_trail, + does_not_affect_liveness], " VA = MR_GC_NEW(struct ML_va); @@ -294,7 +295,8 @@ cmp_version_array_2(I, VAa, VAb, R) :- :- pragma foreign_proc("C", version_array.new(N::in, X::in) = (VA::out), - [will_not_call_mercury, promise_pure, will_not_modify_trail], + [will_not_call_mercury, promise_pure, will_not_modify_trail, + does_not_affect_liveness], " MR_Integer i; @@ -311,7 +313,8 @@ cmp_version_array_2(I, VAa, VAb, R) :- :- pragma foreign_proc("C", resize(VA0::in, N::in, X::in) = (VA::out), - [will_not_call_mercury, promise_pure, will_not_modify_trail], + [will_not_call_mercury, promise_pure, will_not_modify_trail, + does_not_affect_liveness], " MR_Integer i; MR_Integer size_VA0; @@ -337,8 +340,10 @@ cmp_version_array_2(I, VAa, VAb, R) :- resize(N, X, VA, resize(VA, N, X)). -:- pragma foreign_proc("C", size(VA::in) = (N::out), - [will_not_call_mercury, promise_pure, will_not_modify_trail], +:- pragma foreign_proc("C", + size(VA::in) = (N::out), + [will_not_call_mercury, promise_pure, will_not_modify_trail, + does_not_affect_liveness], " N = ML_va_size(VA); "). @@ -347,7 +352,8 @@ resize(N, X, VA, resize(VA, N, X)). :- pragma foreign_proc("C", get_if_in_range(VA::in, I::in, X::out), - [will_not_call_mercury, promise_pure, will_not_modify_trail], + [will_not_call_mercury, promise_pure, will_not_modify_trail, + does_not_affect_liveness], " SUCCESS_INDICATOR = ML_va_get(VA, I, &X); "). @@ -357,14 +363,16 @@ resize(N, X, VA, resize(VA, N, X)). :- pragma foreign_proc("C", set_if_in_range(VA0::in, I::in, X::in, VA::out), - [will_not_call_mercury, promise_pure, will_not_modify_trail], + [will_not_call_mercury, promise_pure, will_not_modify_trail, + does_not_affect_liveness], " SUCCESS_INDICATOR = ML_va_set(VA0, I, X, &VA); "). :- pragma foreign_proc("C", unsafe_rewind(VA0::in) = (VA::out), - [will_not_call_mercury, promise_pure, will_not_modify_trail], + [will_not_call_mercury, promise_pure, will_not_modify_trail, + does_not_affect_liveness], " VA = ML_va_rewind(VA0); "). diff --git a/tests/invalid/Mmakefile b/tests/invalid/Mmakefile index a36d1145d..4ec31f622 100644 --- a/tests/invalid/Mmakefile +++ b/tests/invalid/Mmakefile @@ -168,6 +168,7 @@ SINGLEMODULE= \ string_format_unknown \ tc_err1 \ tc_err2 \ + test_may_duplicate \ tricky_assert1 \ type_inf_loop \ type_loop \ diff --git a/tests/tabling/oota.m b/tests/tabling/oota.m index 81eb2716b..314b7e503 100644 --- a/tests/tabling/oota.m +++ b/tests/tabling/oota.m @@ -1,3 +1,5 @@ +% vim: ts=4 sw=4 et ft=mercury +% % Test taken from the XSB testsuite. % % Under local evaluation it results in: @@ -10,7 +12,6 @@ % % If d/4 is declared nondet, the program compiles without warnings, % but produces no answer when it executes. -% :- module oota. @@ -18,55 +19,85 @@ :- import_module io. -:- pred main(io::di, io::uo) is det. +:- pred main(io::di, io::uo) is cc_multi. :- implementation. -:- import_module std_util, int, list. +:- import_module benchmarking. +:- import_module int. +:- import_module list. +:- import_module maybe. +:- import_module std_util. +:- import_module string. +:- import_module unit. main(!IO) :- - ( d(Out) -> - io__write_string("D = ", !IO), - io__write_int(Out, !IO), - io__write_string("\n", !IO) - ; - io__write_string("failed\n", !IO) - ). + io.command_line_arguments(Args, !IO), + ( + Args = [Arg], + string.to_int(Arg, NumRepeatsPrime) + -> + NumRepeats = NumRepeatsPrime + ; + NumRepeats = 1 + ), + benchmark_det(benchmark_d, unit, MaybeD, NumRepeats, Time), + trace [compiletime(flag("benchmark_oota")), io(!S)] ( + io.format("time taken: %d ms\n", [i(Time)], !S) + ), + ( + MaybeD = yes(D), + io.write_string("D = ", !IO), + io.write_int(D, !IO), + io.write_string("\n", !IO) + ; + MaybeD = no, + io.write_string("failed\n", !IO) + ). + +:- pred benchmark_d(unit::in, maybe(int)::out) is det. + +benchmark_d(unit, MaybeD) :- + ( d(D) -> + MaybeD = yes(D) + ; + MaybeD = no + ). :- pred d(int::out) is semidet. d(D) :- - GC = 10, I = 11, J = 9, - d(GC, I, J, D). + GC = 10, I = 11, J = 9, + d(GC, I, J, D). :- pred d(int::in, int::in, int::in, int::out) is semidet. :- pragma memo(d/4). d(GC, I, J, D) :- - ( I = 0, J = 0 -> - D = 0 - ; I = 0 -> - J1 = J - 1, - d(GC, 0, J1, D1), - D = D1 + GC - ; J = 0 -> - I1 = I - 1, - d(GC, I1, 0, D1), - D = D1 + GC - ; - I1 = I - 1, - J1 = J - 1, - ms(I, J, MS), - d(GC, I1,J1, D1), D_MS = D1 + MS, - d(GC, I1, J, D2), D_G1 = D2 + GC, - d(GC, I, J1, D3), D_G2 = D3 + GC, - min([D_MS, D_G1, D_G2], D) - ). + ( I = 0, J = 0 -> + D = 0 + ; I = 0 -> + J1 = J - 1, + d(GC, 0, J1, D1), + D = D1 + GC + ; J = 0 -> + I1 = I - 1, + d(GC, I1, 0, D1), + D = D1 + GC + ; + I1 = I - 1, + J1 = J - 1, + ms(I, J, MS), + d(GC, I1,J1, D1), D_MS = D1 + MS, + d(GC, I1, J, D2), D_G1 = D2 + GC, + d(GC, I, J1, D3), D_G2 = D3 + GC, + min([D_MS, D_G1, D_G2], D) + ). :- pred min(list(int)::in, int::out) is semidet. min(S, M) :- - list__sort(S, [M|_]). + list.sort(S, [M|_]). :- pred ms(int::in, int::in, int::out) is semidet.