diff --git a/src/ir.cpp b/src/ir.cpp index 2b3b3e14f..77d40dc52 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4227,6 +4227,28 @@ irValue *ir_addr_get_ptr(irProcedure *proc, irAddr const &addr, bool allow_refer } } + case irAddr_RelativePointer: { + Type *rel_ptr = base_type(ir_addr_type(addr)); + GB_ASSERT(rel_ptr->kind == Type_RelativePointer); + + irValue *ptr = ir_emit_conv(proc, addr.addr, t_uintptr); + irValue *offset = ir_emit_conv(proc, ptr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + offset = ir_emit_load(proc, offset); + + if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) { + offset = ir_emit_conv(proc, offset, t_i64); + } + offset = ir_emit_conv(proc, offset, t_uintptr); + irValue *absolute_ptr = ir_emit_arith(proc, Token_Add, ptr, offset, t_uintptr); + absolute_ptr = ir_emit_conv(proc, absolute_ptr, rel_ptr->RelativePointer.pointer_type); + + irValue *cond = ir_emit_comp(proc, Token_CmpEq, offset, ir_value_nil(rel_ptr->RelativePointer.base_integer)); + + // NOTE(bill): nil check + irValue *nil_ptr = ir_value_nil(rel_ptr->RelativePointer.pointer_type); + irValue *final_ptr = ir_emit_select(proc, cond, nil_ptr, absolute_ptr); + return final_ptr; + } case irAddr_BitField: { irValue *v = ir_addr_load(proc, addr); @@ -5101,6 +5123,10 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { t = t->Opaque.elem; } + if (is_type_relative_pointer(t)) { + s = ir_addr_get_ptr(proc, ir_addr(s)); + } + if (is_type_struct(t)) { result_type = alloc_type_pointer(t->Struct.fields[index]->type); } else if (is_type_union(t)) { @@ -5337,6 +5363,8 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, irValue *e, Selection sel) { e = ir_emit_array_epi(proc, e, index); } else if (type->kind == Type_Map) { e = ir_emit_struct_ep(proc, e, index); + } else if (type->kind == Type_RelativePointer) { + e = ir_emit_struct_ep(proc, e, index); } else { GB_PANIC("un-gep-able type %s", type_to_string(type)); } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 5ba641897..d5b2d9f8d 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -145,6 +145,30 @@ lbValue lb_addr_get_ptr(lbProcedure *p, lbAddr const &addr) { return lb_emit_conv(p, ptr, alloc_type_pointer(map_type->Map.value)); } + + case lbAddr_RelativePointer: { + Type *rel_ptr = base_type(lb_addr_type(addr)); + GB_ASSERT(rel_ptr->kind == Type_RelativePointer); + + lbValue ptr = lb_emit_conv(p, addr.addr, t_uintptr); + lbValue offset = lb_emit_conv(p, ptr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + offset = lb_emit_load(p, offset); + + if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) { + offset = lb_emit_conv(p, offset, t_i64); + } + offset = lb_emit_conv(p, offset, t_uintptr); + lbValue absolute_ptr = lb_emit_arith(p, Token_Add, ptr, offset, t_uintptr); + absolute_ptr = lb_emit_conv(p, absolute_ptr, rel_ptr->RelativePointer.pointer_type); + + lbValue cond = lb_emit_comp(p, Token_CmpEq, offset, lb_const_nil(p->module, rel_ptr->RelativePointer.base_integer)); + + // NOTE(bill): nil check + lbValue nil_ptr = lb_const_nil(p->module, rel_ptr->RelativePointer.pointer_type); + lbValue final_ptr = lb_emit_select(p, cond, nil_ptr, absolute_ptr); + return final_ptr; + } + case lbAddr_BitField: { lbValue v = lb_addr_load(p, addr); return lb_address_from_load_or_generate_local(p, v); @@ -6562,6 +6586,10 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { t = t->Opaque.elem; } + if (is_type_relative_pointer(t)) { + s = lb_addr_get_ptr(p, lb_addr(s)); + } + if (is_type_struct(t)) { result_type = get_struct_field_type(t, index); } else if (is_type_union(t)) { @@ -6809,7 +6837,7 @@ lbValue lb_emit_deep_field_gep(lbProcedure *p, lbValue e, Selection sel) { break; default: - GB_PANIC("un-gep-able type"); + GB_PANIC("un-gep-able type %s", type_to_string(type)); break; } } else if (type->kind == Type_Slice) { @@ -6820,6 +6848,8 @@ lbValue lb_emit_deep_field_gep(lbProcedure *p, lbValue e, Selection sel) { e = lb_emit_array_epi(p, e, index); } else if (type->kind == Type_Map) { e = lb_emit_struct_ep(p, e, index); + } else if (type->kind == Type_RelativePointer) { + e = lb_emit_struct_ep(p, e, index); } else { GB_PANIC("un-gep-able type %s", type_to_string(type)); }