Skip to content

Commit

Permalink
Close #82
Browse files Browse the repository at this point in the history
  • Loading branch information
travisdoor committed Dec 18, 2019
1 parent 0305c08 commit 2692e0f
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 30 deletions.
61 changes: 53 additions & 8 deletions src/ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,15 @@
#define NAMED_VARS false
#endif

typedef struct {
LLVMValueRef llvm_var;
MirType * type;
} RTTIIncomplete;

TSMALL_ARRAY_TYPE(LLVMValue, LLVMValueRef, 32);
TSMALL_ARRAY_TYPE(LLVMValue64, LLVMValueRef, 64);
TSMALL_ARRAY_TYPE(LLVMType, LLVMTypeRef, 32);
TSMALL_ARRAY_TYPE(RTTIIncomplete, RTTIIncomplete, 64);

typedef struct {
Assembly *assembly;
Expand All @@ -59,7 +65,8 @@ typedef struct {
/* Constants */
LLVMValueRef llvm_const_i64;

THashTable gstring_cache;
THashTable gstring_cache;
TSmallArray_RTTIIncomplete incomplete_rtti;

struct BuiltinTypes *builtin_types;
bool debug_mode;
Expand All @@ -68,6 +75,12 @@ typedef struct {
static LLVMValueRef
rtti_emit(Context *cnt, MirType *type);

static void
rtti_satisfy_incomplete(Context *cnt, RTTIIncomplete *incomplete);

static LLVMValueRef
_rtti_emit(Context *cnt, MirType *type);

static LLVMValueRef
rtti_emit_base(Context *cnt, MirType *type, u8 kind, usize size);

Expand Down Expand Up @@ -594,7 +607,7 @@ rtti_emit_enum(Context *cnt, MirType *type)
tsa_push_LLVMValue(&llvm_vals, emit_const_string(cnt, name, strlen(name)));

/* base_type */
tsa_push_LLVMValue(&llvm_vals, rtti_emit(cnt, type->data.enm.base_type));
tsa_push_LLVMValue(&llvm_vals, _rtti_emit(cnt, type->data.enm.base_type));

/* variants */
tsa_push_LLVMValue(&llvm_vals, rtti_emit_enum_variants_slice(cnt, type->data.enm.variants));
Expand Down Expand Up @@ -728,7 +741,7 @@ rtti_emit_struct_member(Context *cnt, MirMember *member)
emit_const_string(cnt, member->id->str, strlen(member->id->str)));

/* base_type */
tsa_push_LLVMValue(&llvm_vals, rtti_emit(cnt, member->type));
tsa_push_LLVMValue(&llvm_vals, _rtti_emit(cnt, member->type));

/* offset_bytes */
MirType *offset_type = mir_get_struct_elem_type(rtti_type, 2);
Expand Down Expand Up @@ -821,7 +834,7 @@ rtti_emit_fn(Context *cnt, MirType *type)
tsa_push_LLVMValue(&llvm_vals, rtti_emit_fn_args_slice(cnt, type->data.fn.args));

/* ret_type */
tsa_push_LLVMValue(&llvm_vals, rtti_emit(cnt, type->data.fn.ret_type));
tsa_push_LLVMValue(&llvm_vals, _rtti_emit(cnt, type->data.fn.ret_type));

/* is_vargs */
MirType *is_vargs_type = mir_get_struct_elem_type(rtti_type, 4);
Expand All @@ -848,7 +861,7 @@ rtti_emit_fn_arg(Context *cnt, MirArg *arg)
tsa_push_LLVMValue(&llvm_vals, emit_const_string(cnt, arg->id->str, strlen(arg->id->str)));

/* base_type */
tsa_push_LLVMValue(&llvm_vals, rtti_emit(cnt, arg->type));
tsa_push_LLVMValue(&llvm_vals, _rtti_emit(cnt, arg->type));

LLVMValueRef llvm_result =
LLVMConstNamedStruct(rtti_type->llvm_type, llvm_vals.data, (u32)llvm_vals.size);
Expand Down Expand Up @@ -975,7 +988,7 @@ rtti_emit_ptr(Context *cnt, MirType *type)
rtti_emit_base(cnt, base_type, type->kind, type->store_size_bytes));

/* pointee */
tsa_push_LLVMValue(&llvm_vals, rtti_emit(cnt, type->data.ptr.expr));
tsa_push_LLVMValue(&llvm_vals, _rtti_emit(cnt, type->data.ptr.expr));

LLVMValueRef llvm_result =
LLVMConstNamedStruct(rtti_type->llvm_type, llvm_vals.data, (u32)llvm_vals.size);
Expand All @@ -1000,7 +1013,7 @@ rtti_emit_array(Context *cnt, MirType *type)
tsa_push_LLVMValue(&llvm_vals, emit_const_string(cnt, name, strlen(name)));

/* elem_type */
tsa_push_LLVMValue(&llvm_vals, rtti_emit(cnt, type->data.array.elem_type));
tsa_push_LLVMValue(&llvm_vals, _rtti_emit(cnt, type->data.array.elem_type));

/* len */
MirType *len_type = mir_get_struct_elem_type(rtti_type, 3);
Expand All @@ -1018,6 +1031,33 @@ rtti_emit_array(Context *cnt, MirType *type)

LLVMValueRef
rtti_emit(Context *cnt, MirType *type)
{
LLVMValueRef llvm_value = _rtti_emit(cnt, type);

TSmallArray_RTTIIncomplete *pending = &cnt->incomplete_rtti;
while (pending->size) {
RTTIIncomplete incomplete = tsa_pop_RTTIIncomplete(pending);
rtti_satisfy_incomplete(cnt, &incomplete);
}

return llvm_value;
}

void
rtti_satisfy_incomplete(Context *cnt, RTTIIncomplete *incomplete)
{
MirType * type = incomplete->type;
LLVMValueRef llvm_rtti_var = incomplete->llvm_var;

BL_ASSERT(type->kind == MIR_TYPE_PTR);
LLVMValueRef llvm_value = rtti_emit_ptr(cnt, type);

BL_ASSERT(llvm_value);
LLVMSetInitializer(llvm_rtti_var, llvm_value);
}

LLVMValueRef
_rtti_emit(Context *cnt, MirType *type)
{
BL_ASSERT(type);
BL_ASSERT(assembly_has_rtti(cnt->assembly, type->id.hash));
Expand Down Expand Up @@ -1068,7 +1108,9 @@ rtti_emit(Context *cnt, MirType *type)
break;

case MIR_TYPE_PTR:
llvm_value = rtti_emit_ptr(cnt, type);
tsa_push_RTTIIncomplete(&cnt->incomplete_rtti,
(RTTIIncomplete){.llvm_var = llvm_rtti_var, .type = type});
goto SKIP;
break;

case MIR_TYPE_ARRAY:
Expand Down Expand Up @@ -1096,6 +1138,7 @@ rtti_emit(Context *cnt, MirType *type)

LLVMSetInitializer(llvm_rtti_var, llvm_value);

SKIP:
llvm_rtti_var = LLVMBuildCast(cnt->llvm_builder,
LLVMBitCast,
llvm_rtti_var,
Expand Down Expand Up @@ -2395,6 +2438,7 @@ ir_run(Assembly *assembly)
cnt.llvm_di_builder = assembly->llvm.di_builder;
cnt.debug_mode = builder.options.debug_build;
thtbl_init(&cnt.gstring_cache, sizeof(LLVMValueRef), 1024);
tsa_init(&cnt.incomplete_rtti);

MirInstr *ginstr;
TARRAY_FOREACH(MirInstr *, &assembly->MIR.global_instrs, ginstr)
Expand All @@ -2416,5 +2460,6 @@ ir_run(Assembly *assembly)

LLVMDisposeBuilder(cnt.llvm_builder);

tsa_terminate(&cnt.incomplete_rtti);
thtbl_terminate(&cnt.gstring_cache);
}
46 changes: 28 additions & 18 deletions src/mir.c
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,10 @@ static MirVar *
rtti_gen(Context *cnt, MirType *type);

static MirVar *
_rtti_gen(Context *cnt, MirType *type, MirVar *incomplete);
_rtti_gen(Context *cnt, MirType *type);

static void
rtti_satisfy_incomplete(Context *cnt, RTTIIncomplete *incomplete);

static MirVar *
rtti_gen_integer(Context *cnt, MirType *type);
Expand Down Expand Up @@ -6984,22 +6987,33 @@ analyze_report_unresolved(Context *cnt)
}
}

