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/ir.cpp | |
| parent | 7819fec0a1758880caf428d438ac3380ab894fc8 (diff) | |
Fix edge cases of relative pointers
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index b45f6bf85..2127de7b4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -516,6 +516,9 @@ struct irAddr { irValue *index; Ast *index_expr; } soa; + struct { + bool deref; + } relative; }; }; @@ -3523,6 +3526,15 @@ irValue *ir_address_from_load_or_generate_local(irProcedure *proc, irValue *val) ir_emit_store(proc, local, val); return local; } +irValue *ir_address_from_load(irProcedure *proc, irValue *val) { + if (val->kind == irValue_Instr) { + if (val->Instr.kind == irInstr_Load) { + return val->Instr.Load.address; + } + } + GB_PANIC("ir_address_from_load"); + return nullptr; +} Type *ir_addr_type(irAddr const &addr) { @@ -3636,11 +3648,16 @@ irValue *ir_soa_struct_cap(irProcedure *proc, irValue *value) { } +irValue *ir_addr_load(irProcedure *proc, irAddr const &addr); -void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { +void ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) { if (addr.addr == nullptr) { return; } + if (addr.kind == irAddr_RelativePointer && addr.relative.deref) { + addr = ir_addr(ir_address_from_load(proc, ir_addr_load(proc, addr))); + } + if (addr.kind == irAddr_RelativePointer) { Type *rel_ptr = base_type(ir_addr_type(addr)); GB_ASSERT(rel_ptr->kind == Type_RelativePointer); @@ -3658,6 +3675,11 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { offset = ir_emit_conv(proc, offset, rel_ptr->RelativePointer.base_integer); irValue *offset_ptr = ir_emit_conv(proc, addr.addr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + offset = ir_emit_select(proc, + ir_emit_comp(proc, Token_CmpEq, val_ptr, ir_value_nil(t_uintptr)), + ir_value_nil(rel_ptr->RelativePointer.base_integer), + offset + ); ir_emit_store(proc, offset_ptr, offset); return; @@ -3677,8 +3699,12 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { } offset = ir_emit_conv(proc, offset, rel_ptr->RelativePointer.base_integer); - irValue *offset_ptr = ir_emit_conv(proc, addr.addr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + offset = ir_emit_select(proc, + ir_emit_comp(proc, Token_CmpEq, val_ptr, ir_value_nil(t_uintptr)), + ir_value_nil(rel_ptr->RelativePointer.base_integer), + offset + ); ir_emit_store(proc, offset_ptr, offset); irValue *len = ir_slice_len(proc, value); @@ -8603,7 +8629,9 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { case_ast_node(de, DerefExpr, expr); if (is_type_relative_pointer(type_of_expr(de->expr))) { - return ir_build_addr(proc, de->expr); + irAddr addr = ir_build_addr(proc, de->expr); + addr.relative.deref = true; + return addr; } // TODO(bill): Is a ptr copy needed? |