[cfe-commits] r165015 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ lib/Basic/ lib/Sema/ test/CodeGen/ test/CodeGenCXX/ test/Sema/

Aaron Ballman aaron at aaronballman.com
Tue Oct 2 07:26:08 PDT 2012


Author: aaronballman
Date: Tue Oct  2 09:26:08 2012
New Revision: 165015

URL: http://llvm.org/viewvc/llvm-project?rev=165015&view=rev
Log:
Allowing individual targets to determine whether a given calling convention is allowed or ignored with warning. This allows for correct name mangling for x64 targets on Windows, which in turn allows for linking against the Win32 APIs.

Fixes PR13782

Added:
    cfe/trunk/test/CodeGen/microsoft-call-conv-x64.c
    cfe/trunk/test/Sema/MicrosoftCompatibility-x64.c
    cfe/trunk/test/Sema/stdcall-fastcall-x64.c
Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/Specifiers.h
    cfe/trunk/include/clang/Basic/TargetInfo.h
    cfe/trunk/lib/Basic/Targets.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/CodeGen/microsoft-call-conv.c
    cfe/trunk/test/CodeGen/stdcall-fastcall.c
    cfe/trunk/test/CodeGenCXX/mangle-ms.cpp
    cfe/trunk/test/Sema/MicrosoftCompatibility.c
    cfe/trunk/test/Sema/callingconv.c
    cfe/trunk/test/Sema/stdcall-fastcall.c

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Tue Oct  2 09:26:08 2012
@@ -20,6 +20,7 @@
 #include "clang/Basic/Linkage.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/Visibility.h"
+#include "clang/Basic/Specifiers.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/TemplateName.h"
 #include "llvm/Support/type_traits.h"
@@ -490,18 +491,6 @@
   static const uint32_t AddressSpaceShift = 8;
 };
 
-/// CallingConv - Specifies the calling convention that a function uses.
-enum CallingConv {
-  CC_Default,
-  CC_C,           // __attribute__((cdecl))
-  CC_X86StdCall,  // __attribute__((stdcall))
-  CC_X86FastCall, // __attribute__((fastcall))
-  CC_X86ThisCall, // __attribute__((thiscall))
-  CC_X86Pascal,   // __attribute__((pascal))
-  CC_AAPCS,       // __attribute__((pcs("aapcs")))
-  CC_AAPCS_VFP    // __attribute__((pcs("aapcs-vfp")))
-};
-
 /// A std::pair-like structure for storing a qualified type split
 /// into its local qualifiers and its locally-unqualified type.
 struct SplitQualType {

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Oct  2 09:26:08 2012
@@ -1799,6 +1799,8 @@
 def err_cconv_change : Error<
   "function declared '%0' here was previously declared "
   "%select{'%2'|without calling convention}1">;
+def warn_cconv_ignored : Warning<
+  "calling convention %0 ignored for this target">, InGroup<IgnoredAttributes>;
 def err_cconv_knr : Error<
   "function with no prototype cannot use %0 calling convention">;
 def err_cconv_varargs : Error<

Modified: cfe/trunk/include/clang/Basic/Specifiers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Specifiers.h?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Specifiers.h (original)
+++ cfe/trunk/include/clang/Basic/Specifiers.h Tue Oct  2 09:26:08 2012
@@ -175,6 +175,19 @@
     ICIS_CopyInit, ///< Copy initialization.
     ICIS_ListInit  ///< Direct list-initialization.
   };
+
+  /// \brief CallingConv - Specifies the calling convention that a function uses.
+  enum CallingConv {
+    CC_Default,
+    CC_C,           // __attribute__((cdecl))
+    CC_X86StdCall,  // __attribute__((stdcall))
+    CC_X86FastCall, // __attribute__((fastcall))
+    CC_X86ThisCall, // __attribute__((thiscall))
+    CC_X86Pascal,   // __attribute__((pascal))
+    CC_AAPCS,       // __attribute__((pcs("aapcs")))
+    CC_AAPCS_VFP    // __attribute__((pcs("aapcs-vfp")))
+  };
+
 } // end namespace clang
 
 #endif // LLVM_CLANG_BASIC_SPECIFIERS_H

Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Tue Oct  2 09:26:08 2012
@@ -24,6 +24,7 @@
 #include "llvm/Support/DataTypes.h"
 #include "clang/Basic/AddressSpaces.h"
 #include "clang/Basic/VersionTuple.h"
