Better constant strings for SSA; Fix Type_Info

This commit is contained in:
Ginger Bill
2016-10-26 20:10:32 +01:00
parent aed7a83f5b
commit 09f39ae2cc
12 changed files with 420 additions and 294 deletions

View File

@@ -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)
}

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);
// }
}

View File

@@ -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;
}

View File

@@ -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: