ssa - alloca all variables at the very start

This commit is contained in:
Ginger Bill
2016-09-15 18:58:29 +01:00
parent b6cb4f4d14
commit 807256dea4
8 changed files with 240 additions and 107 deletions

View File

@@ -754,12 +754,14 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
case Addressing_Type:
error(&c->error_collector, ast_node_token(node), "Is not an expression");
break;
default:
if (kind == Expr_Stmt) {
return;
}
error(&c->error_collector, ast_node_token(node), "Expression is not used");
break;
case Addressing_NoValue:
return;
default: {
gbString expr_str = expr_to_string(operand.expr);
defer (gb_string_free(expr_str));
error(&c->error_collector, ast_node_token(node), "Expression is not used: `%s`", expr_str);
} break;
}
case_end;

View File

@@ -387,13 +387,22 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
ssa_fprintf(f, "%%%d = alloca ", value->id);
ssa_print_type(f, m->sizes, type);
ssa_fprintf(f, ", align %lld\n", type_align_of(m->sizes, m->allocator, type));
if (instr->Local.zero_initialized) {
ssa_fprintf(f, "\tstore ");
ssa_print_type(f, m->sizes, type);
ssa_fprintf(f, " zeroinitializer, ");
ssa_print_type(f, m->sizes, type);
ssa_fprintf(f, "* %%%d\n", value->id);
}
// if (instr->Local.zero_initialized) {
// ssa_fprintf(f, "\tstore ");
// ssa_print_type(f, m->sizes, type);
// ssa_fprintf(f, " zeroinitializer, ");
// ssa_print_type(f, m->sizes, type);
// ssa_fprintf(f, "* %%%d\n", value->id);
// }
} break;
case ssaInstr_ZeroInit: {
Type *type = type_deref(ssa_type(instr->ZeroInit.address));
ssa_fprintf(f, "\tstore ");
ssa_print_type(f, m->sizes, type);
ssa_fprintf(f, " zeroinitializer, ");
ssa_print_type(f, m->sizes, type);
ssa_fprintf(f, "* %%%d\n", instr->ZeroInit.address->id);
} break;
case ssaInstr_Store: {
@@ -745,10 +754,23 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
if (proc->body == NULL) {
ssa_fprintf(f, "declare ");
if (proc->tags & ProcTag_dll_import) {
ssa_fprintf(f, "dllimport ");
}
if (proc->tags & ProcTag_dll_export) {
ssa_fprintf(f, "dllexport ");
}
} else {
ssa_fprintf(f, "\ndefine ");
}
if (proc->tags & ProcTag_stdcall) {
ssa_fprintf(f, "cc 64 ");
}
if (proc->tags & ProcTag_fastcall) {
ssa_fprintf(f, "cc 65 ");
}
auto *proc_type = &proc->type->Proc;
if (proc_type->result_count == 0) {
@@ -773,7 +795,9 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
ssa_fprintf(f, ", ");
}
ssa_print_type(f, m->sizes, e->type);
ssa_fprintf(f, " %%%.*s", LIT(e->token.string));
if (proc->body != NULL) {
ssa_fprintf(f, " %%%.*s", LIT(e->token.string));
}
}
}
@@ -787,14 +811,20 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
ssa_fprintf(f, "noinline ");
}
// if (proc->tags & ProcTag_stdcall) {
// ssa_fprintf(f, "\"cc\"=\"64\" ");
// }
// if (proc->tags & ProcTag_fastcall) {
// ssa_fprintf(f, "\"cc\"=\"65\" ");
// }
if (proc->tags & ProcTag_foreign) {
// TODO(bill): Set calling convention
ssa_fprintf(f, "; foreign\n");
}
}
if (proc->body != NULL) {
// ssa_fprintf(f, "nounwind uwtable {\n");
ssa_fprintf(f, "{\n");
gb_for_array(i, proc->blocks) {
ssaBlock *block = proc->blocks[i];

View File

@@ -65,6 +65,8 @@ struct ssaProcedure {
isize scope_index;
gbArray(ssaDefer) defer_stmts;
gbArray(ssaBlock *) blocks;
ssaBlock * decl_block;
ssaBlock * entry_block;
ssaBlock * curr_block;
ssaTargetList * target_list;
};
@@ -78,6 +80,7 @@ struct ssaProcedure {
SSA_INSTR_KIND(Invalid), \
SSA_INSTR_KIND(Comment), \
SSA_INSTR_KIND(Local), \
SSA_INSTR_KIND(ZeroInit), \
SSA_INSTR_KIND(Store), \
SSA_INSTR_KIND(Load), \
SSA_INSTR_KIND(GetElementPtr), \
@@ -151,6 +154,9 @@ struct ssaInstr {
Type * type;
b32 zero_initialized;
} Local;
struct {
ssaValue *address;
} ZeroInit;
struct {
ssaValue *address;
ssaValue *value;
@@ -509,6 +515,13 @@ ssaValue *ssa_make_instr_store(ssaProcedure *p, ssaValue *address, ssaValue *val
return v;
}
ssaValue *ssa_make_instr_zero_init(ssaProcedure *p, ssaValue *address) {
ssaValue *v = ssa_alloc_instr(p, ssaInstr_ZeroInit);
ssaInstr *i = &v->Instr;
i->ZeroInit.address = address;
return v;
}
ssaValue *ssa_make_instr_load(ssaProcedure *p, ssaValue *address) {
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Load);
ssaInstr *i = &v->Instr;
@@ -743,13 +756,26 @@ ssaValue *ssa_emit_select(ssaProcedure *p, ssaValue *cond, ssaValue *t, ssaValue
return ssa_emit(p, ssa_make_instr_select(p, cond, t, f));
}
ssaValue *ssa_emit_zero_init(ssaProcedure *p, ssaValue *address) {
return ssa_emit(p, ssa_make_instr_zero_init(p, address));
}
ssaValue *ssa_emit_comment(ssaProcedure *p, String text) {
return ssa_emit(p, ssa_make_instr_comment(p, text));
}
ssaValue *ssa_add_local(ssaProcedure *proc, Entity *e, b32 zero_initialized = true) {
return ssa_emit(proc, ssa_make_instr_local(proc, e, zero_initialized));
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;
gb_array_append(b->instrs, 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) {
@@ -769,11 +795,11 @@ ssaValue *ssa_add_local_generated(ssaProcedure *proc, Type *type) {
if (proc->curr_block) {
scope = proc->curr_block->scope;
}
Entity *entity = make_entity_variable(proc->module->allocator,
scope,
empty_token,
type);
return ssa_emit(proc, ssa_make_instr_local(proc, entity, true));
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) {
@@ -944,7 +970,9 @@ ssaValue *ssa_lvalue_load(ssaProcedure *proc, ssaAddr lval) {
void ssa_begin_procedure_body(ssaProcedure *proc) {
gb_array_init(proc->blocks, gb_heap_allocator());
gb_array_init(proc->defer_stmts, gb_heap_allocator());
proc->curr_block = ssa_add_block(proc, proc->type_expr, make_string("entry"));
proc->decl_block = ssa_add_block(proc, proc->type_expr, make_string("decls"));
proc->entry_block = ssa_add_block(proc, proc->type_expr, make_string("entry"));
proc->curr_block = proc->entry_block;
if (proc->type->Proc.params != NULL) {
auto *params = &proc->type->Proc.params->Tuple;
@@ -960,6 +988,9 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
ssa_emit_ret(proc, NULL);
}
proc->curr_block = proc->decl_block;
ssa_emit_jump(proc, proc->entry_block);
// Number blocks and registers
i32 reg_id = 0;
@@ -973,6 +1004,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
// NOTE(bill): Ignore non-returning instructions
switch (instr->kind) {
case ssaInstr_Comment:
case ssaInstr_ZeroInit:
case ssaInstr_Store:
case ssaInstr_Br:
case ssaInstr_Ret:

View File

@@ -128,10 +128,10 @@ int main(int argc, char **argv) {
exit_code = win32_exec_command_line_app(
// "../misc/llvm-bin/opt %s -o %.*s.bc "
"opt %s -o %.*s.bc "
"-memcpyopt "
"-mem2reg "
"-die -dse "
"-dce "
// "-memcpyopt "
// "-mem2reg "
// "-die -dse "
// "-dce "
// "-S "
// "-debug-pass=Arguments "
"",
@@ -148,13 +148,14 @@ int main(int argc, char **argv) {
gb_for_array(i, parser.system_libraries) {
String lib = parser.system_libraries[i];
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" -l%.*s.lib", LIT(lib));
" -l%.*s", LIT(lib));
lib_str = gb_string_appendc(lib_str, lib_str_buf);
}
exit_code = win32_exec_command_line_app(
"clang %.*s.bc -o %.*s.exe "
"-O0 "
// "-O2 "
"-Wno-override-module "
"%s",
cast(int)base_name_len, output_name,

View File

@@ -65,12 +65,19 @@ enum DeclKind {
Declaration_Count,
};
enum ProcTag {
enum ProcTag : u64 {
ProcTag_bounds_check = GB_BIT(0),
ProcTag_no_bounds_check = GB_BIT(1),
ProcTag_foreign = GB_BIT(2),
ProcTag_inline = GB_BIT(3),
ProcTag_no_inline = GB_BIT(4),
ProcTag_foreign = GB_BIT(10),
ProcTag_inline = GB_BIT(11),
ProcTag_no_inline = GB_BIT(12),
ProcTag_dll_import = GB_BIT(13),
ProcTag_dll_export = GB_BIT(14),
ProcTag_stdcall = GB_BIT(15),
ProcTag_fastcall = GB_BIT(16),
// ProcTag_cdecl = GB_BIT(17),
};
enum VarDeclTag {
@@ -220,7 +227,7 @@ AST_NODE_KIND(_DeclBegin, "", struct{}) \
AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
AST_NODE_KIND(VarDecl, "variable declaration", struct { \
DeclKind kind; \
u32 tags; \
u64 tags; \
b32 is_using; \
AstNodeArray names; \
AstNode *type; \
@@ -1171,10 +1178,19 @@ b32 is_foreign_name_valid(String name) {
void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) {
// TODO(bill): Add this to procedure literals too
while (f->cursor[0].kind == Token_Hash) {
AstNode *tag_expr = parse_tag_expr(f, NULL);
ast_node(te, TagExpr, tag_expr);
String tag_name = te->name.string;
#define ELSE_IF_ADD_TAG(name) \
else if (are_strings_equal(tag_name, make_string(#name))) { \
check_proc_add_tag(f, tag_expr, tags, ProcTag_##name, tag_name); \
}
if (are_strings_equal(tag_name, make_string("foreign"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name);
if (f->cursor[0].kind == Token_String) {
@@ -1186,19 +1202,21 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) {
next_token(f);
}
} else if (are_strings_equal(tag_name, make_string("bounds_check"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_bounds_check, tag_name);
} else if (are_strings_equal(tag_name, make_string("no_bounds_check"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_no_bounds_check, tag_name);
} else if (are_strings_equal(tag_name, make_string("inline"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_inline, tag_name);
} else if (are_strings_equal(tag_name, make_string("no_inline"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_no_inline, tag_name);
// } else if (are_strings_equal(tag_name, make_string("no_context"))) {
// check_proc_add_tag(f, tag_expr, tags, ProcTag_no_context, tag_name);
} else {
}
ELSE_IF_ADD_TAG(bounds_check)
ELSE_IF_ADD_TAG(no_bounds_check)
ELSE_IF_ADD_TAG(inline)
ELSE_IF_ADD_TAG(no_inline)
ELSE_IF_ADD_TAG(dll_import)
ELSE_IF_ADD_TAG(dll_export)
ELSE_IF_ADD_TAG(stdcall)
ELSE_IF_ADD_TAG(fastcall)
// ELSE_IF_ADD_TAG(cdecl)
else {
ast_file_err(f, ast_node_token(tag_expr), "Unknown procedure tag");
}
#undef ELSE_IF_ADD_TAG
}
if ((*tags & ProcTag_inline) && (*tags & ProcTag_no_inline)) {