+#include "clang/Basic/Specifiers.h"
 #include <cassert>
 #include <vector>
 #include <string>
@@ -712,6 +713,34 @@
 
   bool isBigEndian() const { return BigEndian; }
 
+  /// \brief Gets the default calling convention for the given target and
+  /// declaration context.
+  virtual CallingConv getDefaultCallingConv() const {
+    // Not all targets will specify an explicit calling convention that we can
+    // express.  This will always do the right thing, even though it's not
+    // an explicit calling convention.
+    return CC_Default;
+  }
+
+  enum CallingConvCheckResult {
+    CCCR_OK,
+    CCCR_Warning
+  };
+
+  /// \brief Determines whether a given calling convention is valid for the
+  /// target. A calling convention can either be accepted, produce a warning 
+  /// and be substituted with the default calling convention, or (someday)
+  /// produce an error (such as using thiscall on a non-instance function).
+  virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
+    switch (CC) {
+      default:
+        return CCCR_Warning;
+      case CC_C:
+      case CC_Default:
+        return CCCR_OK;
+    }
+  }
+
 protected:
   virtual uint64_t getPointerWidthV(unsigned AddrSpace) const {
     return PointerWidth;

Modified: cfe/trunk/lib/Basic/Targets.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets.cpp (original)
+++ cfe/trunk/lib/Basic/Targets.cpp Tue Oct  2 09:26:08 2012
@@ -1673,6 +1673,19 @@
     }
     llvm_unreachable("Unhandled CPU kind");
   }
+
+  virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
+    // We accept all non-ARM calling conventions
+    return (CC == CC_X86ThisCall ||
+            CC == CC_X86FastCall ||
+            CC == CC_X86StdCall || 
+            CC == CC_C || 
+            CC == CC_X86Pascal) ? CCCR_OK : CCCR_Warning;
+  }
+
+  virtual CallingConv getDefaultCallingConv() const {
+    return CC_C;
+  }
 };
 
 void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
@@ -2708,6 +2721,15 @@
     if (RegNo == 1) return 1;
     return -1;
   }
+
+  virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
+    return TargetInfo::checkCallingConvention(CC);
+  }
+
+  virtual CallingConv getDefaultCallingConv() const {
+    return CC_Default;
+  }
+
 };
 } // end anonymous namespace
 
@@ -3167,6 +3189,10 @@
     // FIXME: Is this really right?
     return "";
   }
+
+  virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
+    return (CC == CC_AAPCS || CC == CC_AAPCS_VFP) ? CCCR_OK : CCCR_Warning;
+  }
 };
 
 const char * const ARMTargetInfo::GCCRegNames[] = {

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Oct  2 09:26:08 2012
@@ -3638,6 +3638,13 @@
   default: llvm_unreachable("unexpected attribute kind");
   }
 
+  const TargetInfo &TI = Context.getTargetInfo();
+  TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC);
+  if (A == TargetInfo::CCCR_Warning) {
+    Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName();
+    CC = TI.getDefaultCallingConv();
+  }
+
   return false;
 }
 

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Oct  2 09:26:08 2012
@@ -3886,14 +3886,14 @@
     return true;
   }
 
+  // Delay if the type didn't work out to a function.
+  if (!unwrapped.isFunctionType()) return false;
+
   // Otherwise, a calling convention.
   CallingConv CC;
   if (S.CheckCallingConvAttr(attr, CC))
     return true;
 
