Browse Source

cg_emit_load/cg_emit_store

gingerBill 2 years ago
parent
commit
a8afcf1ca9
4 changed files with 174 additions and 0 deletions
  1. 83 0
      src/tilde_backend.cpp
  2. 3 0
      src/tilde_backend.hpp
  3. 4 0
      src/tilde_expr.cpp
  4. 84 0
      src/tilde_stmt.cpp

+ 83 - 0
src/tilde_backend.cpp

@@ -1,5 +1,88 @@
 #include "tilde_backend.hpp"
 
+// returns TB_TYPE_VOID if not trivially possible
+gb_internal TB_DataType cg_data_type(Type *t) {
+	GB_ASSERT(t != nullptr);
+	t = core_type(t);
+	switch (t->kind) {
+	case Type_Basic:
+		switch (t->Basic.kind) {
+		case Basic_bool: return TB_TYPE_BOOL;
+		case Basic_b8:   return TB_TYPE_BOOL;
+		case Basic_b16:  return TB_TYPE_I16;
+		case Basic_b32:  return TB_TYPE_I32;
+		case Basic_b64:  return TB_TYPE_I64;
+
+		case Basic_i8:   return TB_TYPE_I8;
+		case Basic_u8:   return TB_TYPE_I8;
+		case Basic_i16:  return TB_TYPE_I16;
+		case Basic_u16:  return TB_TYPE_I16;
+		case Basic_i32:  return TB_TYPE_I32;
+		case Basic_u32:  return TB_TYPE_I32;
+		case Basic_i64:  return TB_TYPE_I64;
+		case Basic_u64:  return TB_TYPE_I64;
+		case Basic_i128: return TB_TYPE_I128;
+		case Basic_u128: return TB_TYPE_I128;
+
+		case Basic_rune: return TB_TYPE_I32;
+
+		case Basic_f16: return TB_TYPE_I16;
+		case Basic_f32: return TB_TYPE_F32;
+		case Basic_f64: return TB_TYPE_F64;
+
+		case Basic_int:     return TB_TYPE_INTN(cast(u16)build_context.int_size);
+		case Basic_uint:    return TB_TYPE_INTN(cast(u16)build_context.int_size);
+		case Basic_uintptr: return TB_TYPE_INTN(cast(u16)build_context.ptr_size);
+		case Basic_rawptr:  return TB_TYPE_PTR;
+		case Basic_cstring: return TB_TYPE_PTR;
+
+		case Basic_typeid:  return TB_TYPE_INTN(cast(u16)build_context.ptr_size);
+
+		// Endian Specific Types
+		case Basic_i16le:  return TB_TYPE_I16;
+		case Basic_u16le:  return TB_TYPE_I16;
+		case Basic_i32le:  return TB_TYPE_I32;
+		case Basic_u32le:  return TB_TYPE_I32;
+		case Basic_i64le:  return TB_TYPE_I64;
+		case Basic_u64le:  return TB_TYPE_I64;
+		case Basic_i128le: return TB_TYPE_I128;
+		case Basic_u128le: return TB_TYPE_I128;
+
+		case Basic_i16be:  return TB_TYPE_I16;
+		case Basic_u16be:  return TB_TYPE_I16;
+		case Basic_i32be:  return TB_TYPE_I32;
+		case Basic_u32be:  return TB_TYPE_I32;
+		case Basic_i64be:  return TB_TYPE_I64;
+		case Basic_u64be:  return TB_TYPE_I64;
+		case Basic_i128be: return TB_TYPE_I128;
+		case Basic_u128be: return TB_TYPE_I128;
+
+		case Basic_f16le: return TB_TYPE_I16;
+		case Basic_f32le: return TB_TYPE_F32;
+		case Basic_f64le: return TB_TYPE_F64;
+
+		case Basic_f16be: return TB_TYPE_I16;
+		case Basic_f32be: return TB_TYPE_F32;
+		case Basic_f64be: return TB_TYPE_F64;
+		}
+
+	case Type_Pointer:
+	case Type_MultiPointer:
+	case Type_Proc:
+		return TB_TYPE_PTR;
+
+	case Type_BitSet:
+		return cg_data_type(bit_set_to_int(t));
+
+	case Type_RelativePointer:
+		return cg_data_type(t->RelativePointer.base_integer);
+	}
+
+	// unknown
+	return {};
+}
+
+
 gb_internal cgValue cg_value(TB_Global *g, Type *type) {
 	return cg_value((TB_Symbol *)g, type);
 }

+ 3 - 0
src/tilde_backend.hpp

