mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
committed by
Andrew Kelley
parent
4059242f44
commit
28ae5d4158
@@ -1259,11 +1259,6 @@ pub const Object = struct {
|
||||
defer if (deinit_wip) wip.deinit();
|
||||
wip.cursor = .{ .block = try wip.block(0, "Entry") };
|
||||
|
||||
if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
|
||||
.signed => try attributes.addRetAttr(.signext, &o.builder),
|
||||
.unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
|
||||
};
|
||||
|
||||
// This is the list of args we will use that correspond directly to the AIR arg
|
||||
// instructions. Depending on the calling convention, this list is not necessarily
|
||||
// a bijection with the actual LLVM parameters of the function.
|
||||
@@ -2812,7 +2807,11 @@ pub const Object = struct {
|
||||
const raw_llvm_ret_ty = try o.lowerType(.fromInterned(fn_info.return_type));
|
||||
try attributes.addParamAttr(it.llvm_index, .{ .sret = raw_llvm_ret_ty }, &o.builder);
|
||||
it.llvm_index += 1;
|
||||
}
|
||||
} else if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
|
||||
.signed => try attributes.addRetAttr(.signext, &o.builder),
|
||||
.unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
|
||||
};
|
||||
|
||||
const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;
|
||||
if (err_return_tracing) {
|
||||
try attributes.addParamAttr(it.llvm_index, .nonnull, &o.builder);
|
||||
|
||||
@@ -611,14 +611,20 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
|
||||
.no_suspend, .always_inline, .compile_time => unreachable,
|
||||
}
|
||||
|
||||
const ret_ptr = if (!sret) null else blk: {
|
||||
const ret_ptr = if (sret) ret_ptr: {
|
||||
const llvm_ret_ty = try o.lowerType(return_type);
|
||||
try attributes.addParamAttr(0, .{ .sret = llvm_ret_ty }, &o.builder);
|
||||
|
||||
const alignment = return_type.abiAlignment(zcu).toLlvm();
|
||||
const ret_ptr = try self.buildAlloca(llvm_ret_ty, alignment);
|
||||
try llvm_args.append(ret_ptr);
|
||||
break :blk ret_ptr;
|
||||
break :ret_ptr ret_ptr;
|
||||
} else ret_ptr: {
|
||||
if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) {
|
||||
.signed => try attributes.addRetAttr(.signext, &o.builder),
|
||||
.unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
|
||||
};
|
||||
break :ret_ptr null;
|
||||
};
|
||||
|
||||
const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;
|
||||
|
||||
@@ -731,3 +731,33 @@ test "tail call function pointer" {
|
||||
|
||||
S.foo(100);
|
||||
}
|
||||
|
||||
test "tail call with potentially extended types" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
if (builtin.zig_backend == .stage2_llvm) {
|
||||
if (builtin.cpu.arch.isMIPS() or builtin.cpu.arch.isPowerPC() or builtin.cpu.arch.isWasm()) {
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
}
|
||||
|
||||
if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support always tail calls
|
||||
|
||||
const S = struct {
|
||||
fn Test(comptime Return: type) type {
|
||||
return struct {
|
||||
fn callee(@"u8": u8, @"i8": i8, @"u16": u16, @"i16": i16) callconv(.c) Return {
|
||||
return @intCast(@as(i32, @"u8") + @as(i32, @"i8") + @as(i32, @"u16") + @as(i32, @"i16"));
|
||||
}
|
||||
fn caller(@"u8": u8, @"i8": i8, @"u16": u16, @"i16": i16) callconv(.c) Return {
|
||||
return @call(.always_tail, callee, .{ @"u8", @"i8", @"u16", @"i16" });
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
try std.testing.expect(S.Test(u8).caller(1, -2, 3, 4) == 6);
|
||||
try std.testing.expect(S.Test(i8).caller(5, -6, 7, -8) == -2);
|
||||
try std.testing.expect(S.Test(u16).caller(9, 10, 11, 12) == 42);
|
||||
try std.testing.expect(S.Test(i16).caller(13, 14, 15, -16) == 26);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user