aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-07-23 22:07:21 +0100
committergingerBill <bill@gingerbill.org>2023-07-23 22:07:21 +0100
commit2f9c5d2d0b500518acecb9badd4b6947db6fd536 (patch)
treeb0a927ef7821a3b0559a7aed981df9ffe095fc68 /src
parent99c812b02d31d8f827e299ff7bb4a5d0c59bed4b (diff)
Minor clean up to builtin procs
Diffstat (limited to 'src')
-rw-r--r--src/tilde_builtin.cpp136
1 files changed, 120 insertions, 16 deletions
diff --git a/src/tilde_builtin.cpp b/src/tilde_builtin.cpp
index c55cfbb75..6deaf0e9b 100644
--- a/src/tilde_builtin.cpp
+++ b/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);
}
case Basic_cstring:
+ GB_PANIC("TODO(bill): len(cstring)");
break;
}
break;
@@ -51,6 +52,69 @@ gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value) {
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) {
Type *t = base_type(value.type);
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);
}
-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)) {
return x;
}
@@ -138,6 +202,39 @@ gb_internal cgValue cg_builtin_abs(cgProcedure *p, cgValue 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) {
@@ -186,6 +283,17 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
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:
{
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);
}
+ 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:
tb_inst_debugbreak(p->func);
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 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:
@@ -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 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 {};
+ return cg_builtin_mem_copy(p, dst, src, len);
}
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 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 {};
+ return cg_builtin_mem_copy_non_overlapping(p, dst, src, len);
}