diff --git a/src/compiler/enums.h b/src/compiler/enums.h index bf1121d74..a7c4f62c4 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -807,8 +807,9 @@ typedef enum BUILTIN_MEMSET, BUILTIN_MIN, BUILTIN_NEARBYINT, - BUILTIN_CTPOP, // should be here for keeping sorting order + BUILTIN_POPCOUNT, BUILTIN_POW, + BUILTIN_REVERSE, BUILTIN_RINT, BUILTIN_ROUND, BUILTIN_ROUNDEVEN, diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index c9339de82..726b04f78 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -4345,6 +4345,7 @@ unsigned llvm_get_intrinsic(BuiltinFunction func) case BUILTIN_STACKTRACE: case BUILTIN_ABS: case BUILTIN_SHUFFLEVECTOR: + case BUILTIN_REVERSE: UNREACHABLE case BUILTIN_SYSCLOCK: return intrinsic_id.readcyclecounter; @@ -4382,7 +4383,7 @@ unsigned llvm_get_intrinsic(BuiltinFunction func) return intrinsic_id.ctlz; case BUILTIN_CTTZ: return intrinsic_id.cttz; - case BUILTIN_CTPOP: + case BUILTIN_POPCOUNT: return intrinsic_id.ctpop; case BUILTIN_LOG2: return intrinsic_id.log2; @@ -4561,6 +4562,26 @@ INLINE void llvm_emit_shufflevector(GenContext *c, BEValue *result_value, Expr * return; } +INLINE void llvm_emit_reverse(GenContext *c, BEValue *result_value, Expr *expr) +{ + Expr **args = expr->call_expr.arguments; + llvm_emit_expr(c, result_value, args[0]); + llvm_value_rvalue(c, result_value); + Type *rtype = result_value->type; + LLVMValueRef arg1 = result_value->value; + LLVMValueRef arg2 = LLVMGetPoison(LLVMTypeOf(arg1)); + LLVMValueRef buff[128]; + unsigned elements = rtype->array.len; + LLVMValueRef *mask_element = elements > 128 ? MALLOC(sizeof(LLVMValueRef)) : buff; + LLVMTypeRef mask_element_type = llvm_get_type(c, type_int); + for (unsigned i = 0; i < elements; i++) + { + mask_element[i] = LLVMConstInt(mask_element_type, elements - i - 1, false); + } + LLVMValueRef mask = LLVMConstVector(mask_element, elements); + llvm_value_set(result_value, LLVMBuildShuffleVector(c->builder, arg1, arg2, mask, "reverse"), rtype); +} + void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr) { BuiltinFunction func = exprptr(expr->call_expr.function)->builtin_expr.builtin; @@ -4578,6 +4599,11 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr) llvm_emit_shufflevector(c, result_value, expr); return; } + if (func == BUILTIN_REVERSE) + { + llvm_emit_reverse(c, result_value, expr); + return; + } if (func == BUILTIN_STACKTRACE) { if (!c->debug.enable_stacktrace) diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index fdff5a30f..bd47a22dc 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -2506,7 +2506,7 @@ static inline unsigned builtin_expected_args(BuiltinFunction func) case BUILTIN_CEIL: case BUILTIN_COS: case BUILTIN_CTLZ: - case BUILTIN_CTPOP: + case BUILTIN_POPCOUNT: case BUILTIN_CTTZ: case BUILTIN_EXP: case BUILTIN_EXP2: @@ -2527,6 +2527,7 @@ static inline unsigned builtin_expected_args(BuiltinFunction func) case BUILTIN_SYSCALL: case BUILTIN_TRUNC: case BUILTIN_VOLATILE_LOAD: + case BUILTIN_REVERSE: return 1; case BUILTIN_COPYSIGN: case BUILTIN_MAX: @@ -2846,13 +2847,17 @@ static inline bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *ex case BUILTIN_BITREVERSE: case BUILTIN_BSWAP: case BUILTIN_CTLZ: - case BUILTIN_CTPOP: + case BUILTIN_POPCOUNT: case BUILTIN_CTTZ: if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_INTLIKE }, arg_count)) return false; rtype = args[0]->type; break; + case BUILTIN_REVERSE: + if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_VEC }, arg_count)) return false; + rtype = args[0]->type; + break; case BUILTIN_CEIL: case BUILTIN_COPYSIGN: case BUILTIN_COS: diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index bedf51b88..20a6c362b 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -187,7 +187,6 @@ void symtab_init(uint32_t capacity) builtin_list[BUILTIN_COPYSIGN] = KW_DEF("copysign"); builtin_list[BUILTIN_COS] = KW_DEF("cos"); builtin_list[BUILTIN_CTLZ] = KW_DEF("clz"); - builtin_list[BUILTIN_CTPOP] = KW_DEF("popcount"); builtin_list[BUILTIN_CTTZ] = KW_DEF("ctz"); builtin_list[BUILTIN_EXP] = KW_DEF("exp"); builtin_list[BUILTIN_EXP2] = KW_DEF("exp2"); @@ -203,7 +202,9 @@ void symtab_init(uint32_t capacity) builtin_list[BUILTIN_MEMSET] = KW_DEF("memset"); builtin_list[BUILTIN_MIN] = KW_DEF("min"); builtin_list[BUILTIN_NEARBYINT] = KW_DEF("nearbyint"); + builtin_list[BUILTIN_POPCOUNT] = KW_DEF("popcount"); builtin_list[BUILTIN_POW] = KW_DEF("pow"); + builtin_list[BUILTIN_REVERSE] = KW_DEF("reverse"); builtin_list[BUILTIN_RINT] = KW_DEF("rint"); builtin_list[BUILTIN_ROUND] = KW_DEF("round"); builtin_list[BUILTIN_ROUNDEVEN] = KW_DEF("roundeven"); diff --git a/src/version.h b/src/version.h index a951f3e76..6f9d7a128 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.3.44" \ No newline at end of file +#define COMPILER_VERSION "0.3.45" \ No newline at end of file diff --git a/test/test_suite/builtins/reverse_builtin.c3t b/test/test_suite/builtins/reverse_builtin.c3t new file mode 100644 index 000000000..9072e6bea --- /dev/null +++ b/test/test_suite/builtins/reverse_builtin.c3t @@ -0,0 +1,14 @@ +// #target: macos-x64 + +module test; +import std::io; + +fn void main() +{ + int[<4>] a = { 1, -3, 5, -7 }; + io::printfln("%s", $$reverse(a)); +} + +/* #expect: test.ll + +%reverse = shufflevector <4 x i32> %3, <4 x i32> poison, <4 x i32> \ No newline at end of file diff --git a/test/test_suite2/builtins/reverse_builtin.c3t b/test/test_suite2/builtins/reverse_builtin.c3t new file mode 100644 index 000000000..a63183303 --- /dev/null +++ b/test/test_suite2/builtins/reverse_builtin.c3t @@ -0,0 +1,14 @@ +// #target: macos-x64 + +module test; +import std::io; + +fn void main() +{ + int[<4>] a = { 1, -3, 5, -7 }; + io::printfln("%s", $$reverse(a)); +} + +/* #expect: test.ll + +%reverse = shufflevector <4 x i32> %2, <4 x i32> poison, <4 x i32> \ No newline at end of file