From a92b40825a9a8345984433093b166d3b08353f8b Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 4 Apr 2014 20:31:19 +0000 Subject: [PATCH] Driver: add target definition for Windows on ARM 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 | 3 + lib/Basic/Targets.cpp | 101 +++++++++++++++++- lib/Driver/ToolChain.cpp | 3 + lib/Driver/Tools.cpp | 31 +++++- test/Driver/windows-arm-minimal-arch.c | 5 + .../arm-windows-calling-convention-handling.c | 10 ++ test/Preprocessor/woa-defaults.c | 33 ++++++ 7 files changed, 180 insertions(+), 6 deletions(-) create mode 100644 test/Driver/windows-arm-minimal-arch.c create mode 100644 test/Parser/arm-windows-calling-convention-handling.c create mode 100644 test/Preprocessor/woa-defaults.c diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 71080ba552..a64b1ae63c 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -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'">; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 44b92674c8..a6272ef64a 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -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 { + const llvm::Triple Triple; +public: + WindowsARMTargetInfo(const llvm::Triple &Triple) + : WindowsTargetInfo(Triple), Triple(Triple) { + TLSSupported = false; + WCharType = UnsignedShort; + SizeType = UnsignedInt; + UserLabelPrefix = ""; + } + void getVisualStudioDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + WindowsTargetInfo::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 { @@ -6058,6 +6140,15 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { return new RTEMSTargetInfo(Triple); case llvm::Triple::NaCl: return new NaClTargetInfo(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); } diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index d164edd734..dd2a2bc64f 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -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"; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 6acc3d5f58..cd369d72eb 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -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(MArch) diff --git a/test/Driver/windows-arm-minimal-arch.c b/test/Driver/windows-arm-minimal-arch.c new file mode 100644 index 0000000000..cf55b8f99d --- /dev/null +++ b/test/Driver/windows-arm-minimal-arch.c @@ -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 index 0000000000..7717aada53 --- /dev/null +++ b/test/Parser/arm-windows-calling-convention-handling.c @@ -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 index 0000000000..6eab3b96f4 --- /dev/null +++ b/test/Preprocessor/woa-defaults.c @@ -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 -- 2.40.0