mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-18 20:40:28 +00:00
Rename llir -> ir
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
set exe_name=odin.exe
|
||||
|
||||
:: Debug = 0, Release = 1
|
||||
set release_mode=1
|
||||
set release_mode=0
|
||||
|
||||
set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
|
||||
|
||||
@@ -49,5 +49,11 @@ cl %compiler_settings% "src\main.c" ^
|
||||
rem && odin build_dll code/example.odin ^
|
||||
rem && odin run code/demo.odin
|
||||
|
||||
rem pushd src\asm
|
||||
rem nasm hellope.asm -fwin64 -o hellope.obj ^
|
||||
rem && cl /nologo hellope.obj /link kernel32.lib /entry:main ^
|
||||
rem && hellope.exe
|
||||
rem popd
|
||||
|
||||
:end_of_build
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#import "fmt.odin";
|
||||
|
||||
|
||||
|
||||
main :: proc() {
|
||||
{
|
||||
Byte_Size :: enum f64 {
|
||||
@@ -58,3 +56,4 @@ main :: proc() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,11 +88,7 @@ bprint_nl :: proc (buf: ^Buffer) { bprint_rune(buf, '\n'); }
|
||||
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
|
||||
|
||||
bprint_bool :: proc(buffer: ^Buffer, b: bool) {
|
||||
if b {
|
||||
bprint_string(buffer, "true");
|
||||
} else {
|
||||
bprint_string(buffer, "false");
|
||||
}
|
||||
bprint_string(buffer, if b { give "true" } else { give "false" });
|
||||
}
|
||||
|
||||
bprint_pointer :: proc(buffer: ^Buffer, p: rawptr) #inline {
|
||||
@@ -100,9 +96,9 @@ bprint_pointer :: proc(buffer: ^Buffer, p: rawptr) #inline {
|
||||
bprint_u64(buffer, p as uint as u64);
|
||||
}
|
||||
|
||||
// bprint_f16 :: proc (buffer: ^Buffer, f: f32) #inline { print__f64(buffer, f as f64, 4); }
|
||||
bprint_f32 :: proc (buffer: ^Buffer, f: f32) #inline { print__f64(buffer, f as f64, 7); }
|
||||
bprint_f64 :: proc (buffer: ^Buffer, f: f64) #inline { print__f64(buffer, f as f64, 16); }
|
||||
// bprint_f16 :: proc(buffer: ^Buffer, f: f32) #inline { print__f64(buffer, f as f64, 4); }
|
||||
bprint_f32 :: proc(buffer: ^Buffer, f: f32) #inline { print__f64(buffer, f as f64, 7); }
|
||||
bprint_f64 :: proc(buffer: ^Buffer, f: f64) #inline { print__f64(buffer, f as f64, 16); }
|
||||
bprint_u64 :: proc(buffer: ^Buffer, value: u64) {
|
||||
i := value;
|
||||
buf :[20]byte;
|
||||
@@ -189,11 +185,7 @@ bprint_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
|
||||
case ti == type_info(int): bprint_string(buf, "int");
|
||||
case ti == type_info(uint): bprint_string(buf, "uint");
|
||||
default:
|
||||
if info.signed {
|
||||
bprint_string(buf, "i");
|
||||
} else {
|
||||
bprint_string(buf, "u");
|
||||
}
|
||||
bprint_string(buf, if info.signed { give "i" } else { give "u"});
|
||||
bprint_u64(buf, 8*info.size as u64);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ typedef struct DeclInfo {
|
||||
|
||||
AstNode *type_expr;
|
||||
AstNode *init_expr;
|
||||
AstNode *proc_decl; // AstNode_ProcDecl
|
||||
AstNode *proc_lit; // AstNode_ProcLit
|
||||
u32 var_decl_tags;
|
||||
|
||||
MapBool deps; // Key: Entity *
|
||||
@@ -306,9 +306,9 @@ bool decl_info_has_init(DeclInfo *d) {
|
||||
if (d->init_expr != NULL) {
|
||||
return true;
|
||||
}
|
||||
if (d->proc_decl != NULL) {
|
||||
switch (d->proc_decl->kind) {
|
||||
case_ast_node(pd, ProcLit, d->proc_decl);
|
||||
if (d->proc_lit != NULL) {
|
||||
switch (d->proc_lit->kind) {
|
||||
case_ast_node(pd, ProcLit, d->proc_lit);
|
||||
if (pd->body != NULL) {
|
||||
return true;
|
||||
}
|
||||
@@ -1219,7 +1219,7 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
|
||||
d->init_expr = init;
|
||||
} else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
d->proc_decl = init;
|
||||
d->proc_lit = init;
|
||||
} else {
|
||||
e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, (ExactValue){0});
|
||||
d->type_expr = vd->type;
|
||||
|
||||
@@ -329,17 +329,17 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
|
||||
GB_ASSERT(e->type == NULL);
|
||||
if (d->proc_decl->kind != AstNode_ProcLit) {
|
||||
if (d->proc_lit->kind != AstNode_ProcLit) {
|
||||
// TOOD(bill): Better error message
|
||||
error_node(d->proc_decl, "Expected a procedure to check");
|
||||
error_node(d->proc_lit, "Expected a procedure to check");
|
||||
return;
|
||||
}
|
||||
|
||||
Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false, ProcCC_Odin);
|
||||
e->type = proc_type;
|
||||
ast_node(pd, ProcLit, d->proc_decl);
|
||||
ast_node(pd, ProcLit, d->proc_lit);
|
||||
|
||||
check_open_scope(c, pd->type);
|
||||
check_procedure_type(c, proc_type, pd->type);
|
||||
@@ -380,7 +380,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
}
|
||||
|
||||
if (proc_type->Proc.calling_convention != ProcCC_Odin) {
|
||||
error_node(d->proc_decl, "An internal procedure may only have the Odin calling convention");
|
||||
error_node(d->proc_lit, "An internal procedure may only have the Odin calling convention");
|
||||
proc_type->Proc.calling_convention = ProcCC_Odin;
|
||||
}
|
||||
|
||||
@@ -408,7 +408,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Type *this_type = base_type(e->type);
|
||||
Type *other_type = base_type(f->type);
|
||||
if (!are_signatures_similar_enough(this_type, other_type)) {
|
||||
error_node(d->proc_decl,
|
||||
error_node(d->proc_lit,
|
||||
"Redeclaration of #foreign procedure `%.*s` with different type signatures\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
@@ -433,7 +433,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Entity *f = *found;
|
||||
TokenPos pos = f->token.pos;
|
||||
// TODO(bill): Better error message?
|
||||
error_node(d->proc_decl,
|
||||
error_node(d->proc_lit,
|
||||
"Non unique linking name for procedure `%.*s`\n"
|
||||
"\tother at %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
@@ -520,7 +520,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
||||
check_type_decl(c, e, d->type_expr, named_type);
|
||||
break;
|
||||
case Entity_Procedure:
|
||||
check_proc_decl(c, e, d);
|
||||
check_proc_lit(c, e, d);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
|
||||
d->init_expr = init;
|
||||
} else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
d->proc_decl = init;
|
||||
d->proc_lit = init;
|
||||
} else {
|
||||
e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, (ExactValue){0});
|
||||
d->type_expr = vd->type;
|
||||
@@ -130,16 +130,6 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
|
||||
check_arity_match(c, vd);
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(gd, GenericDecl, node);
|
||||
for_array(iota, gd->specs) {
|
||||
AstNode *spec = gd->specs.e[iota];
|
||||
switch (spec->kind) {
|
||||
case_ast_node(bd, BadDecl, spec);
|
||||
case_end;
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
#if 0
|
||||
case_ast_node(pd, ProcDecl, node);
|
||||
if (!ast_node_expect(pd->name, AstNode_Ident)) {
|
||||
@@ -150,7 +140,7 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
|
||||
e->identifier = pd->name;
|
||||
|
||||
DeclInfo *d = make_declaration_info(c->allocator, e->scope);
|
||||
d->proc_decl = node;
|
||||
d->proc_lit = node;
|
||||
|
||||
add_entity_and_decl_info(c, pd->name, e, d);
|
||||
check_entity_decl(c, e, d, NULL, NULL);
|
||||
|
||||
@@ -1295,18 +1295,5 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
// NOTE(bill): Handled elsewhere
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(gd, GenericDecl, node);
|
||||
for_array(spec_index, gd->specs) {
|
||||
AstNode *spec = gd->specs.e[spec_index];
|
||||
switch (spec->kind) {
|
||||
case_ast_node(bd, BadDecl, spec);
|
||||
case_end;
|
||||
default:
|
||||
error(ast_node_token(spec), "Invalid specification in declaration: `%.*s`", LIT(ast_node_strings[spec->kind]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,93 +1,93 @@
|
||||
// Optimizations for the LLIR code
|
||||
// Optimizations for the IR code
|
||||
|
||||
void llir_opt_add_operands(llirValueArray *ops, llirInstr *i) {
|
||||
void ir_opt_add_operands(irValueArray *ops, irInstr *i) {
|
||||
switch (i->kind) {
|
||||
case llirInstr_Comment:
|
||||
case irInstr_Comment:
|
||||
break;
|
||||
case llirInstr_Local:
|
||||
case irInstr_Local:
|
||||
break;
|
||||
case llirInstr_ZeroInit:
|
||||
case irInstr_ZeroInit:
|
||||
array_add(ops, i->ZeroInit.address);
|
||||
break;
|
||||
case llirInstr_Store:
|
||||
case irInstr_Store:
|
||||
array_add(ops, i->Store.address);
|
||||
array_add(ops, i->Store.value);
|
||||
break;
|
||||
case llirInstr_Load:
|
||||
case irInstr_Load:
|
||||
array_add(ops, i->Load.address);
|
||||
break;
|
||||
case llirInstr_ArrayElementPtr:
|
||||
case irInstr_ArrayElementPtr:
|
||||
array_add(ops, i->ArrayElementPtr.address);
|
||||
array_add(ops, i->ArrayElementPtr.elem_index);
|
||||
break;
|
||||
case llirInstr_StructElementPtr:
|
||||
case irInstr_StructElementPtr:
|
||||
array_add(ops, i->StructElementPtr.address);
|
||||
break;
|
||||
case llirInstr_PtrOffset:
|
||||
case irInstr_PtrOffset:
|
||||
array_add(ops, i->PtrOffset.address);
|
||||
array_add(ops, i->PtrOffset.offset);
|
||||
break;
|
||||
case llirInstr_ArrayExtractValue:
|
||||
case irInstr_ArrayExtractValue:
|
||||
array_add(ops, i->ArrayExtractValue.address);
|
||||
break;
|
||||
case llirInstr_StructExtractValue:
|
||||
case irInstr_StructExtractValue:
|
||||
array_add(ops, i->StructExtractValue.address);
|
||||
break;
|
||||
case llirInstr_Conv:
|
||||
case irInstr_Conv:
|
||||
array_add(ops, i->Conv.value);
|
||||
break;
|
||||
case llirInstr_Jump:
|
||||
case irInstr_Jump:
|
||||
break;
|
||||
case llirInstr_If:
|
||||
case irInstr_If:
|
||||
array_add(ops, i->If.cond);
|
||||
break;
|
||||
case llirInstr_Return:
|
||||
case irInstr_Return:
|
||||
if (i->Return.value != NULL) {
|
||||
array_add(ops, i->Return.value);
|
||||
}
|
||||
break;
|
||||
case llirInstr_Select:
|
||||
case irInstr_Select:
|
||||
array_add(ops, i->Select.cond);
|
||||
break;
|
||||
case llirInstr_Phi:
|
||||
case irInstr_Phi:
|
||||
for_array(j, i->Phi.edges) {
|
||||
array_add(ops, i->Phi.edges.e[j]);
|
||||
}
|
||||
break;
|
||||
case llirInstr_Unreachable:
|
||||
case irInstr_Unreachable:
|
||||
break;
|
||||
case llirInstr_UnaryOp:
|
||||
case irInstr_UnaryOp:
|
||||
array_add(ops, i->UnaryOp.expr);
|
||||
break;
|
||||
case llirInstr_BinaryOp:
|
||||
case irInstr_BinaryOp:
|
||||
array_add(ops, i->BinaryOp.left);
|
||||
array_add(ops, i->BinaryOp.right);
|
||||
break;
|
||||
case llirInstr_Call:
|
||||
case irInstr_Call:
|
||||
array_add(ops, i->Call.value);
|
||||
for (isize j = 0; j < i->Call.arg_count; j++) {
|
||||
array_add(ops, i->Call.args[j]);
|
||||
}
|
||||
break;
|
||||
case llirInstr_VectorExtractElement:
|
||||
case irInstr_VectorExtractElement:
|
||||
array_add(ops, i->VectorExtractElement.vector);
|
||||
array_add(ops, i->VectorExtractElement.index);
|
||||
break;
|
||||
case llirInstr_VectorInsertElement:
|
||||
case irInstr_VectorInsertElement:
|
||||
array_add(ops, i->VectorInsertElement.vector);
|
||||
array_add(ops, i->VectorInsertElement.elem);
|
||||
array_add(ops, i->VectorInsertElement.index);
|
||||
break;
|
||||
case llirInstr_VectorShuffle:
|
||||
case irInstr_VectorShuffle:
|
||||
array_add(ops, i->VectorShuffle.vector);
|
||||
break;
|
||||
case llirInstr_StartupRuntime:
|
||||
case irInstr_StartupRuntime:
|
||||
break;
|
||||
case llirInstr_BoundsCheck:
|
||||
case irInstr_BoundsCheck:
|
||||
array_add(ops, i->BoundsCheck.index);
|
||||
array_add(ops, i->BoundsCheck.len);
|
||||
break;
|
||||
case llirInstr_SliceBoundsCheck:
|
||||
case irInstr_SliceBoundsCheck:
|
||||
array_add(ops, i->SliceBoundsCheck.low);
|
||||
array_add(ops, i->SliceBoundsCheck.high);
|
||||
break;
|
||||
@@ -98,26 +98,26 @@ void llir_opt_add_operands(llirValueArray *ops, llirInstr *i) {
|
||||
|
||||
|
||||
|
||||
void llir_opt_block_replace_pred(llirBlock *b, llirBlock *from, llirBlock *to) {
|
||||
void ir_opt_block_replace_pred(irBlock *b, irBlock *from, irBlock *to) {
|
||||
for_array(i, b->preds) {
|
||||
llirBlock *pred = b->preds.e[i];
|
||||
irBlock *pred = b->preds.e[i];
|
||||
if (pred == from) {
|
||||
b->preds.e[i] = to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void llir_opt_block_replace_succ(llirBlock *b, llirBlock *from, llirBlock *to) {
|
||||
void ir_opt_block_replace_succ(irBlock *b, irBlock *from, irBlock *to) {
|
||||
for_array(i, b->succs) {
|
||||
llirBlock *succ = b->succs.e[i];
|
||||
irBlock *succ = b->succs.e[i];
|
||||
if (succ == from) {
|
||||
b->succs.e[i] = to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool llir_opt_block_has_phi(llirBlock *b) {
|
||||
return b->instrs.e[0]->Instr.kind == llirInstr_Phi;
|
||||
bool ir_opt_block_has_phi(irBlock *b) {
|
||||
return b->instrs.e[0]->Instr.kind == irInstr_Phi;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,11 +129,11 @@ bool llir_opt_block_has_phi(llirBlock *b) {
|
||||
|
||||
|
||||
|
||||
llirValueArray llir_get_block_phi_nodes(llirBlock *b) {
|
||||
llirValueArray phis = {0};
|
||||
irValueArray ir_get_block_phi_nodes(irBlock *b) {
|
||||
irValueArray phis = {0};
|
||||
for_array(i, b->instrs) {
|
||||
llirInstr *instr = &b->instrs.e[i]->Instr;
|
||||
if (instr->kind != llirInstr_Phi) {
|
||||
irInstr *instr = &b->instrs.e[i]->Instr;
|
||||
if (instr->kind != irInstr_Phi) {
|
||||
phis = b->instrs;
|
||||
phis.count = i;
|
||||
return phis;
|
||||
@@ -142,15 +142,15 @@ llirValueArray llir_get_block_phi_nodes(llirBlock *b) {
|
||||
return phis;
|
||||
}
|
||||
|
||||
void llir_remove_pred(llirBlock *b, llirBlock *p) {
|
||||
llirValueArray phis = llir_get_block_phi_nodes(b);
|
||||
void ir_remove_pred(irBlock *b, irBlock *p) {
|
||||
irValueArray phis = ir_get_block_phi_nodes(b);
|
||||
isize i = 0;
|
||||
for_array(j, b->preds) {
|
||||
llirBlock *pred = b->preds.e[j];
|
||||
irBlock *pred = b->preds.e[j];
|
||||
if (pred != p) {
|
||||
b->preds.e[i] = b->preds.e[j];
|
||||
for_array(k, phis) {
|
||||
llirInstrPhi *phi = &phis.e[k]->Instr.Phi;
|
||||
irInstrPhi *phi = &phis.e[k]->Instr.Phi;
|
||||
phi->edges.e[i] = phi->edges.e[j];
|
||||
}
|
||||
i++;
|
||||
@@ -158,16 +158,16 @@ void llir_remove_pred(llirBlock *b, llirBlock *p) {
|
||||
}
|
||||
b->preds.count = i;
|
||||
for_array(k, phis) {
|
||||
llirInstrPhi *phi = &phis.e[k]->Instr.Phi;
|
||||
irInstrPhi *phi = &phis.e[k]->Instr.Phi;
|
||||
phi->edges.count = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void llir_remove_dead_blocks(llirProcedure *proc) {
|
||||
void ir_remove_dead_blocks(irProcedure *proc) {
|
||||
isize j = 0;
|
||||
for_array(i, proc->blocks) {
|
||||
llirBlock *b = proc->blocks.e[i];
|
||||
irBlock *b = proc->blocks.e[i];
|
||||
if (b == NULL) {
|
||||
continue;
|
||||
}
|
||||
@@ -178,34 +178,34 @@ void llir_remove_dead_blocks(llirProcedure *proc) {
|
||||
proc->blocks.count = j;
|
||||
}
|
||||
|
||||
void llir_mark_reachable(llirBlock *b) {
|
||||
void ir_mark_reachable(irBlock *b) {
|
||||
isize const WHITE = 0;
|
||||
isize const BLACK = -1;
|
||||
b->index = BLACK;
|
||||
for_array(i, b->succs) {
|
||||
llirBlock *succ = b->succs.e[i];
|
||||
irBlock *succ = b->succs.e[i];
|
||||
if (succ->index == WHITE) {
|
||||
llir_mark_reachable(succ);
|
||||
ir_mark_reachable(succ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void llir_remove_unreachable_blocks(llirProcedure *proc) {
|
||||
void ir_remove_unreachable_blocks(irProcedure *proc) {
|
||||
isize const WHITE = 0;
|
||||
isize const BLACK = -1;
|
||||
for_array(i, proc->blocks) {
|
||||
proc->blocks.e[i]->index = WHITE;
|
||||
}
|
||||
|
||||
llir_mark_reachable(proc->blocks.e[0]);
|
||||
ir_mark_reachable(proc->blocks.e[0]);
|
||||
|
||||
for_array(i, proc->blocks) {
|
||||
llirBlock *b = proc->blocks.e[i];
|
||||
irBlock *b = proc->blocks.e[i];
|
||||
if (b->index == WHITE) {
|
||||
for_array(j, b->succs) {
|
||||
llirBlock *c = b->succs.e[j];
|
||||
irBlock *c = b->succs.e[j];
|
||||
if (c->index == BLACK) {
|
||||
llir_remove_pred(c, b);
|
||||
ir_remove_pred(c, b);
|
||||
}
|
||||
}
|
||||
// NOTE(bill): Mark as empty but don't actually free it
|
||||
@@ -213,26 +213,26 @@ void llir_remove_unreachable_blocks(llirProcedure *proc) {
|
||||
proc->blocks.e[i] = NULL;
|
||||
}
|
||||
}
|
||||
llir_remove_dead_blocks(proc);
|
||||
ir_remove_dead_blocks(proc);
|
||||
}
|
||||
|
||||
bool llir_opt_block_fusion(llirProcedure *proc, llirBlock *a) {
|
||||
bool ir_opt_block_fusion(irProcedure *proc, irBlock *a) {
|
||||
if (a->succs.count != 1) {
|
||||
return false;
|
||||
}
|
||||
llirBlock *b = a->succs.e[0];
|
||||
irBlock *b = a->succs.e[0];
|
||||
if (b->preds.count != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (llir_opt_block_has_phi(b)) {
|
||||
if (ir_opt_block_has_phi(b)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
array_pop(&a->instrs); // Remove branch at end
|
||||
for_array(i, b->instrs) {
|
||||
array_add(&a->instrs, b->instrs.e[i]);
|
||||
llir_set_instr_parent(b->instrs.e[i], a);
|
||||
ir_set_instr_parent(b->instrs.e[i], a);
|
||||
}
|
||||
|
||||
array_clear(&a->succs);
|
||||
@@ -242,28 +242,28 @@ bool llir_opt_block_fusion(llirProcedure *proc, llirBlock *a) {
|
||||
|
||||
// Fix preds links
|
||||
for_array(i, b->succs) {
|
||||
llir_opt_block_replace_pred(b->succs.e[i], b, a);
|
||||
ir_opt_block_replace_pred(b->succs.e[i], b, a);
|
||||
}
|
||||
|
||||
proc->blocks.e[b->index] = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
void llir_opt_blocks(llirProcedure *proc) {
|
||||
llir_remove_unreachable_blocks(proc);
|
||||
void ir_opt_blocks(irProcedure *proc) {
|
||||
ir_remove_unreachable_blocks(proc);
|
||||
|
||||
#if 1
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
for_array(i, proc->blocks) {
|
||||
llirBlock *b = proc->blocks.e[i];
|
||||
irBlock *b = proc->blocks.e[i];
|
||||
if (b == NULL) {
|
||||
continue;
|
||||
}
|
||||
GB_ASSERT(b->index == i);
|
||||
|
||||
if (llir_opt_block_fusion(proc, b)) {
|
||||
if (ir_opt_block_fusion(proc, b)) {
|
||||
changed = true;
|
||||
}
|
||||
// TODO(bill): other simple block optimizations
|
||||
@@ -271,25 +271,25 @@ void llir_opt_blocks(llirProcedure *proc) {
|
||||
}
|
||||
#endif
|
||||
|
||||
llir_remove_dead_blocks(proc);
|
||||
ir_remove_dead_blocks(proc);
|
||||
}
|
||||
void llir_opt_build_referrers(llirProcedure *proc) {
|
||||
void ir_opt_build_referrers(irProcedure *proc) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||
|
||||
llirValueArray ops = {0}; // NOTE(bill): Act as a buffer
|
||||
irValueArray ops = {0}; // NOTE(bill): Act as a buffer
|
||||
array_init_reserve(&ops, proc->module->tmp_allocator, 64); // HACK(bill): This _could_ overflow the temp arena
|
||||
for_array(i, proc->blocks) {
|
||||
llirBlock *b = proc->blocks.e[i];
|
||||
irBlock *b = proc->blocks.e[i];
|
||||
for_array(j, b->instrs) {
|
||||
llirValue *instr = b->instrs.e[j];
|
||||
irValue *instr = b->instrs.e[j];
|
||||
array_clear(&ops);
|
||||
llir_opt_add_operands(&ops, &instr->Instr);
|
||||
ir_opt_add_operands(&ops, &instr->Instr);
|
||||
for_array(k, ops) {
|
||||
llirValue *op = ops.e[k];
|
||||
irValue *op = ops.e[k];
|
||||
if (op == NULL) {
|
||||
continue;
|
||||
}
|
||||
llirValueArray *refs = llir_value_referrers(op);
|
||||
irValueArray *refs = ir_value_referrers(op);
|
||||
if (refs != NULL) {
|
||||
array_add(refs, instr);
|
||||
}
|
||||
@@ -308,36 +308,36 @@ void llir_opt_build_referrers(llirProcedure *proc) {
|
||||
|
||||
// State of Lengauer-Tarjan algorithm
|
||||
// Based on this paper: http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf
|
||||
typedef struct llirLTState {
|
||||
typedef struct irLTState {
|
||||
isize count;
|
||||
// NOTE(bill): These are arrays
|
||||
llirBlock **sdom; // Semidominator
|
||||
llirBlock **parent; // Parent in DFS traversal of CFG
|
||||
llirBlock **ancestor;
|
||||
} llirLTState;
|
||||
irBlock **sdom; // Semidominator
|
||||
irBlock **parent; // Parent in DFS traversal of CFG
|
||||
irBlock **ancestor;
|
||||
} irLTState;
|
||||
|
||||
// §2.2 - bottom of page
|
||||
void llir_lt_link(llirLTState *lt, llirBlock *p, llirBlock *q) {
|
||||
void ir_lt_link(irLTState *lt, irBlock *p, irBlock *q) {
|
||||
lt->ancestor[q->index] = p;
|
||||
}
|
||||
|
||||
i32 llir_lt_depth_first_search(llirLTState *lt, llirBlock *p, i32 i, llirBlock **preorder) {
|
||||
i32 ir_lt_depth_first_search(irLTState *lt, irBlock *p, i32 i, irBlock **preorder) {
|
||||
preorder[i] = p;
|
||||
p->dom.pre = i++;
|
||||
lt->sdom[p->index] = p;
|
||||
llir_lt_link(lt, NULL, p);
|
||||
ir_lt_link(lt, NULL, p);
|
||||
for_array(index, p->succs) {
|
||||
llirBlock *q = p->succs.e[index];
|
||||
irBlock *q = p->succs.e[index];
|
||||
if (lt->sdom[q->index] == NULL) {
|
||||
lt->parent[q->index] = p;
|
||||
i = llir_lt_depth_first_search(lt, q, i, preorder);
|
||||
i = ir_lt_depth_first_search(lt, q, i, preorder);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
llirBlock *llir_lt_eval(llirLTState *lt, llirBlock *v) {
|
||||
llirBlock *u = v;
|
||||
irBlock *ir_lt_eval(irLTState *lt, irBlock *v) {
|
||||
irBlock *u = v;
|
||||
for (;
|
||||
lt->ancestor[v->index] != NULL;
|
||||
v = lt->ancestor[v->index]) {
|
||||
@@ -348,16 +348,16 @@ llirBlock *llir_lt_eval(llirLTState *lt, llirBlock *v) {
|
||||
return u;
|
||||
}
|
||||
|
||||
typedef struct llirDomPrePost {
|
||||
typedef struct irDomPrePost {
|
||||
i32 pre, post;
|
||||
} llirDomPrePost;
|
||||
} irDomPrePost;
|
||||
|
||||
llirDomPrePost llir_opt_number_dom_tree(llirBlock *v, i32 pre, i32 post) {
|
||||
llirDomPrePost result = {pre, post};
|
||||
irDomPrePost ir_opt_number_dom_tree(irBlock *v, i32 pre, i32 post) {
|
||||
irDomPrePost result = {pre, post};
|
||||
|
||||
v->dom.pre = pre++;
|
||||
for_array(i, v->dom.children) {
|
||||
result = llir_opt_number_dom_tree(v->dom.children.e[i], result.pre, result.post);
|
||||
result = ir_opt_number_dom_tree(v->dom.children.e[i], result.pre, result.post);
|
||||
}
|
||||
v->dom.post = post++;
|
||||
|
||||
@@ -367,35 +367,35 @@ llirDomPrePost llir_opt_number_dom_tree(llirBlock *v, i32 pre, i32 post) {
|
||||
}
|
||||
|
||||
|
||||
// NOTE(bill): Requires `llir_opt_blocks` to be called before this
|
||||
void llir_opt_build_dom_tree(llirProcedure *proc) {
|
||||
// NOTE(bill): Requires `ir_opt_blocks` to be called before this
|
||||
void ir_opt_build_dom_tree(irProcedure *proc) {
|
||||
// Based on this paper: http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||
|
||||
isize n = proc->blocks.count;
|
||||
llirBlock **buf = gb_alloc_array(proc->module->tmp_allocator, llirBlock *, 5*n);
|
||||
irBlock **buf = gb_alloc_array(proc->module->tmp_allocator, irBlock *, 5*n);
|
||||
|
||||
llirLTState lt = {0};
|
||||
irLTState lt = {0};
|
||||
lt.count = n;
|
||||
lt.sdom = &buf[0*n];
|
||||
lt.parent = &buf[1*n];
|
||||
lt.ancestor = &buf[2*n];
|
||||
|
||||
llirBlock **preorder = &buf[3*n];
|
||||
llirBlock **buckets = &buf[4*n];
|
||||
llirBlock *root = proc->blocks.e[0];
|
||||
irBlock **preorder = &buf[3*n];
|
||||
irBlock **buckets = &buf[4*n];
|
||||
irBlock *root = proc->blocks.e[0];
|
||||
|
||||
// Step 1 - number vertices
|
||||
i32 pre_num = llir_lt_depth_first_search(<, root, 0, preorder);
|
||||
i32 pre_num = ir_lt_depth_first_search(<, root, 0, preorder);
|
||||
gb_memmove(buckets, preorder, n*gb_size_of(preorder[0]));
|
||||
|
||||
for (i32 i = n-1; i > 0; i--) {
|
||||
llirBlock *w = preorder[i];
|
||||
irBlock *w = preorder[i];
|
||||
|
||||
// Step 3 - Implicitly define idom for nodes
|
||||
for (llirBlock *v = buckets[i]; v != w; v = buckets[v->dom.pre]) {
|
||||
llirBlock *u = llir_lt_eval(<, v);
|
||||
for (irBlock *v = buckets[i]; v != w; v = buckets[v->dom.pre]) {
|
||||
irBlock *u = ir_lt_eval(<, v);
|
||||
if (lt.sdom[u->index]->dom.pre < i) {
|
||||
v->dom.idom = u;
|
||||
} else {
|
||||
@@ -406,14 +406,14 @@ void llir_opt_build_dom_tree(llirProcedure *proc) {
|
||||
// Step 2 - Compute all sdoms
|
||||
lt.sdom[w->index] = lt.parent[w->index];
|
||||
for_array(pred_index, w->preds) {
|
||||
llirBlock *v = w->preds.e[pred_index];
|
||||
llirBlock *u = llir_lt_eval(<, v);
|
||||
irBlock *v = w->preds.e[pred_index];
|
||||
irBlock *u = ir_lt_eval(<, v);
|
||||
if (lt.sdom[u->index]->dom.pre < lt.sdom[w->index]->dom.pre) {
|
||||
lt.sdom[w->index] = lt.sdom[u->index];
|
||||
}
|
||||
}
|
||||
|
||||
llir_lt_link(<, lt.parent[w->index], w);
|
||||
ir_lt_link(<, lt.parent[w->index], w);
|
||||
|
||||
if (lt.parent[w->index] == lt.sdom[w->index]) {
|
||||
w->dom.idom = lt.parent[w->index];
|
||||
@@ -424,13 +424,13 @@ void llir_opt_build_dom_tree(llirProcedure *proc) {
|
||||
}
|
||||
|
||||
// The rest of Step 3
|
||||
for (llirBlock *v = buckets[0]; v != root; v = buckets[v->dom.pre]) {
|
||||
for (irBlock *v = buckets[0]; v != root; v = buckets[v->dom.pre]) {
|
||||
v->dom.idom = root;
|
||||
}
|
||||
|
||||
// Step 4 - Explicitly define idom for nodes (in preorder)
|
||||
for (isize i = 1; i < n; i++) {
|
||||
llirBlock *w = preorder[i];
|
||||
irBlock *w = preorder[i];
|
||||
if (w == root) {
|
||||
w->dom.idom = NULL;
|
||||
} else {
|
||||
@@ -449,32 +449,32 @@ void llir_opt_build_dom_tree(llirProcedure *proc) {
|
||||
}
|
||||
}
|
||||
|
||||
llir_opt_number_dom_tree(root, 0, 0);
|
||||
ir_opt_number_dom_tree(root, 0, 0);
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
void llir_opt_mem2reg(llirProcedure *proc) {
|
||||
// TODO(bill): llir_opt_mem2reg
|
||||
void ir_opt_mem2reg(irProcedure *proc) {
|
||||
// TODO(bill): ir_opt_mem2reg
|
||||
}
|
||||
|
||||
|
||||
|
||||
void llir_opt_tree(llirGen *s) {
|
||||
void ir_opt_tree(irGen *s) {
|
||||
s->opt_called = true;
|
||||
|
||||
for_array(member_index, s->module.procs) {
|
||||
llirProcedure *proc = s->module.procs.e[member_index];
|
||||
irProcedure *proc = s->module.procs.e[member_index];
|
||||
if (proc->blocks.count == 0) { // Prototype/external procedure
|
||||
continue;
|
||||
}
|
||||
|
||||
llir_opt_blocks(proc);
|
||||
ir_opt_blocks(proc);
|
||||
#if 1
|
||||
llir_opt_build_referrers(proc);
|
||||
llir_opt_build_dom_tree(proc);
|
||||
ir_opt_build_referrers(proc);
|
||||
ir_opt_build_dom_tree(proc);
|
||||
|
||||
// TODO(bill): llir optimization
|
||||
// TODO(bill): ir optimization
|
||||
// [ ] cse (common-subexpression) elim
|
||||
// [ ] copy elim
|
||||
// [ ] dead code elim
|
||||
@@ -485,10 +485,10 @@ void llir_opt_tree(llirGen *s) {
|
||||
// [ ] lift/mem2reg
|
||||
// [ ] lift/mem2reg
|
||||
|
||||
llir_opt_mem2reg(proc);
|
||||
ir_opt_mem2reg(proc);
|
||||
#endif
|
||||
|
||||
GB_ASSERT(proc->blocks.count > 0);
|
||||
llir_number_proc_registers(proc);
|
||||
ir_number_proc_registers(proc);
|
||||
}
|
||||
}
|
||||
1515
src/ir_print.c
Normal file
1515
src/ir_print.c
Normal file
File diff suppressed because it is too large
Load Diff
5794
src/llir.c
5794
src/llir.c
File diff suppressed because it is too large
Load Diff
1515
src/llir_print.c
1515
src/llir_print.c
File diff suppressed because it is too large
Load Diff
31
src/main.c
31
src/main.c
@@ -10,9 +10,10 @@ extern "C" {
|
||||
#include "parser.c"
|
||||
// #include "printer.c"
|
||||
#include "checker/checker.c"
|
||||
#include "llir.c"
|
||||
#include "llir_opt.c"
|
||||
#include "llir_print.c"
|
||||
// #include "ssa.c"
|
||||
#include "ir.c"
|
||||
#include "ir_opt.c"
|
||||
#include "ir_print.c"
|
||||
// #include "vm.c"
|
||||
|
||||
// NOTE(bill): `name` is used in debugging and profiling modes
|
||||
@@ -158,29 +159,39 @@ int main(int argc, char **argv) {
|
||||
|
||||
|
||||
#endif
|
||||
// if (global_error_collector.count != 0) {
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
// if (checker.parser->total_token_count < 2) {
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
// ssa_generate(&checker.info, &build_context);
|
||||
|
||||
#if 1
|
||||
|
||||
llirGen llir = {0};
|
||||
if (!llir_gen_init(&llir, &checker, &build_context)) {
|
||||
irGen ir_gen = {0};
|
||||
if (!ir_gen_init(&ir_gen, &checker, &build_context)) {
|
||||
return 1;
|
||||
}
|
||||
// defer (ssa_gen_destroy(&llir));
|
||||
// defer (ssa_gen_destroy(&ir_gen));
|
||||
|
||||
timings_start_section(&timings, str_lit("llvm ir gen"));
|
||||
llir_gen_tree(&llir);
|
||||
ir_gen_tree(&ir_gen);
|
||||
|
||||
timings_start_section(&timings, str_lit("llvm ir opt tree"));
|
||||
llir_opt_tree(&llir);
|
||||
ir_opt_tree(&ir_gen);
|
||||
|
||||
timings_start_section(&timings, str_lit("llvm ir print"));
|
||||
print_llvm_ir(&llir);
|
||||
print_llvm_ir(&ir_gen);
|
||||
|
||||
// prof_print_all();
|
||||
|
||||
#if 1
|
||||
timings_start_section(&timings, str_lit("llvm-opt"));
|
||||
|
||||
char const *output_name = llir.output_file.filename;
|
||||
char const *output_name = ir_gen.output_file.filename;
|
||||
isize base_name_len = gb_path_extension(output_name)-1 - output_name;
|
||||
String output = make_string(cast(u8 *)output_name, base_name_len);
|
||||
|
||||
|
||||
31
src/parser.c
31
src/parser.c
@@ -257,13 +257,6 @@ AST_NODE_KIND(_ComplexStmtEnd, "", i32) \
|
||||
AST_NODE_KIND(_StmtEnd, "", i32) \
|
||||
AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
|
||||
AST_NODE_KIND(GenericDecl, "declaration", struct { \
|
||||
Token token; \
|
||||
Token open, close; \
|
||||
AstNodeArray specs; \
|
||||
u64 tags; \
|
||||
bool is_using; \
|
||||
}) \
|
||||
AST_NODE_KIND(ValueDecl, "value declaration", struct { \
|
||||
bool is_var; \
|
||||
AstNodeArray names; \
|
||||
@@ -491,8 +484,6 @@ Token ast_node_token(AstNode *node) {
|
||||
|
||||
case AstNode_BadDecl:
|
||||
return node->BadDecl.begin;
|
||||
case AstNode_GenericDecl:
|
||||
return node->GenericDecl.token;
|
||||
case AstNode_ValueDecl:
|
||||
return ast_node_token(node->ValueDecl.names.e[0]);
|
||||
case AstNode_ImportDecl:
|
||||
@@ -1066,18 +1057,6 @@ AstNode *make_foreign_library(AstFile *f, Token token, Token filepath, AstNode *
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *make_generic_decl(AstFile *f, Token token, Token open, Token close, AstNodeArray specs, u64 tags, bool is_using) {
|
||||
AstNode *result = make_node(f, AstNode_GenericDecl);
|
||||
result->GenericDecl.token = token;
|
||||
result->GenericDecl.open = open;
|
||||
result->GenericDecl.close = close;
|
||||
result->GenericDecl.specs = specs;
|
||||
result->GenericDecl.tags = tags;
|
||||
result->GenericDecl.is_using = is_using;
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *make_value_decl(AstFile *f, bool is_var, AstNodeArray names, AstNode *type, AstNodeArray values) {
|
||||
AstNode *result = make_node(f, AstNode_ValueDecl);
|
||||
result->ValueDecl.is_var = is_var;
|
||||
@@ -1281,16 +1260,6 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AstNode_GenericDecl:
|
||||
if (s->GenericDecl.close.kind == Token_CloseBrace) {
|
||||
return true;
|
||||
} else if (s->GenericDecl.token.kind == Token_type) {
|
||||
if (f->prev_token.kind == Token_CloseBrace) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user