Browse Source

Minor clean up to builtin procs

gingerBill 2 years ago
parent
commit
2f9c5d2d0b
1 changed files with 120 additions and 16 deletions
  1. 120 16
      src/tilde_builtin.cpp

+ 120 - 16
src/tilde_builtin.cpp

@@ -12,6 +12,7 @@ gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value) {
 				return cg_emit_load(p, len_ptr);
 				return cg_emit_load(p, len_ptr);
 			}
 			}
 		case Basic_cstring:
 		case Basic_cstring:
+			GB_PANIC("TODO(bill): len(cstring)");
 			break;
 			break;
 		}
 		}
 		break;
 		break;
@@ -51,6 +52,69 @@ gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value) {
 	return {};
 	return {};
 }
 }
 
 
+gb_internal cgValue cg_builtin_cap(cgProcedure *p, cgValue value) {
+	Type *t = base_type(value.type);
+
+	switch (t->kind) {
+	case Type_Basic:
+		switch (t->Basic.kind) {
+		case Basic_string:
+			{
+				GB_ASSERT(value.kind == cgValue_Addr);
+				cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type));
+				cgValue len_ptr = cg_emit_struct_ep(p, ptr, 1);
+				return cg_emit_load(p, len_ptr);
+			}
+		case Basic_cstring:
+			GB_PANIC("TODO(bill): cap(cstring)");
+			break;
+		}
+		break;
+	case Type_Array:
+		return cg_const_int(p, t_int, t->Array.count);
+	case Type_EnumeratedArray:
+		return cg_const_int(p, t_int, t->EnumeratedArray.count);
+	case Type_Slice:
+		{
+			GB_ASSERT(value.kind == cgValue_Addr);
+			cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type));
+			cgValue len_ptr = cg_emit_struct_ep(p, ptr, 1);
+			return cg_emit_load(p, len_ptr);
+		}
+	case Type_DynamicArray:
+		{
+			GB_ASSERT(value.kind == cgValue_Addr);
+			cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type));
+			cgValue len_ptr = cg_emit_struct_ep(p, ptr, 2);
+			return cg_emit_load(p, len_ptr);
+		}
+	case Type_Map:
+		{
+			TB_DataType dt_uintptr = cg_data_type(t_uintptr);
+			TB_Node *zero = tb_inst_uint(p->func, dt_uintptr, 0);
+			TB_Node *one  = tb_inst_uint(p->func, dt_uintptr, 0);
+			TB_Node *mask = tb_inst_uint(p->func, dt_uintptr, MAP_CACHE_LINE_SIZE-1);
+
+			TB_Node *data = cg_emit_struct_ev(p, value, 0).node;
+			TB_Node *log2_cap = tb_inst_and(p->func, data, mask);
+			TB_Node *cap = tb_inst_shl(p->func, one, log2_cap, cast(TB_ArithmeticBehavior)0);
+			TB_Node *cmp = tb_inst_cmp_eq(p->func, data, zero);
+
+			cgValue res = cg_value(tb_inst_select(p->func, cmp, zero, cap), t_uintptr);
+			return cg_emit_conv(p, res, t_int);
+		}
+	case Type_Struct:
+		GB_ASSERT(is_type_soa_struct(t));
+		break;
+	case Type_RelativeSlice:
+		break;
+	}
+
+	GB_PANIC("TODO(bill): cg_builtin_cap %s", type_to_string(t));
+	return {};
+}
+
+
 gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &value) {
 gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &value) {
 	Type *t = base_type(value.type);
 	Type *t = base_type(value.type);
 	cgValue res = {};
 	cgValue res = {};
@@ -108,7 +172,7 @@ gb_internal cgValue cg_builtin_max(cgProcedure *p, Type *t, cgValue x, cgValue y
 	return cg_emit_select(p, cg_emit_comp(p, Token_Gt, x, y), x, y);
 	return cg_emit_select(p, cg_emit_comp(p, Token_Gt, x, y), x, y);
 }
 }
 
 
-gb_internal cgValue cg_builtin_abs(cgProcedure *p, cgValue x) {
+gb_internal cgValue cg_builtin_abs(cgProcedure *p, cgValue const &x) {
 	if (is_type_unsigned(x.type)) {
 	if (is_type_unsigned(x.type)) {
 		return x;
 		return x;
 	}
 	}
@@ -138,6 +202,39 @@ gb_internal cgValue cg_builtin_abs(cgProcedure *p, cgValue x) {
 	return cg_emit_select(p, cond, neg, x);
 	return cg_emit_select(p, cond, neg, x);
 }
 }
 
 
+gb_internal cgValue cg_builtin_clamp(cgProcedure *p, Type *t, cgValue const &x, cgValue const &min, cgValue const &max) {
+	cgValue z = x;
+	z = cg_builtin_max(p, t, z, min);
+	z = cg_builtin_min(p, t, z, max);
+	return z;
+}
+
+
+
+gb_internal cgValue cg_builtin_mem_zero(cgProcedure *p, cgValue const &ptr, cgValue const &len) {
+	GB_ASSERT(ptr.kind == cgValue_Value);
+	GB_ASSERT(len.kind == cgValue_Value);
+	tb_inst_memzero(p->func, ptr.node, len.node, 1, false);
+	return ptr;
+}
+
+gb_internal cgValue cg_builtin_mem_copy(cgProcedure *p, cgValue const &dst, cgValue const &src, cgValue const &len) {
+	GB_ASSERT(dst.kind == cgValue_Value);
+	GB_ASSERT(src.kind == cgValue_Value);
+	GB_ASSERT(len.kind == cgValue_Value);
+	// TODO(bill): This needs to be memmove
+	tb_inst_memcpy(p->func, dst.node, src.node, len.node, 1, false);
+	return dst;
+}
+
+gb_internal cgValue cg_builtin_mem_copy_non_overlapping(cgProcedure *p, cgValue const &dst, cgValue const &src, cgValue const &len) {
+	GB_ASSERT(dst.kind == cgValue_Value);
+	GB_ASSERT(src.kind == cgValue_Value);
+	GB_ASSERT(len.kind == cgValue_Value);
+	tb_inst_memcpy(p->func, dst.node, src.node, len.node, 1, false);
+	return dst;
+}
+
 
 
 
 
 gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr) {
 gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr) {
@@ -186,6 +283,17 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
 		return cg_builtin_len(p, v);
 		return cg_builtin_len(p, v);
 	}
 	}
 
 
