From 952d865bd231834adad30905c469edc5a46d000a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 15 Nov 2021 19:09:20 +0100 Subject: [PATCH] stage1: Fix caching of LLVM builtin fns The cache entry must take into account the fact some functions operate on scalar types and some other on vectors of scalar types. Fixes #10147 --- src/stage1/all_types.hpp | 1 + src/stage1/codegen.cpp | 3 +++ test/behavior.zig | 1 + test/behavior/bugs/10147.zig | 12 ++++++++++++ 4 files changed, 17 insertions(+) create mode 100644 test/behavior/bugs/10147.zig diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 284a5a5468..0a3e52f4f4 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -1957,6 +1957,7 @@ struct ZigLLVMFnKey { } bswap; struct { uint32_t bit_count; + uint32_t vector_len; // 0 means not a vector } bit_reverse; } data; }; diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index c3536a4c69..76e9b3edc2 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -5175,11 +5175,13 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *expr_type, BuiltinFn n_args = 2; key.id = ZigLLVMFnIdCtz; key.data.ctz.bit_count = (uint32_t)int_type->data.integral.bit_count; + key.data.ctz.vector_len = vector_len; } else if (fn_id == BuiltinFnIdClz) { fn_name = "ctlz"; n_args = 2; key.id = ZigLLVMFnIdClz; key.data.clz.bit_count = (uint32_t)int_type->data.integral.bit_count; + key.data.clz.vector_len = vector_len; } else if (fn_id == BuiltinFnIdPopCount) { fn_name = "ctpop"; n_args = 1; @@ -5197,6 +5199,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *expr_type, BuiltinFn n_args = 1; key.id = ZigLLVMFnIdBitReverse; key.data.bit_reverse.bit_count = (uint32_t)int_type->data.integral.bit_count; + key.data.bit_reverse.vector_len = vector_len; } else { zig_unreachable(); } diff --git a/test/behavior.zig b/test/behavior.zig index 4f78a9d35a..7cdb8386bc 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -128,6 +128,7 @@ test { _ = @import("behavior/bugs/7250.zig"); _ = @import("behavior/bugs/9584.zig"); _ = @import("behavior/bugs/9967.zig"); + _ = @import("behavior/bugs/10147.zig"); _ = @import("behavior/byteswap.zig"); _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call_stage1.zig"); diff --git a/test/behavior/bugs/10147.zig b/test/behavior/bugs/10147.zig new file mode 100644 index 0000000000..491f2e953e --- /dev/null +++ b/test/behavior/bugs/10147.zig @@ -0,0 +1,12 @@ +const std = @import("std"); + +test "uses correct LLVM builtin" { + var x: u32 = 0x1; + var y: @Vector(4, u32) = [_]u32{ 0x1, 0x1, 0x1, 0x1 }; + // The stage1 compiler used to call the same builtin function for both + // scalar and vector inputs, causing the LLVM module verification to fail. + var a = @clz(u32, x); + var b = @clz(u32, y); + try std.testing.expectEqual(@as(u6, 31), a); + try std.testing.expectEqual([_]u6{ 31, 31, 31, 31 }, b); +}