diff options
| author | gingerBill <bill@gingerbill.org> | 2020-05-17 15:23:27 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2020-05-17 15:23:27 +0100 |
| commit | 3f23a0b3b0c999ae642a447055ee2082f281501b (patch) | |
| tree | 58ffaf0a3196a579e750e2d0b7b978a55ee76875 /src/llvm_backend.cpp | |
| parent | 7819fec0a1758880caf428d438ac3380ab894fc8 (diff) | |
Fix edge cases of relative pointers
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 0b1431472..c0d23019e 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -208,7 +208,7 @@ void lb_emit_slice_bounds_check(lbProcedure *p, Token token, lbValue low, lbValu } } -void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue value) { +void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { if (addr.addr.value == nullptr) { return; } @@ -223,6 +223,10 @@ void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue value) { value.value = LLVMConstNull(lb_type(p->module, t)); } + if (addr.kind == lbAddr_RelativePointer && addr.relative.deref) { + addr = lb_addr(lb_address_from_load(p, lb_addr_load(p, addr))); + } + if (addr.kind == lbAddr_RelativePointer) { Type *rel_ptr = base_type(lb_addr_type(addr)); GB_ASSERT(rel_ptr->kind == Type_RelativePointer); @@ -242,6 +246,11 @@ void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue value) { offset = lb_emit_conv(p, offset, rel_ptr->RelativePointer.base_integer); lbValue offset_ptr = lb_emit_conv(p, addr.addr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + offset = lb_emit_select(p, + lb_emit_comp(p, Token_CmpEq, val_ptr, lb_const_nil(p->module, t_uintptr)), + lb_const_nil(p->module, rel_ptr->RelativePointer.base_integer), + offset + ); LLVMBuildStore(p->builder, offset.value, offset_ptr.value); return; @@ -265,6 +274,11 @@ void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue value) { lbValue offset_ptr = lb_emit_conv(p, addr.addr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + offset = lb_emit_select(p, + lb_emit_comp(p, Token_CmpEq, val_ptr, lb_const_nil(p->module, t_uintptr)), + lb_const_nil(p->module, rel_ptr->RelativePointer.base_integer), + offset + ); LLVMBuildStore(p->builder, offset.value, offset_ptr.value); lbValue len = lb_slice_len(p, value); @@ -6358,6 +6372,17 @@ lbValue lb_address_from_load_or_generate_local(lbProcedure *p, lbValue value) { lb_addr_store(p, res, value); return res.addr; } +lbValue lb_address_from_load(lbProcedure *p, lbValue value) { + if (LLVMIsALoadInst(value.value)) { + lbValue res = {}; + res.value = LLVMGetOperand(value.value, 0); + res.type = alloc_type_pointer(value.type); + return res; + } + + GB_PANIC("lb_address_from_load"); + return {}; +} lbValue lb_copy_value_to_ptr(lbProcedure *p, lbValue val, Type *new_type, i64 alignment) { i64 type_alignment = type_align_of(new_type); @@ -9976,6 +10001,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { case_ast_node(de, DerefExpr, expr); if (is_type_relative_pointer(type_of_expr(de->expr))) { lbAddr addr = lb_build_addr(p, de->expr); + addr.relative.deref = true; return addr; } lbValue addr = lb_build_expr(p, de->expr); |