aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/codegen.cpp19
-rw-r--r--src/codegen/print_llvm.cpp118
-rw-r--r--src/codegen/ssa.cpp41
3 files changed, 157 insertions, 21 deletions
diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp
index ca6771962..87aaab101 100644
--- a/src/codegen/codegen.cpp
+++ b/src/codegen/codegen.cpp
@@ -151,13 +151,12 @@ void ssa_gen_tree(ssaGen *s) {
if (decl->init_expr != NULL) {
TypeAndValue *tav = map_get(&info->types, hash_pointer(decl->init_expr));
- if (tav != NULL && tav->value.kind != ExactValue_Invalid) {
- ExactValue v = tav->value;
- if (v.kind == ExactValue_String) {
- // NOTE(bill): The printer will fix the value correctly
- // g->Global.value = ssa_add_global_string_array(m, v.value_string);
- } else {
- g->Global.value = ssa_make_value_constant(a, tav->type, v);
+ if (tav != NULL) {
+ if (tav->value.kind != ExactValue_Invalid) {
+ ExactValue v = tav->value;
+ if (v.kind != ExactValue_String) {
+ g->Global.value = ssa_add_module_constant(m, tav->type, v);
+ }
}
}
}
@@ -444,10 +443,10 @@ void ssa_gen_tree(ssaGen *s) {
type_set_offsets(m->sizes, a, t); // NOTE(bill): Just incase the offsets have not been set yet
for (isize i = 0; i < t->Record.field_count; i++) {
- // NOTE(bill): Order fields in source order not layout order
- Entity *f = t->Record.fields[i];
+ // TODO(bill): Order fields in source order not layout order
+ Entity *f = t->Record.fields_in_src_order[i];
ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
- i64 foffset = t->Record.struct_offsets[i];
+ i64 foffset = t->Record.struct_offsets[f->Variable.field_index];
GB_ASSERT(f->kind == Entity_Variable && f->Variable.is_field);
isize source_index = f->Variable.field_index;
diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp
index 420bb112f..3957b0e36 100644
--- a/src/codegen/print_llvm.cpp
+++ b/src/codegen/print_llvm.cpp
@@ -263,6 +263,8 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
}
}
+void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type_hint);
+
void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Type *type) {
type = base_type(type);
if (is_type_float(type)) {
@@ -320,6 +322,122 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
ssa_fprintf(f, ")");
}
break;
+
+ case ExactValue_Compound: {
+ // ssa_fprintf(f, "%s", (value.value_bool ? "true" : "false"));
+ type = base_type(type);
+ if (is_type_array(type)) {
+ ssa_fprintf(f, "[");
+ Type *elem_type = type->Array.elem;
+ ast_node(cl, CompoundLit, value.value_compound);
+
+ for (isize i = 0; i < type->Array.count; i++) {
+ if (i > 0) {
+ ssa_fprintf(f, ", ");
+ }
+ ssa_print_type(f, m, elem_type);
+ ssa_fprintf(f, " ");
+
+ TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]);
+ GB_ASSERT(tav != NULL);
+ ssa_print_exact_value(f, m, tav->value, elem_type);
+ }
+
+ ssa_fprintf(f, "]");
+ } else if (is_type_struct(type)) {
+ gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
+ defer (gb_temp_arena_memory_end(tmp));
+
+ ast_node(cl, CompoundLit, value.value_compound);
+
+ if (cl->elems == NULL || gb_array_count(cl->elems) == 0) {
+ ssa_fprintf(f, "zeroinitializer");
+ break;
+ }
+
+
+ isize value_count = type->Record.field_count;
+ ExactValue *values = gb_alloc_array(m->tmp_allocator, ExactValue, value_count);
+
+
+ if (cl->elems[0]->kind == AstNode_FieldValue) {
+ isize elem_count = gb_array_count(cl->elems);
+ for (isize i = 0; i < elem_count; i++) {
+ ast_node(fv, FieldValue, cl->elems[i]);
+ String name = fv->field->Ident.string;
+
+ TypeAndValue *tav = type_and_value_of_expression(m->info, fv->value);
+ GB_ASSERT(tav != NULL);
+
+ Selection sel = lookup_field(m->allocator, type, name, false);
+ Entity *f = type->Record.fields[sel.index[0]];
+
+ values[f->Variable.field_index] = tav->value;
+ }
+ } else {
+ for (isize i = 0; i < value_count; i++) {
+ TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]);
+ GB_ASSERT(tav != NULL);
+
+ Entity *f = type->Record.fields_in_src_order[i];
+
+ values[f->Variable.field_index] = tav->value;
+ }
+ }
+
+
+
+ if (type->Record.struct_is_packed) {
+ ssa_fprintf(f, "<");
+ }
+ ssa_fprintf(f, "{");
+
+
+ for (isize i = 0; i < value_count; i++) {
+ if (i > 0) {
+ ssa_fprintf(f, ", ");
+ }
+ Type *elem_type = type->Record.fields[i]->type;
+
+ ssa_print_type(f, m, elem_type);
+ ssa_fprintf(f, " ");
+
+ ExactValue v = values[i];
+ if (v.kind == ExactValue_Invalid) {
+ ssa_fprintf(f, "zeroinitializer");
+ } else if (v.kind == ExactValue_String) {
+ // HACK NOTE(bill): This is a hack but it works because strings are created at the very end
+ // of the .ll file
+ ssaValue *str_array = ssa_add_global_string_array(m, v.value_string);
+
+ ssa_fprintf(f, "{i8* getelementptr inbounds (");
+ ssa_print_type(f, m, str_array->Global.entity->type);
+ ssa_fprintf(f, ", ");
+ ssa_print_type(f, m, str_array->Global.entity->type);
+ ssa_fprintf(f, "* ");
+ ssa_print_encoded_global(f, str_array->Global.entity->token.string, false);
+ ssa_fprintf(f, ", ");
+ ssa_print_type(f, m, t_int);
+ ssa_fprintf(f, " 0, i32 0), ");
+ ssa_print_type(f, m, t_int);
+ ssa_fprintf(f, " %lld}", cast(i64)v.value_string.len);
+
+ } else {
+ ssa_print_exact_value(f, m, v, elem_type);
+ }
+ }
+
+
+ ssa_fprintf(f, "}");
+ if (type->Record.struct_is_packed) {
+ ssa_fprintf(f, ">");
+ }
+ } else {
+ ssa_fprintf(f, "zeroinitializer");
+ }
+
+ } break;
+
default:
GB_PANIC("Invalid ExactValue: %d", value.kind);
break;
diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp
index c56ff221f..7cc23e2ce 100644
--- a/src/codegen/ssa.cpp
+++ b/src/codegen/ssa.cpp
@@ -64,6 +64,7 @@ struct ssaModule {
i32 global_string_index;
gbArray(ssaValue *) procs; // NOTE(bill): Procedures to generate
+ gbArray(ssaValue *) const_compound_lits;
};
@@ -290,6 +291,7 @@ enum ssaValueKind {
ssaValue_Invalid,
ssaValue_Constant,
+ ssaValue_ConstantArray,
ssaValue_TypeName,
ssaValue_Global,
ssaValue_Param,
@@ -311,8 +313,12 @@ struct ssaValue {
ExactValue value;
} Constant;
struct {
+ Type *type;
+ gbArray(ssaValue *) values;
+ } ConstantArray;
+ struct {
String name;
- Type * type;
+ Type * type;
} TypeName;
struct {
b32 is_constant;
@@ -409,6 +415,7 @@ void ssa_init_module(ssaModule *m, Checker *c) {
map_init(&m->debug_info, gb_heap_allocator());
map_init(&m->type_names, gb_heap_allocator());
gb_array_init(m->procs, gb_heap_allocator());
+ gb_array_init(m->const_compound_lits, gb_heap_allocator());
// Default states
m->stmt_state_flags = 0;
@@ -473,6 +480,7 @@ void ssa_destroy_module(ssaModule *m) {
map_destroy(&m->type_names);
map_destroy(&m->debug_info);
gb_array_free(m->procs);
+ gb_array_free(m->const_compound_lits);
gb_arena_free(&m->arena);
}
@@ -808,6 +816,16 @@ ssaValue *ssa_make_const_bool(gbAllocator a, b32 b) {
return ssa_make_value_constant(a, t_bool, make_exact_value_bool(b != 0));
}
+ssaValue *ssa_add_module_constant(ssaModule *m, Type *type, ExactValue value) {
+ ssaValue *v = ssa_make_value_constant(m->allocator, type, value);
+
+ if (!is_type_constant_type(type)) {
+ gb_array_append(m->const_compound_lits, v);
+ }
+
+ return v;
+}
+
ssaValue *ssa_make_value_procedure(gbAllocator a, ssaModule *m, Entity *entity, Type *type, AstNode *type_expr, AstNode *body, String name) {
ssaValue *v = ssa_alloc_value(a, ssaValue_Proc);
@@ -1201,7 +1219,7 @@ ssaValue *ssa_emit_arith(ssaProcedure *proc, Token op, ssaValue *left, ssaValue
case Token_AndNot: {
// NOTE(bill): x &~ y == x & (~y) == x & (y ~ -1)
// NOTE(bill): "not" `x` == `x` "xor" `-1`
- ssaValue *neg = ssa_make_value_constant(proc->module->allocator, type, make_exact_value_integer(-1));
+ ssaValue *neg = ssa_add_module_constant(proc->module, type, make_exact_value_integer(-1));
op.kind = Token_Xor;
right = ssa_emit_arith(proc, op, right, neg, type);
GB_ASSERT(right->Instr.kind == ssaInstr_BinaryOp);
@@ -1270,7 +1288,7 @@ ssaValue *ssa_emit_struct_gep(ssaProcedure *proc, ssaValue *s, ssaValue *index,
}
ssaValue *ssa_emit_struct_gep(ssaProcedure *proc, ssaValue *s, i32 index, Type *result_type) {
- ssaValue *i = ssa_make_value_constant(proc->module->allocator, t_i32, make_exact_value_integer(index));
+ ssaValue *i = ssa_make_const_i32(proc->module->allocator, index);
return ssa_emit_struct_gep(proc, s, i, result_type);
}
@@ -1540,7 +1558,7 @@ ssaValue *ssa_add_global_string_array(ssaModule *m, String string) {
Type *type = make_type_array(a, t_u8, string.len);
ExactValue ev = make_exact_value_string(string);
Entity *entity = make_entity_constant(a, NULL, token, type, ev);
- ssaValue *g = ssa_make_value_global(a, entity, ssa_make_value_constant(a, type, ev));
+ ssaValue *g = ssa_make_value_global(a, entity, ssa_add_module_constant(m, type, ev));
g->Global.is_private = true;
// g->Global.is_constant = true;
@@ -1628,10 +1646,10 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
ev = exact_value_to_integer(ev);
} else if (is_type_pointer(dst)) {
// IMPORTANT NOTE(bill): LLVM doesn't support pointer constants expect `null`
- ssaValue *i = ssa_make_value_constant(proc->module->allocator, t_uint, ev);
+ ssaValue *i = ssa_add_module_constant(proc->module, t_uint, ev);
return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_inttoptr, i, t_uint, dst));
}
- return ssa_make_value_constant(proc->module->allocator, t, ev);
+ return ssa_add_module_constant(proc->module, t, ev);
}
}
@@ -2007,7 +2025,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
// NOTE(bill): "not" `x` == `x` "xor" `-1`
ExactValue neg_one = make_exact_value_integer(-1);
ssaValue *left = ssa_build_expr(proc, ue->expr);
- ssaValue *right = ssa_make_value_constant(proc->module->allocator, tv->type, neg_one);
+ ssaValue *right = ssa_add_module_constant(proc->module, tv->type, neg_one);
return ssa_emit_arith(proc, ue->op, left, right, tv->type);
} break;
}
@@ -2105,9 +2123,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
case Type_Vector: {
- isize index = 0;
+
ssaValue *result = ssa_emit_load(proc, v);
- for (; index < gb_array_count(cl->elems); index++) {
+ for (isize index = 0; index < gb_array_count(cl->elems); index++) {
AstNode *elem = cl->elems[index];
ssaValue *field_elem = ssa_build_expr(proc, elem);
Type *t = ssa_type(field_elem);
@@ -2116,7 +2134,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssaValue *i = ssa_make_const_int(proc->module->allocator, index);
result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i));
}
- if (index == 1 && bt->Vector.count > 1) {
+
+ if (gb_array_count(cl->elems) == 1 && bt->Vector.count > 1) {
isize index_count = bt->Vector.count;
i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count);
for (isize i = 0; i < index_count; i++) {
@@ -2677,7 +2696,7 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) {
}
}
- return ssa_make_value_constant(proc->module->allocator, tv->type, tv->value);
+ return ssa_add_module_constant(proc->module, tv->type, tv->value);
}
ssaValue *value = NULL;