/* Top-level rtti generation. */
MirVar *
rtti_gen(Context *cnt, MirType *type)
{
MirVar *tmp = _rtti_gen(cnt, type, NULL);
MirVar *tmp = _rtti_gen(cnt, type);

TSmallArray_RTTIIncomplete *pending = &cnt->analyze.incomplete_rtti;
while (pending->size) {
const RTTIIncomplete incomplete = tsa_pop_RTTIIncomplete(pending);
_rtti_gen(cnt, incomplete.type, incomplete.var);
RTTIIncomplete incomplete = tsa_pop_RTTIIncomplete(pending);
rtti_satisfy_incomplete(cnt, &incomplete);
}

return tmp;
}

void
rtti_satisfy_incomplete(Context *cnt, RTTIIncomplete *incomplete)
{
MirType *type = incomplete->type;
MirVar * rtti_var = incomplete->var;

BL_ASSERT(type->kind == MIR_TYPE_PTR);
rtti_gen_ptr(cnt, type, rtti_var);
}

MirVar *
_rtti_gen(Context *cnt, MirType *type, MirVar *incomplete)
_rtti_gen(Context *cnt, MirType *type)
{
BL_ASSERT(type);
if (assembly_has_rtti(cnt->assembly, type->id.hash))
Expand Down Expand Up @@ -7043,13 +7057,9 @@ _rtti_gen(Context *cnt, MirType *type, MirVar *incomplete)
case MIR_TYPE_PTR:
/* We generate dummy pointer RTTI when incomplete is enabled and complete this in
* second pass to prove endless looping. */
if (!incomplete) {
rtti_var = rtti_gen_ptr(cnt, cnt->builtin_types->t_u8_ptr, NULL);
tsa_push_RTTIIncomplete(&cnt->analyze.incomplete_rtti,
(RTTIIncomplete){.var = rtti_var, .type = type});
} else {
rtti_var = rtti_gen_ptr(cnt, type, incomplete);
}
rtti_var = rtti_gen_ptr(cnt, cnt->builtin_types->t_u8_ptr, NULL);
tsa_push_RTTIIncomplete(&cnt->analyze.incomplete_rtti,
(RTTIIncomplete){.var = rtti_var, .type = type});
break;

case MIR_TYPE_ARRAY:
Expand Down Expand Up @@ -7155,7 +7165,7 @@ rtti_gen_ptr(Context *cnt, MirType *type, MirVar *incomplete)
VMStackPtr dest_pointee =
vm_get_struct_elem_ptr(cnt->assembly, cnt->builtin_types->t_TypeInfoPtr, dest, 1);

MirVar *pointee = _rtti_gen(cnt, type->data.ptr.expr, NULL);
MirVar *pointee = _rtti_gen(cnt, type->data.ptr.expr);
vm_write_ptr(dest_pointee_type, dest_pointee, vm_read_var(cnt->vm, pointee));

return rtti_var;
Expand All @@ -7178,7 +7188,7 @@ rtti_gen_array(Context *cnt, MirType *type)
MirType * dest_elem_type = mir_get_struct_elem_type(rtti_type, 2);
VMStackPtr dest_elem = vm_get_struct_elem_ptr(cnt->assembly, rtti_type, dest, 2);

MirVar *elem = _rtti_gen(cnt, type->data.array.elem_type, NULL);
MirVar *elem = _rtti_gen(cnt, type->data.array.elem_type);
vm_write_ptr(dest_elem_type, dest_elem, vm_read_var(cnt->vm, elem));

/* len */
Expand Down Expand Up @@ -7278,7 +7288,7 @@ rtti_gen_enum(Context *cnt, MirType *type)
MirType * dest_base_type_type = mir_get_struct_elem_type(rtti_type, 2);
VMStackPtr dest_base_type = vm_get_struct_elem_ptr(cnt->assembly, rtti_type, dest, 2);

MirVar *base_type = _rtti_gen(cnt, type->data.enm.base_type, NULL);
MirVar *base_type = _rtti_gen(cnt, type->data.enm.base_type);
vm_write_ptr(dest_base_type_type, dest_base_type, vm_read_var(cnt->vm, base_type));

/* variants */
Expand All @@ -7300,7 +7310,7 @@ rtti_gen_struct_member(Context *cnt, VMStackPtr dest, MirMember *member)
/* base_type */
MirType * dest_base_type_type = mir_get_struct_elem_type(rtti_type, 1);
VMStackPtr dest_base_type = vm_get_struct_elem_ptr(cnt->assembly, rtti_type, dest, 1);
MirVar * base_type = _rtti_gen(cnt, member->type, NULL);
MirVar * base_type = _rtti_gen(cnt, member->type);
vm_write_ptr(dest_base_type_type, dest_base_type, vm_read_var(cnt->vm, base_type));

/* offset_bytes */
Expand Down Expand Up @@ -7386,7 +7396,7 @@ rtti_gen_fn_arg(Context *cnt, VMStackPtr dest, MirArg *arg)
/* base_type */
MirType * dest_base_type_type = mir_get_struct_elem_type(rtti_type, 1);
VMStackPtr dest_base_type = vm_get_struct_elem_ptr(cnt->assembly, rtti_type, dest, 1);
MirVar * base_type = _rtti_gen(cnt, arg->type, NULL);
MirVar * base_type = _rtti_gen(cnt, arg->type);
vm_write_ptr(dest_base_type_type, dest_base_type, base_type->value.data);
}

Expand Down Expand Up @@ -7446,7 +7456,7 @@ rtti_gen_fn(Context *cnt, MirType *type)
/* ret_type */
MirType * dest_ret_type_type = mir_get_struct_elem_type(rtti_type, 3);
VMStackPtr dest_ret_type = vm_get_struct_elem_ptr(cnt->assembly, rtti_type, dest, 3);
MirVar * ret_type = _rtti_gen(cnt, type->data.fn.ret_type, NULL);
MirVar * ret_type = _rtti_gen(cnt, type->data.fn.ret_type);
vm_write_ptr(dest_ret_type_type, dest_ret_type, ret_type->value.data);

/* is_vargs */
Expand Down
14 changes: 10 additions & 4 deletions tests/test.bl
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
/* playground */

MyStruct :: struct {
v: *MyStruct;
}
#load "experimental/hash_table.bl"
#load "std/print.bl"

main :: fn () s32 {
info :: typeinfo(MyStruct);
info1 :: typeinfo(*HashTable);
info2 :: typeinfo(*u8);

if info1 == info2 {
print("FUCK!");
} else {
print("OK!");
}
return 0;
}

Expand Down

0 comments on commit 2692e0f

Please sign in to comment.