Skip to content

Commit

Permalink
Start working on ref
Browse files Browse the repository at this point in the history
  • Loading branch information
Victorious3 committed May 6, 2024
1 parent cb2ac85 commit 907831f
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 95 deletions.
2 changes: 1 addition & 1 deletion src/codegen.pr
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def type_to_str(tpe: &typechecking::Type) -> Str {
case 16; ret = "x86_fp80"
case; assert
}
case typechecking::TypeKind::POINTER
case typechecking::TypeKind::POINTER, typechecking::TypeKind::BYREF
if tpe.tpe and tpe.tpe.kind != typechecking::TypeKind::STRUCTURAL {
ret = type_to_str(tpe.tpe)
ret += '*'
Expand Down
65 changes: 27 additions & 38 deletions src/compiler.pr
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,7 @@ export def import_structures(tpe: &typechecking::Type, module: &toolchain::Modul
case typechecking::TypeKind::ARRAY,
typechecking::TypeKind::STATIC_ARRAY,
typechecking::TypeKind::POINTER,
typechecking::TypeKind::BYREF,
typechecking::TypeKind::REFERENCE,
typechecking::TypeKind::WEAK_REF
import_structures(tpe.tpe, module)
Expand Down Expand Up @@ -2168,8 +2169,8 @@ def convert_to(loc: &Value, value: Value, tpe: &typechecking::Type, state: &Stat
var unwrap = load_value(value, loc, state)
// Unwrap reference on the value side
if is_ref(value.tpe) {
let ref = state.extract_value(pointer(right), unwrap, [1], loc)
unwrap = state.load(right, ref, loc)
let _ref = state.extract_value(pointer(right), unwrap, [1], loc)
unwrap = state.load(right, _ref, loc)
}
// Extract element
var elem = state.extract_value(field.tpe, unwrap, [field.index !int], loc)
Expand Down Expand Up @@ -4080,8 +4081,8 @@ def walk_MemberAccess_struct(node: &parser::Node, tpe: &typechecking::Type, memb
let res = walk_MemberAccess_gep(node, tpe, member_type, value, index, state)

if member.is_embed and is_ref(member.tpe) {
let ref = state.load(member.tpe, @res.addr, loc)
let ptr = state.extract_value(pointer(member.tpe.tpe), ref, [1], loc)
let _ref = state.load(member.tpe, @res.addr, loc)
let ptr = state.extract_value(pointer(member.tpe.tpe), _ref, [1], loc)
return make_address_value(pointer(member.tpe.tpe), ptr, state)
}

Expand Down Expand Up @@ -4784,7 +4785,7 @@ export def walk_expression(node: &parser::Node, state: &State) -> Value {
}

if node.parent and node.parent.body and node.kind != parser::NodeKind::FUNC_CALL and node.kind != parser::NodeKind::ASSIGN and
expr.kind != ValueKind::NULL and expr.kind != ValueKind::ADDRESS and expr.tpe and expr.tpe.kind != typechecking::TypeKind::POINTER {
expr.kind != ValueKind::NULL and expr.kind != ValueKind::ADDRESS and expr.tpe and not is_pointer(expr.tpe) {

let loc = make_location(node, state)
let addr = state.alloca(expr.tpe, loc)
Expand Down Expand Up @@ -6628,9 +6629,9 @@ def di_ref_type(value: &Value, tpe: &typechecking::Type, is_weak: bool, state: &
fields(0) = [ name = "ref_count", tpe = typechecking::pointer(builtins::int64_) ] !StructMember
fields(1) = [ name = "value", tpe = typechecking::pointer(tpe.tpe) ] !StructMember
fields(2) = [ name = "tpe", tpe = typechecking::pointer(builtins::Type_) ] !StructMember
let ref = typechecking::make_struct_type(fields)
let _ref = typechecking::make_struct_type(fields)

return di_composite_type(value, ref, "<weak_ref>" if is_weak else "<ref>", "DW_TAG_structure_type", state)
return di_composite_type(value, _ref, "<weak_ref>" if is_weak else "<ref>", "DW_TAG_structure_type", state)
}

def di_type(tpe: &typechecking::Type, state: &State) -> &Value {
Expand Down Expand Up @@ -6689,7 +6690,7 @@ def di_type(tpe: &typechecking::Type, state: &State) -> &Value {
}
case typechecking::TypeKind::FUNCTION
@ditpe = @di_function_type(tpe, state)
case typechecking::TypeKind::POINTER
case typechecking::TypeKind::POINTER, typechecking::TypeKind::BYREF
@ditpe = @di_pointer_type(tpe, state)
case typechecking::TypeKind::REFERENCE, typechecking::TypeKind::WEAK_REF
@ditpe = @di_ref_type(ditpep, tpe, tpe.kind == typechecking::TypeKind::WEAK_REF, state)
Expand Down Expand Up @@ -8253,7 +8254,7 @@ def get_weak_count_ptr(value: Value, loc: &Value, state: &State) -> Value {

def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) {
if typechecking::is_polymorph(tpe) { return }
assert tpe.kind == typechecking::TypeKind::POINTER
assert is_pointer(tpe)

if tpe.tpe and tpe.tpe.kind == typechecking::TypeKind::TUNION {
let stpe = tpe.tpe
Expand Down Expand Up @@ -8299,28 +8300,16 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) {
}

var structure_type = tpe.tpe
var ref: Value
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)])
_ref = state.load(tpe.tpe, value)
ref_count = state.extract_value(pointer(ref_meta), ref, [0])
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)
null_br = make_insn(InsnKind::BR)
Expand Down Expand Up @@ -8351,13 +8340,13 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) {
var size = NO_VALUE
var data = NO_VALUE
if structure_type.kind == typechecking::TypeKind::ARRAY {
let array_ptr = state.extract_value(pointer(structure_type), ref, [1])
let array_ptr = state.extract_value(pointer(structure_type), _ref, [1])
let array = state.load(structure_type, array_ptr)
size = state.extract_value(builtins::size_t_, array, [0])
data = state.extract_value(pointer(structure_type.tpe), array, [1])
} else if structure_type.kind == typechecking::TypeKind::STATIC_ARRAY {
size = [ kind = ValueKind::INT, tpe = builtins::size_t_, i = structure_type.length ] !Value
data = state.extract_value(pointer(structure_type), ref, [1])
data = state.extract_value(pointer(structure_type), _ref, [1])
}

let counter_ptr = state.alloca(builtins::size_t_)
Expand Down Expand Up @@ -8409,10 +8398,10 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) {
var to_end = make_insn(InsnKind::BR_UNC)
var null_br2: &Insn = null
if typechecking::is_ref(tpe.tpe) and (not tpe.tpe.tpe or typechecking::is_interface(tpe.tpe.tpe)) {
let ref = state.load(tpe.tpe, value)
let _ref = state.load(tpe.tpe, value)

// Extract type
let ref_count = get_ref_count_ptr(ref, null, state)
let ref_count = state.extract_value(pointer(builtins::int64_), ref, [0])
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)
Expand All @@ -8425,7 +8414,7 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) {

let fp = unbox((builtins::Type_).field_types(15).tpe)

let ref_tpe = state.extract_value(pointer(builtins::Type_), ref, [2])
let ref_tpe = state.extract_value(pointer(builtins::Type_), _ref, [2])
let ref_tpe_deref = state.load(builtins::Type_, ref_tpe)
let dtor = state.extract_value(fp, ref_tpe_deref, [15])

Expand All @@ -8440,8 +8429,8 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) {
state.module.imported.add(destructor.tpe.type_name)

if typechecking::is_ref(tpe.tpe) {
let ref = state.load(tpe.tpe, value)
value = state.extract_value(pointer(structure_type), ref, [1])
let _ref = state.load(tpe.tpe, value)
value = state.extract_value(pointer(structure_type), _ref, [1])
}
state.call(destructor.tpe.type_name, null, [value])
}
Expand All @@ -8462,8 +8451,8 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) {

var obj: Value
if typechecking::is_ref(value.tpe.tpe) {
let ref = state.load(tpe.tpe, value)
obj = state.extract_value(pointer(structure_type), ref, [1])
let _ref = state.load(tpe.tpe, value)
obj = state.extract_value(pointer(structure_type), _ref, [1])
} else {
obj = value
}
Expand Down Expand Up @@ -8500,7 +8489,7 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) {
predeclare_function(fun, state.module)
state.module.imported.add(fun.type_name)
import_structure(builtins::Ref_, state.module)
state.call(fun.type_name, null, [convert_ref_to_ref(builtins::Ref_, ref, null, 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)
Expand All @@ -8515,14 +8504,14 @@ def create_destructor(tpe: &typechecking::Type, value: Value, state: &State) {
push_label(nonnull, state)
br2.value.br.if_false = nonnull

let cnt = get_weak_count_ptr(ref, null, state)
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)
state.store(cnt, cnt_value)

check_clear_ref_meta(ref_count, null, state)

value = state.extract_value(pointer(tpe.tpe.tpe), ref, [1])
value = state.extract_value(pointer(tpe.tpe.tpe), _ref, [1])

if tpe.tpe.tpe.kind == typechecking::TypeKind::ARRAY {
let array = state.load(tpe.tpe.tpe, value)
Expand Down Expand Up @@ -8705,7 +8694,7 @@ def push_enum_values(tpe: &typechecking::Type, global: Value, module: &toolchain
let svalue = tpe.scope.fields(key)

let name_values = allocate_ref(Value, 2)
name_values(0) = [ kind = ValueKind::INT, tpe = builtins::int64_, i = key.length() + 1 ] !Value
name_values(0) = [ kind = ValueKind::INT, tpe = builtins::int64_, i = key.length() + 1 ] !Value
name_values(1) = [ kind = ValueKind::UNDEF, tpe = pointer(builtins::int8_) ] !Value

let eval_values = allocate_ref(Value, 2)
Expand Down
3 changes: 3 additions & 0 deletions src/consteval.pr
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ export def walk_Def(node: &parser::Node, state: &typechecking::State) {
tpe.type_name = tpe.name = scope::last_path_element(param.value.param.name)
} else {
tpe = typechecking::type_lookup(param.value.param.tpe, state, null, true)
if param.value.param.is_ref {
tpe = typechecking::byref(tpe)
}
}

var value: &compiler::Value
Expand Down
2 changes: 1 addition & 1 deletion src/debug.pr
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ export def type_to_str(tpe: &typechecking::Type, full_name: bool = false) -> Str
return function_t_to_string(tpe, full_name)
case typechecking::TypeKind::TUPLE
return tuple_t_to_string(tpe, full_name)
case typechecking::TypeKind::POINTER
case typechecking::TypeKind::POINTER, typechecking::TypeKind::BYREF
return pointer_t_to_string(tpe, full_name)
case typechecking::TypeKind::REFERENCE
return reference_t_to_string(tpe, full_name)
Expand Down
4 changes: 2 additions & 2 deletions src/eval.pr
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export def get(mem: *, tpe: &typechecking::Type) -> compiler::Value {
return [ kind = compiler::ValueKind::FLOAT, tpe = tpe, f = result ] !compiler::Value
case typechecking::TypeKind::BOOL
return [ kind = compiler::ValueKind::BOOL, tpe = tpe, i = (@(mem !*bool)) !int64 ] !compiler::Value
case typechecking::TypeKind::POINTER
case typechecking::TypeKind::POINTER, typechecking::TypeKind::BYREF
return [ kind = compiler::ValueKind::POINTER, tpe = tpe, i = @(mem !*int64) ] !compiler::Value
case typechecking::TypeKind::REFERENCE, typechecking::TypeKind::WEAK_REF
let values = allocate_ref(compiler::Value, 3)
Expand Down Expand Up @@ -271,7 +271,7 @@ def set(mem: *, tpe: &typechecking::Type, value: compiler::Value) {
} else {
assert(false)
}
case typechecking::TypeKind::POINTER
case typechecking::TypeKind::POINTER, typechecking::TypeKind::BYREF
(@(mem !*int64)) = value.i
case typechecking::TypeKind::REFERENCE, typechecking::TypeKind::WEAK_REF
@(mem !*int64) = value.values(0).i
Expand Down
4 changes: 3 additions & 1 deletion src/lexer.pr
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export type TokenType = enum {
K_TYPE_OF
K_UNDEF
K_WEAK_REF
K_REF
INTEGER
FLOAT
STRING
Expand Down Expand Up @@ -225,7 +226,8 @@ let KEYWORDS = [
[token_type = TokenType::K_TYPE_OF, str = "type_of"] !Keyword,
[token_type = TokenType::K_WEAK_REF, str = "weak_ref"] !Keyword,
[token_type = TokenType::K_YIELD, str = "yield"] !Keyword,
[token_type = TokenType::K_IMPLICIT, str = "implicit"] !Keyword
[token_type = TokenType::K_IMPLICIT, str = "implicit"] !Keyword,
[token_type = TokenType::K_REF, str = "ref"] !Keyword
]

export def token_list_to_json(list: *TokenList) -> &Json {
Expand Down
17 changes: 13 additions & 4 deletions src/parser.pr
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ export type NodeParam = struct {
name: &Node
tpe: &Node
value: &Node
is_ref: bool
}

export type NodeImportModule = struct {
Expand Down Expand Up @@ -1896,10 +1897,10 @@ def expect_weak_ref(parse_state: &ParseState, inline_types: bool) -> &Node {
return node
}

def expect_ptr_ref(parse_state: &ParseState, ref: bool, inline_types: bool) -> &Node {
def expect_ptr_ref(parse_state: &ParseState, _ref: bool, inline_types: bool) -> &Node {
var kind: NodeKind
var tok: lexer::Token
if ref {
if _ref {
kind = NodeKind::REF_T
tok = expect(parse_state, lexer::TokenType::OP_BAND, "Expected '&'")
} else {
Expand Down Expand Up @@ -3368,6 +3369,13 @@ def parse_def(parse_state: &ParseState, share: ShareMarker, impl: bool = false)
var name: &Node = null
var tpe: &Node = null
var value: &Node = null
var is_ref = false

if token.tpe == lexer::TokenType::K_REF {
pop(parse_state)
is_ref = true
token = peek(parse_state)
}

if token.tpe == lexer::TokenType::OP_VARARGS {
if varargs {
Expand Down Expand Up @@ -3429,9 +3437,10 @@ def parse_def(parse_state: &ParseState, share: ShareMarker, impl: bool = false)
kw = kw,
name = name,
tpe = tpe,
value = value
value = value,
is_ref = is_ref
] !NodeParam
param._hash = combine_hashes(param.kind !uint64, varargs !uint64, kw !uint64, hash(name), hash(tpe), hash(value))
param._hash = combine_hashes(param.kind !uint64, varargs !uint64, kw !uint64, is_ref !uint64, hash(name), hash(tpe), hash(value))

params.push(param)

Expand Down
2 changes: 1 addition & 1 deletion src/scope.pr
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ export def generate_function(scope: &Scope, node: &parser::Node, parameter_t: &V
module.dyn_dispatch_consteval.push(tpe)

return value
} else if vector::length(parameter_t) == 1 and first_parameter.tpe.kind == typechecking::TypeKind::POINTER and
} else if vector::length(parameter_t) == 1 and is_pointer(first_parameter.tpe) and
name == "__destruct__" and typechecking::has_destructor(first_parameter.tpe.tpe) {

let args = vector::make(typechecking::NamedParameter)
Expand Down
Loading

0 comments on commit 907831f

Please sign in to comment.