Browse Source

Relative pointers in old backend

gingerBill 5 years ago
parent
commit
95e8668b77
3 changed files with 102 additions and 16 deletions
  1. 89 15
      src/ir.cpp
  2. 12 0
      src/ir_print.cpp
  3. 1 1
      src/llvm_backend.cpp

+ 89 - 15
src/ir.cpp

@@ -493,6 +493,7 @@ enum irAddrKind {
 	irAddr_BitField,
 	irAddr_Context,
 	irAddr_SoaVariable,
+	irAddr_RelativePointer,
 };
 
 struct irAddr {
@@ -517,8 +518,14 @@ struct irAddr {
 	};
 };
 
+Type *ir_type(irValue *value);
+
 irAddr ir_addr(irValue *addr) {
 	irAddr v = {irAddr_Default, addr};
+	if (addr != nullptr && is_type_relative_pointer(type_deref(ir_type(addr)))) {
+		GB_ASSERT(is_type_pointer(ir_type(addr)));
+		v.kind = irAddr_RelativePointer;
+	}
 	return v;
 }
 
@@ -722,7 +729,6 @@ gb_inline bool ir_min_dep_entity(irModule *m, Entity *e) {
 	return ptr_set_exists(&m->min_dep_set, e);
 }
 
-Type *ir_type(irValue *value);
 Type *ir_instr_type(irInstr *instr) {
 	switch (instr->kind) {
 	case irInstr_Local:
@@ -772,6 +778,9 @@ Type *ir_instr_type(irInstr *instr) {
 }
 
 Type *ir_type(irValue *value) {
+	if (value == nullptr) {
+		return nullptr;
+	}
 	switch (value->kind) {
 	case irValue_Constant:
 		return value->Constant.type;
@@ -3626,7 +3635,27 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
 	if (addr.addr == nullptr) {
 		return;
 	}
-	if (addr.kind == irAddr_Map) {
+	if (addr.kind == irAddr_RelativePointer) {
+		Type *rel_ptr = base_type(ir_addr_type(addr));
+		GB_ASSERT(rel_ptr->kind == Type_RelativePointer);
+
+		value = ir_emit_conv(proc, value, rel_ptr->RelativePointer.pointer_type);
+
+		GB_ASSERT(is_type_pointer(ir_type(addr.addr)));
+		irValue *ptr = ir_emit_conv(proc, addr.addr, t_uintptr);
+		irValue *val_ptr = ir_emit_conv(proc, value, t_uintptr);
+		irValue *offset = offset = ir_emit_arith(proc, Token_Sub, val_ptr, ptr, t_uintptr);
+
+		if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) {
+			offset = ir_emit_conv(proc, offset, t_i64);
+		}
+		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));
+		ir_emit_store(proc, offset_ptr, offset);
+		return;
+
+	} else if (addr.kind == irAddr_Map) {
 		ir_insert_dynamic_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value);
 		return;
 	} else if (addr.kind == irAddr_BitField) {
@@ -3770,7 +3799,31 @@ irValue *ir_addr_load(irProcedure *proc, irAddr const &addr) {
 		return nullptr;
 	}
 
-	if (addr.kind == irAddr_Map) {
+	if (addr.kind == 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 ir_emit_load(proc, final_ptr);
+
+	} else if (addr.kind == irAddr_Map) {
 		Type *map_type = base_type(addr.map_type);
 		irValue *v = ir_add_local_generated(proc, map_type->Map.lookup_result_type, true);
 		irValue *h = ir_gen_map_header(proc, addr.addr, map_type);
@@ -6004,19 +6057,22 @@ irValue *ir_typeid(irModule *m, Type *type) {
 		if (flags & BasicFlag_String)   kind = Typeid_String;
 		if (flags & BasicFlag_Rune)     kind = Typeid_Rune;
 	} break;
-	case Type_Pointer:         kind = Typeid_Pointer;       break;
-	case Type_Array:           kind = Typeid_Array;         break;
+	case Type_Pointer:         kind = Typeid_Pointer;         break;
+	case Type_Array:           kind = Typeid_Array;           break;
 	case Type_EnumeratedArray: kind = Typeid_Enumerated_Array; break;
-	case Type_Slice:           kind = Typeid_Slice;         break;
-	case Type_DynamicArray:    kind = Typeid_Dynamic_Array; break;
-	case Type_Map:             kind = Typeid_Map;           break;
-	case Type_Struct:          kind = Typeid_Struct;        break;
-	case Type_Enum:            kind = Typeid_Enum;          break;
-	case Type_Union:           kind = Typeid_Union;         break;
-	case Type_Tuple:           kind = Typeid_Tuple;         break;
-	case Type_Proc:            kind = Typeid_Procedure;     break;
-	case Type_BitField:        kind = Typeid_Bit_Field;     break;
-	case Type_BitSet:          kind = Typeid_Bit_Set;       break;
+	case Type_Slice:           kind = Typeid_Slice;            break;
+	case Type_DynamicArray:    kind = Typeid_Dynamic_Array;    break;
+	case Type_Map:             kind = Typeid_Map;              break;
+	case Type_Struct:          kind = Typeid_Struct;           break;
+	case Type_Enum:            kind = Typeid_Enum;             break;
+	case Type_Union:           kind = Typeid_Union;            break;
+	case Type_Tuple:           kind = Typeid_Tuple;            break;
+	case Type_Proc:            kind = Typeid_Procedure;        break;
+	case Type_BitField:        kind = Typeid_Bit_Field;        break;
+	case Type_BitSet:          kind = Typeid_Bit_Set;          break;
+	case Type_SimdVector:      kind = Typeid_Simd_Vector;      break;
+	case Type_RelativePointer: kind = Typeid_Relative_Pointer; break;
+	case Type_RelativeSlice:   kind = Typeid_Relative_Slice;   break;
 	}
 
 	if (is_type_cstring(type)) {
@@ -8476,6 +8532,10 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
 	case_end;
 
 	case_ast_node(de, DerefExpr, expr);
+		if (is_type_relative_pointer(type_of_expr(de->expr))) {
+			return ir_build_addr(proc, de->expr);
+		}
+
 		// TODO(bill): Is a ptr copy needed?
 		irValue *addr = ir_build_expr(proc, de->expr);
 		addr = ir_emit_ptr_offset(proc, addr, v_zero);
@@ -11935,6 +11995,20 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 				ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), ir_const_int(t->SimdVector.count));
 			}
 			break;
+
+		case Type_RelativePointer:
+			ir_emit_comment(proc, str_lit("Type_RelativePointer"));
+			tag = ir_emit_conv(proc, variant_ptr, t_type_info_relative_pointer_ptr);
+			ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->RelativePointer.pointer_type));
+			ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->RelativePointer.base_integer));
+			break;
+
+		case Type_RelativeSlice:
+			ir_emit_comment(proc, str_lit("Type_RelativeSlice"));
+			tag = ir_emit_conv(proc, variant_ptr, t_type_info_relative_slice_ptr);
+			ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->RelativePointer.pointer_type));
+			ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->RelativePointer.base_integer));
+			break;
 		}
 
 

+ 12 - 0
src/ir_print.cpp

@@ -669,6 +669,18 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) {
 			ir_write_byte(f, '>');
 		}
 		return;
+
+	case Type_RelativePointer:
+		ir_print_type(f, m, t->RelativePointer.base_integer);
+		return;
+
+	case Type_RelativeSlice:
+		ir_write_byte(f, '{');
+		ir_print_type(f, m, t->RelativePointer.base_integer);
+		ir_write_str_lit(f, ", ");
+		ir_print_type(f, m, t->RelativePointer.base_integer);
+		ir_write_byte(f, '}');
+		return;
 	}
 }
 

+ 1 - 1
src/llvm_backend.cpp

@@ -56,7 +56,7 @@ LLVMValueRef llvm_cstring(lbModule *m, String const &str) {
 
 lbAddr lb_addr(lbValue addr) {
 	lbAddr v = {lbAddr_Default, addr};
-	if (is_type_relative_pointer(type_deref(addr.type))) {
+	if (addr.type != nullptr && is_type_relative_pointer(type_deref(addr.type))) {
 		GB_ASSERT(is_type_pointer(addr.type));
 		v.kind = lbAddr_RelativePointer;
 	}