diff --git a/compiler/src/codegen/compcore.re b/compiler/src/codegen/compcore.re index f5297b843..397346d50 100644 --- a/compiler/src/codegen/compcore.re +++ b/compiler/src/codegen/compcore.re @@ -59,8 +59,6 @@ let runtime_heap_next_ptr_name = Ident.unique_name(Ident.create_persistent("runtimeHeapNextPtr")); let metadata_ptr_name = Ident.unique_name(Ident.create_persistent("metadataPtr")); -let reloc_base_name = - Ident.unique_name(Ident.create_persistent("relocBase")); /* Memory allocation */ let malloc_name = Ident.unique_name(Ident.create_persistent("malloc")); @@ -658,8 +656,9 @@ let heap_allocate = (wasm_mod, env, num_words: int) => runtime_heap_next_ptr_name, Type.int32, ), - // fake GC refcount of 1 - Expression.Const.make(wasm_mod, const_int32(1)), + // fake GC refcount of 2 + // this means objects (should) never drop to zero refcount + Expression.Const.make(wasm_mod, const_int32(2)), ), Expression.Binary.make( wasm_mod, @@ -1158,7 +1157,7 @@ let compile_record_op = (wasm_mod, env, rec_imm, op) => { let compile_closure_op = (wasm_mod, env, closure_imm, op) => { let closure = () => compile_imm(wasm_mod, env, closure_imm); switch (op) { - | MClosureSetPtr(idx) => + | MClosureSetPtr(global_offset, idx) => store( ~offset=8, wasm_mod, @@ -1166,7 +1165,11 @@ let compile_closure_op = (wasm_mod, env, closure_imm, op) => { Expression.Binary.make( wasm_mod, Op.add_int32, - Expression.Global_get.make(wasm_mod, reloc_base_name, Type.int32), + Expression.Global_get.make( + wasm_mod, + linked_name(~env, global_offset), + Type.int32, + ), Expression.Const.make(wasm_mod, wrap_int32(idx)), ), ) diff --git a/compiler/src/codegen/mashtree.re b/compiler/src/codegen/mashtree.re index 0c712111b..3a208c927 100644 --- a/compiler/src/codegen/mashtree.re +++ b/compiler/src/codegen/mashtree.re @@ -424,7 +424,7 @@ type record_op = [@deriving sexp] type closure_op = - | MClosureSetPtr(int32); + | MClosureSetPtr(string, int32); [@deriving sexp] type instr = { diff --git a/compiler/src/codegen/transl_anf.re b/compiler/src/codegen/transl_anf.re index 0fa9f1068..8ceab4a9a 100644 --- a/compiler/src/codegen/transl_anf.re +++ b/compiler/src/codegen/transl_anf.re @@ -765,7 +765,10 @@ let lift_imports = (env, imports) => { { instr_desc: MClosureOp( - MClosureSetPtr(Int32.of_int(idx)), + MClosureSetPtr( + get_function_table_global_name(), + Int32.of_int(idx), + ), imm( MImmBinding( MGlobalBind( diff --git a/compiler/src/compile.re b/compiler/src/compile.re index 7a314f459..27887dd4a 100644 --- a/compiler/src/compile.re +++ b/compiler/src/compile.re @@ -149,6 +149,7 @@ let next_state = (~is_root_file=false, {cstate_desc, cstate_filename} as cs) => Grain_utils.Config.apply_attribute_flags( ~no_pervasives=has_attr("noPervasives"), ~runtime_mode=has_attr("runtimeMode"), + ~no_exception_mod=has_attr("exceptionMod"), ); Well_formedness.check_well_formedness(p); diff --git a/compiler/src/parsing/driver.re b/compiler/src/parsing/driver.re index dcfa1612a..e6e600da3 100644 --- a/compiler/src/parsing/driver.re +++ b/compiler/src/parsing/driver.re @@ -161,6 +161,7 @@ let read_imports = (program: Parsetree.parsed_program) => { Grain_utils.Config.with_attribute_flags( ~no_pervasives=module_has_attr("noPervasives"), ~runtime_mode=module_has_attr("runtimeMode"), + ~no_exception_mod=module_has_attr("exceptionMod"), Grain_utils.Config.get_implicit_opens, ), ); diff --git a/compiler/src/parsing/well_formedness.re b/compiler/src/parsing/well_formedness.re index 103edf655..8eb34e8a7 100644 --- a/compiler/src/parsing/well_formedness.re +++ b/compiler/src/parsing/well_formedness.re @@ -402,6 +402,7 @@ let disallowed_attributes = (errs, super) => { let known_module_attributes = [ {name: "runtimeMode", arity: 0}, {name: "noPervasives", arity: 0}, + {name: "exceptionMod", arity: 0}, ]; validate_against_known(attributes, known_module_attributes, "module"); super.enter_parsed_program(prog); diff --git a/compiler/src/utils/config.re b/compiler/src/utils/config.re index 2f41324a0..252e82221 100644 --- a/compiler/src/utils/config.re +++ b/compiler/src/utils/config.re @@ -411,6 +411,8 @@ type compilation_mode = let compilation_mode = internal_opt(Normal, NotDigestible); +let no_exception_mod = internal_opt(false, NotDigestible); + let statically_link = toggle_flag( ~names=["no-link"], @@ -566,7 +568,8 @@ let module_search_path = () => { }; }; -let apply_attribute_flags = (~no_pervasives as np, ~runtime_mode as rm) => { +let apply_attribute_flags = + (~no_pervasives as np, ~runtime_mode as rm, ~no_exception_mod as ne) => { // Only apply options if attributes were explicitly given so as to not // unintentionally override options set previously e.g. compiling a // wasi-polyfill file in non-runtime-mode if @runtimeMode is not specified @@ -576,11 +579,15 @@ let apply_attribute_flags = (~no_pervasives as np, ~runtime_mode as rm) => { if (rm) { compilation_mode := Runtime; }; + if (ne) { + no_exception_mod := true; + }; }; -let with_attribute_flags = (~no_pervasives, ~runtime_mode, thunk) => { +let with_attribute_flags = + (~no_pervasives, ~runtime_mode, ~no_exception_mod, thunk) => { preserve_config(() => { - apply_attribute_flags(~no_pervasives, ~runtime_mode); + apply_attribute_flags(~no_pervasives, ~runtime_mode, ~no_exception_mod); thunk(); }); }; @@ -611,11 +618,13 @@ let get_implicit_opens = () => { if (compilation_mode^ == Runtime) { []; } else { + let ret = + if (no_exception_mod^) { + ret; + } else { + [Exception_mod, ...ret]; + }; // Pervasives goes first, just for good measure. - List.rev([ - Gc_mod, - Exception_mod, - ...ret, - ]); + List.rev([Gc_mod, ...ret]); }; }; diff --git a/compiler/src/utils/config.rei b/compiler/src/utils/config.rei index 7ea10bcee..c67c7ed79 100644 --- a/compiler/src/utils/config.rei +++ b/compiler/src/utils/config.rei @@ -184,10 +184,17 @@ let with_cli_options: 'a => Cmdliner.Term.t('a); /** Applies compile flags provided as module attributes */ -let apply_attribute_flags: (~no_pervasives: bool, ~runtime_mode: bool) => unit; +let apply_attribute_flags: + (~no_pervasives: bool, ~runtime_mode: bool, ~no_exception_mod: bool) => unit; let with_attribute_flags: - (~no_pervasives: bool, ~runtime_mode: bool, unit => 'a) => 'a; + ( + ~no_pervasives: bool, + ~runtime_mode: bool, + ~no_exception_mod: bool, + unit => 'a + ) => + 'a; type implicit_opens = | Pervasives_mod diff --git a/compiler/test/suites/basic_functionality.re b/compiler/test/suites/basic_functionality.re index e29f856d9..1dd539339 100644 --- a/compiler/test/suites/basic_functionality.re +++ b/compiler/test/suites/basic_functionality.re @@ -377,6 +377,6 @@ describe("basic functionality", ({test, testSkip}) => { ~config_fn=smallestFileConfig, "smallest_grain_program", "", - 6829, + 6417, ); }); diff --git a/stdlib/exception.gr b/stdlib/exception.gr index bdd9a4958..da33b8663 100644 --- a/stdlib/exception.gr +++ b/stdlib/exception.gr @@ -12,8 +12,6 @@ */ module Exception -from "runtime/unsafe/wasmi32" include WasmI32 -from "runtime/unsafe/memory" include Memory from "runtime/exception" include Exception /** diff --git a/stdlib/runtime/exception.gr b/stdlib/runtime/exception.gr index 483d957ba..d5701b779 100644 --- a/stdlib/runtime/exception.gr +++ b/stdlib/runtime/exception.gr @@ -1,4 +1,5 @@ @noPervasives +@exceptionMod module Exception from "runtime/unsafe/panic" include Panic