aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorjockus <joakim.hentula@gmail.com>2020-08-27 08:24:59 +0100
committerjockus <joakim.hentula@gmail.com>2020-08-27 08:24:59 +0100
commit914c99a15edf325399fb758605b80fe31d5f4813 (patch)
treece86f022b368fb42a61041e01051c80765b86d64 /src/ir.cpp
parent8de70ce73dd3fc9740a0589e6167d950d02f244d (diff)
parentd31c63c0ae76115d1b9aa8b5d1f8bf7130e74977 (diff)
Merge branch 'master' into fix-core-path-name-extension
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp28
1 files changed, 28 insertions, 0 deletions
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));
}