Index: include/clang/Basic/TargetInfo.h =================================================================== --- include/clang/Basic/TargetInfo.h +++ include/clang/Basic/TargetInfo.h @@ -807,6 +807,13 @@ // \brief Validate the contents of the __builtin_cpu_supports(const char*) // argument. virtual bool validateCpuSupports(StringRef Name) const { return false; } + + /// Handle arguments passed to LLVM's option processing. + /// + /// \return False on error. + virtual bool handleLLVMArgs(std::vector &Args) { + return true; + } // \brief Returns maximal number of args passed in registers. unsigned getRegParmMax() const { Index: include/clang/Basic/TargetOptions.h =================================================================== --- include/clang/Basic/TargetOptions.h +++ include/clang/Basic/TargetOptions.h @@ -47,6 +47,10 @@ std::vector Features; std::vector Reciprocals; + + /// \brief A list of arguments to forward to LLVM's option processing; this + /// should only be used for debugging and experimental features. + std::vector LLVMArgs; }; } // end namespace clang Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1300,6 +1300,7 @@ def mno_rdseed : Flag<["-"], "mno-rdseed">, Group; def mno_adx : Flag<["-"], "mno-adx">, Group; def mno_sha : Flag<["-"], "mno-sha">, Group; +def malign_double : Flag<["-"], "malign-double">, Group; def munaligned_access : Flag<["-"], "munaligned-access">, Group, HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">; Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -723,7 +723,7 @@ if (Triple.getArch() == llvm::Triple::arm) { // Handled in ARM's setABI(). } else if (Triple.getArch() == llvm::Triple::x86) { - this->DataLayoutString = "e-m:e-p:32:32-i64:64-n8:16:32-S128"; + // Handled in X86_32's setDataLayoutString. } else if (Triple.getArch() == llvm::Triple::x86_64) { this->DataLayoutString = "e-m:e-p:32:32-i64:64-n8:16:32:64-S128"; } else if (Triple.getArch() == llvm::Triple::mipsel) { @@ -3569,13 +3569,21 @@ // X86-32 generic target class X86_32TargetInfo : public X86TargetInfo { + virtual void setDataLayoutString() { + if (getTriple().isOSNaCl()) + DataLayoutString = "e-m:e-p:32:32-i64:64-n8:16:32-S128"; + else if (HasAlignedDouble) + DataLayoutString = "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-S128"; + else + DataLayoutString = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"; + } + bool HasAlignedDouble; public: X86_32TargetInfo(const llvm::Triple &Triple) : X86TargetInfo(Triple) { DoubleAlign = LongLongAlign = 32; LongDoubleWidth = 96; LongDoubleAlign = 32; SuitableAlign = 128; - DataLayoutString = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"; SizeType = UnsignedInt; PtrDiffType = SignedInt; IntPtrType = SignedInt; @@ -3620,6 +3628,16 @@ return X86TargetInfo::validateOperandSize(Constraint, Size); } + + bool handleLLVMArgs(std::vector &Args) override { + HasAlignedDouble = false; + auto it = std::find(Args.begin(), Args.end(), "-malign-double"); + if (it != Args.end()) { + HasAlignedDouble = true; + } + setDataLayoutString(); + return true; + } }; class NetBSDI386TargetInfo : public NetBSDTargetInfo { @@ -3659,6 +3677,9 @@ }; class DarwinI386TargetInfo : public DarwinTargetInfo { + void setDataLayoutString() override { + DataLayoutString = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128"; + } public: DarwinI386TargetInfo(const llvm::Triple &Triple) : DarwinTargetInfo(Triple) { @@ -3667,7 +3688,6 @@ SuitableAlign = 128; SizeType = UnsignedLong; IntPtrType = SignedLong; - DataLayoutString = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128"; HasAlignMac68kSupport = true; } @@ -3685,17 +3705,19 @@ // x86-32 Windows target class WindowsX86_32TargetInfo : public WindowsTargetInfo { -public: - WindowsX86_32TargetInfo(const llvm::Triple &Triple) - : WindowsTargetInfo(Triple) { - WCharType = UnsignedShort; - DoubleAlign = LongLongAlign = 64; + void setDataLayoutString() override { bool IsWinCOFF = getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF(); DataLayoutString = IsWinCOFF ? "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"; } +public: + WindowsX86_32TargetInfo(const llvm::Triple &Triple) + : WindowsTargetInfo(Triple) { + WCharType = UnsignedShort; + DoubleAlign = LongLongAlign = 64; + } void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override { WindowsTargetInfo::getTargetDefines(Opts, Builder); @@ -3770,13 +3792,15 @@ // x86-32 Cygwin target class CygwinX86_32TargetInfo : public X86_32TargetInfo { + void setDataLayoutString() override { + DataLayoutString = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"; + } public: CygwinX86_32TargetInfo(const llvm::Triple &Triple) : X86_32TargetInfo(Triple) { TLSSupported = false; WCharType = UnsignedShort; DoubleAlign = LongLongAlign = 64; - DataLayoutString = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"; } void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override { @@ -7778,5 +7802,8 @@ if (!Target->handleTargetFeatures(Opts->Features, Diags)) return nullptr; + if (!Target->handleLLVMArgs(Opts->LLVMArgs)) + return nullptr; + return Target.release(); } Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -1911,6 +1911,11 @@ << A->getOption().getName() << Value; } } + + if (Args.getLastArg(options::OPT_malign_double)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-malign-double"); + } } void Clang::AddHexagonTargetArgs(const ArgList &Args, Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1867,6 +1867,7 @@ Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version); Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ); + Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm); // Use the default target triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getDefaultTargetTriple(); Index: test/Driver/malign-double.c =================================================================== --- /dev/null +++ test/Driver/malign-double.c @@ -0,0 +1,22 @@ +// RUN: %clang -v -c -malign-double %s -target i686-unknown-linux 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-I686 %s + +// CHECK-I686: -cc1 +// CHECK-I686: -mllvm -malign-double +// CHECK-I686-NOT: backend data layout {{'[^']+'}} does not match expected target description {{'[^']+'}} + +// RUN: %clang -v -c -malign-double %s -target x86_64-unknown-linux 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-X86_64 %s + +// CHECK-X86_64: -cc1 +// CHECK-X86_64: -mllvm -malign-double + +// RUN: not %clang -v -c -mno-align-double %s -target i686-unknown-linux 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-I686 %s + +// CHECK-NO-I686: unknown argument: '-mno-align-double' + +// RUN: not %clang -v -c -mno-align-double %s -target x86_64-unknown-linux 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-X86_64 %s + +// CHECK-NO-X86_64: unknown argument: '-mno-align-double'