Index: include/clang/Basic/TargetOptions.h =================================================================== --- include/clang/Basic/TargetOptions.h +++ include/clang/Basic/TargetOptions.h @@ -27,6 +27,10 @@ /// target will be selected to match the host. std::string Triple; + /// When compiling for the device side, contains the triple used to compile + /// for the host. + std::string HostTriple; + /// If given, the name of the target CPU to generate code for. std::string CPU; Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -65,6 +65,9 @@ Builder.defineMacro("__tune_" + CPUName + "__"); } +static TargetInfo *AllocateTarget(const llvm::Triple &Triple, + const TargetOptions &Opts); + //===----------------------------------------------------------------------===// // Defines specific to certain operating systems. //===----------------------------------------------------------------------===// @@ -1623,7 +1626,7 @@ } GPU; public: - NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &) + NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : TargetInfo(Triple) { BigEndian = false; TLSSupported = false; @@ -1635,6 +1638,61 @@ NoAsmVariants = true; // Set the default GPU to sm20 GPU = GK_SM20; + + std::unique_ptr HostTarget( + AllocateTarget(llvm::Triple(Opts.HostTriple), Opts)); + if (!HostTarget) { + return; + } + + // Match the host's types. + PointerWidth = HostTarget->getPointerWidth(/* AddrSpace = */ 0); + PointerAlign = HostTarget->getPointerAlign(/* AddrSpace = */ 0); + BoolWidth = HostTarget->getBoolWidth(); + BoolAlign = HostTarget->getBoolAlign(); + IntWidth = HostTarget->getIntWidth(); + IntWidth = HostTarget->getIntWidth(); + HalfWidth = HostTarget->getHalfWidth(); + HalfWidth = HostTarget->getHalfWidth(); + FloatWidth = HostTarget->getFloatWidth(); + FloatWidth = HostTarget->getFloatWidth(); + DoubleWidth = HostTarget->getDoubleWidth(); + DoubleWidth = HostTarget->getDoubleWidth(); + LongWidth = HostTarget->getLongWidth(); + LongAlign = HostTarget->getLongAlign(); + LongLongWidth = HostTarget->getLongLongWidth(); + LongLongAlign = HostTarget->getLongLongAlign(); + MinGlobalAlign = HostTarget->getMinGlobalAlign(); + DefaultAlignForAttributeAligned = + HostTarget->getDefaultAlignForAttributeAligned(); + SizeType = HostTarget->getSizeType(); + IntMaxType = HostTarget->getIntMaxType(); + PtrDiffType = HostTarget->getPtrDiffType(/* AddrSpace = */ 0); + IntPtrType = HostTarget->getIntPtrType(); + WCharType = HostTarget->getWCharType(); + WIntType = HostTarget->getWIntType(); + Char16Type = HostTarget->getChar16Type(); + Char32Type = HostTarget->getChar32Type(); + Int64Type = HostTarget->getInt64Type(); + SigAtomicType = HostTarget->getSigAtomicType(); + ProcessIDType = HostTarget->getProcessIDType(); + + UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment(); + UseZeroLengthBitfieldAlignment = + HostTarget->useZeroLengthBitfieldAlignment(); + UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment(); + ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary(); + + // Properties intentionally not copied from host: + // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the + // host/device boundary. + // - SuitableAlign: Not visible across the host/device boundary, and may + // correctly be different on host/device, e.g. if host has wider vector + // types than device. + // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same + // as its double type, but that's not necessarily true on the host. + // TODO: nvcc emits a warning when using long double on device; we should + // do the same. } void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override { Index: lib/Frontend/CompilerInstance.cpp =================================================================== --- lib/Frontend/CompilerInstance.cpp +++ lib/Frontend/CompilerInstance.cpp @@ -836,8 +836,9 @@ // Create TargetInfo for the other side of CUDA compilation. if (getLangOpts().CUDA && !getFrontendOpts().AuxTriple.empty()) { - std::shared_ptr TO(new TargetOptions); + auto TO = std::make_shared(); TO->Triple = getFrontendOpts().AuxTriple; + TO->HostTriple = getTarget().getTriple().str(); setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO)); } Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2152,6 +2152,12 @@ LangOpts.ObjCExceptions = 1; } + // During CUDA device-side compilation, the aux triple is the triple used for + // host compilation. + if (LangOpts.CUDA && LangOpts.CUDAIsDevice) { + Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple; + } + // FIXME: Override value name discarding when asan or msan is used because the // backend passes depend on the name of the alloca in order to print out // names. Index: test/SemaCUDA/wint_t.cu =================================================================== --- /dev/null +++ test/SemaCUDA/wint_t.cu @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu \ +// RUN: -aux-triple nvptx-nvidia-cuda -verify %s +// RUN: %clang_cc1 -std=c++11 -fcuda-is-device -triple nvptx-nvidia-cuda \ +// RUN: -aux-triple x86_64-unknown-linux-gnu -verify %s + +// expected-no-diagnostics + +// Check that __WINT_TYPE__ is unsigned int on both x86-64 and nvptx. + +template +struct IsSame { + static constexpr bool value = false; +}; + +template +struct IsSame { + static constexpr bool value = true; +}; + +__attribute__((host)) __attribute__((device)) void foo() { + static_assert(IsSame<__WINT_TYPE__, unsigned int>::value, + "Wrong __WINT_TYPE__."); +}