authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-30 17:13:35+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-30 12:22:07-07:00
log65d37239682b6418b6dd25f07187ae99088e67f0
treeb8ea48551a149e889247f07a09353eb452ff4e1f
parentc558de6655e2e9b72c5733b2d477ff18520d1c6b

Sema: check that target supports tail calls


4 files changed, 19 insertions(+), 1 deletions(-)

lib/std/target.zig+10
...@@ -1440,6 +1440,16 @@ pub const Target = struct {...@@ -1440,6 +1440,16 @@ pub const Target = struct {
1440 return !self.cpu.arch.isWasm();1440 return !self.cpu.arch.isWasm();
1441 }1441 }
14421442
1443 pub fn supportsTailCall(self: Target) bool {
1444 switch (self.cpu.arch) {
1445 .wasm32, .wasm64 => return wasm.featureSetHas(self.cpu.features, .tail_call),
1446 // TODO these might not be true but LLVM doesn't seem to be able to handle them
1447 .mips, .mipsel, .mips64, .mips64el => return false,
1448 .powerpc, .powerpcle, .powerpc64, .powerpc64le => return false,
1449 else => return true,
1450 }
1451 }
1452
1443 pub const FloatAbi = enum {1453 pub const FloatAbi = enum {
1444 hard,1454 hard,
1445 soft,1455 soft,
src/Sema.zig+4
...@@ -6160,6 +6160,10 @@ fn analyzeCall(...@@ -6160,6 +6160,10 @@ fn analyzeCall(
6160}6160}
61616161
6162fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Type, result: Air.Inst.Ref) !Air.Inst.Ref {6162fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Type, result: Air.Inst.Ref) !Air.Inst.Ref {
6163 const target = sema.mod.getTarget();
6164 if (!target.supportsTailCall()) {
6165 return sema.fail(block, call_src, "unable to perform tail call: target does not support tail calls", .{});
6166 }
6163 const func_decl = sema.mod.declPtr(sema.owner_func.?.owner_decl);6167 const func_decl = sema.mod.declPtr(sema.owner_func.?.owner_decl);
6164 if (!func_ty.eql(func_decl.ty, sema.mod)) {6168 if (!func_ty.eql(func_decl.ty, sema.mod)) {
6165 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{6169 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{
test/behavior/call.zig+4
...@@ -270,6 +270,8 @@ test "forced tail call" {...@@ -270,6 +270,8 @@ test "forced tail call" {
270 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO270 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
271 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO271 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
272272
273 if (comptime !builtin.target.supportsTailCall()) return error.SkipZigTest;
274
273 const S = struct {275 const S = struct {
274 fn fibonacciTailInternal(n: u16, a: u16, b: u16) u16 {276 fn fibonacciTailInternal(n: u16, a: u16, b: u16) u16 {
275 if (n == 0) return a;277 if (n == 0) return a;
...@@ -296,6 +298,8 @@ test "inline call preserves tail call" {...@@ -296,6 +298,8 @@ test "inline call preserves tail call" {
296 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO298 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
297 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO299 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
298300
301 if (comptime !builtin.target.supportsTailCall()) return error.SkipZigTest;
302
299 const max = std.math.maxInt(u16);303 const max = std.math.maxInt(u16);
300 const S = struct {304 const S = struct {
301 var a: u16 = 0;305 var a: u16 = 0;
test/cases/taill_call_noreturn.zig+1-1
...@@ -15,4 +15,4 @@ pub fn main() void {...@@ -15,4 +15,4 @@ pub fn main() void {
1515
16// run16// run
17// backend=llvm17// backend=llvm
18// target=native18// target=x86_64-linux,x86_64-macos,aarch64-linux,aarch64-macos