mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-27 16:53:55 +00:00
Better constant strings for SSA; Fix Type_Info
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
#import "fmt.odin"
|
||||
|
||||
str := "Hellope"
|
||||
|
||||
a: [12]u8
|
||||
main :: proc() {
|
||||
v: [4]f32
|
||||
v[0] = 123
|
||||
fmt.println("Hellope!", v, v[0], a)
|
||||
fmt.println(str, v, v[0], a)
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ struct CheckerInfo {
|
||||
Map<Entity *> foreign_procs; // Key: String
|
||||
Map<AstFile *> files; // Key: String (full path)
|
||||
Map<isize> type_info_map; // Key: Type *
|
||||
isize type_info_index;
|
||||
isize type_info_count;
|
||||
Entity * implicit_values[ImplicitValue_Count];
|
||||
};
|
||||
|
||||
@@ -536,7 +536,7 @@ void init_checker_info(CheckerInfo *i) {
|
||||
map_init(&i->foreign_procs, a);
|
||||
map_init(&i->type_info_map, a);
|
||||
map_init(&i->files, a);
|
||||
i->type_info_index = 0;
|
||||
i->type_info_count = 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -736,19 +736,21 @@ void add_type_info_type(Checker *c, Type *t) {
|
||||
Type *prev_type = cast(Type *)e->key.ptr;
|
||||
if (are_types_identical(t, prev_type)) {
|
||||
// Duplicate entry
|
||||
ti_index = i;
|
||||
ti_index = e->value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ti_index < 0) {
|
||||
// Unique entry
|
||||
// NOTE(bill): map entries grow linearly and in order
|
||||
ti_index = c->info.type_info_index;
|
||||
c->info.type_info_index++;
|
||||
ti_index = c->info.type_info_count;
|
||||
c->info.type_info_count++;
|
||||
}
|
||||
map_set(&c->info.type_info_map, hash_pointer(t), ti_index);
|
||||
|
||||
|
||||
|
||||
|
||||
// Add nested types
|
||||
|
||||
if (t->kind == Type_Named) {
|
||||
@@ -758,6 +760,8 @@ void add_type_info_type(Checker *c, Type *t) {
|
||||
}
|
||||
|
||||
Type *bt = base_type(t);
|
||||
add_type_info_type(c, bt);
|
||||
|
||||
switch (bt->kind) {
|
||||
case Type_Basic: {
|
||||
switch (bt->Basic.kind) {
|
||||
|
||||
@@ -248,16 +248,17 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||
CycleChecker *cycle_checker, String context) {
|
||||
PROF_PROC();
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
Map<Entity *> entity_map = {};
|
||||
map_init(&entity_map, heap_allocator());
|
||||
defer (map_destroy(&entity_map));
|
||||
map_init_with_reserve(&entity_map, c->tmp_allocator, 2*(field_count+other_field_count));
|
||||
// defer (map_destroy(&entity_map));
|
||||
|
||||
isize other_field_index = 0;
|
||||
Entity *using_index_expr = NULL;
|
||||
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
struct Delay {
|
||||
Entity *e;
|
||||
AstNode *t;
|
||||
@@ -661,9 +662,13 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
|
||||
GB_ASSERT(is_type_enum(enum_type));
|
||||
ast_node(et, EnumType, node);
|
||||
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
Map<Entity *> entity_map = {};
|
||||
map_init(&entity_map, heap_allocator());
|
||||
defer (map_destroy(&entity_map));
|
||||
map_init_with_reserve(&entity_map, c->tmp_allocator, 2*(et->fields.count));
|
||||
// defer (map_destroy(&entity_map));
|
||||
|
||||
Type *base_type = t_int;
|
||||
if (et->base_type != NULL) {
|
||||
|
||||
@@ -633,7 +633,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
Token token;
|
||||
};
|
||||
|
||||
Map<TypeAndToken> seen = {}; // Multimap
|
||||
Map<TypeAndToken> seen = {}; // NOTE(bill): Multimap
|
||||
map_init(&seen, heap_allocator());
|
||||
defer (map_destroy(&seen));
|
||||
for_array(i, bs->stmts) {
|
||||
|
||||
@@ -1347,7 +1347,7 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
for (isize i = 1; i < type->Record.field_count; i++) {
|
||||
Entity *f = type->Record.fields[i];
|
||||
GB_ASSERT(f->kind == Entity_TypeName);
|
||||
if (i > 0) {
|
||||
if (i > 1) {
|
||||
str = gb_string_appendc(str, "; ");
|
||||
}
|
||||
str = gb_string_append_length(str, f->token.string.text, f->token.string.len);
|
||||
@@ -1362,8 +1362,9 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
for (isize i = 0; i < type->Record.field_count; i++) {
|
||||
Entity *f = type->Record.fields[i];
|
||||
GB_ASSERT(f->kind == Entity_Variable);
|
||||
if (i > 0)
|
||||
if (i > 0) {
|
||||
str = gb_string_appendc(str, ", ");
|
||||
}
|
||||
str = gb_string_append_length(str, f->token.string.text, f->token.string.len);
|
||||
str = gb_string_appendc(str, ": ");
|
||||
str = write_type_to_string(str, f->type);
|
||||
|
||||
@@ -215,14 +215,15 @@ struct Map {
|
||||
Array<MapEntry<T> > entries;
|
||||
};
|
||||
|
||||
template <typename T> void map_init (Map<T> *h, gbAllocator a);
|
||||
template <typename T> void map_destroy(Map<T> *h);
|
||||
template <typename T> T * map_get (Map<T> *h, HashKey key);
|
||||
template <typename T> void map_set (Map<T> *h, HashKey key, T value);
|
||||
template <typename T> void map_remove (Map<T> *h, HashKey key);
|
||||
template <typename T> void map_clear (Map<T> *h);
|
||||
template <typename T> void map_grow (Map<T> *h);
|
||||
template <typename T> void map_rehash (Map<T> *h, isize new_count);
|
||||
template <typename T> void map_init (Map<T> *h, gbAllocator a);
|
||||
template <typename T> void map_init_with_reserve(Map<T> *h, gbAllocator a, isize capacity);
|
||||
template <typename T> void map_destroy (Map<T> *h);
|
||||
template <typename T> T * map_get (Map<T> *h, HashKey key);
|
||||
template <typename T> void map_set (Map<T> *h, HashKey key, T value);
|
||||
template <typename T> void map_remove (Map<T> *h, HashKey key);
|
||||
template <typename T> void map_clear (Map<T> *h);
|
||||
template <typename T> void map_grow (Map<T> *h);
|
||||
template <typename T> void map_rehash (Map<T> *h, isize new_count);
|
||||
|
||||
template <typename T> MapEntry<T> *multi_map_find_first(Map<T> *h, HashKey key);
|
||||
template <typename T> MapEntry<T> *multi_map_find_next (Map<T> *h, MapEntry<T> *e);
|
||||
@@ -242,6 +243,12 @@ gb_inline void map_init(Map<T> *h, gbAllocator a) {
|
||||
array_init(&h->entries, a);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
gb_inline void map_init_with_reserve(Map<T> *h, gbAllocator a, isize capacity) {
|
||||
array_init(&h->hashes, a, capacity);
|
||||
array_init(&h->entries, a, capacity);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
gb_inline void map_destroy(Map<T> *h) {
|
||||
array_free(&h->entries);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
b32 ssa_valid_char(u8 c) {
|
||||
if (c >= 0x80)
|
||||
if (c >= 0x80) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gb_char_is_alphanumeric(c))
|
||||
if (gb_char_is_alphanumeric(c)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case '$':
|
||||
@@ -20,8 +22,9 @@ void ssa_print_escape_string(ssaFileBuffer *f, String name, b32 print_quotes) {
|
||||
isize extra = 0;
|
||||
for (isize i = 0; i < name.len; i++) {
|
||||
u8 c = name.text[i];
|
||||
if (!ssa_valid_char(c))
|
||||
if (!ssa_valid_char(c)) {
|
||||
extra += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (extra == 0) {
|
||||
@@ -185,7 +188,9 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
|
||||
} else {
|
||||
ssa_fprintf(f, "{");
|
||||
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
||||
if (i > 0) ssa_fprintf(f, ", ");
|
||||
if (i > 0) {
|
||||
ssa_fprintf(f, ", ");
|
||||
}
|
||||
ssa_print_type(f, m, t->Tuple.variables[i]->type);
|
||||
}
|
||||
ssa_fprintf(f, "}");
|
||||
@@ -225,23 +230,6 @@ void ssa_print_compound_element(ssaFileBuffer *f, ssaModule *m, ExactValue v, Ty
|
||||
|
||||
if (v.kind == ExactValue_Invalid || base_type(elem_type) == t_any) {
|
||||
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);
|
||||
}
|
||||
@@ -269,9 +257,33 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
|
||||
ssa_fprintf(f, "%s", (value.value_bool ? "true" : "false"));
|
||||
break;
|
||||
case ExactValue_String: {
|
||||
ssa_fprintf(f, "c\"");
|
||||
ssa_print_escape_string(f, value.value_string, false);
|
||||
ssa_fprintf(f, "\"");
|
||||
String str = value.value_string;
|
||||
if (str.len == 0) {
|
||||
ssa_fprintf(f, "zeroinitializer");
|
||||
break;
|
||||
}
|
||||
if (!is_type_string(type)) {
|
||||
GB_ASSERT(is_type_array(type));
|
||||
ssa_fprintf(f, "c\"");
|
||||
ssa_print_escape_string(f, str, false);
|
||||
ssa_fprintf(f, "\"");
|
||||
} else {
|
||||
// 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, str);
|
||||
|
||||
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)str.len);
|
||||
}
|
||||
} break;
|
||||
case ExactValue_Integer: {
|
||||
if (is_type_pointer(type)) {
|
||||
@@ -954,6 +966,78 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
||||
ssa_fprintf(f, "\n");
|
||||
} break;
|
||||
|
||||
case ssaInstr_BoundsCheck: {
|
||||
auto *bc = &instr->BoundsCheck;
|
||||
ssa_fprintf(f, "call void ");
|
||||
ssa_print_encoded_global(f, make_string("__bounds_check_error"), false);
|
||||
ssa_fprintf(f, "(");
|
||||
ssa_print_compound_element(f, m, make_exact_value_string(bc->pos.file), t_string);
|
||||
ssa_fprintf(f, ", ");
|
||||
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_exact_value(f, m, make_exact_value_integer(bc->pos.line), t_int);
|
||||
ssa_fprintf(f, ", ");
|
||||
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_exact_value(f, m, make_exact_value_integer(bc->pos.column), t_int);
|
||||
ssa_fprintf(f, ", ");
|
||||
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_value(f, m, bc->index, t_int);
|
||||
ssa_fprintf(f, ", ");
|
||||
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_value(f, m, bc->len, t_int);
|
||||
|
||||
ssa_fprintf(f, ")\n");
|
||||
} break;
|
||||
|
||||
case ssaInstr_SliceBoundsCheck: {
|
||||
auto *bc = &instr->SliceBoundsCheck;
|
||||
ssa_fprintf(f, "call void ");
|
||||
if (bc->is_substring) {
|
||||
ssa_print_encoded_global(f, make_string("__substring_expr_error"), false);
|
||||
} else {
|
||||
ssa_print_encoded_global(f, make_string("__slice_expr_error"), false);
|
||||
}
|
||||
|
||||
ssa_fprintf(f, "(");
|
||||
ssa_print_compound_element(f, m, make_exact_value_string(bc->pos.file), t_string);
|
||||
ssa_fprintf(f, ", ");
|
||||
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_exact_value(f, m, make_exact_value_integer(bc->pos.line), t_int);
|
||||
ssa_fprintf(f, ", ");
|
||||
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_exact_value(f, m, make_exact_value_integer(bc->pos.column), t_int);
|
||||
ssa_fprintf(f, ", ");
|
||||
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_value(f, m, bc->low, t_int);
|
||||
ssa_fprintf(f, ", ");
|
||||
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_value(f, m, bc->high, t_int);
|
||||
|
||||
if (!bc->is_substring) {
|
||||
ssa_fprintf(f, ", ");
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_value(f, m, bc->max, t_int);
|
||||
}
|
||||
|
||||
ssa_fprintf(f, ")\n");
|
||||
} break;
|
||||
|
||||
|
||||
default: {
|
||||
GB_PANIC("<unknown instr> %d\n", instr->kind);
|
||||
|
||||
@@ -85,42 +85,6 @@ void ssa_build_defer_stmt(ssaProcedure *proc, ssaDefer d) {
|
||||
}
|
||||
|
||||
|
||||
void ssa_array_bounds_check(ssaProcedure *proc, Token token, ssaValue *index, ssaValue *len) {
|
||||
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
gbAllocator a = proc->module->allocator;
|
||||
ssaValue **args = gb_alloc_array(a, ssaValue *, 5);
|
||||
args[0] = ssa_emit_global_string(proc, token.pos.file);
|
||||
args[1] = ssa_make_const_int(a, token.pos.line);
|
||||
args[2] = ssa_make_const_int(a, token.pos.column);
|
||||
args[3] = ssa_emit_conv(proc, index, t_int);
|
||||
args[4] = ssa_emit_conv(proc, len, t_int);
|
||||
|
||||
ssa_emit_global_call(proc, "__bounds_check_error", args, 5);
|
||||
}
|
||||
|
||||
void ssa_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low, ssaValue *high, ssaValue *max, b32 is_substring) {
|
||||
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
gbAllocator a = proc->module->allocator;
|
||||
ssaValue **args = gb_alloc_array(a, ssaValue *, 6);
|
||||
args[0] = ssa_emit_global_string(proc, token.pos.file);
|
||||
args[1] = ssa_make_const_int(a, token.pos.line);
|
||||
args[2] = ssa_make_const_int(a, token.pos.column);
|
||||
args[3] = ssa_emit_conv(proc, low, t_int);
|
||||
args[4] = ssa_emit_conv(proc, high, t_int);
|
||||
args[5] = ssa_emit_conv(proc, max, t_int);
|
||||
|
||||
if (!is_substring) {
|
||||
ssa_emit_global_call(proc, "__slice_expr_error", args, 6);
|
||||
} else {
|
||||
ssa_emit_global_call(proc, "__substring_expr_error", args, 5);
|
||||
}
|
||||
}
|
||||
|
||||
ssaValue *ssa_find_global_variable(ssaProcedure *proc, String name) {
|
||||
ssaValue **value = map_get(&proc->module->members, hash_string(name));
|
||||
@@ -498,13 +462,13 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
ssaValue *elem_size = ssa_make_const_int(allocator, s);
|
||||
ssaValue *elem_align = ssa_make_const_int(allocator, a);
|
||||
|
||||
ssaValue *len =ssa_emit_conv(proc, ssa_build_expr(proc, ce->args[1]), t_int);
|
||||
ssaValue *len = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args[1]), t_int);
|
||||
ssaValue *cap = len;
|
||||
if (ce->args.count == 3) {
|
||||
cap = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args[2]), t_int);
|
||||
}
|
||||
|
||||
ssa_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, cap, false);
|
||||
ssa_emit_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, cap, false);
|
||||
|
||||
ssaValue *slice_size = ssa_emit_arith(proc, Token_Mul, elem_size, cap, t_int);
|
||||
|
||||
@@ -548,10 +512,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
expr_str.len = expr_len;
|
||||
|
||||
ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 4);
|
||||
args[0] = ssa_emit_global_string(proc, pos.file);
|
||||
args[0] = ssa_make_const_string(proc->module->allocator, pos.file);
|
||||
args[1] = ssa_make_const_int(proc->module->allocator, pos.line);
|
||||
args[2] = ssa_make_const_int(proc->module->allocator, pos.column);
|
||||
args[3] = ssa_emit_global_string(proc, expr_str);
|
||||
args[3] = ssa_make_const_string(proc->module->allocator, expr_str);
|
||||
ssa_emit_global_call(proc, "__assert", args, 4);
|
||||
|
||||
ssa_emit_jump(proc, done);
|
||||
@@ -569,7 +533,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
TokenPos pos = token.pos;
|
||||
|
||||
ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 4);
|
||||
args[0] = ssa_emit_global_string(proc, pos.file);
|
||||
args[0] = ssa_make_const_string(proc->module->allocator, pos.file);
|
||||
args[1] = ssa_make_const_int(proc->module->allocator, pos.line);
|
||||
args[2] = ssa_make_const_int(proc->module->allocator, pos.column);
|
||||
args[3] = msg;
|
||||
@@ -904,16 +868,6 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) {
|
||||
GB_ASSERT_NOT_NULL(tv);
|
||||
|
||||
if (tv->value.kind != ExactValue_Invalid) {
|
||||
if (tv->value.kind == ExactValue_String) {
|
||||
ssa_emit_comment(proc, make_string("Emit string constant"));
|
||||
if (tv->value.value_string.len > 0) {
|
||||
return ssa_emit_global_string(proc, tv->value.value_string);
|
||||
} else {
|
||||
ssaValue *null_string = ssa_add_local_generated(proc, t_string);
|
||||
return ssa_emit_load(proc, null_string);
|
||||
}
|
||||
}
|
||||
|
||||
return ssa_add_module_constant(proc->module, tv->type, tv->value);
|
||||
}
|
||||
|
||||
@@ -957,21 +911,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
Entity *e = entity_of_ident(proc->module->info, expr);
|
||||
TypeAndValue *tv = map_get(&proc->module->info->types, hash_pointer(expr));
|
||||
|
||||
if (e->kind == Entity_Constant) {
|
||||
if (base_type(e->type) == t_string) {
|
||||
// HACK TODO(bill): This is lazy but it works
|
||||
String str = e->Constant.value.value_string;
|
||||
ssaValue *global_array = ssa_add_global_string_array(proc->module, str);
|
||||
ssaValue *elem = ssa_array_elem(proc, global_array);
|
||||
ssaValue *len = ssa_make_const_int(proc->module->allocator, str.len);
|
||||
ssaValue *v = ssa_add_local_generated(proc, e->type);
|
||||
ssaValue *str_elem = ssa_emit_struct_ep(proc, v, 0);
|
||||
ssaValue *str_len = ssa_emit_struct_ep(proc, v, 1);
|
||||
ssa_emit_store(proc, str_elem, elem);
|
||||
ssa_emit_store(proc, str_len, len);
|
||||
return ssa_make_addr(v, expr);
|
||||
}
|
||||
}
|
||||
GB_ASSERT(e->kind != Entity_Constant);
|
||||
|
||||
ssaValue *v = NULL;
|
||||
ssaValue **found = map_get(&proc->module->values, hash_pointer(e));
|
||||
@@ -1087,7 +1027,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
}
|
||||
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
||||
ssaValue *len = ssa_make_const_int(a, t->Vector.count);
|
||||
ssa_array_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
ssa_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
return ssa_make_addr_vector(vector, index, expr);
|
||||
} break;
|
||||
|
||||
@@ -1104,7 +1044,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
||||
ssaValue *elem = ssa_emit_array_ep(proc, array, index);
|
||||
ssaValue *len = ssa_make_const_int(a, t->Vector.count);
|
||||
ssa_array_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
ssa_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
return ssa_make_addr(elem, expr);
|
||||
} break;
|
||||
|
||||
@@ -1121,7 +1061,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
ssaValue *elem = ssa_slice_elem(proc, slice);
|
||||
ssaValue *len = ssa_slice_len(proc, slice);
|
||||
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
||||
ssa_array_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
ssa_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
ssaValue *v = ssa_emit_ptr_offset(proc, elem, index);
|
||||
return ssa_make_addr(v, expr);
|
||||
|
||||
@@ -1129,31 +1069,26 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
|
||||
case Type_Basic: { // Basic_string
|
||||
TypeAndValue *tv = map_get(&proc->module->info->types, hash_pointer(ie->expr));
|
||||
ssaValue *elem = NULL;
|
||||
ssaValue *len = NULL;
|
||||
if (tv != NULL && tv->mode == Addressing_Constant) {
|
||||
ssaValue *array = ssa_add_global_string_array(proc->module, tv->value.value_string);
|
||||
elem = ssa_array_elem(proc, array);
|
||||
len = ssa_make_const_int(a, tv->value.value_string.len);
|
||||
ssaValue *str;
|
||||
ssaValue *elem;
|
||||
ssaValue *len;
|
||||
ssaValue *index;
|
||||
|
||||
if (using_addr != NULL) {
|
||||
str = ssa_emit_load(proc, using_addr);
|
||||
} else {
|
||||
ssaValue *str = NULL;
|
||||
if (using_addr != NULL) {
|
||||
str = ssa_emit_load(proc, using_addr);
|
||||
} else {
|
||||
str = ssa_build_expr(proc, ie->expr);
|
||||
if (deref) {
|
||||
str = ssa_emit_load(proc, str);
|
||||
}
|
||||
str = ssa_build_expr(proc, ie->expr);
|
||||
if (deref) {
|
||||
str = ssa_emit_load(proc, str);
|
||||
}
|
||||
elem = ssa_string_elem(proc, str);
|
||||
len = ssa_string_len(proc, str);
|
||||
}
|
||||
elem = ssa_string_elem(proc, str);
|
||||
len = ssa_string_len(proc, str);
|
||||
|
||||
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
||||
ssa_array_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
|
||||
ssa_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||
|
||||
ssaValue *v = ssa_emit_ptr_offset(proc, elem, index);
|
||||
return ssa_make_addr(v, expr);
|
||||
return ssa_make_addr(ssa_emit_ptr_offset(proc, elem, index), expr);
|
||||
} break;
|
||||
}
|
||||
case_end;
|
||||
@@ -1188,7 +1123,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
if (max == NULL) max = ssa_slice_cap(proc, base);
|
||||
GB_ASSERT(max != NULL);
|
||||
|
||||
ssa_slice_bounds_check(proc, se->open, low, high, max, false);
|
||||
ssa_emit_slice_bounds_check(proc, se->open, low, high, max, false);
|
||||
|
||||
ssaValue *elem = ssa_slice_elem(proc, base);
|
||||
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
||||
@@ -1212,7 +1147,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
if (max == NULL) max = ssa_array_cap(proc, base);
|
||||
GB_ASSERT(max != NULL);
|
||||
|
||||
ssa_slice_bounds_check(proc, se->open, low, high, max, false);
|
||||
ssa_emit_slice_bounds_check(proc, se->open, low, high, max, false);
|
||||
|
||||
ssaValue *elem = ssa_array_elem(proc, addr);
|
||||
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
||||
@@ -1235,7 +1170,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
high = ssa_string_len(proc, base);
|
||||
}
|
||||
|
||||
ssa_slice_bounds_check(proc, se->open, low, high, high, true);
|
||||
ssa_emit_slice_bounds_check(proc, se->open, low, high, high, true);
|
||||
|
||||
ssaValue *elem, *len;
|
||||
len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
||||
@@ -1258,7 +1193,8 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
|
||||
case_ast_node(de, DerefExpr, expr);
|
||||
// TODO(bill): Is a ptr copy needed?
|
||||
ssaValue *addr = ssa_emit_ptr_offset(proc, ssa_build_expr(proc, de->expr), v_zero);
|
||||
ssaValue *addr = ssa_build_expr(proc, de->expr);
|
||||
addr = ssa_emit_ptr_offset(proc, addr, v_zero);
|
||||
return ssa_make_addr(addr, expr);
|
||||
case_end;
|
||||
|
||||
@@ -1268,15 +1204,8 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
Type *t = default_type(type_of_expr(proc->module->info, expr));
|
||||
GB_ASSERT(is_type_tuple(t));
|
||||
|
||||
Type *elem = ssa_type(maybe);
|
||||
GB_ASSERT(is_type_maybe(elem));
|
||||
elem = base_type(elem)->Maybe.elem;
|
||||
|
||||
ssaValue *result = ssa_add_local_generated(proc, t);
|
||||
ssaValue *gep0 = ssa_emit_struct_ep(proc, result, 0);
|
||||
ssaValue *gep1 = ssa_emit_struct_ep(proc, result, 1);
|
||||
ssa_emit_store(proc, gep0, ssa_emit_struct_ev(proc, maybe, 0));
|
||||
ssa_emit_store(proc, gep1, ssa_emit_struct_ev(proc, maybe, 1));
|
||||
ssa_emit_store(proc, result, maybe);
|
||||
|
||||
return ssa_make_addr(result, expr);
|
||||
case_end;
|
||||
|
||||
@@ -149,9 +149,9 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
if (tav != NULL) {
|
||||
if (tav->value.kind != ExactValue_Invalid) {
|
||||
ExactValue v = tav->value;
|
||||
if (v.kind != ExactValue_String) {
|
||||
// if (v.kind != ExactValue_String) {
|
||||
g->Global.value = ssa_add_module_constant(m, tav->type, v);
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,7 +293,9 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
Type *t_string_slice_ptr = make_type_pointer(a, make_type_slice(a, t_string));
|
||||
|
||||
auto get_type_info_ptr = [](ssaProcedure *proc, ssaValue *type_info_data, Type *type) -> ssaValue * {
|
||||
return ssa_emit_array_ep(proc, type_info_data, cast(i32)ssa_type_info_index(proc->module->info, type));
|
||||
i32 index = cast(i32)ssa_type_info_index(proc->module->info, type);
|
||||
// gb_printf_err("%d %s\n", index, type_to_string(type));
|
||||
return ssa_emit_array_ep(proc, type_info_data, index);
|
||||
};
|
||||
|
||||
i32 type_info_member_index = 0;
|
||||
@@ -319,16 +321,11 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_named);
|
||||
|
||||
// TODO(bill): Which is better? The mangled name or actual name?
|
||||
// ssaValue *gsa = ssa_add_global_string_array(proc, make_exact_value_string(t->Named.name));
|
||||
ssaValue *gsa = ssa_add_global_string_array(m, t->Named.type_name->token.string);
|
||||
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);
|
||||
ssaValue *name = ssa_make_const_string(a, t->Named.type_name->token.string);
|
||||
ssaValue *gtip = get_type_info_ptr(proc, type_info_data, t->Named.base);
|
||||
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), name);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 1), gep);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 1), gtip);
|
||||
} break;
|
||||
|
||||
case Type_Basic:
|
||||
@@ -453,7 +450,7 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
ssaValue *offset = ssa_emit_struct_ep(proc, field, 2);
|
||||
|
||||
if (f->token.string.len > 0) {
|
||||
ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string));
|
||||
ssa_emit_store(proc, name, ssa_make_const_string(a, f->token.string));
|
||||
}
|
||||
ssa_emit_store(proc, type_info, tip);
|
||||
ssa_emit_store(proc, offset, ssa_make_const_int(a, foffset));
|
||||
@@ -502,7 +499,7 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
|
||||
|
||||
if (f->token.string.len > 0) {
|
||||
ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string));
|
||||
ssa_emit_store(proc, name, ssa_make_const_string(a, f->token.string));
|
||||
}
|
||||
ssa_emit_store(proc, type_info, tip);
|
||||
ssa_emit_store(proc, offset, ssa_make_const_int(a, 0));
|
||||
@@ -571,7 +568,7 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
ssaValue *name_gep = ssa_emit_struct_ep(proc, name_array, i);
|
||||
|
||||
ssa_emit_store(proc, value_gep, ssa_make_const_i64(a, fields[i]->Constant.value.value_integer));
|
||||
ssa_emit_store(proc, name_gep, ssa_emit_global_string(proc, fields[i]->token.string));
|
||||
ssa_emit_store(proc, name_gep, ssa_make_const_string(a, fields[i]->token.string));
|
||||
}
|
||||
|
||||
ssaValue *v_count = ssa_make_const_int(a, count);
|
||||
@@ -617,7 +614,7 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
|
||||
|
||||
if (f->token.string.len > 0) {
|
||||
ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string));
|
||||
ssa_emit_store(proc, name, ssa_make_const_string(a, f->token.string));
|
||||
}
|
||||
ssa_emit_store(proc, type_info, tip);
|
||||
}
|
||||
|
||||
145
src/ssa/emit.cpp
145
src/ssa/emit.cpp
@@ -37,56 +37,6 @@ ssaValue *ssa_emit_comment(ssaProcedure *p, String text) {
|
||||
}
|
||||
|
||||
|
||||
ssaValue *ssa_add_local(ssaProcedure *proc, Entity *e, b32 zero_initialized = true) {
|
||||
ssaBlock *b = proc->decl_block; // all variables must be in the first block
|
||||
ssaValue *instr = ssa_make_instr_local(proc, e, zero_initialized);
|
||||
instr->Instr.parent = b;
|
||||
array_add(&b->instrs, instr);
|
||||
array_add(&b->locals, instr);
|
||||
|
||||
// if (zero_initialized) {
|
||||
ssa_emit_zero_init(proc, instr);
|
||||
// }
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_local_for_identifier(ssaProcedure *proc, AstNode *name, b32 zero_initialized) {
|
||||
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(name));
|
||||
if (found) {
|
||||
Entity *e = *found;
|
||||
ssa_emit_comment(proc, e->token.string);
|
||||
return ssa_add_local(proc, e, zero_initialized);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_local_generated(ssaProcedure *proc, Type *type) {
|
||||
GB_ASSERT(type != NULL);
|
||||
|
||||
Scope *scope = NULL;
|
||||
if (proc->curr_block) {
|
||||
scope = proc->curr_block->scope;
|
||||
}
|
||||
Entity *e = make_entity_variable(proc->module->allocator,
|
||||
scope,
|
||||
empty_token,
|
||||
type);
|
||||
return ssa_add_local(proc, e, true);
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_param(ssaProcedure *proc, Entity *e) {
|
||||
ssaValue *v = ssa_make_value_param(proc->module->allocator, proc, e);
|
||||
#if 1
|
||||
ssaValue *l = ssa_add_local(proc, e);
|
||||
ssa_emit_store(proc, l, v);
|
||||
#else
|
||||
ssa_module_add_value(proc->module, e, v);
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
ssaValue *ssa_emit_call(ssaProcedure *p, ssaValue *value, ssaValue **args, isize arg_count) {
|
||||
Type *pt = base_type(ssa_type(value));
|
||||
GB_ASSERT(pt->kind == Type_Proc);
|
||||
@@ -602,31 +552,6 @@ ssaValue *ssa_add_local_slice(ssaProcedure *proc, Type *slice_type, ssaValue *ba
|
||||
return slice;
|
||||
}
|
||||
|
||||
|
||||
ssaValue *ssa_add_global_string_array(ssaModule *m, String string) {
|
||||
gbAllocator a = m->allocator;
|
||||
|
||||
isize max_len = 6+8+1;
|
||||
u8 *str = cast(u8 *)gb_alloc_array(a, u8, max_len);
|
||||
isize len = gb_snprintf(cast(char *)str, max_len, "__str$%x", m->global_string_index);
|
||||
m->global_string_index++;
|
||||
|
||||
String name = make_string(str, len-1);
|
||||
Token token = {Token_String};
|
||||
token.string = name;
|
||||
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_add_module_constant(m, type, ev));
|
||||
g->Global.is_private = true;
|
||||
// g->Global.is_constant = true;
|
||||
|
||||
ssa_module_add_value(m, entity, g);
|
||||
map_set(&m->members, hash_string(name), g);
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
ssaValue *ssa_emit_string(ssaProcedure *proc, ssaValue *elem, ssaValue *len) {
|
||||
ssaValue *str = ssa_add_local_generated(proc, t_string);
|
||||
ssaValue *str_elem = ssa_emit_struct_ep(proc, str, 0);
|
||||
@@ -637,14 +562,6 @@ ssaValue *ssa_emit_string(ssaProcedure *proc, ssaValue *elem, ssaValue *len) {
|
||||
}
|
||||
|
||||
|
||||
ssaValue *ssa_emit_global_string(ssaProcedure *proc, String str) {
|
||||
ssaValue *global_array = ssa_add_global_string_array(proc->module, str);
|
||||
ssaValue *elem = ssa_array_elem(proc, global_array);
|
||||
ssaValue *len = ssa_make_const_int(proc->module->allocator, str.len);
|
||||
return ssa_emit_string(proc, elem, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
|
||||
@@ -1101,10 +1018,15 @@ ssaValue *ssa_type_info(ssaProcedure *proc, Type *type) {
|
||||
ssaValue **found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_NAME)));
|
||||
GB_ASSERT(found != NULL);
|
||||
ssaValue *type_info_data = *found;
|
||||
|
||||
CheckerInfo *info = proc->module->info;
|
||||
ssaValue *entry_index = ssa_make_const_i32(proc->module->allocator, ssa_type_info_index(info, type));
|
||||
return ssa_emit_array_ep(proc, type_info_data, entry_index);
|
||||
|
||||
type = default_type(type);
|
||||
|
||||
i32 entry_index = ssa_type_info_index(info, type);
|
||||
|
||||
// gb_printf_err("%d %s\n", entry_index, type_to_string(type));
|
||||
|
||||
return ssa_emit_array_ep(proc, type_info_data, ssa_make_const_i32(proc->module->allocator, entry_index));
|
||||
}
|
||||
|
||||
|
||||
@@ -1172,6 +1094,57 @@ ssaValue *ssa_emit_logical_binary_expr(ssaProcedure *proc, AstNode *expr) {
|
||||
}
|
||||
|
||||
|
||||
void ssa_emit_bounds_check(ssaProcedure *proc, Token token, ssaValue *index, ssaValue *len) {
|
||||
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
index = ssa_emit_conv(proc, index, t_int);
|
||||
len = ssa_emit_conv(proc, len, t_int);
|
||||
|
||||
ssa_emit(proc, ssa_make_instr_bounds_check(proc, token.pos, index, len));
|
||||
|
||||
// gbAllocator a = proc->module->allocator;
|
||||
// ssaValue **args = gb_alloc_array(a, ssaValue *, 5);
|
||||
// args[0] = ssa_emit_global_string(proc, token.pos.file);
|
||||
// args[1] = ssa_make_const_int(a, token.pos.line);
|
||||
// args[2] = ssa_make_const_int(a, token.pos.column);
|
||||
// args[3] = ssa_emit_conv(proc, index, t_int);
|
||||
// args[4] = ssa_emit_conv(proc, len, t_int);
|
||||
|
||||
// ssa_emit_global_call(proc, "__bounds_check_error", args, 5);
|
||||
}
|
||||
|
||||
void ssa_emit_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low, ssaValue *high, ssaValue *max, b32 is_substring) {
|
||||
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
low = ssa_emit_conv(proc, low, t_int);
|
||||
high = ssa_emit_conv(proc, high, t_int);
|
||||
max = ssa_emit_conv(proc, max, t_int);
|
||||
|
||||
ssa_emit(proc, ssa_make_instr_slice_bounds_check(proc, token.pos, low, high, max, is_substring));
|
||||
|
||||
// gbAllocator a = proc->module->allocator;
|
||||
// ssaValue **args = gb_alloc_array(a, ssaValue *, 6);
|
||||
// args[0] = ssa_emit_global_string(proc, token.pos.file);
|
||||
// args[1] = ssa_make_const_int(a, token.pos.line);
|
||||
// args[2] = ssa_make_const_int(a, token.pos.column);
|
||||
// args[3] = ssa_emit_conv(proc, low, t_int);
|
||||
// args[4] = ssa_emit_conv(proc, high, t_int);
|
||||
// args[5] = ssa_emit_conv(proc, max, t_int);
|
||||
|
||||
// if (!is_substring) {
|
||||
// ssa_emit_global_call(proc, "__slice_expr_error", args, 6);
|
||||
// } else {
|
||||
// ssa_emit_global_call(proc, "__substring_expr_error", args, 5);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
169
src/ssa/make.cpp
169
src/ssa/make.cpp
@@ -1,4 +1,8 @@
|
||||
void ssa_module_add_value(ssaModule *m, Entity *e, ssaValue *v);
|
||||
ssaValue *ssa_emit_zero_init(ssaProcedure *p, ssaValue *address);
|
||||
ssaValue *ssa_emit_comment(ssaProcedure *p, String text);
|
||||
ssaValue *ssa_emit_store(ssaProcedure *p, ssaValue *address, ssaValue *value);
|
||||
ssaValue *ssa_emit_load(ssaProcedure *p, ssaValue *address);
|
||||
|
||||
|
||||
ssaValue *ssa_alloc_value(gbAllocator a, ssaValueKind kind) {
|
||||
@@ -255,6 +259,23 @@ ssaValue *ssa_make_instr_comment(ssaProcedure *p, String text) {
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_bounds_check(ssaProcedure *p, TokenPos pos, ssaValue *index, ssaValue *len) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_BoundsCheck);
|
||||
v->Instr.BoundsCheck.pos = pos;
|
||||
v->Instr.BoundsCheck.index = index;
|
||||
v->Instr.BoundsCheck.len = len;
|
||||
return v;
|
||||
}
|
||||
ssaValue *ssa_make_instr_slice_bounds_check(ssaProcedure *p, TokenPos pos, ssaValue *low, ssaValue *high, ssaValue *max, b32 is_substring) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_SliceBoundsCheck);
|
||||
v->Instr.SliceBoundsCheck.pos = pos;
|
||||
v->Instr.SliceBoundsCheck.low = low;
|
||||
v->Instr.SliceBoundsCheck.high = high;
|
||||
v->Instr.SliceBoundsCheck.max = max;
|
||||
v->Instr.SliceBoundsCheck.is_substring = is_substring;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ssaValue *ssa_make_value_constant(gbAllocator a, Type *type, ExactValue value) {
|
||||
@@ -273,6 +294,14 @@ ssaValue *ssa_make_value_constant_slice(gbAllocator a, Type *type, ssaValue *bac
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_value_constant_string(gbAllocator a, Type *type, String string) {
|
||||
ssaValue *v = ssa_alloc_value(a, ssaValue_ConstantString);
|
||||
v->ConstantString.type = type;
|
||||
v->ConstantString.string = string;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
ssaValue *ssa_make_const_int(gbAllocator a, i64 i) {
|
||||
return ssa_make_value_constant(a, t_int, make_exact_value_integer(i));
|
||||
}
|
||||
@@ -285,41 +314,10 @@ ssaValue *ssa_make_const_i64(gbAllocator a, i64 i) {
|
||||
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) {
|
||||
if (is_type_slice(type)) {
|
||||
ast_node(cl, CompoundLit, value.value_compound);
|
||||
gbAllocator a = m->allocator;
|
||||
|
||||
isize count = cl->elems.count;
|
||||
if (count > 0) {
|
||||
Type *elem = base_type(type)->Slice.elem;
|
||||
Type *t = make_type_array(a, elem, count);
|
||||
ssaValue *backing_array = ssa_add_module_constant(m, t, value);
|
||||
|
||||
|
||||
isize max_len = 7+8+1;
|
||||
u8 *str = cast(u8 *)gb_alloc_array(a, u8, max_len);
|
||||
isize len = gb_snprintf(cast(char *)str, max_len, "__csba$%x", m->global_array_index);
|
||||
m->global_array_index++;
|
||||
|
||||
String name = make_string(str, len-1);
|
||||
|
||||
Entity *e = make_entity_constant(a, NULL, make_token_ident(name), t, value);
|
||||
ssaValue *g = ssa_make_value_global(a, e, backing_array);
|
||||
ssa_module_add_value(m, e, g);
|
||||
map_set(&m->members, hash_string(name), g);
|
||||
|
||||
return ssa_make_value_constant_slice(a, type, g, count);
|
||||
} else {
|
||||
return ssa_make_value_constant_slice(a, type, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return ssa_make_value_constant(m->allocator, type, value);
|
||||
ssaValue *ssa_make_const_string(gbAllocator a, String s) {
|
||||
return ssa_make_value_constant(a, t_string, make_exact_value_string(s));
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
v->Proc.module = m;
|
||||
@@ -390,5 +388,110 @@ ssaDefer ssa_add_defer_instr(ssaProcedure *proc, isize scope_index, ssaValue *in
|
||||
|
||||
|
||||
|
||||
ssaValue *ssa_add_module_constant(ssaModule *m, Type *type, ExactValue value) {
|
||||
if (is_type_slice(type)) {
|
||||
ast_node(cl, CompoundLit, value.value_compound);
|
||||
gbAllocator a = m->allocator;
|
||||
|
||||
isize count = cl->elems.count;
|
||||
if (count == 0) {
|
||||
return ssa_make_value_nil(a, type);
|
||||
}
|
||||
Type *elem = base_type(type)->Slice.elem;
|
||||
Type *t = make_type_array(a, elem, count);
|
||||
ssaValue *backing_array = ssa_add_module_constant(m, t, value);
|
||||
|
||||
|
||||
isize max_len = 7+8+1;
|
||||
u8 *str = cast(u8 *)gb_alloc_array(a, u8, max_len);
|
||||
isize len = gb_snprintf(cast(char *)str, max_len, "__csba$%x", m->global_array_index);
|
||||
m->global_array_index++;
|
||||
|
||||
String name = make_string(str, len-1);
|
||||
|
||||
Entity *e = make_entity_constant(a, NULL, make_token_ident(name), t, value);
|
||||
ssaValue *g = ssa_make_value_global(a, e, backing_array);
|
||||
ssa_module_add_value(m, e, g);
|
||||
map_set(&m->members, hash_string(name), g);
|
||||
|
||||
return ssa_make_value_constant_slice(a, type, g, count);
|
||||
}
|
||||
|
||||
return ssa_make_value_constant(m->allocator, type, value);
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_global_string_array(ssaModule *m, String string) {
|
||||
gbAllocator a = m->allocator;
|
||||
|
||||
isize max_len = 6+8+1;
|
||||
u8 *str = cast(u8 *)gb_alloc_array(a, u8, max_len);
|
||||
isize len = gb_snprintf(cast(char *)str, max_len, "__str$%x", m->global_string_index);
|
||||
m->global_string_index++;
|
||||
|
||||
String name = make_string(str, len-1);
|
||||
Token token = {Token_String};
|
||||
token.string = name;
|
||||
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_add_module_constant(m, type, ev));
|
||||
g->Global.is_private = true;
|
||||
// g->Global.is_constant = true;
|
||||
|
||||
ssa_module_add_value(m, entity, g);
|
||||
map_set(&m->members, hash_string(name), g);
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ssaValue *ssa_add_local(ssaProcedure *proc, Entity *e, b32 zero_initialized = true) {
|
||||
ssaBlock *b = proc->decl_block; // all variables must be in the first block
|
||||
ssaValue *instr = ssa_make_instr_local(proc, e, zero_initialized);
|
||||
instr->Instr.parent = b;
|
||||
array_add(&b->instrs, instr);
|
||||
array_add(&b->locals, instr);
|
||||
|
||||
// if (zero_initialized) {
|
||||
ssa_emit_zero_init(proc, instr);
|
||||
// }
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_local_for_identifier(ssaProcedure *proc, AstNode *name, b32 zero_initialized) {
|
||||
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(name));
|
||||
if (found) {
|
||||
Entity *e = *found;
|
||||
ssa_emit_comment(proc, e->token.string);
|
||||
return ssa_add_local(proc, e, zero_initialized);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_local_generated(ssaProcedure *proc, Type *type) {
|
||||
GB_ASSERT(type != NULL);
|
||||
|
||||
Scope *scope = NULL;
|
||||
if (proc->curr_block) {
|
||||
scope = proc->curr_block->scope;
|
||||
}
|
||||
Entity *e = make_entity_variable(proc->module->allocator,
|
||||
scope,
|
||||
empty_token,
|
||||
type);
|
||||
return ssa_add_local(proc, e, true);
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_param(ssaProcedure *proc, Entity *e) {
|
||||
ssaValue *v = ssa_make_value_param(proc->module->allocator, proc, e);
|
||||
#if 1
|
||||
ssaValue *l = ssa_add_local(proc, e);
|
||||
ssa_emit_store(proc, l, v);
|
||||
#else
|
||||
ssa_module_add_value(proc->module, e, v);
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -169,7 +169,9 @@ struct ssaProcedure {
|
||||
SSA_INSTR_KIND(VectorExtractElement), \
|
||||
SSA_INSTR_KIND(VectorInsertElement), \
|
||||
SSA_INSTR_KIND(VectorShuffle), \
|
||||
SSA_INSTR_KIND(StartupRuntime),
|
||||
SSA_INSTR_KIND(StartupRuntime), \
|
||||
SSA_INSTR_KIND(BoundsCheck), \
|
||||
SSA_INSTR_KIND(SliceBoundsCheck), \
|
||||
|
||||
#define SSA_CONV_KINDS \
|
||||
SSA_CONV_KIND(Invalid), \
|
||||
@@ -319,6 +321,18 @@ struct ssaInstr {
|
||||
} VectorShuffle;
|
||||
|
||||
struct {} StartupRuntime;
|
||||
struct {
|
||||
TokenPos pos;
|
||||
ssaValue *index;
|
||||
ssaValue *len;
|
||||
} BoundsCheck;
|
||||
struct {
|
||||
TokenPos pos;
|
||||
ssaValue *low;
|
||||
ssaValue *high;
|
||||
ssaValue *max;
|
||||
b32 is_substring;
|
||||
} SliceBoundsCheck;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -328,6 +342,7 @@ enum ssaValueKind {
|
||||
|
||||
ssaValue_Constant,
|
||||
ssaValue_ConstantSlice,
|
||||
ssaValue_ConstantString,
|
||||
ssaValue_Nil,
|
||||
ssaValue_TypeName,
|
||||
ssaValue_Global,
|
||||
@@ -349,10 +364,14 @@ struct ssaValue {
|
||||
ExactValue value;
|
||||
} Constant;
|
||||
struct {
|
||||
Type *type;
|
||||
Type * type;
|
||||
ssaValue *backing_array;
|
||||
i64 count;
|
||||
i64 count;
|
||||
} ConstantSlice;
|
||||
struct {
|
||||
Type * type;
|
||||
String string;
|
||||
} ConstantString;
|
||||
struct {
|
||||
Type *type;
|
||||
} Nil;
|
||||
@@ -361,18 +380,18 @@ struct ssaValue {
|
||||
Type * type;
|
||||
} TypeName;
|
||||
struct {
|
||||
b32 is_constant;
|
||||
b32 is_private;
|
||||
b32 is_thread_local;
|
||||
Entity * entity;
|
||||
Type * type;
|
||||
ssaValue *value;
|
||||
b32 is_constant;
|
||||
b32 is_private;
|
||||
b32 is_thread_local;
|
||||
Entity * entity;
|
||||
Type * type;
|
||||
ssaValue * value;
|
||||
Array<ssaValue *> referrers;
|
||||
} Global;
|
||||
struct {
|
||||
ssaProcedure *parent;
|
||||
Entity *entity;
|
||||
Type * type;
|
||||
ssaProcedure * parent;
|
||||
Entity * entity;
|
||||
Type * type;
|
||||
Array<ssaValue *> referrers;
|
||||
} Param;
|
||||
ssaProcedure Proc;
|
||||
@@ -523,6 +542,8 @@ Type *ssa_type(ssaValue *value) {
|
||||
return value->Constant.type;
|
||||
case ssaValue_ConstantSlice:
|
||||
return value->ConstantSlice.type;
|
||||
case ssaValue_ConstantString:
|
||||
return value->ConstantString.type;
|
||||
case ssaValue_Nil:
|
||||
return value->Nil.type;
|
||||
case ssaValue_TypeName:
|
||||
|
||||
Reference in New Issue
Block a user