]> granicus.if.org Git - clang/commitdiff
Driver: add target definition for Windows on ARM
authorSaleem Abdulrasool <compnerd@compnerd.org>
Fri, 4 Apr 2014 20:31:19 +0000 (20:31 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Fri, 4 Apr 2014 20:31:19 +0000 (20:31 +0000)
This introduces the definitions needed for the Windows on ARM target.  Add
target definitions for both the MSVC environment and the MSVC + Itanium C++ ABI
environment.  The Visual Studio definitions correspond to the definitions
provided by Visual Studio 2012.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205650 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticDriverKinds.td
lib/Basic/Targets.cpp
lib/Driver/ToolChain.cpp
lib/Driver/Tools.cpp
test/Driver/windows-arm-minimal-arch.c [new file with mode: 0644]
test/Parser/arm-windows-calling-convention-handling.c [new file with mode: 0644]
test/Preprocessor/woa-defaults.c [new file with mode: 0644]

index 71080ba552f74f90c3604b086c226a27efa2dbf8..a64b1ae63ce7c67f195d81857e14f0abbc4b9580 100644 (file)
@@ -82,6 +82,9 @@ def err_drv_invalid_libcxx_deployment : Error<
 def err_drv_malformed_sanitizer_blacklist : Error<
   "malformed sanitizer blacklist: '%0'">;
 
+def err_target_unsupported_arch
+  : Error<"the target architecture '%0' is not supported by the target '%1'">;
+
 def err_drv_I_dash_not_supported : Error<
   "'%0' not supported, please use -iquote instead">;
 def err_drv_unknown_argument : Error<"unknown argument: '%0'">;
index 44b92674c8532181a1be9a4ff96e6df9e2e78a82..a6272ef64a0d8382bcf2f67bc863568c0767d2a0 100644 (file)
@@ -3708,6 +3708,9 @@ class ARMTargetInfo : public TargetInfo {
   static const Builtin::Info BuiltinInfo[];
 
   static bool shouldUseInlineAtomic(const llvm::Triple &T) {
+    if (T.isOSWindows())
+      return true;
+
     // On linux, binaries targeting old cpus call functions in libgcc to
     // perform atomic operations. The implementation in libgcc then calls into
     // the kernel which on armv6 and newer uses ldrex and strex. The net result
@@ -3774,19 +3777,30 @@ class ARMTargetInfo : public TargetInfo {
     if (IsThumb) {
       // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
       // so set preferred for small types to 32.
-      if (T.isOSBinFormatMachO())
+      if (T.isOSBinFormatMachO()) {
         DescriptionString = BigEndian ?
                               "E-m:o-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-"
                               "v128:64:128-a:0:32-n32-S64" :
                               "e-m:o-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-"
                               "v128:64:128-a:0:32-n32-S64";
-      else
+      } else if (T.isOSWindows()) {
+        // FIXME: this is invalid for WindowsCE
+        assert(!BigEndian && "Windows on ARM does not support big endian");
+        DescriptionString = "e"
+                            "-m:e"
+                            "-p:32:32"
+                            "-i1:8:32-i8:8:32-i16:16:32-i64:64"
+                            "-v128:64:128"
+                            "-a:0:32"
+                            "-n32"
+                            "-S64";
+      } else {
         DescriptionString = BigEndian ?
                               "E-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-"
                               "v128:64:128-a:0:32-n32-S64" :
                               "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-"
                               "v128:64:128-a:0:32-n32-S64";
-
+      }
     } else {
       if (T.isOSBinFormatMachO())
         DescriptionString = BigEndian ?
@@ -4093,12 +4107,14 @@ public:
 
     // FIXME: It's more complicated than this and we don't really support
     // interworking.
-    if (5 <= CPUArchVer && CPUArchVer <= 8)
+    // Windows on ARM does not "support" interworking
+    if (5 <= CPUArchVer && CPUArchVer <= 8 && !getTriple().isOSWindows())
       Builder.defineMacro("__THUMB_INTERWORK__");
 
     if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
       // Embedded targets on Darwin follow AAPCS, but not EABI.
-      if (!getTriple().isOSDarwin())
+      // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
+      if (!getTriple().isOSDarwin() && !getTriple().isOSWindows())
         Builder.defineMacro("__ARM_EABI__");
       Builder.defineMacro("__ARM_PCS", "1");
 
@@ -4370,6 +4386,72 @@ public:
 };
 } // end anonymous namespace.
 
+namespace {
+class WindowsARMTargetInfo : public WindowsTargetInfo<ARMleTargetInfo> {
+  const llvm::Triple Triple;
+public:
+  WindowsARMTargetInfo(const llvm::Triple &Triple)
+    : WindowsTargetInfo<ARMleTargetInfo>(Triple), Triple(Triple) {
+    TLSSupported = false;
+    WCharType = UnsignedShort;
+    SizeType = UnsignedInt;
+    UserLabelPrefix = "";
+  }
+  void getVisualStudioDefines(const LangOptions &Opts,
+                              MacroBuilder &Builder) const {
+    WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder);
+
+    // FIXME: this is invalid for WindowsCE
+    Builder.defineMacro("_M_ARM_NT", "1");
+    Builder.defineMacro("_M_ARMT", "_M_ARM");
+    Builder.defineMacro("_M_THUMB", "_M_ARM");
+
+    assert((Triple.getArch() == llvm::Triple::arm ||
+            Triple.getArch() == llvm::Triple::thumb) &&
+           "invalid architecture for Windows ARM target info");
+    unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
+    Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
+
+    // TODO map the complete set of values
+    // 31: VFPv3 40: VFPv4
+    Builder.defineMacro("_M_ARM_FP", "31");
+  }
+};
+
+// Windows ARM + Itanium C++ ABI Target
+class ItaniumWindowsARMleTargetInfo : public WindowsARMTargetInfo {
+public:
+  ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple)
+    : WindowsARMTargetInfo(Triple) {
+    TheCXXABI.set(TargetCXXABI::GenericARM);
+  }
+
+  void getTargetDefines(const LangOptions &Opts,
+                        MacroBuilder &Builder) const override {
+    WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+
+    if (Opts.MSVCCompat)
+      WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
+  }
+};
+
+// Windows ARM, MS (C++) ABI
+class MicrosoftARMleTargetInfo : public WindowsARMTargetInfo {
+public:
+  MicrosoftARMleTargetInfo(const llvm::Triple &Triple)
+    : WindowsARMTargetInfo(Triple) {
+    TheCXXABI.set(TargetCXXABI::Microsoft);
+  }
+
+  void getTargetDefines(const LangOptions &Opts,
+                        MacroBuilder &Builder) const override {
+    WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+    WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
+  }
+};
+}
+
+
 namespace {
 class DarwinARMTargetInfo :
   public DarwinTargetInfo<ARMleTargetInfo> {
@@ -6058,6 +6140,15 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
       return new RTEMSTargetInfo<ARMleTargetInfo>(Triple);
     case llvm::Triple::NaCl:
       return new NaClTargetInfo<ARMleTargetInfo>(Triple);
+    case llvm::Triple::Win32:
+      switch (Triple.getEnvironment()) {
+      default:
+        return new ARMleTargetInfo(Triple);
+      case llvm::Triple::Itanium:
+        return new ItaniumWindowsARMleTargetInfo(Triple);
+      case llvm::Triple::MSVC:
+        return new MicrosoftARMleTargetInfo(Triple);
+      }
     default:
       return new ARMleTargetInfo(Triple);
     }
index d164edd7347335613212ba9bf78b049bc869e8d0..dd2a2bc64fd11746cc4ace2a280ce13a4d81f937 100644 (file)
@@ -214,6 +214,9 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
     bool ThumbDefault = Suffix.startswith("v6m") || Suffix.startswith("v7m") ||
       Suffix.startswith("v7em") ||
       (Suffix.startswith("v7") && getTriple().isOSBinFormatMachO());
+    // FIXME: this is invalid for WindowsCE
+    if (getTriple().isOSWindows())
+      ThumbDefault = true;
     std::string ArchName;
     if (IsBigEndian)
       ArchName = "armeb";
index 6acc3d5f58a57f1baca6452e60e4ad196908d9a4..cd369d72eb59a0c85f51b32adff9503d0c2f697c 100644 (file)
@@ -475,6 +475,10 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
   case llvm::Triple::arm64:
   case llvm::Triple::arm:
   case llvm::Triple::armeb:
+    if (Triple.isOSDarwin() || Triple.isOSWindows())
+      return true;
+    return false;
+
   case llvm::Triple::ppc:
   case llvm::Triple::ppc64:
     if (Triple.isOSDarwin())
@@ -645,6 +649,11 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
       break;
     }
 
+    // FIXME: this is invalid for WindowsCE
+    case llvm::Triple::Win32:
+      FloatABI = "hard";
+      break;
+
     case llvm::Triple::FreeBSD:
       switch(Triple.getEnvironment()) {
       case llvm::Triple::GNUEABIHF:
@@ -772,6 +781,9 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
     } else {
       ABIName = "apcs-gnu";
     }
+  } else if (Triple.isOSWindows()) {
+    // FIXME: this is invalid for WindowsCE
+    ABIName = "aapcs";
   } else {
     // Select the default based on the platform.
     switch(Triple.getEnvironment()) {
@@ -2198,6 +2210,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
   CmdArgs.push_back(Args.MakeArgString(TripleStr));
 
+  const llvm::Triple TT(TripleStr);
+  if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
+                           TT.getArch() == llvm::Triple::thumb)) {
+    unsigned Offset = TT.getArch() == llvm::Triple::arm ? 4 : 6;
+    unsigned Version;
+    TT.getArchName().substr(Offset).getAsInteger(10, Version);
+    if (Version < 7)
+      D.Diag(diag::err_target_unsupported_arch) << TT.getArchName() << TripleStr;
+  }
+
   // Push all default warning arguments that are specific to
   // the given target.  These come before user provided warning options
   // are provided.