@@ -7,6 +7,9 @@
 
 #include "tilde/tb.h"
 
+#define TB_TYPE_I128  TB_DataType{ { TB_INT, 0, 128 } }
+
+
 #if defined(GB_SYSTEM_WINDOWS)
 	#pragma warning(pop)
 #endif

+ 4 - 0
src/tilde_expr.cpp

@@ -50,6 +50,10 @@ gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr) {
 	}
 
 	cgValue res = cg_build_expr_internal(p, expr);
+	if (res.kind == cgValue_Symbol) {
+		GB_ASSERT(is_type_pointer(res.type));
+		res = cg_value(tb_inst_get_symbol_address(p->func, res.symbol), res.type);
+	}
 
 	if (expr->state_flags & StateFlag_SelectorCallExpr) {
 		// map_set(&p->selector_values, expr, res);

+ 84 - 0
src/tilde_stmt.cpp

@@ -96,6 +96,90 @@ gb_internal void cg_build_assignment(cgProcedure *p, Array<cgAddr> const &lhs, S
 }
 
 
+gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_volatile=false) {
+	GB_ASSERT(is_type_pointer(ptr.type));
+	Type *type = type_deref(ptr.type);
+	TB_DataType dt = cg_data_type(type);
+
+	if (TB_IS_VOID_TYPE(dt)) {
+		switch (ptr.kind) {
+		case cgValue_Value:
+			return cg_lvalue_addr(ptr.node, type);
+		case cgValue_Addr:
+			GB_PANIC("NOT POSSIBLE");
+			break;
+		case cgValue_Symbol:
+			return cg_lvalue_addr(tb_inst_get_symbol_address(p->func, ptr.symbol), type);
+		}
+	}
+
+	TB_CharUnits alignment = 1; // for the time being
+
+	TB_Node *the_ptr = nullptr;
+	switch (ptr.kind) {
+	case cgValue_Value:
+		the_ptr = ptr.node;
+		break;
+	case cgValue_Addr:
+		the_ptr = tb_inst_load(p->func, TB_TYPE_PTR, ptr.node, alignment, is_volatile);
+		break;
+	case cgValue_Symbol:
+		the_ptr = tb_inst_get_symbol_address(p->func, ptr.symbol);
+		break;
+	}
+	return cg_value(tb_inst_load(p->func, dt, the_ptr, alignment, is_volatile), type);
+}
+
+gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue const &src, bool is_volatile=false) {
+	if (dst.kind == cgValue_Addr) {
+		dst = cg_emit_load(p, dst, is_volatile);
+	} else if (dst.kind = cgValue_Symbol) {
+		dst = cg_value(tb_inst_get_symbol_address(p->func, dst.symbol), dst.type);
+	}
+
+	GB_ASSERT(is_type_pointer(dst.type));
+	Type *dst_type = type_deref(dst.type);
+
+	GB_ASSERT_MSG(are_types_identical(dst_type, src.type), "%s vs %s", type_to_string(dst_type), type_to_string(src.type));
+
+	TB_DataType dt = cg_data_type(dst_type);
+	TB_DataType st = cg_data_type(src.type);
+	GB_ASSERT(dt.raw == st.raw);
+
+	if (TB_IS_VOID_TYPE(dt)) {
+		// TODO(bill): needs to be memmove
+		GB_PANIC("todo emit store to aggregate type");
+		return;
+	}
+
+	TB_CharUnits alignment = 1; // for the time being
+
+	switch (dst.kind) {
+	case cgValue_Value:
+		switch (dst.kind) {
+		case cgValue_Value:
+			tb_inst_store(p->func, dt, dst.node, src.node, alignment, is_volatile);
+			return;
+		case cgValue_Addr:
+			tb_inst_store(p->func, dt, dst.node,
+			              tb_inst_load(p->func, st, src.node, alignment, is_volatile),
+			              alignment, is_volatile);
+			return;
+		case cgValue_Symbol:
+			tb_inst_store(p->func, dt, dst.node,
+			              tb_inst_get_symbol_address(p->func, src.symbol),
+			              alignment, is_volatile);
+			return;
+		}
+	case cgValue_Addr:
+	case cgValue_Symbol:
+		GB_PANIC("should be handled above");
+		break;
+	}
+}
+
+
+
 gb_internal void cg_build_assign_stmt(cgProcedure *p, AstAssignStmt *as) {
 	if (as->op.kind == Token_Eq) {
 		auto lvals = array_make<cgAddr>(permanent_allocator(), 0, as->lhs.count);