diff --git a/src/compiler.pr b/src/compiler.pr index 71974db..b09dd88 100644 --- a/src/compiler.pr +++ b/src/compiler.pr @@ -600,6 +600,7 @@ export type State = struct { return_address: Value // This is used as the return address in inline functions return_br: &Insn // This is used to jump back to the end of the function inline_start_block: &Block // This represents the first block of the current function + context_ptr: int // Counts up the current free_context } export def destruct(state: *State) { @@ -1544,7 +1545,7 @@ def convert_ref_to_ptr(tpe: &typechecking::Type, value: Value, loc: &Value, stat // Reference metadata struct var _ref_meta: &typechecking::Type -def ref_meta -> &typechecking::Type { +export def ref_meta -> &typechecking::Type { if not _ref_meta { _ref_meta = typechecking::make_struct_type([ [ tpe = builtins::int64_, name = "refcount" ] !typechecking::StructMember, @@ -3616,9 +3617,13 @@ def copy_reference(value: Value, loc: &Value, state: &State) -> Value { let size = [ kind = ValueKind::INT, tpe = builtins::int64_, i = value.tpe.tpe.size ] !Value let size_int64 = [ kind = ValueKind::INT, tpe = builtins::int64_, i = builtins::int64_.size ] !Value - let ref_count_ptr_i8 = state.call("malloc", pointer(builtins::int8_), [size_int64], loc) - let ref_count_ptr = state.bitcast(pointer(builtins::int64_), ref_count_ptr_i8) - state.store(ref_count_ptr, [ kind = ValueKind::INT, tpe = builtins::int64_, i = 0 ] !Value) + let ref_count_i8 = state.call("malloc", pointer(builtins::int8_), [[ kind = ValueKind::INT, tpe = builtins::size_t_, i = ref_meta().size ] !Value]) + let ref_count = state.bitcast(pointer(ref_meta()), ref_count_i8) + state.store(ref_count, [ kind = ValueKind::STRUCT, tpe = ref_meta(), values = [ + [kind = ValueKind::INT, tpe = builtins::int64_, i = 0 ] !Value, + [kind = ValueKind::INT, tpe = builtins::int64_, i = 1 ] !Value + ]] !Value) + let value_ptr = state.extract_value(pointer(value.tpe.tpe), value, [1], loc) let type_ptr = state.extract_value(pointer(builtins::Type_), value, [2], loc) @@ -3628,7 +3633,7 @@ def copy_reference(value: Value, loc: &Value, state: &State) -> Value { let copy_ptr = state.bitcast(pointer(value.tpe.tpe), copy_ptr_i8, loc) var ret = [ kind = ValueKind::UNDEF, tpe = value.tpe ] !Value - ret = state.insert_value(value.tpe, ret, ref_count_ptr, [0], loc) + ret = state.insert_value(value.tpe, ret, ref_count_i8, [0], loc) ret = state.insert_value(value.tpe, ret, copy_ptr, [1], loc) ret = state.insert_value(value.tpe, ret, type_ptr, [2], loc) @@ -7653,9 +7658,10 @@ export def create_function( let parameter_t2 = vector::make(typechecking::NamedParameter) parameter_t2.push([ name = "__context", _tpe = typechecking::pointer(null) ] !typechecking::NamedParameter) - let free_context_tpe = typechecking::make_function_type_n(parser::make_identifier(tpe.name + ".free_context"), - free_context_parameters, vector::make(type &typechecking::Type), state.module, context = state.module + let free_context_tpe = typechecking::make_function_type_n(parser::make_identifier(tpe.name + ".free_context." + state.context_ptr), + free_context_parameters, vector::make(type &typechecking::Type), state.module, context = function.module ) + state.context_ptr += 1 let free_context = predeclare_function(free_context_tpe, state.module) free_context.is_compiled = true @@ -8296,11 +8302,24 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) { var ref: Value var ref_count: Value var null_br: &Insn, br: &Insn + var br1: &Insn if typechecking::is_ref(tpe.tpe) and tpe.tpe.tpe and not is_interface(tpe.tpe.tpe) { // Decrease ref count ref = state.load(tpe.tpe, value) ref_count = state.extract_value(pointer(ref_meta()), ref, [0]) + let ref_count_value1 = state.ptr_to_int(ref_count) + + let isnull = state.icmp(CompareInt::eq, ref_count_value1, + [ kind = ValueKind::INT, tpe = builtins::int64_, i = 0 ] !Value) + + br1 = make_insn(InsnKind::BR) + br1.value.br = [ cond = isnull ] !InsnBr + push_insn(br1, state) + let nonnull = make_label(state) + push_label(nonnull, state) + br1.value.br.if_false = nonnull + let ref_count_ptr = state.gep(pointer(builtins::int64_), ref_meta(), ref_count, [make_int_value(0), make_int_value(0)]) let ref_count_value = state.ptr_to_int(ref_count_ptr) let null_cond = state.icmp(CompareInt::eq, ref_count_value, [ kind = ValueKind::INT, tpe = builtins::int64_, i = 0 ] !Value) @@ -8393,7 +8412,7 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) { let ref = state.load(tpe.tpe, value) // Extract type - let ref_count = state.extract_value(pointer(builtins::int64_), ref, [0]) + let ref_count = get_ref_count_ptr(ref, null, state) let ref_count_value = state.ptr_to_int(ref_count) let cond = state.icmp(CompareInt::eq, ref_count_value, [ kind = ValueKind::INT, tpe = builtins::int64_, i = 0 ] !Value) null_br2 = make_insn(InsnKind::BR) @@ -8484,6 +8503,18 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) { state.call(fun.type_name, null, [convert_ref_to_ref(builtins::Ref_, ref, null, state)]) } + let ref_count_value1 = state.ptr_to_int(ref_count) + + let isnull = state.icmp(CompareInt::eq, ref_count_value1, + [ kind = ValueKind::INT, tpe = builtins::int64_, i = 0 ] !Value) + + let br2 = make_insn(InsnKind::BR) + br2.value.br = [ cond = isnull ] !InsnBr + push_insn(br2, state) + let nonnull = make_label(state) + push_label(nonnull, state) + br2.value.br.if_false = nonnull + let cnt = get_weak_count_ptr(ref, null, state) var cnt_value = state.load(builtins::int64_, cnt) cnt_value = state.sub(builtins::int64_, cnt_value, [ kind = ValueKind::INT, tpe = builtins::int64_, i = 1 ] !Value) @@ -8510,6 +8541,9 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) { to_end.value.br_unc.label_ = end_label br.value.br.if_false = end_label null_br.value.br.if_true = end_label + br1.value.br.if_true = end_label + br2.value.br.if_true = end_label + push_label(end_label, state) } } diff --git a/src/repl.pr b/src/repl.pr index d9c9f18..a744754 100644 --- a/src/repl.pr +++ b/src/repl.pr @@ -442,7 +442,7 @@ def execute(source: Str) { stack_frame = eval::make_stack_frame(main_function.block, "main", 1) - let mem = allocate(size_of type *) !** + let mem = allocate(16) !** // FIXME What are we doing here??? @mem = (*_args) !* stack_frame.locals("args.value") = mem diff --git a/src/runtime.pr b/src/runtime.pr index fbddf30..cf15caf 100644 --- a/src/runtime.pr +++ b/src/runtime.pr @@ -89,8 +89,13 @@ export type Field = struct { tpe: *Type } +export type Refcount = struct { + strong_cnt: int64 + weak_cnt: int64 +} + export type Ref = struct { - ref_count: *int64 + ref_count: *Refcount value: * tpe: *Type }