aboutsummaryrefslogtreecommitdiff
path: root/src/tilde_builtin.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-07-23 12:21:27 +0100
committergingerBill <bill@gingerbill.org>2023-07-23 21:44:50 +0100
commit99c812b02d31d8f827e299ff7bb4a5d0c59bed4b (patch)
treed1c3ba2ccbd8aa18bf20780d5161e409584db729 /src/tilde_builtin.cpp
parentd82c2ce50ff37ca624d32208f2e0249966b5542d (diff)
Begin working on a minimum build
Diffstat (limited to 'src/tilde_builtin.cpp')
-rw-r--r--src/tilde_builtin.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/tilde_builtin.cpp b/src/tilde_builtin.cpp
index d6e161ec3..c55cfbb75 100644
--- a/src/tilde_builtin.cpp
+++ b/src/tilde_builtin.cpp
@@ -61,6 +61,7 @@ gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &value) {
cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type));
cgValue data_ptr = cg_emit_struct_ep(p, ptr, 0);
res = cg_emit_load(p, data_ptr);
+ GB_ASSERT(is_type_multi_pointer(res.type));
}
break;
case Type_DynamicArray:
@@ -82,7 +83,12 @@ gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &value) {
}
break;
case Type_Pointer:
+ GB_ASSERT(is_type_array_like(t->Pointer.elem));
+ GB_ASSERT(value.kind == cgValue_Value);
+ res = cg_value(value.node, alloc_type_multi_pointer(base_array_type(t->Pointer.elem)));
+ break;
case Type_MultiPointer:
+
GB_PANIC("TODO(bill) %s", type_to_string(value.type));
// res = cg_emit_conv(p, value, tv.type);
break;
@@ -102,6 +108,37 @@ 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);
}
+gb_internal cgValue cg_builtin_abs(cgProcedure *p, cgValue x) {
+ if (is_type_unsigned(x.type)) {
+ return x;
+ }
+
+ if (is_type_quaternion(x.type)) {
+ GB_PANIC("TODO(bill): abs quaternion");
+ } else if (is_type_complex(x.type)) {
+ GB_PANIC("TODO(bill): abs complex");
+ }
+
+ TB_DataType dt = cg_data_type(x.type);
+ GB_ASSERT(!TB_IS_VOID_TYPE(dt));
+ TB_Node *zero = nullptr;
+ if (dt.type == TB_FLOAT) {
+ if (dt.data == 32) {
+ zero = tb_inst_float32(p->func, 0);
+ } else if (dt.data == 64) {
+ zero = tb_inst_float64(p->func, 0);
+ }
+ } else {
+ zero = tb_inst_uint(p->func, dt, 0);
+ }
+ GB_ASSERT(zero != nullptr);
+
+ cgValue cond = cg_emit_comp(p, Token_Lt, x, cg_value(zero, x.type));
+ cgValue neg = cg_emit_unary_arith(p, Token_Sub, x, x.type);
+ return cg_emit_select(p, cond, neg, x);
+}
+
+
gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr) {
ast_node(ce, CallExpr, expr);
@@ -149,6 +186,12 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
return cg_builtin_len(p, v);
}
+ case BuiltinProc_raw_data:
+ {
+ cgValue v = cg_build_expr(p, ce->args[0]);
+ return cg_builtin_raw_data(p, v);
+ }
+
case BuiltinProc_min:
if (ce->args.count == 2) {
Type *t = type_of_expr(expr);
@@ -176,6 +219,96 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
}
break;
+ case BuiltinProc_abs:
+ {
+ cgValue x = cg_build_expr(p, ce->args[0]);
+ return cg_builtin_abs(p, x);
+ }
+
+ case BuiltinProc_debug_trap:
+ tb_inst_debugbreak(p->func);
+ return {};
+ case BuiltinProc_trap:
+ tb_inst_trap(p->func);
+ return {};
+
+ case BuiltinProc_mem_zero:
+ {
+ cgValue ptr = cg_build_expr(p, ce->args[0]);
+ 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 {};
+ }
+
+ case BuiltinProc_mem_copy:
+ {
+ cgValue dst = cg_build_expr(p, ce->args[0]);
+ cgValue src = cg_build_expr(p, ce->args[1]);
+ 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 {};
+ }
+
+ case BuiltinProc_mem_copy_non_overlapping:
+ {
+ cgValue dst = cg_build_expr(p, ce->args[0]);
+ cgValue src = cg_build_expr(p, ce->args[1]);
+ 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 {};
+ }
+
+
+ case BuiltinProc_overflow_add:
+ {
+ Type *res_type = type_of_expr(expr);
+ GB_ASSERT(res_type->kind == Type_Tuple);
+ GB_ASSERT(res_type->Tuple.variables.count == 2);
+ // TODO(bill): do a proper overflow add
+ Type *type = res_type->Tuple.variables[0]->type;
+ Type *ok_type = res_type->Tuple.variables[1]->type;
+ cgValue x = cg_build_expr(p, ce->args[0]);
+ cgValue y = cg_build_expr(p, ce->args[1]);
+ x = cg_emit_conv(p, x, type);
+ y = cg_emit_conv(p, y, type);
+ cgValue res = cg_emit_arith(p, Token_Add, x, y, type);
+ cgValue ok = cg_const_int(p, ok_type, false);
+
+ return cg_value_multi2(res, ok, res_type);
+ }
+
+
+ case BuiltinProc_ptr_offset:
+ {
+ cgValue ptr = cg_build_expr(p, ce->args[0]);
+ cgValue len = cg_build_expr(p, ce->args[1]);
+ len = cg_emit_conv(p, len, t_int);
+ return cg_emit_ptr_offset(p, ptr, len);
+ }
+ case BuiltinProc_ptr_sub:
+ {
+ Type *elem0 = type_deref(type_of_expr(ce->args[0]));
+ Type *elem1 = type_deref(type_of_expr(ce->args[1]));
+ GB_ASSERT(are_types_identical(elem0, elem1));
+ Type *elem = elem0;
+
+ cgValue ptr0 = cg_emit_conv(p, cg_build_expr(p, ce->args[0]), t_uintptr);
+ cgValue ptr1 = cg_emit_conv(p, cg_build_expr(p, ce->args[1]), t_uintptr);
+
+ cgValue diff = cg_emit_arith(p, Token_Sub, ptr0, ptr1, t_uintptr);
+ diff = cg_emit_conv(p, diff, t_int);
+ return cg_emit_arith(p, Token_Quo, diff, cg_const_int(p, t_int, type_size_of(elem)), t_int);
+ }
+
}