Fix $$min/$$max for vector.

This commit is contained in:
Christoffer Lerno
2022-08-29 10:23:16 +02:00
parent bb9c8fb93e
commit 54d6b1a4ec
8 changed files with 78 additions and 10 deletions

View File

@@ -2143,6 +2143,7 @@ bool type_is_user_defined(Type *type);
bool type_is_structurally_equivalent(Type *type1, Type *type); bool type_is_structurally_equivalent(Type *type1, Type *type);
bool type_flat_is_floatlike(Type *type); bool type_flat_is_floatlike(Type *type);
bool type_flat_is_intlike(Type *type); bool type_flat_is_intlike(Type *type);
bool type_flat_is_numlike(Type *type);
bool type_may_have_sub_elements(Type *type); bool type_may_have_sub_elements(Type *type);
const char *type_to_error_string(Type *type); const char *type_to_error_string(Type *type);
const char *type_quoted_error_string(Type *type); const char *type_quoted_error_string(Type *type);

View File

@@ -569,7 +569,8 @@ typedef enum
TYPE_BOOL, TYPE_BOOL,
TYPE_I8, TYPE_I8,
TYPE_INTEGER_FIRST = TYPE_I8, TYPE_INTEGER_FIRST = TYPE_I8,
TYPE_INT_FIRST = TYPE_I8, TYPE_NUM_FIRST = TYPE_INTEGER_FIRST,
TYPE_INT_FIRST = TYPE_INTEGER_FIRST,
TYPE_I16, TYPE_I16,
TYPE_I32, TYPE_I32,
TYPE_I64, TYPE_I64,
@@ -589,6 +590,7 @@ typedef enum
TYPE_F64, TYPE_F64,
TYPE_F128, TYPE_F128,
TYPE_FLOAT_LAST = TYPE_F128, TYPE_FLOAT_LAST = TYPE_F128,
TYPE_NUM_LAST = TYPE_FLOAT_LAST,
TYPE_ANY, TYPE_ANY,
TYPE_ANYERR, TYPE_ANYERR,
TYPE_TYPEID, TYPE_TYPEID,

View File

@@ -4544,6 +4544,7 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
if (func == BUILTIN_MAX) if (func == BUILTIN_MAX)
{ {
Type *type = type_flatten(expr->call_expr.arguments[0]->type); Type *type = type_flatten(expr->call_expr.arguments[0]->type);
RETRY:
switch (type->type_kind) switch (type->type_kind)
{ {
case ALL_SIGNED_INTS: case ALL_SIGNED_INTS:
@@ -4556,6 +4557,9 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
case ALL_FLOATS: case ALL_FLOATS:
intrinsic = intrinsic_id.maxnum; intrinsic = intrinsic_id.maxnum;
break; break;
case TYPE_VECTOR:
type = type->array.base;
goto RETRY;
default: default:
UNREACHABLE UNREACHABLE
} }
@@ -4563,6 +4567,7 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
else if (func == BUILTIN_MIN) else if (func == BUILTIN_MIN)
{ {
Type *type = type_flatten(expr->call_expr.arguments[0]->type); Type *type = type_flatten(expr->call_expr.arguments[0]->type);
RETRY2:
switch (type->type_kind) switch (type->type_kind)
{ {
case ALL_SIGNED_INTS: case ALL_SIGNED_INTS:
@@ -4575,6 +4580,9 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
case ALL_FLOATS: case ALL_FLOATS:
intrinsic = intrinsic_id.minnum; intrinsic = intrinsic_id.minnum;
break; break;
case TYPE_VECTOR:
type = type->array.base;
goto RETRY2;
default: default:
UNREACHABLE UNREACHABLE
} }

View File

@@ -2504,6 +2504,7 @@ typedef enum
BA_CHAR, BA_CHAR,
BA_FLOATLIKE, BA_FLOATLIKE,
BA_INTLIKE, BA_INTLIKE,
BA_NUMLIKE,
} BuiltinArg; } BuiltinArg;
static bool sema_check_builtin_args_match(Expr **args, size_t arg_len) static bool sema_check_builtin_args_match(Expr **args, size_t arg_len)
@@ -2567,6 +2568,13 @@ static bool sema_check_builtin_args(Expr **args, BuiltinArg *arg_type, size_t ar
return false; return false;
} }
break; break;
case BA_NUMLIKE:
if (!type_flat_is_numlike(type))
{
SEMA_ERROR(args[i], "Expected a number or vector.");
return false;
}
break;
case BA_FLOATLIKE: case BA_FLOATLIKE:
if (!type_flat_is_floatlike(type)) if (!type_flat_is_floatlike(type))
{ {
@@ -2711,14 +2719,7 @@ static inline bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *ex
break; break;
case BUILTIN_MAX: case BUILTIN_MAX:
case BUILTIN_MIN: case BUILTIN_MIN:
if (type_is_integer(args[0]->type)) if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_NUMLIKE, BA_NUMLIKE }, arg_count)) return false;
{
if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_INTLIKE, BA_INTLIKE }, arg_count)) return false;
}
else
{
if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_FLOATLIKE, BA_FLOATLIKE }, arg_count)) return false;
}
if (!sema_check_builtin_args_match(args, arg_count)) return false; if (!sema_check_builtin_args_match(args, arg_count)) return false;
rtype = args[0]->type; rtype = args[0]->type;
break; break;