-  // Delay if the type didn't work out to a function.
-  if (!unwrapped.isFunctionType()) return false;
-
   const FunctionType *fn = unwrapped.get();
   CallingConv CCOld = fn->getCallConv();
   if (S.Context.getCanonicalCallConv(CC) ==

Added: cfe/trunk/test/CodeGen/microsoft-call-conv-x64.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/microsoft-call-conv-x64.c?rev=165015&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/microsoft-call-conv-x64.c (added)
+++ cfe/trunk/test/CodeGen/microsoft-call-conv-x64.c Tue Oct  2 09:26:08 2012
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm < %s | FileCheck %s
+
+void __fastcall f1(void);
+void __stdcall f2(void);
+void __fastcall f4(void) {
+// CHECK: define void @f4()
+  f1();
+// CHECK: call void @f1()
+}
+void __stdcall f5(void) {
+// CHECK: define void @f5()
+  f2();
+// CHECK: call void @f2()
+}
+
+// PR5280
+void (__fastcall *pf1)(void) = f1;
+void (__stdcall *pf2)(void) = f2;
+void (__fastcall *pf4)(void) = f4;
+void (__stdcall *pf5)(void) = f5;
+
+int main(void) {
+    f4(); f5();
+    // CHECK: call void @f4()
+    // CHECK: call void @f5()
+    pf1(); pf2(); pf4(); pf5();
+    // CHECK: call void %{{.*}}()
+    // CHECK: call void %{{.*}}()
+    // CHECK: call void %{{.*}}()
+    // CHECK: call void %{{.*}}()
+    return 0;
+}
+
+// PR7117
+void __stdcall f7(foo) int foo; {}
+void f8(void) {
+  f7(0);
+  // CHECK: call void @f7(i32 0)
+}

Modified: cfe/trunk/test/CodeGen/microsoft-call-conv.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/microsoft-call-conv.c?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/microsoft-call-conv.c (original)
+++ cfe/trunk/test/CodeGen/microsoft-call-conv.c Tue Oct  2 09:26:08 2012
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm < %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-pc-linux -emit-llvm < %s | FileCheck %s
 
 void __fastcall f1(void);
 void __stdcall f2(void);

Modified: cfe/trunk/test/CodeGen/stdcall-fastcall.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/stdcall-fastcall.c?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/stdcall-fastcall.c (original)
+++ cfe/trunk/test/CodeGen/stdcall-fastcall.c Tue Oct  2 09:26:08 2012
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm < %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm < %s | FileCheck %s
 
 void __attribute__((fastcall)) f1(void);
 void __attribute__((stdcall)) f2(void);

Modified: cfe/trunk/test/CodeGenCXX/mangle-ms.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms.cpp?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms.cpp Tue Oct  2 09:26:08 2012
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fms-compatibility -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
 
 // CHECK: @"\01?a@@3HA"
 // CHECK: @"\01?b at N@@3HA"
@@ -109,6 +110,7 @@
 }
 
 // CHECK: @"\01?alpha@@YGXMN at Z"
+// X64: @"\01?alpha@@YAXMN at Z"
 
 // Make sure tag-type mangling works.
 void gamma(class foo, struct bar, union baz, enum quux) {}

Added: cfe/trunk/test/Sema/MicrosoftCompatibility-x64.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/MicrosoftCompatibility-x64.c?rev=165015&view=auto
==============================================================================
--- cfe/trunk/test/Sema/MicrosoftCompatibility-x64.c (added)
+++ cfe/trunk/test/Sema/MicrosoftCompatibility-x64.c Tue Oct  2 09:26:08 2012
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-compatibility -triple x86_64-pc-win32
+int __stdcall f(void); /* expected-warning {{calling convention '__stdcall' ignored for this target}} */
+
+/* This should compile without warning because __stdcall is treated
+as __cdecl in MS compatibility mode for x64 compiles*/
+int __cdecl f(void) {
+  return 0;
+}

Modified: cfe/trunk/test/Sema/MicrosoftCompatibility.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/MicrosoftCompatibility.c?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/test/Sema/MicrosoftCompatibility.c (original)
+++ cfe/trunk/test/Sema/MicrosoftCompatibility.c Tue Oct  2 09:26:08 2012
@@ -18,4 +18,10 @@
 __declspec(align(32768)) struct S1 { int a; } s;	/* expected-error {{requested alignment must be 8192 bytes or smaller}} */
 struct __declspec(aligned) S2 {}; /* expected-warning {{unknown __declspec attribute 'aligned' ignored}} */
 
-struct __declspec(appdomain) S3 {}; /* expected-warning {{__declspec attribute 'appdomain' is not supported}} */
\ No newline at end of file
+struct __declspec(appdomain) S3 {}; /* expected-warning {{__declspec attribute 'appdomain' is not supported}} */
+
+int __stdcall f(void); /* expected-note {{previous declaration is here}} */
+
+int __cdecl f(void) { /* expected-error {{function declared 'cdecl' here was previously declared 'stdcall'}} */
+  return 0;
+}

