aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoachimschmidt557 <joachim.schmidt557@outlook.com>2021-03-27 22:23:14 +0100
committerJakub Konka <kubkon@jakubkonka.com>2021-03-31 23:27:50 +0200
commit1b657e6e41bcaf362d1cc9455c17e06e57973554 (patch)
tree796f29c590abe7d5dc5d0ab5ad195ab8a890e7d0
parente088a17f56a154ecc43c36e8308833d657e6f43e (diff)
downloadzig-1b657e6e41bcaf362d1cc9455c17e06e57973554.tar.gz
zig-1b657e6e41bcaf362d1cc9455c17e06e57973554.zip
stage2 codegen: Make sure function return value is in a callee
preserved register
-rw-r--r--src/codegen.zig10
-rw-r--r--test/stage2/arm.zig41
2 files changed, 51 insertions, 0 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 6365d66ec6..bc3480ca01 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -2194,6 +2194,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
unreachable;
}
+ switch (info.return_value) {
+ .register => |reg| {
+ if (Register.allocIndex(reg) == null) {
+ // Save function return value in a callee saved register
+ return try self.copyToNewRegister(&inst.base, info.return_value);
+ }
+ },
+ else => {},
+ }
+
return info.return_value;
}
diff --git a/test/stage2/arm.zig b/test/stage2/arm.zig
index 1bc3f23058..31bbfc3170 100644
--- a/test/stage2/arm.zig
+++ b/test/stage2/arm.zig
@@ -378,4 +378,45 @@ pub fn addCases(ctx: *TestContext) !void {
"",
);
}
+
+ {
+ var case = ctx.exe("save function return values in callee preserved register", linux_arm);
+ // Here, it is necessary to save the result of bar() into a
+ // callee preserved register, otherwise it will be overwritten
+ // by the first parameter to baz.
+ case.addCompareOutput(
+ \\export fn _start() noreturn {
+ \\ assert(foo() == 43);
+ \\ exit();
+ \\}
+ \\
+ \\fn foo() u32 {
+ \\ return bar() + baz(42);
+ \\}
+ \\
+ \\fn bar() u32 {
+ \\ return 1;
+ \\}
+ \\
+ \\fn baz(x: u32) u32 {
+ \\ return x;
+ \\}
+ \\
+ \\fn assert(ok: bool) void {
+ \\ if (!ok) unreachable;
+ \\}
+ \\
+ \\fn exit() noreturn {
+ \\ asm volatile ("svc #0"
+ \\ :
+ \\ : [number] "{r7}" (1),
+ \\ [arg1] "{r0}" (0)
+ \\ : "memory"
+ \\ );
+ \\ unreachable;
+ \\}
+ ,
+ "",
+ );
+ }
}