diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Basic/Targets.cpp | 176 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 17 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 12 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 17 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 81 | ||||
-rw-r--r-- | clang/lib/Driver/Driver.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChain.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains.cpp | 29 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains.h | 21 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 57 |
12 files changed, 417 insertions, 7 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 285b194803b..b07a21301ee 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -684,6 +684,7 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericMIPS: case TargetCXXABI::GenericItanium: + case TargetCXXABI::WebAssembly: return CreateItaniumCXXABI(*this); case TargetCXXABI::Microsoft: return CreateMicrosoftCXXABI(*this); @@ -8431,6 +8432,7 @@ MangleContext *ASTContext::createMangleContext() { case TargetCXXABI::GenericMIPS: case TargetCXXABI::iOS: case TargetCXXABI::iOS64: + case TargetCXXABI::WebAssembly: return ItaniumMangleContext::create(*this, getDiagnostics()); case TargetCXXABI::Microsoft: return MicrosoftMangleContext::create(*this, getDiagnostics()); diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index c29a8001fd8..8b87ffde9d2 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -734,6 +734,35 @@ public: } }; +namespace { +// WebAssembly target +template <typename Target> +class WebAssemblyOSTargetInfo : public OSTargetInfo<Target> { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override final { + // A common platform macro. + if (Opts.POSIXThreads) + Builder.defineMacro("_REENTRANT"); + // Follow g++ convention and predefine _GNU_SOURCE for C++. + if (Opts.CPlusPlus) + Builder.defineMacro("_GNU_SOURCE"); + } + + // As an optimization, group static init code together in a section. + const char *getStaticInitSectionSpecifier() const override final { + return ".text.__startup"; + } + +public: + explicit WebAssemblyOSTargetInfo(const llvm::Triple &Triple) + : OSTargetInfo<Target>(Triple) { + this->MCountName = "__mcount"; + this->UserLabelPrefix = ""; + this->TheCXXABI.set(TargetCXXABI::WebAssembly); + } +}; +} // end anonymous namespace + //===----------------------------------------------------------------------===// // Specific target implementations. //===----------------------------------------------------------------------===// @@ -6955,6 +6984,145 @@ public: bool hasProtectedVisibility() const override { return false; } }; + +class WebAssemblyTargetInfo : public TargetInfo { + static const Builtin::Info BuiltinInfo[]; + + enum SIMDEnum { + NoSIMD, + SIMD128, + } SIMDLevel; + +public: + explicit WebAssemblyTargetInfo(const llvm::Triple &T) + : TargetInfo(T), SIMDLevel(NoSIMD) { + BigEndian = false; + NoAsmVariants = true; + SuitableAlign = 128; + LargeArrayMinWidth = 128; + LargeArrayAlign = 128; + SimdDefaultAlign = 128; + } + +protected: + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + defineCPUMacros(Builder, "wasm", /*Tuning=*/false); + if (SIMDLevel >= SIMD128) + Builder.defineMacro("__wasm_simd128__"); + } + +private: + bool initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, + StringRef CPU, + std::vector<std::string> &FeaturesVec) const override { + if (CPU == "bleeding-edge") + Features["simd128"] = true; + return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); + } + bool hasFeature(StringRef Feature) const override final { + return llvm::StringSwitch<bool>(Feature) + .Case("simd128", SIMDLevel >= SIMD128) + .Default(false); + } + bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) override final { + for (const auto &Feature : Features) { + if (Feature == "+simd128") { + SIMDLevel = std::max(SIMDLevel, SIMD128); + continue; + } + if (Feature == "-simd128") { + SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1)); + continue; + } + + Diags.Report(diag::err_opt_not_valid_with_opt) << Feature + << "-target-feature"; + return false; + } + return true; + } + bool setCPU(const std::string &Name) override final { + return llvm::StringSwitch<bool>(Name) + .Case("mvp", true) + .Case("bleeding-edge", true) + .Case("generic", true) + .Default(false); + } + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const override final { + Records = BuiltinInfo; + NumRecords = clang::WebAssembly::LastTSBuiltin - Builtin::FirstTSBuiltin; + } + BuiltinVaListKind getBuiltinVaListKind() const override final { + // TODO: Implement va_list properly. + return VoidPtrBuiltinVaList; + } + void getGCCRegNames(const char *const *&Names, + unsigned &NumNames) const override final { + Names = nullptr; + NumNames = 0; + } + void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const override final { + Aliases = nullptr; + NumAliases = 0; + } + bool + validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override final { + return false; + } + const char *getClobbers() const override final { return ""; } + bool isCLZForZeroUndef() const override final { return false; } + bool hasInt128Type() const override final { return true; } +}; + +const Builtin::Info WebAssemblyTargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr }, +#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ + { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr }, +#include "clang/Basic/BuiltinsWebAssembly.def" +}; + +class WebAssembly32TargetInfo : public WebAssemblyTargetInfo { +public: + explicit WebAssembly32TargetInfo(const llvm::Triple &T) + : WebAssemblyTargetInfo(T) { + // TODO: Set this to the correct value once the spec issues are resolved. + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0; + DataLayoutString = "e-p:32:32-i64:64-n32:64-S128"; + } + +protected: + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WebAssemblyTargetInfo::getTargetDefines(Opts, Builder); + defineCPUMacros(Builder, "wasm32", /*Tuning=*/false); + } +}; + +class WebAssembly64TargetInfo : public WebAssemblyTargetInfo { +public: + explicit WebAssembly64TargetInfo(const llvm::Triple &T) + : WebAssemblyTargetInfo(T) { + LongAlign = LongWidth = 64; + PointerAlign = PointerWidth = 64; + // TODO: Set this to the correct value once the spec issues are resolved. + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0; + DataLayoutString = "e-p:64:64-i64:64-n32:64-S128"; + } + +protected: + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + WebAssemblyTargetInfo::getTargetDefines(Opts, Builder); + defineCPUMacros(Builder, "wasm64", /*Tuning=*/false); + } +}; + } // end anonymous namespace. const Builtin::Info Le64TargetInfo::BuiltinInfo[] = { @@ -7559,6 +7727,14 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { return nullptr; return new SPIR64TargetInfo(Triple); } + case llvm::Triple::wasm32: + if (!(Triple == llvm::Triple("wasm32-unknown-unknown"))) + return nullptr; + return new WebAssemblyOSTargetInfo<WebAssembly32TargetInfo>(Triple); + case llvm::Triple::wasm64: + if (!(Triple == llvm::Triple("wasm64-unknown-unknown"))) + return nullptr; + return new WebAssemblyOSTargetInfo<WebAssembly64TargetInfo>(Triple); } } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 9079462cd83..8f68d29ad06 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -1888,6 +1888,9 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, case llvm::Triple::nvptx: case llvm::Triple::nvptx64: return EmitNVPTXBuiltinExpr(BuiltinID, E); + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + return EmitWebAssemblyBuiltinExpr(BuiltinID, E); default: return nullptr; } @@ -7032,3 +7035,17 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, return nullptr; } } + +Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + switch (BuiltinID) { + case WebAssembly::BI__builtin_wasm_page_size: { + llvm::Type *ResultType = ConvertType(E->getType()); + Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_page_size, ResultType); + return Builder.CreateCall(Callee); + } + + default: + return nullptr; + } +} diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 4852d3a393f..c42dd959f1f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2626,6 +2626,8 @@ public: llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitSystemZBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E); + llvm::Value *EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, + const CallExpr *E); llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E); llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 6c79cfd678c..b9eefac2d9f 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -66,6 +66,7 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) { case TargetCXXABI::iOS64: case TargetCXXABI::GenericMIPS: case TargetCXXABI::GenericItanium: + case TargetCXXABI::WebAssembly: return CreateItaniumCXXABI(CGM); case TargetCXXABI::Microsoft: return CreateMicrosoftCXXABI(CGM); @@ -819,9 +820,14 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, if (alignment) F->setAlignment(alignment); - // C++ ABI requires 2-byte alignment for member functions. - if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D)) - F->setAlignment(2); + // Some C++ ABIs require 2-byte alignment for member functions, in order to + // reserve a bit for differentiating between virtual and non-virtual member + // functions. If the current target's C++ ABI requires this and this is a + // member function, set its alignment accordingly. + if (getTarget().getCXXABI().areMemberFunctionsAligned()) { + if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D)) + F->setAlignment(2); + } } void CodeGenModule::SetCommonAttributes(const Decl *D, diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 9fa4f06338a..b28ffbf3b77 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -354,6 +354,20 @@ public: // ARM64 libraries are prepared for non-unique RTTI. bool shouldRTTIBeUnique() const override { return false; } }; + +class WebAssemblyCXXABI final : public ItaniumCXXABI { +public: + explicit WebAssemblyCXXABI(CodeGen::CodeGenModule &CGM) + : ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true, + /*UseARMGuardVarABI=*/true) {} + +private: + bool HasThisReturn(GlobalDecl GD) const override { + return isa<CXXConstructorDecl>(GD.getDecl()) || + (isa<CXXDestructorDecl>(GD.getDecl()) && + GD.getDtorType() != Dtor_Deleting); + } +}; } CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { @@ -377,6 +391,9 @@ CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { case TargetCXXABI::GenericMIPS: return new ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true); + case TargetCXXABI::WebAssembly: + return new WebAssemblyCXXABI(CGM); + case TargetCXXABI::GenericItanium: if (CGM.getContext().getTargetInfo().getTriple().getArch() == llvm::Triple::le32) { diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index f1b8b03eb60..70b02dbebdc 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -445,6 +445,83 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const { } //===----------------------------------------------------------------------===// +// WebAssembly ABI Implementation +// +// This is a very simple ABI that relies a lot on DefaultABIInfo. +//===----------------------------------------------------------------------===// + +class WebAssemblyABIInfo final : public DefaultABIInfo { +public: + explicit WebAssemblyABIInfo(CodeGen::CodeGenTypes &CGT) + : DefaultABIInfo(CGT) {} + +private: + ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType Ty) const; + + // DefaultABIInfo's classifyReturnType and classifyArgumentType are + // non-virtual, but computeInfo is virtual, so we overload that. + void computeInfo(CGFunctionInfo &FI) const override { + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + for (auto &Arg : FI.arguments()) + Arg.info = classifyArgumentType(Arg.type); + } +}; + +class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo { +public: + explicit WebAssemblyTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) + : TargetCodeGenInfo(new WebAssemblyABIInfo(CGT)) {} +}; + +/// \brief Classify argument of given type \p Ty. +ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (isAggregateTypeForABI(Ty)) { + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + unsigned TypeAlign = getContext().getTypeAlignInChars(Ty).getQuantity(); + if (auto RAA = getRecordArgABI(Ty, getCXXABI())) + return ABIArgInfo::getIndirect(TypeAlign, + RAA == CGCXXABI::RAA_DirectInMemory); + // Ignore empty structs/unions. + if (isEmptyRecord(getContext(), Ty, true)) + return ABIArgInfo::getIgnore(); + // Lower single-element structs to just pass a regular value. TODO: We + // could do reasonable-size multiple-element structs too, using getExpand(), + // though watch out for things like bitfields. + if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) + return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); + return ABIArgInfo::getIndirect(TypeAlign); + } + + // Otherwise just do the default thing. + return DefaultABIInfo::classifyArgumentType(Ty); +} + +ABIArgInfo WebAssemblyABIInfo::classifyReturnType(QualType RetTy) const { + if (isAggregateTypeForABI(RetTy)) { + // Records with non-trivial destructors/copy-constructors should not be + // returned by value. + if (!getRecordArgABI(RetTy, getCXXABI())) { + // Ignore empty structs/unions. + if (isEmptyRecord(getContext(), RetTy, true)) + return ABIArgInfo::getIgnore(); + // Lower single-element structs to just return a regular value. TODO: We + // could do reasonable-size multiple-element structs too, using + // ABIArgInfo::getDirect(). + if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) + return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); + } + } + + // Otherwise just do the default thing. + return DefaultABIInfo::classifyReturnType(RetTy); +} + +//===----------------------------------------------------------------------===// // le32/PNaCl bitcode ABI Implementation // // This is a simplified version of the x86_32 ABI. Arguments and return values @@ -7155,6 +7232,10 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { return *(TheTargetCodeGenInfo = new AArch64TargetCodeGenInfo(Types, Kind)); } + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + return *(TheTargetCodeGenInfo = new WebAssemblyTargetCodeGenInfo(Types)); + case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 56d1afbc08c..2edb6ce7178 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2265,6 +2265,10 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::shave: TC = new toolchains::SHAVEToolChain(*this, Target, Args); break; + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + TC = new toolchains::WebAssembly(*this, Target, Args); + break; default: if (Target.isOSBinFormatELF()) TC = new toolchains::Generic_ELF(*this, Target, Args); diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index d4381e7e23f..e034f72a265 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -244,11 +244,13 @@ ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { bool ToolChain::isThreadModelSupported(const StringRef Model) const { if (Model == "single") { - // FIXME: 'single' is only supported on ARM so far. + // FIXME: 'single' is only supported on ARM and WebAssembly so far. return Triple.getArch() == llvm::Triple::arm || Triple.getArch() == llvm::Triple::armeb || Triple.getArch() == llvm::Triple::thumb || - Triple.getArch() == llvm::Triple::thumbeb; + Triple.getArch() == llvm::Triple::thumbeb || + Triple.getArch() == llvm::Triple::wasm32 || + Triple.getArch() == llvm::Triple::wasm64; } else if (Model == "posix") return true; diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index 91317d601a8..d7989a7993f 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -3937,3 +3937,32 @@ Tool *SHAVEToolChain::buildAssembler() const { // assembler to the driver, except not the way it expects. llvm_unreachable("SHAVEToolChain can't buildAssembler"); } + +bool WebAssembly::IsMathErrnoDefault() const { return false; } + +bool WebAssembly::IsObjCNonFragileABIDefault() const { return true; } + +bool WebAssembly::UseObjCMixedDispatch() const { return true; } + +bool WebAssembly::isPICDefault() const { return false; } + +bool WebAssembly::isPIEDefault() const { return false; } + +bool WebAssembly::isPICDefaultForced() const { return false; } + +bool WebAssembly::IsIntegratedAssemblerDefault() const { return true; } + +// TODO: Support Objective C stuff. +bool WebAssembly::SupportsObjCGC() const { return false; } + +bool WebAssembly::hasBlocksRuntime() const { return false; } + +// TODO: Support profiling. +bool WebAssembly::SupportsProfiling() const { return false; } + +void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasFlag(options::OPT_fuse_init_array, + options::OPT_fno_use_init_array, true)) + CC1Args.push_back("-fuse-init-array"); +} diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h index cc6b4c1aee6..b953516d07d 100644 --- a/clang/lib/Driver/ToolChains.h +++ b/clang/lib/Driver/ToolChains.h @@ -931,6 +931,27 @@ private: mutable std::unique_ptr<Tool> Assembler; }; +class LLVM_LIBRARY_VISIBILITY WebAssembly final : public ToolChain { +public: + WebAssembly(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) + : ToolChain(D, Triple, Args) {} + +private: + bool IsMathErrnoDefault() const override; + bool IsObjCNonFragileABIDefault() const override; + bool UseObjCMixedDispatch() const override; + bool isPICDefault() const override; + bool isPIEDefault() const override; + bool isPICDefaultForced() const override; + bool IsIntegratedAssemblerDefault() const override; + bool hasBlocksRuntime() const override; + bool SupportsObjCGC() const override; + bool SupportsProfiling() const override; + void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; +}; + } // end namespace toolchains } // end namespace driver } // end namespace clang diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index eb245b38e09..fdb1b1815c4 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -484,6 +484,8 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) { return false; case llvm::Triple::xcore: + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: return true; } } @@ -1553,6 +1555,25 @@ static const char *getX86TargetCPU(const ArgList &Args, } } +/// Get the (LLVM) name of the WebAssembly cpu we are targeting. +static StringRef getWebAssemblyTargetCPU(const ArgList &Args) { + // If we have -mcpu=, use that. + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { + StringRef CPU = A->getValue(); + +#ifdef __wasm__ + // Handle "native" by examining the host. "native" isn't meaningful when + // cross compiling, so only support this when the host is also WebAssembly. + if (CPU == "native") + return llvm::sys::getHostCPUName(); +#endif + + return CPU; + } + + return "generic"; +} + static std::string getCPUName(const ArgList &Args, const llvm::Triple &T, bool FromAs = false) { switch (T.getArch()) { @@ -1625,6 +1646,10 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T, case llvm::Triple::r600: case llvm::Triple::amdgcn: return getR600TargetGPU(Args); + + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + return getWebAssemblyTargetCPU(Args); } } @@ -2074,6 +2099,24 @@ static void getAArch64TargetFeatures(const Driver &D, Features.push_back("+reserve-x18"); } +static void getWebAssemblyTargetFeatures(const ArgList &Args, + std::vector<const char *> &Features) { + for (const Arg *A : Args.filtered(options::OPT_m_wasm_Features_Group)) { + StringRef Name = A->getOption().getName(); + A->claim(); + + // Skip over "-m". + assert(Name.startswith("m") && "Invalid feature name."); + Name = Name.substr(1); + + bool IsNegative = Name.startswith("no-"); + if (IsNegative) + Name = Name.substr(3); + + Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name)); + } +} + static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, ArgStringList &CmdArgs, bool ForAS) { @@ -2111,6 +2154,10 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, case llvm::Triple::x86_64: getX86TargetFeatures(D, Triple, Args, Features); break; + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + getWebAssemblyTargetFeatures(Args, Features); + break; } // Find the last of each feature. @@ -2590,9 +2637,15 @@ static bool areOptimizationsEnabled(const ArgList &Args) { static bool shouldUseFramePointerForTarget(const ArgList &Args, const llvm::Triple &Triple) { - // XCore never wants frame pointers, regardless of OS. - if (Triple.getArch() == llvm::Triple::xcore) { + switch (Triple.getArch()) { + case llvm::Triple::xcore: + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + // XCore never wants frame pointers, regardless of OS. + // WebAssembly never wants frame pointers. return false; + default: + break; } if (Triple.isOSLinux()) { |