aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGBuiltin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGBuiltin.cpp')
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp63
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"