diff options
| author | gingerBill <bill@gingerbill.org> | 2020-03-04 22:09:58 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2020-03-04 22:09:58 +0000 |
| commit | e1da631d2620d87085f1a288e57ba39e1d7e92e5 (patch) | |
| tree | 9c80cab406f2d94f49f129838bba317c480cae12 /src/llvm_backend.cpp | |
| parent | 6151fdb324714c0350f5c3731357cdf7243ade97 (diff) | |
General functionality without `context`
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 227 |
1 files changed, 205 insertions, 22 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index b4231d61a..3657eec60 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1196,13 +1196,17 @@ lbValue lb_add_param(lbProcedure *p, Entity *e, Ast *expr, Type *abi_type, i32 i return {}; } - void lb_start_block(lbProcedure *p, lbBlock *b) { GB_ASSERT(b != nullptr); - p->curr_block = b; + if (!b->appended) { + b->appended = true; + LLVMAppendExistingBasicBlock(p->value, b->block); + } LLVMPositionBuilderAtEnd(p->builder, b->block); + p->curr_block = b; } + void lb_begin_procedure_body(lbProcedure *p) { DeclInfo *decl = decl_info_of_entity(p->entity); if (decl != nullptr) { @@ -1215,8 +1219,8 @@ void lb_begin_procedure_body(lbProcedure *p) { p->builder = LLVMCreateBuilder(); - p->decl_block = lb_create_block(p, "decls"); - p->entry_block = lb_create_block(p, "entry"); + p->decl_block = lb_create_block(p, "decls", true); + p->entry_block = lb_create_block(p, "entry", true); lb_start_block(p, p->entry_block); GB_ASSERT(p->type != nullptr); @@ -1391,9 +1395,15 @@ void lb_add_edge(lbBlock *from, lbBlock *to) { } -lbBlock *lb_create_block(lbProcedure *p, char const *name) { +lbBlock *lb_create_block(lbProcedure *p, char const *name, bool append) { lbBlock *b = gb_alloc_item(heap_allocator(), lbBlock); - b->block = LLVMAppendBasicBlockInContext(p->module->ctx, p->value, name); + b->block = LLVMCreateBasicBlockInContext(p->module->ctx, name); + b->appended = false; + if (append) { + b->appended = true; + LLVMAppendExistingBasicBlock(p->value, b->block); + } + b->scope = p->curr_scope; b->scope_index = p->scope_index; @@ -1431,7 +1441,10 @@ void lb_emit_if(lbProcedure *p, lbValue cond, lbBlock *true_block, lbBlock *fals lb_add_edge(b, true_block); lb_add_edge(b, false_block); - LLVMBuildCondBr(p->builder, cond.value, true_block->block, false_block->block); + + LLVMValueRef cv = cond.value; + cv = LLVMBuildTruncOrBitCast(p->builder, cv, lb_type(p->module, t_llvm_bool), ""); + LLVMBuildCondBr(p->builder, cv, true_block->block, false_block->block); } lbValue lb_build_cond(lbProcedure *p, Ast *cond, lbBlock *true_block, lbBlock *false_block) { @@ -2689,8 +2702,9 @@ lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast lb_start_block(p, rhs); lbValue edge = lb_build_expr(p, right); + incoming_values[done->preds.count] = edge.value; - incoming_blocks[done->preds.count] = rhs->block; + incoming_blocks[done->preds.count] = p->curr_block->block; lb_emit_jump(p, done); lb_start_block(p, done); @@ -2698,10 +2712,10 @@ lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast lbValue res = {}; res.type = type; res.value = LLVMBuildPhi(p->builder, lb_type(m, type), ""); - + GB_ASSERT(incoming_values.count == incoming_blocks.count); LLVMAddIncoming(res.value, incoming_values.data, incoming_blocks.data, cast(unsigned)incoming_values.count); - return res; + return short_circuit; } @@ -4031,11 +4045,8 @@ lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type) switch (op) { case Token_Not: // Boolean not - res.value = LLVMBuildNot(p->builder, x.value, ""); - res.type = x.type; - return res; case Token_Xor: // Bitwise not - res.value = LLVMBuildXor(p->builder, x.value, LLVMConstAllOnes(lb_type(p->module, x.type)), ""); + res.value = LLVMBuildNot(p->builder, x.value, ""); res.type = x.type; return res; case Token_Sub: // Number negation @@ -4058,14 +4069,172 @@ lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type) lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type) { lbModule *m = p->module; + if (is_type_array(lhs.type) || is_type_array(rhs.type)) { + lhs = lb_emit_conv(p, lhs, type); + rhs = lb_emit_conv(p, rhs, type); + + lbValue x = lb_address_from_load_or_generate_local(p, lhs); + lbValue y = lb_address_from_load_or_generate_local(p, rhs); + + GB_ASSERT(is_type_array(type)); + Type *elem_type = base_array_type(type); + + lbAddr res = lb_add_local_generated(p, type, false); + i64 count = base_type(type)->Array.count; + + bool inline_array_arith = type_size_of(type) <= build_context.max_align; + + if (inline_array_arith) { + for (i64 i = 0; i < count; i++) { + lbValue a = lb_emit_load(p, lb_emit_array_epi(p, x, i)); + lbValue b = lb_emit_load(p, lb_emit_array_epi(p, y, i)); + lbValue c = lb_emit_arith(p, op, a, b, elem_type); + lb_emit_store(p, lb_emit_array_epi(p, res.addr, i), c); + } + } else { + auto loop_data = lb_loop_start(p, count); + + lbValue a = lb_emit_load(p, lb_emit_array_ep(p, x, loop_data.idx)); + lbValue b = lb_emit_load(p, lb_emit_array_ep(p, y, loop_data.idx)); + lbValue c = lb_emit_arith(p, op, a, b, elem_type); + lb_emit_store(p, lb_emit_array_ep(p, res.addr, loop_data.idx), c); + + lb_loop_end(p, loop_data); + } + + return lb_addr_load(p, res); + } else if (is_type_complex(type)) { + lhs = lb_emit_conv(p, lhs, type); + rhs = lb_emit_conv(p, rhs, type); + + Type *ft = base_complex_elem_type(type); + + if (op == Token_Quo) { + auto args = array_make<lbValue>(heap_allocator(), 2); + args[0] = lhs; + args[1] = rhs; + + switch (type_size_of(ft)) { + case 4: return lb_emit_runtime_call(p, "quo_complex64", args); + case 8: return lb_emit_runtime_call(p, "quo_complex128", args); + default: GB_PANIC("Unknown float type"); break; + } + } + + lbAddr res = lb_add_local_generated(p, type, false); // NOTE: initialized in full later + lbValue a = lb_emit_struct_ev(p, lhs, 0); + lbValue b = lb_emit_struct_ev(p, lhs, 1); + lbValue c = lb_emit_struct_ev(p, rhs, 0); + lbValue d = lb_emit_struct_ev(p, rhs, 1); + + lbValue real = {}; + lbValue imag = {}; + + switch (op) { + case Token_Add: + real = lb_emit_arith(p, Token_Add, a, c, ft); + imag = lb_emit_arith(p, Token_Add, b, d, ft); + break; + case Token_Sub: + real = lb_emit_arith(p, Token_Sub, a, c, ft); + imag = lb_emit_arith(p, Token_Sub, b, d, ft); + break; + case Token_Mul: { + lbValue x = lb_emit_arith(p, Token_Mul, a, c, ft); + lbValue y = lb_emit_arith(p, Token_Mul, b, d, ft); + real = lb_emit_arith(p, Token_Sub, x, y, ft); + lbValue z = lb_emit_arith(p, Token_Mul, b, c, ft); + lbValue w = lb_emit_arith(p, Token_Mul, a, d, ft); + imag = lb_emit_arith(p, Token_Add, z, w, ft); + break; + } + } + + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 0), real); + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 1), imag); + + return lb_addr_load(p, res); + } else if (is_type_quaternion(type)) { + lhs = lb_emit_conv(p, lhs, type); + rhs = lb_emit_conv(p, rhs, type); + + Type *ft = base_complex_elem_type(type); + + if (op == Token_Add || op == Token_Sub) { + lbAddr res = lb_add_local_generated(p, type, false); // NOTE: initialized in full later + lbValue x0 = lb_emit_struct_ev(p, lhs, 0); + lbValue x1 = lb_emit_struct_ev(p, lhs, 1); + lbValue x2 = lb_emit_struct_ev(p, lhs, 2); + lbValue x3 = lb_emit_struct_ev(p, lhs, 3); + + lbValue y0 = lb_emit_struct_ev(p, rhs, 0); + lbValue y1 = lb_emit_struct_ev(p, rhs, 1); + lbValue y2 = lb_emit_struct_ev(p, rhs, 2); + lbValue y3 = lb_emit_struct_ev(p, rhs, 3); + + lbValue z0 = lb_emit_arith(p, op, x0, y0, ft); + lbValue z1 = lb_emit_arith(p, op, x1, y1, ft); + lbValue z2 = lb_emit_arith(p, op, x2, y2, ft); + lbValue z3 = lb_emit_arith(p, op, x3, y3, ft); + + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 0), z0); + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 1), z1); + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 2), z2); + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 3), z3); + + return lb_addr_load(p, res); + } else if (op == Token_Mul) { + auto args = array_make<lbValue>(heap_allocator(), 2); + args[0] = lhs; + args[1] = rhs; + + switch (8*type_size_of(ft)) { + case 32: return lb_emit_runtime_call(p, "mul_quaternion128", args); + case 64: return lb_emit_runtime_call(p, "mul_quaternion256", args); + default: GB_PANIC("Unknown float type"); break; + } + } else if (op == Token_Quo) { + auto args = array_make<lbValue>(heap_allocator(), 2); + args[0] = lhs; + args[1] = rhs; + + switch (8*type_size_of(ft)) { + case 32: return lb_emit_runtime_call(p, "quo_quaternion128", args); + case 64: return lb_emit_runtime_call(p, "quo_quaternion256", args); + default: GB_PANIC("Unknown float type"); break; + } + } + } + + if (is_type_integer(type) && is_type_different_to_arch_endianness(type)) { + switch (op) { + case Token_AndNot: + case Token_And: + case Token_Or: + case Token_Xor: + goto handle_op; + } + + Type *platform_type = integer_endian_type_to_platform_type(type); + lbValue x = lb_emit_byte_swap(p, lhs, integer_endian_type_to_platform_type(lhs.type)); + lbValue y = lb_emit_byte_swap(p, rhs, integer_endian_type_to_platform_type(rhs.type)); + + lbValue res = lb_emit_arith(p, op, x, y, platform_type); + + return lb_emit_byte_swap(p, res, type); + } + + + +handle_op: lhs = lb_emit_conv(p, lhs, type); rhs = lb_emit_conv(p, rhs, type); - lbValue res = {}; res.type = type; + switch (op) { case Token_Add: if (is_type_float(type)) { @@ -4143,8 +4312,7 @@ lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Ty return res; case Token_AndNot: { - LLVMValueRef all_ones = LLVMConstAllOnes(lb_type(m, type)); - LLVMValueRef new_rhs = LLVMBuildXor(p->builder, all_ones, rhs.value, ""); + LLVMValueRef new_rhs = LLVMBuildNot(p->builder, rhs.value, ""); res.value = LLVMBuildAnd(p->builder, lhs.value, new_rhs, ""); return res; } @@ -4852,7 +5020,7 @@ void lb_emit_init_context(lbProcedure *p, lbValue c) { gbAllocator a = heap_allocator(); auto args = array_make<lbValue>(a, 1); args[0] = c.value != nullptr ? c : m->global_default_context.addr; - // lb_emit_runtime_call(p, "__init_context", args); + lb_emit_runtime_call(p, "__init_context", args); } void lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx) { @@ -4866,10 +5034,6 @@ lbAddr lb_find_or_generate_context_ptr(lbProcedure *p) { return p->context_stack[p->context_stack.count-1].ctx; } - // lbBlock *tmp_block = p->curr_block; - // p->curr_block = p->blocks[0]; - // defer (p->curr_block = tmp_block); - lbAddr c = lb_add_local_generated(p, t_context, false); c.kind = lbAddr_Context; lb_push_context_onto_stack(p, c); @@ -6495,10 +6659,29 @@ void lb_emit_increment(lbProcedure *p, lbValue addr) { lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *platform_type) { Type *vt = core_type(value.type); GB_ASSERT(type_size_of(vt) == type_size_of(platform_type)); + GB_ASSERT(is_type_integer(vt)); + // TODO(bill): lb_emit_byte_swap lbValue res = {}; res.type = platform_type; res.value = value.value; + + // int sz = cast(int)type_size_of(vt); + // if (sz > 1) { + // char buf[32] = {}; + // gb_snprintf(buf, gb_count_of(buf), "llvm.bswap.i%d", sz*8); + // unsigned id = LLVMLookupIntrinsicID(buf, gb_strlen(buf)); + // gb_printf(">>> %s %u\n", buf, id); + + // LLVMTypeRef types[2] = {}; + // types[0] = lb_type(p->module, value.type); + // types[1] = lb_type(p->module, value.type); + + // LLVMValueRef fn = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types)); + + // res.value = LLVMBuildCall(p->builder, fn, &value.value, 1, ""); + // } + return res; } |