summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lerouge <jlerouge@apple.com>2014-08-26 21:52:27 +0000
committerJulien Lerouge <jlerouge@apple.com>2014-08-26 21:52:27 +0000
commit0056256b5595e8d8d3af2c927749092825454faf (patch)
treec561b46cdf24c7e5cc01638c054e34370d4882fd
parent04d3b3ea0fb7a1ed7d9a290bad1c60e2cd7ad2e2 (diff)
downloadbcm5719-llvm-0056256b5595e8d8d3af2c927749092825454faf.tar.gz
bcm5719-llvm-0056256b5595e8d8d3af2c927749092825454faf.zip
Win64 ABI shouldn't extend integer type arguments.
Summary: MSVC doesn't extend integer types smaller than 64bit, so to preserve binary compatibility, clang shouldn't either. For example, the following C code built with MSVC: unsigned test(unsigned v); unsigned foobar(unsigned short); int main() { return test(0xffffffff) + foobar(28); } Produces the following: 0000000000000004: B9 FF FF FF FF mov ecx,0FFFFFFFFh 0000000000000009: E8 00 00 00 00 call test 000000000000000E: 89 44 24 20 mov dword ptr [rsp+20h],eax 0000000000000012: 66 B9 1C 00 mov cx,1Ch 0000000000000016: E8 00 00 00 00 call foobar And as you can see, when setting up the call to foobar, only cx is overwritten. If foobar is compiled with clang, then the zero extension added by clang means the rest of the register, which contains garbage, could be used. For example if foobar is: unsigned foobar(unsigned short v) { return v; } Compiled with clang -fomit-frame-pointer -O3 gives the following assembly: foobar: 0000000000000000: 89 C8 mov eax,ecx 0000000000000002: C3 ret And that function would return garbage because the 16 most significant bits of ecx still contain garbage from the first call. With this change, the code for that function is now: foobar: 0000000000000000: 0F B7 C1 movzx eax,cx 0000000000000003: C3 ret Reviewers: chapuni, rnk Reviewed By: rnk Subscribers: majnemer, cfe-commits Differential Revision: http://reviews.llvm.org/D4380 llvm-svn: 216491
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp3
-rw-r--r--clang/test/CodeGen/2007-06-18-SextAttrAggregate.c4
-rw-r--r--clang/test/CodeGen/x86_64-arguments-win32.c16
3 files changed, 19 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index ea5f7c22399..4e4f03b6c09 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -2773,9 +2773,6 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, bool IsReturnType) const {
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size));
}
- if (Ty->isPromotableIntegerType())
- return ABIArgInfo::getExtend();
-
return ABIArgInfo::getDirect();
}
diff --git a/clang/test/CodeGen/2007-06-18-SextAttrAggregate.c b/clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
index 92171e2bd9b..22aa95a6bff 100644
--- a/clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
+++ b/clang/test/CodeGen/2007-06-18-SextAttrAggregate.c
@@ -1,11 +1,13 @@
// RUN: %clang_cc1 %s -o - -emit-llvm | FileCheck %s
-// XFAIL: aarch64, arm64
+// XFAIL: aarch64, arm64, x86_64-pc-win32
// PR1513
// AArch64 ABI actually requires the reverse of what this is testing: the callee
// does any extensions and remaining bits are unspecified.
+// Win64 ABI does expect extensions for type smaller than 64bits.
+
// Technically this test wasn't written to test that feature, but it's a
// valuable check nevertheless.
diff --git a/clang/test/CodeGen/x86_64-arguments-win32.c b/clang/test/CodeGen/x86_64-arguments-win32.c
new file mode 100644
index 00000000000..5aea7fc6236
--- /dev/null
+++ b/clang/test/CodeGen/x86_64-arguments-win32.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -w -triple x86_64-pc-win32 -emit-llvm -o - %s | FileCheck %s
+
+// To be ABI compatible with code generated by MSVC, there shouldn't be any
+// sign/zero extensions on types smaller than 64bit.
+
+// CHECK-LABEL: define void @f1(i8 %a)
+void f1(char a) {}
+
+// CHECK-LABEL: define void @f2(i8 %a)
+void f2(unsigned char a) {}
+
+// CHECK-LABEL: define void @f3(i16 %a)
+void f3(short a) {}
+
+// CHECK-LABEL: define void @f4(i16 %a)
+void f4(unsigned short a) {}
OpenPOWER on IntegriCloud