diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-09-30 20:38:46 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-09-30 20:38:46 +0100 |
| commit | c6aac264fa8001ff5e55e5ac6f56289ff0a755ee (patch) | |
| tree | 4ff0521b330e5a2b0183d3bab2f762a669b5efa5 /src/codegen | |
| parent | 04b5d8c132e8aabb3bb5dff31683cb45d4dff9c0 (diff) | |
Begin work on const llvm aggregate literals
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/codegen.cpp | 19 | ||||
| -rw-r--r-- | src/codegen/print_llvm.cpp | 118 | ||||
| -rw-r--r-- | src/codegen/ssa.cpp | 41 |
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; |