diff options
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 156 |
1 files changed, 96 insertions, 60 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index d993df8e1..c5cf04ddb 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -160,8 +160,6 @@ gbAllocator ir_allocator(void) { } - - #define IR_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime" #define IR_TYPE_INFO_DATA_NAME "__$type_info_data" #define IR_TYPE_INFO_TYPES_NAME "__$type_info_types_data" @@ -2190,12 +2188,53 @@ irValue *ir_map_cap(irProcedure *proc, irValue *value) { } - void ir_emit_increment(irProcedure *proc, irValue *addr); irValue *ir_emit_array_ep(irProcedure *proc, irValue *s, irValue *index); irValue *ir_emit_array_epi(irProcedure *proc, irValue *s, i32 index); irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index); +struct irLoopData { + irValue *idx_addr; + irValue *idx; + irBlock *body; + irBlock *done; + irBlock *loop; +}; + +irLoopData ir_loop_start(irProcedure *proc, isize count) { + irLoopData data = {}; + + irValue *max = ir_const_int(count); + + data.idx_addr = ir_add_local_generated(proc, t_int); + + data.body = ir_new_block(proc, nullptr, "loop.body"); + data.done = ir_new_block(proc, nullptr, "loop.done"); + data.loop = ir_new_block(proc, nullptr, "loop.loop"); + + ir_emit_jump(proc, data.loop); + ir_start_block(proc, data.loop); + + data.idx = ir_emit_load(proc, data.idx_addr); + + irValue *cond = ir_emit_comp(proc, Token_Lt, data.idx, max); + ir_emit_if(proc, cond, data.body, data.done); + ir_start_block(proc, data.body); + + return data; +} + +void ir_loop_end(irProcedure *proc, irLoopData const &data) { + if (data.idx_addr != nullptr) { + ir_emit_increment(proc, data.idx_addr); + ir_emit_jump(proc, data.loop); + ir_start_block(proc, data.done); + } +} + + + + irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset) { offset = ir_emit_conv(proc, offset, t_int); return ir_emit(proc, ir_instr_ptr_offset(proc, ptr, offset)); @@ -2223,10 +2262,26 @@ irValue *ir_emit_unary_arith(irProcedure *proc, TokenKind op, irValue *x, Type * Type *elem_type = base_array_type(type); irValue *res = ir_add_local_generated(proc, type); - for (i32 i = 0; i < tl->Array.count; i++) { - irValue *e = ir_emit_load(proc, ir_emit_array_epi(proc, val, i)); + + bool inline_array_arith = type_size_of(type) <= build_context.max_align; + + i32 count = cast(i32)tl->Array.count; + + if (inline_array_arith) { + // inline + for (i32 i = 0; i < count; i++) { + irValue *e = ir_emit_load(proc, ir_emit_array_epi(proc, val, i)); + irValue *z = ir_emit_unary_arith(proc, op, e, elem_type); + ir_emit_store(proc, ir_emit_array_epi(proc, res, i), z); + } + } else { + auto loop_data = ir_loop_start(proc, count); + + irValue *e = ir_emit_load(proc, ir_emit_array_ep(proc, val, loop_data.idx)); irValue *z = ir_emit_unary_arith(proc, op, e, elem_type); - ir_emit_store(proc, ir_emit_array_epi(proc, res, i), z); + ir_emit_store(proc, ir_emit_array_ep(proc, res, loop_data.idx), z); + + ir_loop_end(proc, loop_data); } ir_emit_comment(proc, str_lit("array.arith.end")); return ir_emit_load(proc, res); @@ -2266,31 +2321,14 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue * ir_emit_store(proc, ir_emit_array_epi(proc, res, i), z); } } else { - irValue *idx_addr = ir_add_local_generated(proc, t_int); - irValue *max = ir_const_int(count); - - irBlock *body = ir_new_block(proc, nullptr, "array.arith.body"); - irBlock *done = ir_new_block(proc, nullptr, "array.arith.done"); - irBlock *loop = ir_new_block(proc, nullptr, "array.arith.loop"); + auto loop_data = ir_loop_start(proc, count); - ir_emit_jump(proc, loop); - ir_start_block(proc, loop); - - irValue *idx = ir_emit_load(proc, idx_addr); - - irValue *cond = ir_emit_comp(proc, Token_Lt, idx, max); - ir_emit_if(proc, cond, body, done); - ir_start_block(proc, body); - - irValue *x = ir_emit_load(proc, ir_emit_array_ep(proc, lhs, idx)); - irValue *y = ir_emit_load(proc, ir_emit_array_ep(proc, rhs, idx)); + irValue *x = ir_emit_load(proc, ir_emit_array_ep(proc, lhs, loop_data.idx)); + irValue *y = ir_emit_load(proc, ir_emit_array_ep(proc, rhs, loop_data.idx)); irValue *z = ir_emit_arith(proc, op, x, y, elem_type); - ir_emit_store(proc, ir_emit_array_ep(proc, res, idx), z); - - ir_emit_increment(proc, idx_addr); - ir_emit_jump(proc, loop); + ir_emit_store(proc, ir_emit_array_ep(proc, res, loop_data.idx), z); - ir_start_block(proc, done); + ir_loop_end(proc, loop_data); } ir_emit_comment(proc, str_lit("array.arith.end")); return ir_emit_load(proc, res); @@ -2353,6 +2391,7 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue * } +#if 0 if (op == Token_Add) { if (is_type_pointer(t_left)) { irValue *ptr = ir_emit_conv(proc, left, type); @@ -2381,7 +2420,7 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue * return ir_emit_arith(proc, Token_Quo, diff, elem_size, type); } } - +#endif switch (op) { case Token_Shl: @@ -2416,14 +2455,13 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue * } if (op == Token_ModMod) { - irValue *n = left; - irValue *m = right; if (is_type_unsigned(type)) { - return ir_emit_arith(proc, Token_Mod, n, m, type); + op = Token_Mod; + } else { + irValue *a = ir_emit_arith(proc, Token_Mod, left, right, type); + irValue *b = ir_emit_arith(proc, Token_Add, a, right, type); + return ir_emit_arith(proc, Token_Mod, b, right, type); } - irValue *a = ir_emit_arith(proc, Token_Mod, n, m, type); - irValue *b = ir_emit_arith(proc, Token_Add, a, m, type); - return ir_emit_arith(proc, Token_Mod, b, m, type); } return ir_emit(proc, ir_instr_binary_op(proc, op, left, right, type)); @@ -2550,12 +2588,26 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal cmp_op = Token_Or; } - // IMPORTANT TODO(bill): Make this much more efficient - for (i32 i = 0; i < tl->Array.count; i++) { - irValue *x = ir_emit_load(proc, ir_emit_array_epi(proc, lhs, i)); - irValue *y = ir_emit_load(proc, ir_emit_array_epi(proc, rhs, i)); + bool inline_array_arith = type_size_of(tl) <= build_context.max_align; + i32 count = cast(i32)tl->Array.count; + + if (inline_array_arith) { + // inline + for (i32 i = 0; i < count; i++) { + irValue *x = ir_emit_load(proc, ir_emit_array_epi(proc, lhs, i)); + irValue *y = ir_emit_load(proc, ir_emit_array_epi(proc, rhs, i)); + irValue *cmp = ir_emit_comp(proc, op_kind, x, y); + res = ir_emit_arith(proc, cmp_op, res, cmp, t_bool); + } + } else { + auto loop_data = ir_loop_start(proc, count); + + irValue *x = ir_emit_load(proc, ir_emit_array_ep(proc, lhs, loop_data.idx)); + irValue *y = ir_emit_load(proc, ir_emit_array_ep(proc, rhs, loop_data.idx)); irValue *cmp = ir_emit_comp(proc, op_kind, x, y); res = ir_emit_arith(proc, cmp_op, res, cmp, t_bool); + + ir_loop_end(proc, loop_data); } return ir_emit_conv(proc, res, t_bool); @@ -6610,34 +6662,13 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { case_ast_node(bs, EmptyStmt, node); case_end; - // case_ast_node(fb, ForeignBlockDecl, node); - // ir_build_stmt_list(proc, fb->decls); - // case_end; - case_ast_node(us, UsingStmt, node); - for_array(i, us->list) { - Ast *decl = unparen_expr(us->list[i]); - // if (decl->kind == Ast_GenDecl) { - // ir_build_stmt(proc, decl); - // } - } case_end; case_ast_node(ws, WhenStmt, node); ir_build_when_stmt(proc, ws); case_end; - #if 0 - case_ast_node(s, IncDecStmt, node); - TokenKind op = Token_Add; - if (s->op.kind == Token_Dec) { - op = Token_Sub; - } - irAddr const &addr = ir_build_addr(proc, s->expr); - ir_build_assign_op(proc, addr, v_one, op); - case_end; - #endif - case_ast_node(vd, ValueDecl, node); if (vd->is_mutable) { irModule *m = proc->module; @@ -6853,9 +6884,12 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { case_ast_node(is, IfStmt, node); ir_emit_comment(proc, str_lit("IfStmt")); if (is->init != nullptr) { + // TODO(bill): Should this have a separate block to begin with? + #if 1 irBlock *init = ir_new_block(proc, node, "if.init"); ir_emit_jump(proc, init); ir_start_block(proc, init); + #endif ir_build_stmt(proc, is->init); } irBlock *then = ir_new_block(proc, node, "if.then"); @@ -6891,9 +6925,11 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { ir_emit_comment(proc, str_lit("ForStmt")); if (fs->init != nullptr) { + #if 1 irBlock *init = ir_new_block(proc, node, "for.init"); ir_emit_jump(proc, init); ir_start_block(proc, init); + #endif ir_build_stmt(proc, fs->init); } irBlock *body = ir_new_block(proc, node, "for.body"); |