mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Fix slicing and add clamp
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
set exe_name=odin.exe
|
set exe_name=odin.exe
|
||||||
|
|
||||||
:: Debug = 0, Release = 1
|
:: Debug = 0, Release = 1
|
||||||
set release_mode=0
|
set release_mode=1
|
||||||
|
|
||||||
set compiler_flags= -nologo -Oi -TC -W4 -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
|
set compiler_flags= -nologo -Oi -TC -W4 -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -359,8 +359,8 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|||||||
case Float:
|
case Float:
|
||||||
match type f : arg {
|
match type f : arg {
|
||||||
// case f16: print_f64_to_buffer(buf, f as f64)
|
// case f16: print_f64_to_buffer(buf, f as f64)
|
||||||
case f32: print_f64_to_buffer(buf, f as f64)
|
case f32: print_f32_to_buffer(buf, f)
|
||||||
case f64: print_f64_to_buffer(buf, f as f64)
|
case f64: print_f64_to_buffer(buf, f)
|
||||||
// case f128: print_f64_to_buffer(buf, f as f64)
|
// case f128: print_f64_to_buffer(buf, f as f64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ typedef enum BuiltinProcId {
|
|||||||
BuiltinProc_min,
|
BuiltinProc_min,
|
||||||
BuiltinProc_max,
|
BuiltinProc_max,
|
||||||
BuiltinProc_abs,
|
BuiltinProc_abs,
|
||||||
|
BuiltinProc_clamp,
|
||||||
|
|
||||||
BuiltinProc_enum_to_string,
|
BuiltinProc_enum_to_string,
|
||||||
|
|
||||||
@@ -133,7 +134,7 @@ typedef enum BuiltinProcId {
|
|||||||
typedef struct BuiltinProc {
|
typedef struct BuiltinProc {
|
||||||
String name;
|
String name;
|
||||||
isize arg_count;
|
isize arg_count;
|
||||||
bool variadic;
|
bool variadic;
|
||||||
ExprKind kind;
|
ExprKind kind;
|
||||||
} BuiltinProc;
|
} BuiltinProc;
|
||||||
gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
||||||
@@ -169,6 +170,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
|||||||
{STR_LIT("min"), 2, false, Expr_Expr},
|
{STR_LIT("min"), 2, false, Expr_Expr},
|
||||||
{STR_LIT("max"), 2, false, Expr_Expr},
|
{STR_LIT("max"), 2, false, Expr_Expr},
|
||||||
{STR_LIT("abs"), 1, false, Expr_Expr},
|
{STR_LIT("abs"), 1, false, Expr_Expr},
|
||||||
|
{STR_LIT("clamp"), 3, false, Expr_Expr},
|
||||||
|
|
||||||
{STR_LIT("enum_to_string"), 1, false, Expr_Expr},
|
{STR_LIT("enum_to_string"), 1, false, Expr_Expr},
|
||||||
};
|
};
|
||||||
|
|||||||
+99
-1
@@ -2572,6 +2572,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
default:
|
||||||
|
GB_PANIC("Implement builtin procedure: %.*s", LIT(builtin_procs[id].name));
|
||||||
|
break;
|
||||||
|
|
||||||
case BuiltinProc_new: {
|
case BuiltinProc_new: {
|
||||||
// new :: proc(Type) -> ^Type
|
// new :: proc(Type) -> ^Type
|
||||||
Operand op = {0};
|
Operand op = {0};
|
||||||
@@ -3248,7 +3252,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
if (b.mode == Addressing_Invalid) {
|
if (b.mode == Addressing_Invalid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!is_type_comparable(b.type) || !(is_type_numeric(type) || is_type_string(type))) {
|
if (!is_type_comparable(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) {
|
||||||
gbString type_str = type_to_string(b.type);
|
gbString type_str = type_to_string(b.type);
|
||||||
error(ast_node_token(call),
|
error(ast_node_token(call),
|
||||||
"Expected a comparable numeric or string type to `max`, got `%s`",
|
"Expected a comparable numeric or string type to `max`, got `%s`",
|
||||||
@@ -3328,6 +3332,100 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
operand->type = type;
|
operand->type = type;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case BuiltinProc_clamp: {
|
||||||
|
// clamp :: proc(a, min, max: comparable) -> comparable
|
||||||
|
Type *type = base_type(operand->type);
|
||||||
|
if (!is_type_comparable(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||||
|
gbString type_str = type_to_string(operand->type);
|
||||||
|
error(ast_node_token(call),
|
||||||
|
"Expected a comparable numeric or string type to `clamp`, got `%s`",
|
||||||
|
type_str);
|
||||||
|
gb_string_free(type_str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *min_arg = ce->args.e[1];
|
||||||
|
AstNode *max_arg = ce->args.e[2];
|
||||||
|
Operand x = *operand;
|
||||||
|
Operand y = {0};
|
||||||
|
Operand z = {0};
|
||||||
|
|
||||||
|
check_expr(c, &y, min_arg);
|
||||||
|
if (y.mode == Addressing_Invalid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_type_comparable(y.type) || !(is_type_numeric(y.type) || is_type_string(y.type))) {
|
||||||
|
gbString type_str = type_to_string(y.type);
|
||||||
|
error(ast_node_token(call),
|
||||||
|
"Expected a comparable numeric or string type to `clamp`, got `%s`",
|
||||||
|
type_str);
|
||||||
|
gb_string_free(type_str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_expr(c, &z, max_arg);
|
||||||
|
if (z.mode == Addressing_Invalid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_type_comparable(z.type) || !(is_type_numeric(z.type) || is_type_string(z.type))) {
|
||||||
|
gbString type_str = type_to_string(z.type);
|
||||||
|
error(ast_node_token(call),
|
||||||
|
"Expected a comparable numeric or string type to `clamp`, got `%s`",
|
||||||
|
type_str);
|
||||||
|
gb_string_free(type_str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x.mode == Addressing_Constant &&
|
||||||
|
y.mode == Addressing_Constant &&
|
||||||
|
z.mode == Addressing_Constant) {
|
||||||
|
ExactValue a = x.value;
|
||||||
|
ExactValue b = y.value;
|
||||||
|
ExactValue c = z.value;
|
||||||
|
|
||||||
|
operand->mode = Addressing_Constant;
|
||||||
|
if (compare_exact_values(Token_Lt, a, b)) {
|
||||||
|
operand->value = b;
|
||||||
|
operand->type = y.type;
|
||||||
|
} else if (compare_exact_values(Token_Gt, a, c)) {
|
||||||
|
operand->value = c;
|
||||||
|
operand->type = z.type;
|
||||||
|
} else {
|
||||||
|
operand->value = a;
|
||||||
|
operand->type = x.type;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
operand->mode = Addressing_Value;
|
||||||
|
operand->type = type;
|
||||||
|
|
||||||
|
convert_to_typed(c, &x, y.type, 0);
|
||||||
|
if (x.mode == Addressing_Invalid) { return false; }
|
||||||
|
convert_to_typed(c, &y, x.type, 0);
|
||||||
|
if (y.mode == Addressing_Invalid) { return false; }
|
||||||
|
convert_to_typed(c, &x, z.type, 0);
|
||||||
|
if (x.mode == Addressing_Invalid) { return false; }
|
||||||
|
convert_to_typed(c, &z, x.type, 0);
|
||||||
|
if (z.mode == Addressing_Invalid) { return false; }
|
||||||
|
convert_to_typed(c, &y, z.type, 0);
|
||||||
|
if (y.mode == Addressing_Invalid) { return false; }
|
||||||
|
convert_to_typed(c, &z, y.type, 0);
|
||||||
|
if (z.mode == Addressing_Invalid) { return false; }
|
||||||
|
|
||||||
|
if (!are_types_identical(x.type, y.type) || !are_types_identical(x.type, z.type)) {
|
||||||
|
gbString type_x = type_to_string(x.type);
|
||||||
|
gbString type_y = type_to_string(y.type);
|
||||||
|
gbString type_z = type_to_string(z.type);
|
||||||
|
error(ast_node_token(call),
|
||||||
|
"Mismatched types to `clamp`, `%s`, `%s`, `%s`",
|
||||||
|
type_x, type_y, type_z);
|
||||||
|
gb_string_free(type_z);
|
||||||
|
gb_string_free(type_y);
|
||||||
|
gb_string_free(type_x);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_enum_to_string: {
|
case BuiltinProc_enum_to_string: {
|
||||||
Type *type = base_type(operand->type);
|
Type *type = base_type(operand->type);
|
||||||
if (!is_type_enum(type)) {
|
if (!is_type_enum(type)) {
|
||||||
|
|||||||
@@ -3012,16 +3012,18 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
|
|
||||||
case BuiltinProc_min: {
|
case BuiltinProc_min: {
|
||||||
ssa_emit_comment(proc, str_lit("min"));
|
ssa_emit_comment(proc, str_lit("min"));
|
||||||
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
|
Type *t = type_of_expr(proc->module->info, expr);
|
||||||
ssaValue *y = ssa_build_expr(proc, ce->args.e[1]);
|
ssaValue *x = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[0]), t);
|
||||||
|
ssaValue *y = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[1]), t);
|
||||||
ssaValue *cond = ssa_emit_comp(proc, Token_Lt, x, y);
|
ssaValue *cond = ssa_emit_comp(proc, Token_Lt, x, y);
|
||||||
return ssa_emit_select(proc, cond, x, y);
|
return ssa_emit_select(proc, cond, x, y);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_max: {
|
case BuiltinProc_max: {
|
||||||
ssa_emit_comment(proc, str_lit("max"));
|
ssa_emit_comment(proc, str_lit("max"));
|
||||||
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
|
Type *t = type_of_expr(proc->module->info, expr);
|
||||||
ssaValue *y = ssa_build_expr(proc, ce->args.e[1]);
|
ssaValue *x = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[0]), t);
|
||||||
|
ssaValue *y = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[1]), t);
|
||||||
ssaValue *cond = ssa_emit_comp(proc, Token_Gt, x, y);
|
ssaValue *cond = ssa_emit_comp(proc, Token_Gt, x, y);
|
||||||
return ssa_emit_select(proc, cond, x, y);
|
return ssa_emit_select(proc, cond, x, y);
|
||||||
} break;
|
} break;
|
||||||
@@ -3067,6 +3069,20 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
return v;
|
return v;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case BuiltinProc_clamp: {
|
||||||
|
ssa_emit_comment(proc, str_lit("clamp"));
|
||||||
|
Type *t = type_of_expr(proc->module->info, expr);
|
||||||
|
ssaValue *x = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[0]), t);
|
||||||
|
ssaValue *min = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[1]), t);
|
||||||
|
ssaValue *max = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[2]), t);
|
||||||
|
ssaValue *cond;
|
||||||
|
cond = ssa_emit_comp(proc, Token_Gt, min, x);
|
||||||
|
x = ssa_emit_select(proc, cond, min, x);
|
||||||
|
cond = ssa_emit_comp(proc, Token_Lt, max, x);
|
||||||
|
x = ssa_emit_select(proc, cond, max, x);
|
||||||
|
return x;
|
||||||
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_enum_to_string: {
|
case BuiltinProc_enum_to_string: {
|
||||||
ssa_emit_comment(proc, str_lit("enum_to_string"));
|
ssa_emit_comment(proc, str_lit("enum_to_string"));
|
||||||
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
|
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
|
||||||
@@ -3471,9 +3487,9 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
|
|
||||||
ssa_emit_slice_bounds_check(proc, se->open, low, high, max, false);
|
ssa_emit_slice_bounds_check(proc, se->open, low, high, max, false);
|
||||||
|
|
||||||
ssaValue *elem = ssa_slice_elem(proc, base);
|
ssaValue *elem = ssa_emit_ptr_offset(proc, ssa_slice_elem(proc, base), low);
|
||||||
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
||||||
ssaValue *cap = ssa_emit_arith(proc, Token_Sub, max, low, t_int);
|
ssaValue *cap = ssa_emit_arith(proc, Token_Sub, max, low, t_int);
|
||||||
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
||||||
|
|
||||||
ssaValue *gep0 = ssa_emit_struct_ep(proc, slice, 0);
|
ssaValue *gep0 = ssa_emit_struct_ep(proc, slice, 0);
|
||||||
@@ -3495,7 +3511,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
|
|
||||||
ssa_emit_slice_bounds_check(proc, se->open, low, high, max, false);
|
ssa_emit_slice_bounds_check(proc, se->open, low, high, max, false);
|
||||||
|
|
||||||
ssaValue *elem = ssa_array_elem(proc, addr);
|
ssaValue *elem = ssa_emit_ptr_offset(proc, ssa_array_elem(proc, addr), low);
|
||||||
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
||||||
ssaValue *cap = ssa_emit_arith(proc, Token_Sub, max, low, t_int);
|
ssaValue *cap = ssa_emit_arith(proc, Token_Sub, max, low, t_int);
|
||||||
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
||||||
@@ -5128,14 +5144,9 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), gep);
|
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), gep);
|
||||||
|
|
||||||
isize ez = type_size_of(m->sizes, a, t->Vector.elem);
|
isize ez = type_size_of(m->sizes, a, t->Vector.elem);
|
||||||
ssaValue *elem_size = ssa_emit_struct_ep(proc, tag, 1);
|
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 1), ssa_make_const_int(a, ez));
|
||||||
ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez));
|
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 2), ssa_make_const_int(a, t->Vector.count));
|
||||||
|
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 3), ssa_make_const_int(a, type_align_of(m->sizes, a, t)));
|
||||||
ssaValue *count = ssa_emit_struct_ep(proc, tag, 2);
|
|
||||||
ssa_emit_store(proc, count, ssa_make_const_int(a, t->Vector.count));
|
|
||||||
|
|
||||||
ssaValue *align = ssa_emit_struct_ep(proc, tag, 3);
|
|
||||||
ssa_emit_store(proc, count, ssa_make_const_int(a, type_align_of(m->sizes, a, t)));
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
|
|||||||
Reference in New Issue
Block a user