@@ -4835,9 +4857,16 @@ const char *arm::getARMCPUForMArch(const ArgList &Args,
     }
   }
 
-  if (Triple.getOS() == llvm::Triple::NetBSD) {
+  switch (Triple.getOS()) {
+  case llvm::Triple::NetBSD:
     if (MArch == "armv6")
       return "arm1176jzf-s";
+    break;
+  case llvm::Triple::Win32:
+    // FIXME: this is invalid for WindowsCE
+    return "cortex-a9";
+  default:
+    break;
   }
 
   const char *result = llvm::StringSwitch<const char *>(MArch)
diff --git a/test/Driver/windows-arm-minimal-arch.c b/test/Driver/windows-arm-minimal-arch.c
new file mode 100644 (file)
index 0000000..cf55b8f
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: not %clang -target thumbv5-windows -mcpu=arm10tdmi %s -o /dev/null 2>&1 \
+// RUN:   | FileCheck %s
+
+// CHECK: error: the target architecture 'thumbv5' is not supported by the target 'thumbv5--windows-msvc'
+
diff --git a/test/Parser/arm-windows-calling-convention-handling.c b/test/Parser/arm-windows-calling-convention-handling.c
new file mode 100644 (file)
index 0000000..7717aad
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -fsyntax-only -verify %s
+
+int __cdecl cdecl(int a, int b, int c, int d) { // expected-warning {{calling convention '__cdecl' ignored for this target}}
+  return a + b + c + d;
+}
+
+float __stdcall stdcall(float a, float b, float c, float d) { // expected-warning {{calling convention '__stdcall' ignored for this target}}
+  return a + b + c + d;
+}
+
diff --git a/test/Preprocessor/woa-defaults.c b/test/Preprocessor/woa-defaults.c
new file mode 100644 (file)
index 0000000..6eab3b9
--- /dev/null
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -dM -triple armv7-windows -E %s | FileCheck %s
+// RUN: %clang_cc1 -dM -fno-signed-char -triple armv7-windows -E %s \
+// RUN:   | FileCheck %s -check-prefix CHECK-UNSIGNED-CHAR
+
+// CHECK: #define _INTEGRAL_MAX_BITS 64
+// CHECK: #define _M_ARM 7
+// CHECK: #define _M_ARMT _M_ARM
+// CHECK: #define _M_ARM_FP 31
+// CHECK: #define _M_ARM_NT 1
+// CHECK: #define _M_THUMB _M_ARM
+// CHECK: #define _WIN32 1
+
+// CHECK: #define __ARM_PCS 1
+// CHECK: #define __ARM_PCS_VFP 1
+// CHECK: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+// CHECK: #define __SIZEOF_DOUBLE__ 8
+// CHECK: #define __SIZEOF_FLOAT__ 4
+// CHECK: #define __SIZEOF_INT__ 4
+// CHECK: #define __SIZEOF_LONG_DOUBLE__ 8
+// CHECK: #define __SIZEOF_LONG_LONG__ 8
+// CHECK: #define __SIZEOF_LONG__ 4
+// CHECK: #define __SIZEOF_POINTER__ 4
+// CHECK: #define __SIZEOF_PTRDIFF_T__ 4
+// CHECK: #define __SIZEOF_SHORT__ 2
+// CHECK: #define __SIZEOF_SIZE_T__ 4
+// CHECK: #define __SIZEOF_WCHAR_T__ 2
+// CHECK: #define __SIZEOF_WINT_T__ 4
+
+// CHECK-NOT: __THUMB_INTERWORK__
+// CHECK-NOT: __ARM_EABI__
+// CHECK-NOT: _CHAR_UNSIGNED
+
+// CHECK-UNSIGNED-CHAR: #define _CHAR_UNSIGNED 1