diff options
author | Tim Northover <tnorthover@apple.com> | 2014-06-10 10:50:24 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2014-06-10 10:50:24 +0000 |
commit | e1db6ac10bcdbfde9f32a9180684de5e5c6ee75b (patch) | |
tree | 056196f5095b1293e5afbeae555e567d711572c8 | |
parent | efbf7d1ceb55d891afb39842be75014807c7042f (diff) | |
download | llvm-e1db6ac10bcdbfde9f32a9180684de5e5c6ee75b.tar.gz llvm-e1db6ac10bcdbfde9f32a9180684de5e5c6ee75b.tar.bz2 llvm-e1db6ac10bcdbfde9f32a9180684de5e5c6ee75b.tar.xz |
AArch64: disallow x30 & x29 as the destination for indirect tail calls
As Ana Pazos pointed out, these have to be restored to their incoming values
before a function returns; i.e. before the tail call. So they can't be used
correctly as the destination register.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210525 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/AArch64/AArch64RegisterInfo.td | 2 | ||||
-rw-r--r-- | test/CodeGen/AArch64/regress-tail-livereg.ll | 14 |
2 files changed, 15 insertions, 1 deletions
diff --git a/lib/Target/AArch64/AArch64RegisterInfo.td b/lib/Target/AArch64/AArch64RegisterInfo.td index 21c927f238..a30e4ad0b5 100644 --- a/lib/Target/AArch64/AArch64RegisterInfo.td +++ b/lib/Target/AArch64/AArch64RegisterInfo.td @@ -175,7 +175,7 @@ def GPR64all : RegisterClass<"AArch64", [i64], 64, (add GPR64common, XZR, SP)>; // This is for indirect tail calls to store the address of the destination. def tcGPR64 : RegisterClass<"AArch64", [i64], 64, (sub GPR64common, X19, X20, X21, X22, X23, X24, X25, X26, - X27, X28)>; + X27, X28, FP, LR)>; // GPR register classes for post increment amount of vector load/store that // has alternate printing when Rm=31 and prints a constant immediate value diff --git a/test/CodeGen/AArch64/regress-tail-livereg.ll b/test/CodeGen/AArch64/regress-tail-livereg.ll index e32ac8458f..03c3f33d94 100644 --- a/test/CodeGen/AArch64/regress-tail-livereg.ll +++ b/test/CodeGen/AArch64/regress-tail-livereg.ll @@ -17,3 +17,17 @@ define void @foo() { ; CHECK: br {{x([0-79]|1[0-8])}} ret void } + +; No matter how tempting it is, LLVM should not use x30 since that'll be +; restored to its incoming value before the "br". +define void @test_x30_tail() { +; CHECK-LABEL: test_x30_tail: +; CHECK: mov [[DEST:x[0-9]+]], x30 +; CHECK: br [[DEST]] + %addr = call i8* @llvm.returnaddress(i32 0) + %faddr = bitcast i8* %addr to void()* + tail call void %faddr() + ret void +} + +declare i8* @llvm.returnaddress(i32) |