diff options
Diffstat (limited to 'clang/lib/CodeGen/CGBuiltin.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index d454ccc..734eb5a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -10638,6 +10638,9 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, BuiltinID <= clang::AArch64::LastSMEBuiltin) return EmitAArch64SMEBuiltinExpr(BuiltinID, E); + if (BuiltinID == Builtin::BI__builtin_cpu_supports) + return EmitAArch64CpuSupports(E); + unsigned HintID = static_cast<unsigned>(-1); switch (BuiltinID) { default: break; @@ -14025,6 +14028,19 @@ Value *CodeGenFunction::EmitX86CpuInit() { return Builder.CreateCall(Func); } +Value *CodeGenFunction::EmitAArch64CpuSupports(const CallExpr *E) { + const Expr *ArgExpr = E->getArg(0)->IgnoreParenCasts(); + StringRef ArgStr = cast<StringLiteral>(ArgExpr)->getString(); + llvm::SmallVector<StringRef, 8> Features; + ArgStr.split(Features, "+"); + for (auto &Feature : Features) { + Feature = Feature.trim(); + if (Feature != "default") + Features.push_back(Feature); + } + return EmitAArch64CpuSupports(Features); +} + llvm::Value * CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) { uint64_t FeaturesMask = llvm::AArch64::getCpuSupportsMask(FeaturesStrs); @@ -16542,12 +16558,59 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, Intrinsic::ID ID = Intrinsic::not_intrinsic; +#include "llvm/TargetParser/PPCTargetParser.def" + auto GenAIXPPCBuiltinCpuExpr = [&](unsigned SupportMethod, unsigned FieldIdx, + unsigned CompOp, + unsigned OpValue) -> Value * { + if (SupportMethod == AIX_BUILTIN_PPC_FALSE) + return llvm::ConstantInt::getFalse(ConvertType(E->getType())); + + if (SupportMethod == AIX_BUILTIN_PPC_TRUE) + return llvm::ConstantInt::getTrue(ConvertType(E->getType())); + + assert(SupportMethod <= USE_SYS_CONF && "Invalid value for SupportMethod."); + assert((CompOp == COMP_EQ) && "Only equal comparisons are supported."); + + llvm::Type *STy = llvm::StructType::get(PPC_SYSTEMCONFIG_TYPE); + llvm::Constant *SysConf = + CGM.CreateRuntimeVariable(STy, "_system_configuration"); + + // Grab the appropriate field from _system_configuration. + llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0), + ConstantInt::get(Int32Ty, FieldIdx)}; + + llvm::Value *FieldValue = Builder.CreateGEP(STy, SysConf, Idxs); + FieldValue = Builder.CreateAlignedLoad(Int32Ty, FieldValue, + CharUnits::fromQuantity(4)); + assert(FieldValue->getType()->isIntegerTy(32) && + "Only 32-bit integers are supported in GenAIXPPCBuiltinCpuExpr()."); + return Builder.CreateICmp(ICmpInst::ICMP_EQ, FieldValue, + ConstantInt::get(Int32Ty, OpValue)); + }; + switch (BuiltinID) { default: return nullptr; case Builtin::BI__builtin_cpu_is: { const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString(); + llvm::Triple Triple = getTarget().getTriple(); + + if (Triple.isOSAIX()) { + unsigned IsCpuSupport, FieldIdx, CompareOp, CpuIdValue; + typedef std::tuple<unsigned, unsigned, unsigned, unsigned> CPUType; + std::tie(IsCpuSupport, FieldIdx, CompareOp, CpuIdValue) = + static_cast<CPUType>(StringSwitch<CPUType>(CPUStr) +#define PPC_AIX_CPU(NAME, SUPPORT_MAGIC, INDEX, COMPARE_OP, VALUE) \ + .Case(NAME, {SUPPORT_MAGIC, INDEX, COMPARE_OP, VALUE}) +#include "llvm/TargetParser/PPCTargetParser.def" + ); + return GenAIXPPCBuiltinCpuExpr(IsCpuSupport, FieldIdx, CompareOp, + CpuIdValue); + } + + assert(Triple.isOSLinux() && + "__builtin_cpu_is() is only supported for AIX and Linux."); unsigned NumCPUID = StringSwitch<unsigned>(CPUStr) #define PPC_LNX_CPU(Name, NumericID) .Case(Name, NumericID) #include "llvm/TargetParser/PPCTargetParser.def" |