View File

@@ -320,6 +320,14 @@ RETRY:
} }
bool type_flat_is_numlike(Type *type)
{
type = type_flatten(type);
if (type->type_kind == TYPE_VECTOR) type = type->array.base;
TypeKind kind = type->type_kind;
return kind >= TYPE_NUM_FIRST && kind <= TYPE_NUM_LAST;
}
bool type_flat_is_floatlike(Type *type) bool type_flat_is_floatlike(Type *type)
{ {
type = type_flatten(type); type = type_flatten(type);

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.3.33" #define COMPILER_VERSION "0.3.34"

View File

@@ -0,0 +1,24 @@
// #target: macos-x64
module test;
fn void main()
{
{
float[<2>] vf1 = { 1, -1 };
float[<2>] vf2 = { 1, 1 };
float[<2>] max = $$max(vf1, vf2);
float[<2>] min = $$min(vf1, vf2);
}
{
int[<2>] v1 = { 1, -1 };
int[<2>] v2 = { 1, 1 };
int[<2>] max = $$max(v1, v2);
int[<2>] min = $$min(v1, v2);
}
}
/* #expect: test.ll
%2 = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %0, <2 x float> %1)
%5 = call <2 x float> @llvm.minnum.v2f32(<2 x float> %3, <2 x float> %4)
%8 = call <2 x i32> @llvm.smax.v2i32(<2 x i32> %6, <2 x i32> %7)
%11 = call <2 x i32> @llvm.smin.v2i32(<2 x i32> %9, <2 x i32> %10)

View File

@@ -0,0 +1,24 @@
// #target: macos-x64
module test;
fn void main()
{
{
float[<2>] vf1 = { 1, -1 };
float[<2>] vf2 = { 1, 1 };
float[<2>] max = $$max(vf1, vf2);
float[<2>] min = $$min(vf1, vf2);
}
{
int[<2>] v1 = { 1, -1 };
int[<2>] v2 = { 1, 1 };
int[<2>] max = $$max(v1, v2);
int[<2>] min = $$min(v1, v2);
}
}
/* #expect: test.ll
%2 = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %0, <2 x float> %1)
%5 = call <2 x float> @llvm.minnum.v2f32(<2 x float> %3, <2 x float> %4)
%8 = call <2 x i32> @llvm.smax.v2i32(<2 x i32> %6, <2 x i32> %7)
%11 = call <2 x i32> @llvm.smin.v2i32(<2 x i32> %9, <2 x i32> %10)