aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-09-07 14:03:17 +0100
committerGinger Bill <bill@gingerbill.org>2016-09-07 14:03:17 +0100
commit61fcfd6f3d3c6cffd7e610abab83445b4cd1950d (patch)
treef61e6d7be5f13c79ab3d98c76fcb836901b3c25e /src
parent455820fc8438ab72c963ef354b9e32f6e5af1e65 (diff)
Begin Type_Info
Missing stuff in records, procedures, and tuples
Diffstat (limited to 'src')
-rw-r--r--src/checker/checker.cpp55
-rw-r--r--src/checker/expr.cpp68
-rw-r--r--src/codegen/codegen.cpp164
-rw-r--r--src/codegen/print_llvm.cpp20
-rw-r--r--src/codegen/ssa.cpp110
-rw-r--r--src/main.cpp12
-rw-r--r--src/parser.cpp17
7 files changed, 343 insertions, 103 deletions
diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp
index 04b68eb9b..94917d7c7 100644
--- a/src/checker/checker.cpp
+++ b/src/checker/checker.cpp
@@ -150,6 +150,8 @@ enum BuiltinProcId {
BuiltinProc_max,
BuiltinProc_abs,
+ BuiltinProc_type_info,
+
BuiltinProc_Count,
};
struct BuiltinProc {
@@ -188,6 +190,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT("min"), 2, false, Expr_Expr},
{STR_LIT("max"), 2, false, Expr_Expr},
{STR_LIT("abs"), 1, false, Expr_Expr},
+
+ {STR_LIT("type_info"), 1, false, Expr_Expr},
};
struct CheckerContext {
@@ -197,13 +201,14 @@ struct CheckerContext {
// NOTE(bill): Symbol tables
struct CheckerInfo {
- Map<TypeAndValue> types; // Key: AstNode * | Expression -> Type (and value)
- Map<Entity *> definitions; // Key: AstNode * | Identifier -> Entity
- Map<Entity *> uses; // Key: AstNode * | Identifier -> Entity
- Map<Scope *> scopes; // Key: AstNode * | Node -> Scope
- Map<ExpressionInfo> untyped; // Key: AstNode * | Expression -> ExpressionInfo
- Map<DeclInfo *> entities; // Key: Entity *
- Map<Entity *> foreign_procs; // Key: String
+ Map<TypeAndValue> types; // Key: AstNode * | Expression -> Type (and value)
+ Map<Entity *> definitions; // Key: AstNode * | Identifier -> Entity
+ Map<Entity *> uses; // Key: AstNode * | Identifier -> Entity
+ Map<Scope *> scopes; // Key: AstNode * | Node -> Scope
+ Map<ExpressionInfo> untyped; // Key: AstNode * | Expression -> ExpressionInfo
+ Map<DeclInfo *> entities; // Key: Entity *
+ Map<Entity *> foreign_procs; // Key: String
+ Map<Type *> type_info_types; // Key: Type *
};
struct Checker {
@@ -383,6 +388,26 @@ void add_global_constant(gbAllocator a, String name, Type *type, ExactValue valu
add_global_entity(entity);
}
+
+Type *t_type_info = NULL;
+Type *t_type_info_ptr = NULL;
+
+Type *t_type_info_named = NULL;
+Type *t_type_info_integer = NULL;
+Type *t_type_info_float = NULL;
+Type *t_type_info_string = NULL;
+Type *t_type_info_boolean = NULL;
+Type *t_type_info_pointer = NULL;
+Type *t_type_info_procedure = NULL;
+Type *t_type_info_array = NULL;
+Type *t_type_info_slice = NULL;
+Type *t_type_info_vector = NULL;
+Type *t_type_info_struct = NULL;
+Type *t_type_info_union = NULL;
+Type *t_type_info_raw_union = NULL;
+Type *t_type_info_enum = NULL;
+
+
void init_universal_scope(void) {
// NOTE(bill): No need to free these
gbAllocator a = gb_heap_allocator();
@@ -425,13 +450,14 @@ void init_universal_scope(void) {
void init_checker_info(CheckerInfo *i) {
gbAllocator a = gb_heap_allocator();
- map_init(&i->types, a);
- map_init(&i->definitions, a);
- map_init(&i->uses, a);
- map_init(&i->scopes, a);
- map_init(&i->entities, a);
- map_init(&i->untyped, a);
- map_init(&i->foreign_procs, a);
+ map_init(&i->types, a);
+ map_init(&i->definitions, a);
+ map_init(&i->uses, a);
+ map_init(&i->scopes, a);
+ map_init(&i->entities, a);
+ map_init(&i->untyped, a);
+ map_init(&i->foreign_procs, a);
+ map_init(&i->type_info_types, a);
}
@@ -443,6 +469,7 @@ void destroy_checker_info(CheckerInfo *i) {
map_destroy(&i->entities);
map_destroy(&i->untyped);
map_destroy(&i->foreign_procs);
+ map_destroy(&i->type_info_types);
}
diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp
index eff3852ac..b8919c0bb 100644
--- a/src/checker/expr.cpp
+++ b/src/checker/expr.cpp
@@ -1900,6 +1900,42 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
return NULL;
}
+void add_type_info_type(Checker *c, Type *t) {
+ if (t == NULL) {
+ return;
+ }
+ t = default_type(t);
+ if (map_get(&c->info.type_info_types, hash_pointer(t)) != NULL) {
+ // Types have already been added
+ return;
+ }
+
+ map_set(&c->info.type_info_types, hash_pointer(t), t);
+ Type *bt = get_base_type(t);
+ switch (bt->kind) {
+ case Type_Named: add_type_info_type(c, bt->Named.base); break;
+ case Type_Array: add_type_info_type(c, bt->Array.elem); break;
+ case Type_Slice: add_type_info_type(c, bt->Slice.elem); break;
+ case Type_Vector: add_type_info_type(c, bt->Vector.elem); break;
+ case Type_Pointer: add_type_info_type(c, bt->Pointer.elem); break;
+ case Type_Record: {
+ switch (bt->Record.kind) {
+ case TypeRecord_Enum:
+ add_type_info_type(c, bt->Record.enum_base);
+ break;
+ default:
+ for (isize i = 0; i < bt->Record.field_count; i++) {
+ Entity *f = bt->Record.fields[i];
+ add_type_info_type(c, f->type);
+ }
+ break;
+ }
+ } break;
+ }
+ // TODO(bill): Type info for procedures and tuples
+ // TODO(bill): Remove duplicate identical types efficiently
+}
+
b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) {
GB_ASSERT(call->kind == AstNode_CallExpr);
ast_node(ce, CallExpr, call);
@@ -2652,6 +2688,38 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
operand->type = type;
} break;
+
+ case BuiltinProc_type_info: {
+ if (t_type_info == NULL) {
+ String type_info_str = make_string("Type_Info");
+ Entity **found = map_get(&c->global_scope->elements, hash_string(type_info_str));
+ GB_ASSERT_MSG(found != NULL, "Internal Compiler Error: Could not find type declaration for `Type_Info`");
+ Entity *e = *found;
+ t_type_info = e->type;
+ t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
+
+ auto *record = &get_base_type(e->type)->Record;
+ GB_ASSERT(record->field_count == 15);
+ t_type_info_named = record->fields[ 1]->type;
+ t_type_info_integer = record->fields[ 2]->type;
+ t_type_info_float = record->fields[ 3]->type;
+ t_type_info_string = record->fields[ 4]->type;
+ t_type_info_boolean = record->fields[ 5]->type;
+ t_type_info_pointer = record->fields[ 6]->type;
+ t_type_info_procedure = record->fields[ 7]->type;
+ t_type_info_array = record->fields[ 8]->type;
+ t_type_info_slice = record->fields[ 9]->type;
+ t_type_info_vector = record->fields[10]->type;
+ t_type_info_struct = record->fields[11]->type;
+ t_type_info_union = record->fields[12]->type;
+ t_type_info_raw_union = record->fields[13]->type;
+ t_type_info_enum = record->fields[14]->type;
+ }
+
+ add_type_info_type(c, operand->type);
+ operand->mode = Addressing_Value;
+ operand->type = t_type_info_ptr;
+ } break;
}
return true;
diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp
index 7ad1d56e2..5d8df5060 100644
--- a/src/codegen/codegen.cpp
+++ b/src/codegen/codegen.cpp
@@ -31,27 +31,6 @@ b32 ssa_gen_init(ssaGen *s, Checker *c) {
if (err != gbFileError_None)
return false;
-#if 0
- Map<i32> type_map; // Key: Type *
- map_init(&type_map, gb_heap_allocator());
- i32 index = 0;
- gb_for_array(i, c->info.types.entries) {
- TypeAndValue tav = c->info.types.entries[i].value;
- Type *type = tav.type;
- HashKey key = hash_pointer(type);
- auto found = map_get(&type_map, key);
- if (!found) {
- map_set(&type_map, key, index);
- index++;
- }
- }
- gb_for_array(i, type_map.entries) {
- auto *e = &type_map.entries[i];
- Type *t = cast(Type *)cast(uintptr)e->key.key;
- gb_printf("%s\n", type_to_string(t));
- }
-#endif
-
return true;
}
@@ -199,6 +178,149 @@ void ssa_gen_tree(ssaGen *s) {
}
}
+ { // NOTE(bill): Setup type_info data
+ ssaValue **found = map_get(&proc->module->members, hash_string(make_string("__type_info_data")));
+ GB_ASSERT(found != NULL);
+ ssaValue *type_info_data = *found;
+ CheckerInfo *info = proc->module->info;
+
+
+ Type *t_int_ptr = make_type_pointer(a, t_int);
+ Type *t_bool_ptr = make_type_pointer(a, t_bool);
+ Type *t_string_ptr = make_type_pointer(a, t_string);
+ Type *t_type_info_ptr_ptr = make_type_pointer(a, t_type_info_ptr);
+
+ auto get_type_info_ptr = [](ssaProcedure *proc, ssaValue *type_info_data, Type *type) -> ssaValue * {
+ auto *info = proc->module->info;
+ MapFindResult fr = map__find(&info->type_info_types, hash_pointer(type));
+ GB_ASSERT(fr.entry_index >= 0);
+ return ssa_emit_struct_gep(proc, type_info_data, fr.entry_index, t_type_info_ptr);
+ };
+
+
+ gb_for_array(entry_index, info->type_info_types.entries) {
+ auto *entry = &info->type_info_types.entries[entry_index];
+ Type *t = entry->value;
+
+ ssaValue *tag = NULL;
+
+ switch (t->kind) {
+ case Type_Named: {
+ tag = ssa_add_local_generated(proc, t_type_info_named);
+
+ ssaValue *gsa = ssa_add_global_string_array(proc, make_exact_value_string(t->Named.name));
+ ssaValue *elem = ssa_array_elem(proc, gsa);
+ ssaValue *len = ssa_array_len(proc, ssa_emit_load(proc, gsa));
+ ssaValue *name = ssa_emit_string(proc, elem, len);
+
+ ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Named.base);
+
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero, t_string_ptr), name);
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_type_info_ptr), gep);
+ } break;
+
+ case Type_Basic:
+ switch (t->Basic.kind) {
+ case Basic_bool:
+ tag = ssa_add_local_generated(proc, t_type_info_boolean);
+ break;
+ case Basic_i8:
+ case Basic_i16:
+ case Basic_i32:
+ case Basic_i64:
+ case Basic_i128:
+ case Basic_u8:
+ case Basic_u16:
+ case Basic_u32:
+ case Basic_u64:
+ case Basic_u128:
+ case Basic_int:
+ case Basic_uint: {
+ tag = ssa_add_local_generated(proc, t_type_info_integer);
+ b32 is_unsigned = (basic_types[t->Basic.kind].flags & BasicFlag_Unsigned) != 0;
+ ssaValue *bits = ssa_make_value_constant(a, t_int, make_exact_value_integer(8*type_size_of(m->sizes, a, t)));
+ ssaValue *is_signed = ssa_make_value_constant(a, t_bool, make_exact_value_bool(!is_unsigned));
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_int_ptr), bits);
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_bool_ptr), is_signed);
+ } break;
+
+ case Basic_f32:
+ case Basic_f64: {
+ tag = ssa_add_local_generated(proc, t_type_info_float);
+ ssaValue *bits = ssa_make_value_constant(a, t_int, make_exact_value_integer(8*type_size_of(m->sizes, a, t)));
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_int_ptr), bits);
+ } break;
+
+ case Basic_rawptr:
+ tag = ssa_add_local_generated(proc, t_type_info_pointer);
+ break;
+
+ case Basic_string:
+ tag = ssa_add_local_generated(proc, t_type_info_string);
+ break;
+ }
+ break;
+
+ case Type_Pointer: {
+ tag = ssa_add_local_generated(proc, t_type_info_pointer);
+ ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Pointer.elem);
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
+ } break;
+ case Type_Array: {
+ tag = ssa_add_local_generated(proc, t_type_info_array);
+ ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Array.elem);
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
+ } break;
+ case Type_Slice: {
+ tag = ssa_add_local_generated(proc, t_type_info_slice);
+ ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Slice.elem);
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
+ } break;
+ case Type_Vector: {
+ tag = ssa_add_local_generated(proc, t_type_info_vector);
+ ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Vector.elem);
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
+ } break;
+ case Type_Record: {
+ switch (t->Record.kind) {
+ // TODO(bill): Record members for `Type_Info`
+ case TypeRecord_Struct:
+ tag = ssa_add_local_generated(proc, t_type_info_struct);
+ break;
+ case TypeRecord_Union:
+ tag = ssa_add_local_generated(proc, t_type_info_union);
+ break;
+ case TypeRecord_RawUnion:
+ tag = ssa_add_local_generated(proc, t_type_info_raw_union);
+ break;
+ case TypeRecord_Enum: {
+ tag = ssa_add_local_generated(proc, t_type_info_enum);
+ Type *enum_base = t->Record.enum_base;
+ if (enum_base == NULL) {
+ enum_base = t_int;
+ }
+ ssaValue *gep = get_type_info_ptr(proc, type_info_data, enum_base);
+ ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
+ } break;
+ }
+ } break;
+
+ case Type_Tuple:
+ // TODO(bill): Type_Info for tuples
+ break;
+ case Type_Proc:
+ // TODO(bill): Type_Info for procedures
+ break;
+ }
+
+ if (tag != NULL) {
+ ssaValue *gep = ssa_emit_struct_gep(proc, type_info_data, entry_index, t_type_info_ptr);
+ ssaValue *val = ssa_emit_conv(proc, ssa_emit_load(proc, tag), t_type_info);
+ ssa_emit_store(proc, gep, val);
+ }
+ }
+ }
+
ssa_end_procedure_body(proc);
}
diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp
index fffdee805..c8dff6d6b 100644
--- a/src/codegen/print_llvm.cpp
+++ b/src/codegen/print_llvm.cpp
@@ -314,7 +314,7 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
void ssa_print_block_name(ssaFileBuffer *f, ssaBlock *b) {
ssa_print_escape_string(f, b->label, false);
- ssa_fprintf(f, "..%d", b->id);
+ ssa_fprintf(f, "-%d", b->id);
}
void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type_hint) {
@@ -352,7 +352,9 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
switch (instr->kind) {
case ssaInstr_StartupRuntime: {
- ssa_fprintf(f, "call void @." SSA_STARTUP_RUNTIME_PROC_NAME "()\n");
+ ssa_fprintf(f, "call void ");
+ ssa_print_encoded_global(f, make_string(SSA_STARTUP_RUNTIME_PROC_NAME));
+ ssa_fprintf(f, "()\n");
} break;
case ssaInstr_Comment:
@@ -642,20 +644,6 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
ssa_fprintf(f, "\n");
} break;
- case ssaInstr_MemCopy: {
- ssa_fprintf(f, "call void @.memory_move");
- ssa_fprintf(f, "(i8* ");
- ssa_print_value(f, m, instr->CopyMemory.dst, t_rawptr);
- ssa_fprintf(f, ", i8* ");
- ssa_print_value(f, m, instr->CopyMemory.src, t_rawptr);
- ssa_fprintf(f, ", ");
- ssa_print_type(f, m->sizes, t_int);
- ssa_fprintf(f, " ");
- ssa_print_value(f, m, instr->CopyMemory.len, t_int);
- ssa_fprintf(f, ")\n");
- } break;
-
-
case ssaInstr_ExtractElement: {
Type *vt = ssa_type(instr->ExtractElement.vector);
ssa_fprintf(f, "%%%d = extractelement ", value->id);
diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp
index e7d4aaf4b..5bff4a344 100644
--- a/src/codegen/ssa.cpp
+++ b/src/codegen/ssa.cpp
@@ -85,7 +85,6 @@ struct ssaProcedure {
SSA_INSTR_KIND(Unreachable), \
SSA_INSTR_KIND(BinaryOp), \
SSA_INSTR_KIND(Call), \
- SSA_INSTR_KIND(MemCopy), \
SSA_INSTR_KIND(NoOp), \
SSA_INSTR_KIND(ExtractElement), \
SSA_INSTR_KIND(InsertElement), \
@@ -199,13 +198,6 @@ struct ssaInstr {
isize arg_count;
} Call;
struct {
- ssaValue *dst, *src;
- ssaValue *len;
- i32 align;
- b32 is_volatile;
- } CopyMemory;
-
- struct {
ssaValue *vector;
ssaValue *index;
} ExtractElement;
@@ -315,6 +307,25 @@ void ssa_module_init(ssaModule *m, Checker *c) {
map_init(&m->values, gb_heap_allocator());
map_init(&m->members, gb_heap_allocator());
+
+ {
+ // Add type info data
+ ssaValue *ssa_make_value_global(gbAllocator a, Entity *e, ssaValue *value);
+
+
+ String name = make_string("__type_info_data");
+ Token token = {};
+ token.kind = Token_Identifier;
+ token.string = name;
+
+
+ isize count = gb_array_count(c->info.type_info_types.entries);
+ Entity *e = make_entity_variable(m->allocator, NULL, token, make_type_array(m->allocator, t_type_info, count));
+ ssaValue *g = ssa_make_value_global(m->allocator, e, NULL);
+ g->Global.is_private = true;
+ map_set(&m->values, hash_pointer(e), g);
+ map_set(&m->members, hash_string(name), g);
+ }
}
void ssa_module_destroy(ssaModule *m) {
@@ -356,9 +367,6 @@ Type *ssa_type(ssaInstr *instr) {
}
return NULL;
} break;
- case ssaInstr_MemCopy:
- return t_int;
-
case ssaInstr_ExtractElement: {
Type *vt = ssa_type(instr->ExtractElement.vector);
Type *bt = base_vector_type(get_base_type(vt));
@@ -545,16 +553,6 @@ ssaValue *ssa_make_instr_call(ssaProcedure *p, ssaValue *value, ssaValue **args,
return v;
}
-ssaValue *ssa_make_instr_copy_memory(ssaProcedure *p, ssaValue *dst, ssaValue *src, ssaValue *len, i32 align, b32 is_volatile) {
- ssaValue *v = ssa_alloc_instr(p, ssaInstr_MemCopy);
- v->Instr.CopyMemory.dst = dst;
- v->Instr.CopyMemory.src = src;
- v->Instr.CopyMemory.len = len;
- v->Instr.CopyMemory.align = align;
- v->Instr.CopyMemory.is_volatile = is_volatile;
- return v;
-}
-
ssaValue *ssa_make_instr_conv(ssaProcedure *p, ssaConvKind kind, ssaValue *value, Type *from, Type *to) {
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Conv);
v->Instr.Conv.kind = kind;
@@ -925,7 +923,6 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
case ssaInstr_Br:
case ssaInstr_Ret:
case ssaInstr_Unreachable:
- case ssaInstr_MemCopy:
case ssaInstr_StartupRuntime:
continue;
case ssaInstr_Call:
@@ -2008,11 +2005,13 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
make_exact_value_integer(size_of_elem));
ssaValue *byte_count = ssa_emit_arith(proc, mul, len, elem_size, t_int);
+ ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 3);
+ args[0] = dst;
+ args[1] = src;
+ args[2] = byte_count;
- i32 align = cast(i32)type_align_of(proc->module->sizes, proc->module->allocator, elem_type);
- b32 is_volatile = false;
+ ssa_emit_global_call(proc, "memory_move", args, 3);
- ssa_emit(proc, ssa_make_instr_copy_memory(proc, dst, src, byte_count, align, is_volatile));
return len;
} break;
case BuiltinProc_append: {
@@ -2056,7 +2055,12 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
item = ssa_emit_ptr_offset(proc, item, v_zero);
item = ssa_emit_conv(proc, item, t_rawptr, true);
- ssa_emit(proc, ssa_make_instr_copy_memory(proc, offset, item, byte_count, 1, false));
+ ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 3);
+ args[0] = offset;
+ args[1] = item;
+ args[2] = byte_count;
+
+ ssa_emit_global_call(proc, "memory_move", args, 3);
// Increment slice length
Token add = {Token_Add};
@@ -2172,6 +2176,22 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssaValue *cond = ssa_emit_comp(proc, lt, x, v_zero);
return ssa_emit_select(proc, cond, neg_x, x);
} break;
+
+
+ case BuiltinProc_type_info: {
+ ssaValue **found = map_get(&proc->module->members, hash_string(make_string("__type_info_data")));
+ GB_ASSERT(found != NULL);
+ ssaValue *type_info_data = *found;
+ ssaValue *x = ssa_build_expr(proc, ce->arg_list);
+ Type *t = default_type(type_of_expr(proc->module->info, ce->arg_list));
+ MapFindResult fr = map__find(&proc->module->info->type_info_types, hash_pointer(t));
+ GB_ASSERT(fr.entry_index >= 0);
+ // Zero is null and void
+ isize offset = fr.entry_index;
+
+ ssaValue *gep = ssa_emit_struct_gep(proc, type_info_data, offset, t_type_info_ptr);
+ return gep;
+ } break;
}
}
}
@@ -3153,11 +3173,16 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
Type *union_type = type_deref(ssa_type(parent));
GB_ASSERT(is_type_union(union_type));
+ ssa_emit_comment(proc, make_string("get union's tag"));
ssaValue *tag_index = ssa_emit_struct_gep(proc, parent, v_one32, make_type_pointer(allocator, t_int));
tag_index = ssa_emit_load(proc, tag_index);
ssaValue *data = ssa_emit_conv(proc, parent, t_rawptr);
+ ssaBlock *start_block = ssa_add_block(proc, node, make_string("type-match.case.first"));
+ ssa_emit_jump(proc, start_block);
+ proc->curr_block = start_block;
+
ssaBlock *done = ssa__make_block(proc, node, make_string("type-match.done")); // NOTE(bill): Append later
ast_node(body, BlockStmt, ms->body);
@@ -3173,30 +3198,22 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
for (AstNode *clause = body->list;
clause != NULL;
clause = clause->next, i++) {
- ssaBlock *body = NULL;
- b32 append_body = false;
-
ast_node(cc, CaseClause, clause);
- if (body == NULL) {
- append_body = true;
- if (cc->list == NULL) {
- body = ssa__make_block(proc, clause, make_string("type-match.dflt.body"));
- } else {
- body = ssa__make_block(proc, clause, make_string("type-match.case.body"));
- }
- }
-
-
if (cc->list == NULL) {
// default case
default_stmts = cc->stmts;
- default_block = body;
+ default_block = ssa__make_block(proc, clause, make_string("type-match.dflt.body"));
continue;
}
+
+ ssaBlock *body = ssa__make_block(proc, clause, make_string("type-match.case.body"));
+
+
Scope *scope = *map_get(&proc->module->info->scopes, hash_pointer(clause));
Entity *tag_var_entity = current_scope_lookup_entity(scope, tag_var_name);
+ GB_ASSERT(tag_var_entity != NULL);
ssaValue *tag_var = ssa_add_local(proc, tag_var_entity);
ssaValue *data_ptr = ssa_emit_conv(proc, data, tag_var_entity->type);
ssa_emit_store(proc, tag_var, data_ptr);
@@ -3205,10 +3222,13 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
Type *base_type = type_deref(tag_var_entity->type);
ssaValue *index = NULL;
- for (isize i = 0; i < get_base_type(union_type)->Record.field_count; i++) {
- Entity *f = get_base_type(union_type)->Record.fields[i];
+ Type *ut = get_base_type(union_type);
+ GB_ASSERT(ut->Record.kind == TypeRecord_Union);
+ for (isize field_index = 1; field_index < ut->Record.field_count; field_index++) {
+ Entity *f = get_base_type(union_type)->Record.fields[field_index];
if (are_types_identical(f->type, base_type)) {
- index = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(i));
+ index = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(field_index));
+ break;
}
}
GB_ASSERT(index != NULL);
@@ -3220,9 +3240,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
gb_array_append(proc->blocks, next_cond);
proc->curr_block = next_cond;
- if (append_body) {
- gb_array_append(proc->blocks, body);
- }
+ gb_array_append(proc->blocks, body);
proc->curr_block = body;
ssa_push_target_list(proc, done, NULL, NULL);
ssa_build_stmt_list(proc, cc->stmts);
diff --git a/src/main.cpp b/src/main.cpp
index 0b4c955d1..6099e10f7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -41,6 +41,7 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
}
+#if 0
#define INIT_TIMER() u64 start_time, end_time = 0, total_time = 0; start_time = gb_utc_time_now()
#define PRINT_TIMER(section) do { \
u64 diff; \
@@ -54,6 +55,11 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
#define PRINT_ACCUMULATION() do { \
gb_printf_err("Total compilation time: %lld ms\n", total_time/1000); \
} while (0)
+#else
+#define INIT_TIMER()
+#define PRINT_TIMER(section)
+#define PRINT_ACCUMULATION()
+#endif
int main(int argc, char **argv) {
@@ -117,8 +123,10 @@ int main(int argc, char **argv) {
i32 exit_code = 0;
+ // For more passes arguments: http://llvm.org/docs/Passes.html
exit_code = win32_exec_command_line_app(
- "../misc/llvm-bin/opt %s -o %.*s.bc "
+ // "../misc/llvm-bin/opt %s -o %.*s.bc "
+ "opt %s -o %.*s.bc "
"-memcpyopt "
"-mem2reg "
"-die -dse "
@@ -144,7 +152,7 @@ int main(int argc, char **argv) {
}
exit_code = win32_exec_command_line_app(
- "clang %.*s.bc -o %.*s.o "
+ "clang %.*s.bc -o %.*s.exe "
"-O0 "
"-Wno-override-module "
"%s",
diff --git a/src/parser.cpp b/src/parser.cpp
index afe52ae6b..3efb0451d 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -2063,8 +2063,15 @@ AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) {
declaration_kind = Declaration_Immutable;
next_token(f);
- if (f->cursor[0].kind == Token_type) {
- Token token = expect_token(f, Token_type);
+ if (f->cursor[0].kind == Token_type ||
+ f->cursor[0].kind == Token_struct ||
+ f->cursor[0].kind == Token_enum ||
+ f->cursor[0].kind == Token_union ||
+ f->cursor[0].kind == Token_raw_union) {
+ Token token = f->cursor[0];
+ if (token.kind == Token_type) {
+ next_token(f);
+ }
if (name_count != 1) {
ast_file_err(f, ast_node_token(name_list), "You can only declare one type at a time");
return make_bad_decl(f, name_list->Ident, token);
@@ -2290,9 +2297,9 @@ AstNode *parse_match_stmt(AstFile *f) {
Token open, close;
if (allow_token(f, Token_type)) {
- tag = parse_expr(f, true);
- expect_token(f, Token_ArrowRight);
AstNode *var = parse_identifier(f);
+ expect_token(f, Token_Colon);
+ tag = parse_simple_stmt(f);
open = expect_token(f, Token_OpenBrace);
AstNode *list = NULL;
@@ -2307,6 +2314,8 @@ AstNode *parse_match_stmt(AstFile *f) {
close = expect_token(f, Token_CloseBrace);
body = make_block_stmt(f, list, list_count, open, close);
+
+ tag = convert_stmt_to_expr(f, tag, make_string("type match expression"));
return make_type_match_stmt(f, token, tag, var, body);
} else {
if (f->cursor[0].kind != Token_OpenBrace) {