+	case BuiltinProc_cap: {
+		cgValue v = cg_build_expr(p, ce->args[0]);
+		Type *t = base_type(v.type);
+		if (is_type_pointer(t)) {
+			// IMPORTANT TODO(bill): Should there be a nil pointer check?
+			v = cg_emit_load(p, v);
+			t = type_deref(t);
+		}
+		return cg_builtin_cap(p, v);
+	}
+
 	case BuiltinProc_raw_data:
 	case BuiltinProc_raw_data:
 		{
 		{
 			cgValue v = cg_build_expr(p, ce->args[0]);
 			cgValue v = cg_build_expr(p, ce->args[0]);
@@ -225,6 +333,14 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
 			return cg_builtin_abs(p, x);
 			return cg_builtin_abs(p, x);
 		}
 		}
 
 
+	case BuiltinProc_clamp:
+		{
+			cgValue x   = cg_build_expr(p, ce->args[0]);
+			cgValue min = cg_build_expr(p, ce->args[1]);
+			cgValue max = cg_build_expr(p, ce->args[2]);
+			return cg_builtin_clamp(p, type_of_expr(expr), x, min, max);
+		}
+
 	case BuiltinProc_debug_trap:
 	case BuiltinProc_debug_trap:
 		tb_inst_debugbreak(p->func);
 		tb_inst_debugbreak(p->func);
 		return {};
 		return {};
@@ -236,10 +352,7 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
 		{
 		{
 			cgValue ptr = cg_build_expr(p, ce->args[0]);
 			cgValue ptr = cg_build_expr(p, ce->args[0]);
 			cgValue len = cg_build_expr(p, ce->args[1]);
 			cgValue len = cg_build_expr(p, ce->args[1]);
-			GB_ASSERT(ptr.kind == cgValue_Value);
-			GB_ASSERT(len.kind == cgValue_Value);
-			tb_inst_memzero(p->func, ptr.node, len.node, 1, false);
-			return {};
+			return cg_builtin_mem_zero(p, ptr, len);
 		}
 		}
 
 
 	case BuiltinProc_mem_copy:
 	case BuiltinProc_mem_copy:
@@ -247,12 +360,7 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
 			cgValue dst = cg_build_expr(p, ce->args[0]);
 			cgValue dst = cg_build_expr(p, ce->args[0]);
 			cgValue src = cg_build_expr(p, ce->args[1]);
 			cgValue src = cg_build_expr(p, ce->args[1]);
 			cgValue len = cg_build_expr(p, ce->args[2]);
 			cgValue len = cg_build_expr(p, ce->args[2]);
-			GB_ASSERT(dst.kind == cgValue_Value);
-			GB_ASSERT(src.kind == cgValue_Value);
-			GB_ASSERT(len.kind == cgValue_Value);
-			// TODO(bill): This needs to be memmove
-			tb_inst_memcpy(p->func, dst.node, src.node, len.node, 1, false);
-			return {};
+			return cg_builtin_mem_copy(p, dst, src, len);
 		}
 		}
 
 
 	case BuiltinProc_mem_copy_non_overlapping:
 	case BuiltinProc_mem_copy_non_overlapping:
@@ -260,11 +368,7 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
 			cgValue dst = cg_build_expr(p, ce->args[0]);
 			cgValue dst = cg_build_expr(p, ce->args[0]);
 			cgValue src = cg_build_expr(p, ce->args[1]);
 			cgValue src = cg_build_expr(p, ce->args[1]);
 			cgValue len = cg_build_expr(p, ce->args[2]);
 			cgValue len = cg_build_expr(p, ce->args[2]);
-			GB_ASSERT(dst.kind == cgValue_Value);
-			GB_ASSERT(src.kind == cgValue_Value);
-			GB_ASSERT(len.kind == cgValue_Value);
-			tb_inst_memcpy(p->func, dst.node, src.node, len.node, 1, false);
-			return {};
+			return cg_builtin_mem_copy_non_overlapping(p, dst, src, len);
 		}
 		}