Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -5851,6 +5851,114 @@ #include "clang/Basic/BuiltinsHexagon.def" }; +class LanaiTargetInfo : public TargetInfo { + // Class for Lanai (32-bit). + // The CPU profiles supported by the Lanai backend + enum CPUKind { + CK_NONE, + CK_V11, + } CPU; + + static const Builtin::Info BuiltinInfo[]; + static const TargetInfo::GCCRegAlias GCCRegAliases[]; + static const char *const GCCRegNames[]; + bool SoftFloat; + + public: + LanaiTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { + // Description string has to be kept in sync with backend. + DataLayoutString = + "E" // Big endian + "-m:e" // ELF name manging + "-p:32:32" // 32-bit pointers work aligned + "-i64:64" // 64 bit integers, 64 bit aligned + "-a:0:32" // 32 bit alignment of objects of aggregate type + "-n32" // 32 bit native integer width + "-S64"; // 64 bit natural stack alignment + + // Setting RegParmMax equal to what mregparm was set to in the old + // toolchain + RegParmMax = 4; + + // Set the default CPU to V11 + CPU = CK_V11; + + // Temporary approach to make everything at least word-aligned and allow for + // safely casting between pointers with different alignment requirements. + // TODO: Remove this when there are no more cast align warnings on the + // firmware. + MinGlobalAlign = 32; + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + // Define __lanai__ when building for target lanai. + Builder.defineMacro("__lanai__"); + + // Set define for the CPU specified. + switch (CPU) { + case CK_V11: + Builder.defineMacro("__LANAI_V11__"); + break; + default: + llvm_unreachable("Unhandled target CPU"); + } + } + + bool setCPU(const std::string &Name) override { + CPU = llvm::StringSwitch(Name) + .Case("v11", CK_V11) + .Default(CK_NONE); + + return CPU != CK_NONE; + } + + bool hasFeature(StringRef Feature) const override { + return llvm::StringSwitch(Feature) + .Case("lanai", true) + .Default(false); + } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::VoidPtrBuiltinVaList; + } + ArrayRef getGCCRegNames() const override; + ArrayRef getGCCRegAliases() const override; + + ArrayRef getTargetBuiltins() const override { + return None; + } + + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override { + return false; + } + const char *getClobbers() const override { return ""; } +}; + +const char *const LanaiTargetInfo::GCCRegNames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", + "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"}; + +ArrayRef LanaiTargetInfo::getGCCRegNames() const { + return llvm::makeArrayRef(GCCRegNames); +} + +const TargetInfo::GCCRegAlias LanaiTargetInfo::GCCRegAliases[] = { + {{"pc"}, "r2"}, + {{"sp"}, "r4"}, + {{"fp"}, "r5"}, + {{"rv"}, "r8"}, + {{"rr1"}, "r10"}, + {{"rr2"}, "r11"}, + {{"rca"}, "r15"}, +}; + +ArrayRef LanaiTargetInfo::getGCCRegAliases() const { + return llvm::makeArrayRef(GCCRegAliases); +} + // Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit). class SparcTargetInfo : public TargetInfo { static const TargetInfo::GCCRegAlias GCCRegAliases[]; @@ -7543,6 +7651,9 @@ case llvm::Triple::hexagon: return new HexagonTargetInfo(Triple); + case llvm::Triple::lanai: + return new LanaiTargetInfo(Triple); + case llvm::Triple::aarch64: if (Triple.isOSDarwin()) return new DarwinAArch64TargetInfo(Triple); Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -19,6 +19,7 @@ #include "CodeGenFunction.h" #include "clang/AST/RecordLayout.h" #include "clang/CodeGen/CGFunctionInfo.h" +#include "clang/Driver/DriverDiagnostic.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" @@ -6488,6 +6489,114 @@ } //===----------------------------------------------------------------------===// +// Lanai ABI Implementation +//===----------------------------------------------------------------------===// + +class LanaiABIInfo : public DefaultABIInfo { + enum Class { Integer, Float }; + + unsigned DefaultNumRegisterParameters; + + Class classify(QualType Ty) const; + +public: + LanaiABIInfo(CodeGen::CodeGenTypes &CGT, unsigned NumRegisterParameters) + : DefaultABIInfo(CGT) { + DefaultNumRegisterParameters = NumRegisterParameters; + } + + static bool isRegisterSize(unsigned Size) { + return (Size == 8 || Size == 16 || Size == 32); + } + + bool shouldUseInReg(QualType Ty, CCState &State) const; + + void computeInfo(CGFunctionInfo &FI) const override { + CCState State(FI.getCallingConvention()); + if (State.CC == llvm::CallingConv::Fast) { + State.FreeRegs = 4; + } else if (FI.getHasRegParm()) { + State.FreeRegs = FI.getRegParm(); + } else { + State.FreeRegs = DefaultNumRegisterParameters; + } + + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + for (auto &I : FI.arguments()) + I.info = classifyArgumentType(I.type, State); + } + + ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const; +}; + +LanaiABIInfo::Class LanaiABIInfo::classify(QualType Ty) const { + const Type *T = isSingleElementStruct(Ty, getContext()); + if (!T) + T = Ty.getTypePtr(); + + if (const BuiltinType *BT = T->getAs()) { + BuiltinType::Kind K = BT->getKind(); + if (K == BuiltinType::Float || K == BuiltinType::Double) + return Float; + } + return Integer; +} + +bool LanaiABIInfo::shouldUseInReg(QualType Ty, CCState &State) const { + Class C = classify(Ty); + if (C == Float) + return false; + + unsigned Size = getContext().getTypeSize(Ty); + unsigned SizeInRegs = (Size + 31) / 32; + + if (SizeInRegs == 0) + return false; + + if (SizeInRegs > State.FreeRegs) { + State.FreeRegs = 0; + return false; + } + + State.FreeRegs -= SizeInRegs; + + return true; +} + +ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty, + CCState &State) const { + if (isAggregateTypeForABI(Ty)) + return getNaturalAlignIndirect(Ty); + + // Treat an enum type as its underlying type. + if (const EnumType *EnumTy = Ty->getAs()) + Ty = EnumTy->getDecl()->getIntegerType(); + + bool InReg = shouldUseInReg(Ty, State); + if (Ty->isPromotableIntegerType()) { + if (InReg) { + return ABIArgInfo::getDirectInReg(); + } + return ABIArgInfo::getExtend(); + } + if (InReg) + return ABIArgInfo::getDirectInReg(); + + return ABIArgInfo::getDirect(); +} + +namespace { +class LanaiTargetCodeGenInfo : public TargetCodeGenInfo { +public: + LanaiTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, + unsigned DefaultNumRegisterParameters) + : TargetCodeGenInfo(new LanaiABIInfo(CGT, DefaultNumRegisterParameters)) { + } +}; +} + +//===----------------------------------------------------------------------===// // AMDGPU ABI Implementation //===----------------------------------------------------------------------===// @@ -7600,6 +7709,16 @@ } case llvm::Triple::hexagon: return *(TheTargetCodeGenInfo = new HexagonTargetCodeGenInfo(Types)); + case llvm::Triple::lanai: + // Allow compiling with mregparm unset (NumRegisterParameters is 0) or + // mregparm=4. + if (CodeGenOpts.NumRegisterParameters == 0 || + CodeGenOpts.NumRegisterParameters == 4) { + return *(TheTargetCodeGenInfo = new LanaiTargetCodeGenInfo(Types, 4)); + } else { + getDiags().Report(diag::err_drv_unsupported_opt_for_target) << "-mregparm" + << "lanai"; + } case llvm::Triple::r600: return *(TheTargetCodeGenInfo = new AMDGPUTargetCodeGenInfo(Types)); case llvm::Triple::amdgcn: Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -2344,6 +2344,9 @@ case llvm::Triple::hexagon: TC = new toolchains::HexagonToolChain(*this, Target, Args); break; + case llvm::Triple::lanai: + TC = new toolchains::LanaiToolChain(*this, Target, Args); + break; case llvm::Triple::xcore: TC = new toolchains::XCoreToolChain(*this, Target, Args); break; Index: lib/Driver/ToolChains.h =================================================================== --- lib/Driver/ToolChains.h +++ lib/Driver/ToolChains.h @@ -867,6 +867,14 @@ std::string LibSuffix; }; +class LLVM_LIBRARY_VISIBILITY LanaiToolChain : public Generic_ELF { +public: + LanaiToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) + : Generic_ELF(D, Triple, Args) {} + bool IsIntegratedAssemblerDefault() const override { return true; } +}; + class LLVM_LIBRARY_VISIBILITY HexagonToolChain : public Linux { protected: GCCVersion GCCLibAndIncVersion; Index: lib/Driver/Tools.h =================================================================== --- lib/Driver/Tools.h +++ lib/Driver/Tools.h @@ -82,6 +82,8 @@ llvm::opt::ArgStringList &CmdArgs) const; void AddHexagonTargetArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + void AddLanaiTargetArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; void AddWebAssemblyTargetArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -1555,6 +1555,13 @@ return ""; } +static std::string getLanaiTargetCPU(const ArgList &Args) { + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { + return A->getValue(); + } + return ""; +} + void Clang::AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); @@ -1772,6 +1779,9 @@ return "hexagon" + toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str(); + case llvm::Triple::lanai: + return getLanaiTargetCPU(Args); + case llvm::Triple::systemz: return getSystemZTargetCPU(Args); @@ -2081,6 +2091,16 @@ CmdArgs.push_back("-machine-sink-split=0"); } +void Clang::AddLanaiTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { + StringRef CPUName = A->getValue(); + + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(Args.MakeArgString(CPUName)); + } +} + void Clang::AddWebAssemblyTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { // Default to "hidden" visibility. @@ -4093,6 +4113,10 @@ AddX86TargetArgs(Args, CmdArgs); break; + case llvm::Triple::lanai: + AddLanaiTargetArgs(Args, CmdArgs); + break; + case llvm::Triple::hexagon: AddHexagonTargetArgs(Args, CmdArgs); break;