Modified: cfe/trunk/test/Sema/callingconv.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/callingconv.c?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/test/Sema/callingconv.c (original)
+++ cfe/trunk/test/Sema/callingconv.c Tue Oct  2 09:26:08 2012
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -triple i386-unknown-unknown -verify
 
 void __attribute__((fastcall)) foo(float *a) { 
 }
@@ -40,8 +40,9 @@
 int __attribute__((pcs())) pcs2(void); // expected-error {{attribute takes one argument}}
 int __attribute__((pcs(pcs1))) pcs3(void); // expected-error {{attribute takes one argument}}
 int __attribute__((pcs(0))) pcs4(void); // expected-error {{'pcs' attribute requires parameter 1 to be a string}}
-int __attribute__((pcs("aapcs"))) pcs5(void); // no-error
-int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // no-error
+/* These are ignored because the target is i386 and not ARM */
+int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{calling convention 'pcs' ignored for this target}}
+int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{calling convention 'pcs' ignored for this target}}
 int __attribute__((pcs("foo"))) pcs7(void); // expected-error {{Invalid PCS type}}
 
 // PR6361

Added: cfe/trunk/test/Sema/stdcall-fastcall-x64.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/stdcall-fastcall-x64.c?rev=165015&view=auto
==============================================================================
--- cfe/trunk/test/Sema/stdcall-fastcall-x64.c (added)
+++ cfe/trunk/test/Sema/stdcall-fastcall-x64.c Tue Oct  2 09:26:08 2012
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-linux-gnu %s
+
+// CC qualifier can be applied only to functions
+int __attribute__((stdcall)) var1; // expected-warning{{'stdcall' only applies to function types; type here is 'int'}}
+int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' only applies to function types; type here is 'int'}}
+
+// Different CC qualifiers are not compatible
+void __attribute__((stdcall, fastcall)) foo3(void); // expected-warning{{calling convention 'stdcall' ignored for this target}} expected-warning {{calling convention 'fastcall' ignored for this target}}
+void __attribute__((stdcall)) foo4(); // expected-warning{{calling convention 'stdcall' ignored for this target}}
+void __attribute__((fastcall)) foo4(void); // expected-warning {{calling convention 'fastcall' ignored for this target}}
+
+// rdar://8876096
+void rdar8876096foo1(int i, int j) __attribute__((fastcall, cdecl)); // expected-warning{{calling convention 'fastcall' ignored for this target}}
+void rdar8876096foo2(int i, int j) __attribute__((fastcall, stdcall)); // expected-warning{{calling convention 'stdcall' ignored for this target}} expected-warning {{calling convention 'fastcall' ignored for this target}}
+void rdar8876096foo3(int i, int j) __attribute__((fastcall, regparm(2))); // expected-warning {{calling convention 'fastcall' ignored for this target}}
+void rdar8876096foo4(int i, int j) __attribute__((stdcall, cdecl)); // expected-warning{{calling convention 'stdcall' ignored for this target}}
+void rdar8876096foo5(int i, int j) __attribute__((stdcall, fastcall)); // expected-warning{{calling convention 'stdcall' ignored for this target}} expected-warning {{calling convention 'fastcall' ignored for this target}}
+void rdar8876096foo6(int i, int j) __attribute__((cdecl, fastcall)); // expected-warning {{calling convention 'fastcall' ignored for this target}}
+void rdar8876096foo7(int i, int j) __attribute__((cdecl, stdcall)); // expected-warning{{calling convention 'stdcall' ignored for this target}}
+void rdar8876096foo8(int i, int j) __attribute__((regparm(2), fastcall)); // expected-warning {{calling convention 'fastcall' ignored for this target}}

Modified: cfe/trunk/test/Sema/stdcall-fastcall.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/stdcall-fastcall.c?rev=165015&r1=165014&r2=165015&view=diff
==============================================================================
--- cfe/trunk/test/Sema/stdcall-fastcall.c (original)
+++ cfe/trunk/test/Sema/stdcall-fastcall.c Tue Oct  2 09:26:08 2012
@@ -1,4 +1,3 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-linux-gnu %s
 // RUN: %clang_cc1 -fsyntax-only -verify -triple i686-apple-darwin10 %s
 
 // CC qualifier can be applied only to functions





More information about the cfe-commits mailing list