aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen')
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp8
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp45
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGCUDANV.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGCXX.cpp5
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp28
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGCleanup.h1
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp12
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGDecl.cpp14
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGException.cpp4
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp12
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGExprCXX.cpp60
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp10
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp18
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp5
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp244
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp7
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp4
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp122
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CodeGenPGO.cpp4
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp437
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/TargetInfo.h3
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/Targets/RISCV.cpp35
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/Targets/X86.cpp5
24 files changed, 791 insertions, 296 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp
index a6142d99f3b6..ec203f6f28bc 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp
@@ -1001,8 +1001,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
}
if (CodeGenOpts.FatLTO) {
- assert(CodeGenOpts.UnifiedLTO && "FatLTO requires UnifiedLTO");
- MPM.addPass(PB.buildFatLTODefaultPipeline(Level));
+ MPM.addPass(PB.buildFatLTODefaultPipeline(
+ Level, PrepareForThinLTO,
+ PrepareForThinLTO || shouldEmitRegularLTOSummary()));
} else if (PrepareForThinLTO) {
MPM.addPass(PB.buildThinLTOPreLinkDefaultPipeline(Level));
} else if (PrepareForLTO) {
@@ -1073,8 +1074,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",
uint32_t(CodeGenOpts.EnableSplitLTOUnit));
- // FatLTO always means UnifiedLTO
- if (!TheModule->getModuleFlag("UnifiedLTO"))
+ if (CodeGenOpts.UnifiedLTO && !TheModule->getModuleFlag("UnifiedLTO"))
TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1));
}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp
index 998fcc3af581..7ef764b8e1ac 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp
@@ -1019,7 +1019,7 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type,
FAMSize = Builder.CreateIntCast(FAMSize, ResType, IsSigned);
Value *Res = FAMSize;
- if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
+ if (isa<DeclRefExpr>(Base)) {
// The whole struct is specificed in the __bdos.
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(OuterRD);
@@ -10056,7 +10056,7 @@ CodeGenFunction::getSVEOverloadTypes(const SVETypeFlags &TypeFlags,
llvm::Type *DefaultType = getSVEType(TypeFlags);
- if (TypeFlags.isOverloadWhile())
+ if (TypeFlags.isOverloadWhileOrMultiVecCvt())
return {DefaultType, Ops[1]->getType()};
if (TypeFlags.isOverloadWhileRW())
@@ -13287,7 +13287,7 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,
const auto *DR = cast<DeclRefExpr>(CE->getSubExpr());
const auto *Enumerator = cast<EnumConstantDecl>(DR->getDecl());
- auto &InitVal = Enumerator->getInitVal();
+ auto InitVal = Enumerator->getInitVal();
std::string InitValStr;
if (InitVal.isNegative() || InitVal > uint64_t(INT64_MAX))
InitValStr = std::to_string(InitVal.getSExtValue());
@@ -18178,6 +18178,45 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
llvm::Function *F = CGM.getIntrinsic(IID, {ArgTy});
return Builder.CreateCall(F, {Addr, Val, ZeroI32, ZeroI32, ZeroI1});
}
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_i32:
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_v2i32:
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4f16:
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4i16:
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8f16:
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8i16: {
+
+ llvm::Type *ArgTy;
+ switch (BuiltinID) {
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_i32:
+ ArgTy = llvm::Type::getInt32Ty(getLLVMContext());
+ break;
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_v2i32:
+ ArgTy = llvm::FixedVectorType::get(
+ llvm::Type::getInt32Ty(getLLVMContext()), 2);
+ break;
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4f16:
+ ArgTy = llvm::FixedVectorType::get(
+ llvm::Type::getHalfTy(getLLVMContext()), 4);
+ break;
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4i16:
+ ArgTy = llvm::FixedVectorType::get(
+ llvm::Type::getInt16Ty(getLLVMContext()), 4);
+ break;
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8f16:
+ ArgTy = llvm::FixedVectorType::get(
+ llvm::Type::getHalfTy(getLLVMContext()), 8);
+ break;
+ case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8i16:
+ ArgTy = llvm::FixedVectorType::get(
+ llvm::Type::getInt16Ty(getLLVMContext()), 8);
+ break;
+ }
+
+ llvm::Value *Addr = EmitScalarExpr(E->getArg(0));
+ llvm::Function *F =
+ CGM.getIntrinsic(Intrinsic::amdgcn_global_load_tr, {ArgTy});
+ return Builder.CreateCall(F, {Addr});
+ }
case AMDGPU::BI__builtin_amdgcn_read_exec:
return EmitAMDGCNBallotForExec(*this, E, Int64Ty, Int64Ty, false);
case AMDGPU::BI__builtin_amdgcn_read_exec_lo:
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCUDANV.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGCUDANV.cpp
index 353370f1d761..5b43272bfa62 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGCUDANV.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGCUDANV.cpp
@@ -893,7 +893,7 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
llvm::raw_svector_ostream OS(ModuleID);
OS << ModuleIDPrefix << llvm::format("%" PRIx64, FatbinWrapper->getGUID());
llvm::Constant *ModuleIDConstant = makeConstantArray(
- std::string(ModuleID.str()), "", ModuleIDSectionName, 32, /*AddNull=*/true);
+ std::string(ModuleID), "", ModuleIDSectionName, 32, /*AddNull=*/true);
// Create an alias for the FatbinWrapper that nvcc will look for.
llvm::GlobalAlias::create(llvm::GlobalValue::ExternalLinkage,
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCXX.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGCXX.cpp
index 110e21f7cb6d..e95a735f92f7 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGCXX.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGCXX.cpp
@@ -40,6 +40,11 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
if (getCodeGenOpts().OptimizationLevel == 0)
return true;
+ // Disable this optimization for ARM64EC. FIXME: This probably should work,
+ // but getting the symbol table correct is complicated.
+ if (getTarget().getTriple().isWindowsArm64EC())
+ return true;
+
// If sanitizing memory to check for use-after-dtor, do not emit as
// an alias, unless this class owns no members.
if (getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp
index 13677cf150ae..28c211aa631e 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp
@@ -1767,14 +1767,31 @@ static void AddAttributesFromFunctionProtoType(ASTContext &Ctx,
FPT->isNothrow())
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
- if (FPT->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
+ unsigned SMEBits = FPT->getAArch64SMEAttributes();
+ if (SMEBits & FunctionType::SME_PStateSMEnabledMask)
FuncAttrs.addAttribute("aarch64_pstate_sm_enabled");
- if (FPT->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask)
+ if (SMEBits & FunctionType::SME_PStateSMCompatibleMask)
FuncAttrs.addAttribute("aarch64_pstate_sm_compatible");
- if (FPT->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask)
+
+ // ZA
+ if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Out ||
+ FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_InOut)
+ FuncAttrs.addAttribute("aarch64_pstate_za_shared");
+ if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Preserves ||
+ FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_In) {
FuncAttrs.addAttribute("aarch64_pstate_za_shared");
- if (FPT->getAArch64SMEAttributes() & FunctionType::SME_PStateZAPreservedMask)
FuncAttrs.addAttribute("aarch64_pstate_za_preserved");
+ }
+
+ // ZT0
+ if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_Preserves)
+ FuncAttrs.addAttribute("aarch64_preserves_zt0");
+ if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_In)
+ FuncAttrs.addAttribute("aarch64_in_zt0");
+ if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_Out)
+ FuncAttrs.addAttribute("aarch64_out_zt0");
+ if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_InOut)
+ FuncAttrs.addAttribute("aarch64_inout_zt0");
}
static void AddAttributesFromAssumes(llvm::AttrBuilder &FuncAttrs,
@@ -2446,9 +2463,6 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
if (TargetDecl->hasAttr<ArmLocallyStreamingAttr>())
FuncAttrs.addAttribute("aarch64_pstate_sm_body");
-
- if (TargetDecl->hasAttr<ArmNewZAAttr>())
- FuncAttrs.addAttribute("aarch64_pstate_za_new");
}
// Attach "no-builtins" attributes to:
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCleanup.h b/contrib/llvm-project/clang/lib/CodeGen/CGCleanup.h
index 079a3e25d6dc..fcfbf41b0eaf 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGCleanup.h
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGCleanup.h
@@ -613,6 +613,7 @@ struct EHPersonality {
static const EHPersonality MSVC_CxxFrameHandler3;
static const EHPersonality GNU_Wasm_CPlusPlus;
static const EHPersonality XL_CPlusPlus;
+ static const EHPersonality ZOS_CPlusPlus;
/// Does this personality use landingpads or the family of pad instructions
/// designed to form funclets?
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp
index 236d53bee4e8..0f3f684d61dc 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1926,7 +1926,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
int ThisAdjustment = 0;
if (VTableContextBase::hasVtableSlot(Method)) {
- if (Method->isPure())
+ if (Method->isPureVirtual())
SPFlags |= llvm::DISubprogram::SPFlagPureVirtual;
else
SPFlags |= llvm::DISubprogram::SPFlagVirtual;
@@ -2201,6 +2201,14 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
TemplateParams.push_back(DBuilder.createTemplateValueParameter(
TheCU, Name, TTy, defaultParameter, V));
} break;
+ case TemplateArgument::StructuralValue: {
+ QualType T = TA.getStructuralValueType();
+ llvm::DIType *TTy = getOrCreateType(T, Unit);
+ llvm::Constant *V = ConstantEmitter(CGM).emitAbstract(
+ SourceLocation(), TA.getAsStructuralValue(), T);
+ TemplateParams.push_back(DBuilder.createTemplateValueParameter(
+ TheCU, Name, TTy, defaultParameter, V));
+ } break;
case TemplateArgument::Template: {
std::string QualName;
llvm::raw_string_ostream OS(QualName);
@@ -5401,6 +5409,8 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const {
// feasible some day.
return TA.getAsIntegral().getBitWidth() <= 64 &&
IsReconstitutableType(TA.getIntegralType());
+ case TemplateArgument::StructuralValue:
+ return false;
case TemplateArgument::Type:
return IsReconstitutableType(TA.getAsType());
default:
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGDecl.cpp
index a5da0aa2965a..bbe14ef4c172 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGDecl.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGDecl.cpp
@@ -1759,20 +1759,34 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type,
const VarDecl &D,
Address Loc) {
auto trivialAutoVarInit = getContext().getLangOpts().getTrivialAutoVarInit();
+ auto trivialAutoVarInitMaxSize =
+ getContext().getLangOpts().TrivialAutoVarInitMaxSize;
CharUnits Size = getContext().getTypeSizeInChars(type);
bool isVolatile = type.isVolatileQualified();
if (!Size.isZero()) {
+ // We skip auto-init variables by their alloc size. Take this as an example:
+ // "struct Foo {int x; char buff[1024];}" Assume the max-size flag is 1023.
+ // All Foo type variables will be skipped. Ideally, we only skip the buff
+ // array and still auto-init X in this example.
+ // TODO: Improve the size filtering to by member size.
+ auto allocSize = CGM.getDataLayout().getTypeAllocSize(Loc.getElementType());
switch (trivialAutoVarInit) {
case LangOptions::TrivialAutoVarInitKind::Uninitialized:
llvm_unreachable("Uninitialized handled by caller");
case LangOptions::TrivialAutoVarInitKind::Zero:
if (CGM.stopAutoInit())
return;
+ if (trivialAutoVarInitMaxSize > 0 &&
+ allocSize > trivialAutoVarInitMaxSize)
+ return;
emitStoresForZeroInit(CGM, D, Loc, isVolatile, Builder);
break;
case LangOptions::TrivialAutoVarInitKind::Pattern:
if (CGM.stopAutoInit())
return;
+ if (trivialAutoVarInitMaxSize > 0 &&
+ allocSize > trivialAutoVarInitMaxSize)
+ return;
emitStoresForPatternInit(CGM, D, Loc, isVolatile, Builder);
break;
}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGException.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGException.cpp
index 56a246eb65e0..5a9d06da12de 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGException.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGException.cpp
@@ -127,6 +127,8 @@ const EHPersonality
EHPersonality::GNU_Wasm_CPlusPlus = { "__gxx_wasm_personality_v0", nullptr };
const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1",
nullptr};
+const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2",
+ nullptr};
static const EHPersonality &getCPersonality(const TargetInfo &Target,
const LangOptions &L) {
@@ -187,6 +189,8 @@ static const EHPersonality &getCXXPersonality(const TargetInfo &Target,
return EHPersonality::GNU_CPlusPlus_SEH;
if (L.hasWasmExceptions())
return EHPersonality::GNU_Wasm_CPlusPlus;
+ if (T.isOSzOS())
+ return EHPersonality::ZOS_CPlusPlus;
return EHPersonality::GNU_CPlusPlus;
}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp
index d12e85b48d0b..c5f6b6d3a99f 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp
@@ -1516,6 +1516,14 @@ LValue CodeGenFunction::EmitLValue(const Expr *E,
return LV;
}
+static QualType getConstantExprReferredType(const FullExpr *E,
+ const ASTContext &Ctx) {
+ const Expr *SE = E->getSubExpr()->IgnoreImplicit();
+ if (isa<OpaqueValueExpr>(SE))
+ return SE->getType();
+ return cast<CallExpr>(SE)->getCallReturnType(Ctx)->getPointeeType();
+}
+
LValue CodeGenFunction::EmitLValueHelper(const Expr *E,
KnownNonNull_t IsKnownNonNull) {
ApplyDebugLocation DL(*this, E);
@@ -1554,9 +1562,7 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E,
case Expr::ConstantExprClass: {
const ConstantExpr *CE = cast<ConstantExpr>(E);
if (llvm::Value *Result = ConstantEmitter(*this).tryEmitConstantExpr(CE)) {
- QualType RetType = cast<CallExpr>(CE->getSubExpr()->IgnoreImplicit())
- ->getCallReturnType(getContext())
- ->getPointeeType();
+ QualType RetType = getConstantExprReferredType(CE, getContext());
return MakeNaturalAlignAddrLValue(Result, RetType);
}
return EmitLValue(cast<ConstantExpr>(E)->getSubExpr(), IsKnownNonNull);
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExprCXX.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExprCXX.cpp
index 98ae56e2df88..d136bfc37278 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1038,11 +1038,25 @@ void CodeGenFunction::EmitNewArrayInitializer(
return true;
};
+ const InitListExpr *ILE = dyn_cast<InitListExpr>(Init);
+ const CXXParenListInitExpr *CPLIE = nullptr;
+ const StringLiteral *SL = nullptr;
+ const ObjCEncodeExpr *OCEE = nullptr;
+ const Expr *IgnoreParen = nullptr;
+ if (!ILE) {
+ IgnoreParen = Init->IgnoreParenImpCasts();
+ CPLIE = dyn_cast<CXXParenListInitExpr>(IgnoreParen);
+ SL = dyn_cast<StringLiteral>(IgnoreParen);
+ OCEE = dyn_cast<ObjCEncodeExpr>(IgnoreParen);
+ }
+
// If the initializer is an initializer list, first do the explicit elements.
- if (const InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
+ if (ILE || CPLIE || SL || OCEE) {
// Initializing from a (braced) string literal is a special case; the init
// list element does not initialize a (single) array element.
- if (ILE->isStringLiteralInit()) {
+ if ((ILE && ILE->isStringLiteralInit()) || SL || OCEE) {
+ if (!ILE)
+ Init = IgnoreParen;
// Initialize the initial portion of length equal to that of the string
// literal. The allocation must be for at least this much; we emitted a
// check for that earlier.
@@ -1054,12 +1068,13 @@ void CodeGenFunction::EmitNewArrayInitializer(
AggValueSlot::DoesNotOverlap,
AggValueSlot::IsNotZeroed,
AggValueSlot::IsSanitizerChecked);
- EmitAggExpr(ILE->getInit(0), Slot);
+ EmitAggExpr(ILE ? ILE->getInit(0) : Init, Slot);
// Move past these elements.
InitListElements =
- cast<ConstantArrayType>(ILE->getType()->getAsArrayTypeUnsafe())
- ->getSize().getZExtValue();
+ cast<ConstantArrayType>(Init->getType()->getAsArrayTypeUnsafe())
+ ->getSize()
+ .getZExtValue();
CurPtr = Builder.CreateConstInBoundsGEP(
CurPtr, InitListElements, "string.init.end");
@@ -1073,7 +1088,9 @@ void CodeGenFunction::EmitNewArrayInitializer(
return;
}
- InitListElements = ILE->getNumInits();
+ ArrayRef<const Expr *> InitExprs =
+ ILE ? ILE->inits() : CPLIE->getInitExprs();
+ InitListElements = InitExprs.size();
// If this is a multi-dimensional array new, we will initialize multiple
// elements with each init list element.
@@ -1101,7 +1118,8 @@ void CodeGenFunction::EmitNewArrayInitializer(
}
CharUnits StartAlign = CurPtr.getAlignment();
- for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) {
+ unsigned i = 0;
+ for (const Expr *IE : InitExprs) {
// Tell the cleanup that it needs to destroy up to this
// element. TODO: some of these stores can be trivially
// observed to be unnecessary.
@@ -1111,18 +1129,17 @@ void CodeGenFunction::EmitNewArrayInitializer(
// FIXME: If the last initializer is an incomplete initializer list for
// an array, and we have an array filler, we can fold together the two
// initialization loops.
- StoreAnyExprIntoOneUnit(*this, ILE->getInit(i),
- ILE->getInit(i)->getType(), CurPtr,
+ StoreAnyExprIntoOneUnit(*this, IE, IE->getType(), CurPtr,
AggValueSlot::DoesNotOverlap);
CurPtr = Address(Builder.CreateInBoundsGEP(
CurPtr.getElementType(), CurPtr.getPointer(),
Builder.getSize(1), "array.exp.next"),
CurPtr.getElementType(),
- StartAlign.alignmentAtOffset((i + 1) * ElementSize));
+ StartAlign.alignmentAtOffset((++i) * ElementSize));
}
// The remaining elements are filled with the array filler expression.
- Init = ILE->getArrayFiller();
+ Init = ILE ? ILE->getArrayFiller() : CPLIE->getArrayFiller();
// Extract the initializer for the individual array elements by pulling
// out the array filler from all the nested initializer lists. This avoids
@@ -1561,16 +1578,23 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
// 1. Build a call to the allocation function.
FunctionDecl *allocator = E->getOperatorNew();
- // If there is a brace-initializer, cannot allocate fewer elements than inits.
+ // If there is a brace-initializer or C++20 parenthesized initializer, cannot
+ // allocate fewer elements than inits.
unsigned minElements = 0;
if (E->isArray() && E->hasInitializer()) {
- const InitListExpr *ILE = dyn_cast<InitListExpr>(E->getInitializer());
- if (ILE && ILE->isStringLiteralInit())
+ const Expr *Init = E->getInitializer();
+ const InitListExpr *ILE = dyn_cast<InitListExpr>(Init);
+ const CXXParenListInitExpr *CPLIE = dyn_cast<CXXParenListInitExpr>(Init);
+ const Expr *IgnoreParen = Init->IgnoreParenImpCasts();
+ if ((ILE && ILE->isStringLiteralInit()) ||
+ isa<StringLiteral>(IgnoreParen) || isa<ObjCEncodeExpr>(IgnoreParen)) {
minElements =
- cast<ConstantArrayType>(ILE->getType()->getAsArrayTypeUnsafe())
- ->getSize().getZExtValue();
- else if (ILE)
- minElements = ILE->getNumInits();
+ cast<ConstantArrayType>(Init->getType()->getAsArrayTypeUnsafe())
+ ->getSize()
+ .getZExtValue();
+ } else if (ILE || CPLIE) {
+ minElements = ILE ? ILE->getNumInits() : CPLIE->getInitExprs().size();
+ }
}
llvm::Value *numElements = nullptr;
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp
index e532794b71bd..839fe16cd772 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp
@@ -892,6 +892,9 @@ ComplexPairTy ComplexExprEmitter::EmitRangeReductionDiv(llvm::Value *LHSr,
llvm::Value *LHSi,
llvm::Value *RHSr,
llvm::Value *RHSi) {
+ // FIXME: This could eventually be replaced by an LLVM intrinsic to
+ // avoid this long IR sequence.
+
// (a + ib) / (c + id) = (e + if)
llvm::Value *FAbsRHSr = EmitllvmFAbs(CGF, RHSr); // |c|
llvm::Value *FAbsRHSi = EmitllvmFAbs(CGF, RHSi); // |d|
@@ -936,7 +939,7 @@ ComplexPairTy ComplexExprEmitter::EmitRangeReductionDiv(llvm::Value *LHSr,
llvm::Value *RC = Builder.CreateFMul(CdD, RHSr); // rc
llvm::Value *DpRC = Builder.CreateFAdd(RHSi, RC); // tmp=d+rc
- llvm::Value *T7 = Builder.CreateFMul(LHSr, RC); // ar
+ llvm::Value *T7 = Builder.CreateFMul(LHSr, CdD); // ar
llvm::Value *T8 = Builder.CreateFAdd(T7, LHSi); // ar+b
llvm::Value *DSTFr = Builder.CreateFDiv(T8, DpRC); // (ar+b)/tmp
@@ -978,7 +981,10 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi);
else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited)
return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi);
- else if (!CGF.getLangOpts().FastMath) {
+ else if (!CGF.getLangOpts().FastMath ||
+ // '-ffast-math' is used in the command line but followed by an
+ // '-fno-cx-limited-range'.
+ Op.FPFeatures.getComplexRange() == LangOptions::CX_Full) {
LHSi = OrigLHSi;
// If we have a complex operand on the RHS and FastMath is not allowed, we
// delegate to a libcall to handle all of the complexities and minimize
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp
index 9ec185153d12..181b15e9c7d0 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4960,6 +4960,13 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
CGF.getProfileCount(lhsExpr));
CGF.EmitBlock(LHSBlock);
+
+ // If the top of the logical operator nest, update the MCDC bitmap for the
+ // ConditionalOperator prior to visiting its LHS and RHS blocks, since they
+ // may also contain a boolean expression.
+ if (CGF.MCDCLogOpStack.empty())
+ CGF.maybeUpdateMCDCTestVectorBitmap(condExpr);
+
CGF.incrementProfileCounter(E);
eval.begin(CGF);
Value *LHS = Visit(lhsExpr);
@@ -4969,6 +4976,13 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
Builder.CreateBr(ContBlock);
CGF.EmitBlock(RHSBlock);
+
+ // If the top of the logical operator nest, update the MCDC bitmap for the
+ // ConditionalOperator prior to visiting its LHS and RHS blocks, since they
+ // may also contain a boolean expression.
+ if (CGF.MCDCLogOpStack.empty())
+ CGF.maybeUpdateMCDCTestVectorBitmap(condExpr);
+
eval.begin(CGF);
Value *RHS = Visit(rhsExpr);
eval.end(CGF);
@@ -4987,10 +5001,6 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
PN->addIncoming(LHS, LHSBlock);
PN->addIncoming(RHS, RHSBlock);
- // If the top of the logical operator nest, update the MCDC bitmap.
- if (CGF.MCDCLogOpStack.empty())
- CGF.maybeUpdateMCDCTestVectorBitmap(condExpr);
-
return PN;
}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp
index acc85165a470..03fc0ec7ff54 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp
@@ -3941,6 +3941,8 @@ static unsigned getBaseMachOPlatformID(const llvm::Triple &TT) {
return llvm::MachO::PLATFORM_TVOS;
case llvm::Triple::WatchOS:
return llvm::MachO::PLATFORM_WATCHOS;
+ case llvm::Triple::XROS:
+ return llvm::MachO::PLATFORM_XROS;
case llvm::Triple::DriverKit:
return llvm::MachO::PLATFORM_DRIVERKIT;
default:
@@ -4024,6 +4026,9 @@ static bool isFoundationNeededForDarwinAvailabilityCheck(
case llvm::Triple::MacOSX:
FoundationDroppedInVersion = VersionTuple(/*Major=*/10, /*Minor=*/15);
break;
+ case llvm::Triple::XROS:
+ // XROS doesn't need Foundation.
+ return false;
case llvm::Triple::DriverKit:
// DriverKit doesn't need Foundation.
return false;
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp
index cd1a0b6a130f..a36b0cdddaf0 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -18,6 +18,8 @@
#include "CGObjCRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "CodeGenTypes.h"
+#include "SanitizerMetadata.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
@@ -597,6 +599,10 @@ public:
llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD) override;
+
+ // Map to unify direct method definitions.
+ llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *>
+ DirectMethodDefinitions;
void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD) override;
@@ -917,6 +923,14 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
ClassAliasSection,
ConstantStringSection
};
+ /// The subset of `objc_class_flags` used at compile time.
+ enum ClassFlags {
+ /// This is a metaclass
+ ClassFlagMeta = (1 << 0),
+ /// This class has been initialised by the runtime (+initialize has been
+ /// sent if necessary).
+ ClassFlagInitialized = (1 << 8),
+ };
static const char *const SectionsBaseNames[8];
static const char *const PECOFFSectionsBaseNames[8];
template<SectionKind K>
@@ -932,6 +946,8 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
/// structure describing the receiver and the class, and a selector as
/// arguments. Returns the IMP for the corresponding method.
LazyRuntimeFunction MsgLookupSuperFn;
+ /// Function to ensure that +initialize is sent to a class.
+ LazyRuntimeFunction SentInitializeFn;
/// A flag indicating if we've emitted at least one protocol.
/// If we haven't, then we need to emit an empty protocol, to ensure that the
/// __start__objc_protocols and __stop__objc_protocols sections exist.
@@ -1431,12 +1447,24 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
const std::string &TypeEncoding) override {
return GetConstantSelector(Sel, TypeEncoding);
}
+ std::string GetSymbolNameForTypeEncoding(const std::string &TypeEncoding) {
+ std::string MangledTypes = std::string(TypeEncoding);
+ // @ is used as a special character in ELF symbol names (used for symbol
+ // versioning), so mangle the name to not include it. Replace it with a
+ // character that is not a valid type encoding character (and, being
+ // non-printable, never will be!)
+ if (CGM.getTriple().isOSBinFormatELF())
+ std::replace(MangledTypes.begin(), MangledTypes.end(), '@', '\1');
+ // = in dll exported names causes lld to fail when linking on Windows.
+ if (CGM.getTriple().isOSWindows())
+ std::replace(MangledTypes.begin(), MangledTypes.end(), '=', '\2');
+ return MangledTypes;
+ }
llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) {
if (TypeEncoding.empty())
return NULLPtr;
- std::string MangledTypes = std::string(TypeEncoding);
- std::replace(MangledTypes.begin(), MangledTypes.end(),
- '@', '\1');
+ std::string MangledTypes =
+ GetSymbolNameForTypeEncoding(std::string(TypeEncoding));
std::string TypesVarName = ".objc_sel_types_" + MangledTypes;
auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName);
if (!TypesGlobal) {
@@ -1453,13 +1481,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
}
llvm::Constant *GetConstantSelector(Selector Sel,
const std::string &TypeEncoding) override {
- // @ is used as a special character in symbol names (used for symbol
- // versioning), so mangle the name to not include it. Replace it with a
- // character that is not a valid type encoding character (and, being
- // non-printable, never will be!)
- std::string MangledTypes = TypeEncoding;
- std::replace(MangledTypes.begin(), MangledTypes.end(),
- '@', '\1');
+ std::string MangledTypes = GetSymbolNameForTypeEncoding(TypeEncoding);
auto SelVarName = (StringRef(".objc_selector_") + Sel.getAsString() + "_" +
MangledTypes).str();
if (auto *GV = TheModule.getNamedGlobal(SelVarName))
@@ -1671,9 +1693,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
const ObjCIvarDecl *Ivar) override {
std::string TypeEncoding;
CGM.getContext().getObjCEncodingForType(Ivar->getType(), TypeEncoding);
- // Prevent the @ from being interpreted as a symbol version.
- std::replace(TypeEncoding.begin(), TypeEncoding.end(),
- '@', '\1');
+ TypeEncoding = GetSymbolNameForTypeEncoding(TypeEncoding);
const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
+ '.' + Ivar->getNameAsString() + '.' + TypeEncoding;
return Name;
@@ -1715,7 +1735,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
metaclassFields.addInt(LongTy, 0);
// unsigned long info;
// objc_class_flag_meta
- metaclassFields.addInt(LongTy, 1);
+ metaclassFields.addInt(LongTy, ClassFlags::ClassFlagMeta);
// long instance_size;
// Setting this to zero is consistent with the older ABI, but it might be
// more sensible to set this to sizeof(struct objc_class)
@@ -1989,6 +2009,8 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
CGObjCGNUstep2(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 10, 4, 2) {
MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
PtrToObjCSuperTy, SelectorTy);
+ SentInitializeFn.init(&CGM, "objc_send_initialize",
+ llvm::Type::getVoidTy(VMContext), IdTy);
// struct objc_property
// {
// const char *name;
@@ -2002,6 +2024,106 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
{ PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
}
+ void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
+ const ObjCMethodDecl *OMD,
+ const ObjCContainerDecl *CD) override {
+ auto &Builder = CGF.Builder;
+ bool ReceiverCanBeNull = true;
+ auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
+ auto selfValue = Builder.CreateLoad(selfAddr);
+
+ // Generate:
+ //
+ // /* unless the receiver is never NULL */
+ // if (self == nil) {
+ // return (ReturnType){ };
+ // }
+ //
+ // /* for class methods only to force class lazy initialization */
+ // if (!__objc_{class}_initialized)
+ // {
+ // objc_send_initialize(class);
+ // __objc_{class}_initialized = 1;
+ // }
+ //
+ // _cmd = @selector(...)
+ // ...
+
+ if (OMD->isClassMethod()) {
+ const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
+
+ // Nullable `Class` expressions cannot be messaged with a direct method
+ // so the only reason why the receive can be null would be because
+ // of weak linking.
+ ReceiverCanBeNull = isWeakLinkedClass(OID);
+ }
+
+ llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+ if (ReceiverCanBeNull) {
+ llvm::BasicBlock *SelfIsNilBlock =
+ CGF.createBasicBlock("objc_direct_method.self_is_nil");
+ llvm::BasicBlock *ContBlock =
+ CGF.createBasicBlock("objc_direct_method.cont");
+
+ // if (self == nil) {
+ auto selfTy = cast<llvm::PointerType>(selfValue->getType());
+ auto Zero = llvm::ConstantPointerNull::get(selfTy);
+
+ Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero),
+ SelfIsNilBlock, ContBlock,
+ MDHelper.createBranchWeights(1, 1 << 20));
+
+ CGF.EmitBlock(SelfIsNilBlock);
+
+ // return (ReturnType){ };
+ auto retTy = OMD->getReturnType();
+ Builder.SetInsertPoint(SelfIsNilBlock);
+ if (!retTy->isVoidType()) {
+ CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
+ }
+ CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
+ // }
+
+ // rest of the body
+ CGF.EmitBlock(ContBlock);
+ Builder.SetInsertPoint(ContBlock);
+ }
+
+ if (OMD->isClassMethod()) {
+ // Prefix of the class type.
+ auto *classStart =
+ llvm::StructType::get(PtrTy, PtrTy, PtrTy, LongTy, LongTy);
+ auto &astContext = CGM.getContext();
+ auto flags = Builder.CreateLoad(
+ Address{Builder.CreateStructGEP(classStart, selfValue, 4), LongTy,
+ CharUnits::fromQuantity(
+ astContext.getTypeAlign(astContext.UnsignedLongTy))});
+ auto isInitialized =
+ Builder.CreateAnd(flags, ClassFlags::ClassFlagInitialized);
+ llvm::BasicBlock *notInitializedBlock =
+ CGF.createBasicBlock("objc_direct_method.class_uninitialized");
+ llvm::BasicBlock *initializedBlock =
+ CGF.createBasicBlock("objc_direct_method.class_initialized");
+ Builder.CreateCondBr(Builder.CreateICmpEQ(isInitialized, Zeros[0]),
+ notInitializedBlock, initializedBlock,
+ MDHelper.createBranchWeights(1, 1 << 20));
+ CGF.EmitBlock(notInitializedBlock);
+ Builder.SetInsertPoint(notInitializedBlock);
+ CGF.EmitRuntimeCall(SentInitializeFn, selfValue);
+ Builder.CreateBr(initializedBlock);
+ CGF.EmitBlock(initializedBlock);
+ Builder.SetInsertPoint(initializedBlock);
+ }
+
+ // only synthesize _cmd if it's referenced
+ if (OMD->getCmdDecl()->isUsed()) {
+ // `_cmd` is not a parameter to direct methods, so storage must be
+ // explicitly declared for it.
+ CGF.EmitVarDecl(*OMD->getCmdDecl());
+ Builder.CreateStore(GetSelector(CGF, OMD),
+ CGF.GetAddrOfLocalVar(OMD->getCmdDecl()));
+ }
+ }
};
const char *const CGObjCGNUstep2::SectionsBaseNames[8] =
@@ -2645,13 +2767,18 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
}
}
+ bool isDirect = Method && Method->isDirectMethod();
+
IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
llvm::Value *cmd;
- if (Method)
- cmd = GetSelector(CGF, Method);
- else
- cmd = GetSelector(CGF, Sel);
- cmd = EnforceType(Builder, cmd, SelectorTy);
+ if (!isDirect) {
+ if (Method)
+ cmd = GetSelector(CGF, Method);
+ else
+ cmd = GetSelector(CGF, Sel);
+ cmd = EnforceType(Builder, cmd, SelectorTy);
+ }
+
Receiver = EnforceType(Builder, Receiver, IdTy);
llvm::Metadata *impMD[] = {
@@ -2663,7 +2790,8 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
CallArgList ActualArgs;
ActualArgs.add(RValue::get(Receiver), ASTIdTy);
- ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType());
+ if (!isDirect)
+ ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType());
ActualArgs.addFrom(CallArgs);
MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
@@ -2682,7 +2810,7 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
// Rather than doing a whole target-specific analysis, we assume it
// only works for void, integer, and pointer types, and in all
// other cases we do an explicit nil check is emitted code. In
- // addition to ensuring we produe a zero value for other types, this
+ // addition to ensuring we produce a zero value for other types, this
// sidesteps the few outright CC incompatibilities we know about that
// could otherwise lead to crashes, like when a method is expected to
// return on the x87 floating point stack or adjust the stack pointer
@@ -2716,8 +2844,9 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
// FIXME: we probably need a size limit here, but we've
// never imposed one before
} else {
- // Otherwise, use an explicit check just to be sure.
- requiresExplicitZeroResult = true;
+ // Otherwise, use an explicit check just to be sure, unless we're
+ // calling a direct method, where the implementation does this for us.
+ requiresExplicitZeroResult = !isDirect;
}
}
@@ -2761,10 +2890,14 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
// Get the IMP to call
llvm::Value *imp;
- // If we have non-legacy dispatch specified, we try using the objc_msgSend()
- // functions. These are not supported on all platforms (or all runtimes on a
- // given platform), so we
- switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
+ // If this is a direct method, just emit it here.
+ if (isDirect)
+ imp = GenerateMethod(Method, Method->getClassInterface());
+ else
+ // If we have non-legacy dispatch specified, we try using the
+ // objc_msgSend() functions. These are not supported on all platforms
+ // (or all runtimes on a given platform), so we
+ switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
case CodeGenOptions::Legacy:
imp = LookupIMP(CGF, Receiver, cmd, node, MSI);
break;
@@ -2787,7 +2920,7 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
llvm::FunctionType::get(IdTy, IdTy, true), "objc_msgSend")
.getCallee();
}
- }
+ }
// Reset the receiver in case the lookup modified it
ActualArgs[0] = CallArg(RValue::get(Receiver), ASTIdTy);
@@ -2797,7 +2930,8 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
llvm::CallBase *call;
CGCallee callee(CGCalleeInfo(), imp);
RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
- call->setMetadata(msgSendMDKind, node);
+ if (!isDirect)
+ call->setMetadata(msgSendMDKind, node);
if (requiresNilReceiverCheck) {
llvm::BasicBlock *nonNilPathBB = CGF.Builder.GetInsertBlock();
@@ -3920,14 +4054,50 @@ llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
CodeGenTypes &Types = CGM.getTypes();
llvm::FunctionType *MethodTy =
Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
- std::string FunctionName = getSymbolNameForMethod(OMD);
-
- llvm::Function *Method
- = llvm::Function::Create(MethodTy,
- llvm::GlobalValue::InternalLinkage,
- FunctionName,
- &TheModule);
- return Method;
+
+ bool isDirect = OMD->isDirectMethod();
+ std::string FunctionName =
+ getSymbolNameForMethod(OMD, /*include category*/ !isDirect);
+
+ if (!isDirect)
+ return llvm::Function::Create(MethodTy,
+ llvm::GlobalVariable::InternalLinkage,
+ FunctionName, &TheModule);
+
+ auto *COMD = OMD->getCanonicalDecl();
+ auto I = DirectMethodDefinitions.find(COMD);
+ llvm::Function *OldFn = nullptr, *Fn = nullptr;
+
+ if (I == DirectMethodDefinitions.end()) {
+ auto *F =
+ llvm::Function::Create(MethodTy, llvm::GlobalVariable::ExternalLinkage,
+ FunctionName, &TheModule);
+ DirectMethodDefinitions.insert(std::make_pair(COMD, F));
+ return F;
+ }
+
+ // Objective-C allows for the declaration and implementation types
+ // to differ slightly.
+ //
+ // If we're being asked for the Function associated for a method
+ // implementation, a previous value might have been cached
+ // based on the type of the canonical declaration.
+ //
+ // If these do not match, then we'll replace this function with
+ // a new one that has the proper type below.
+ if (!OMD->getBody() || COMD->getReturnType() == OMD->getReturnType())
+ return I->second;
+
+ OldFn = I->second;
+ Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage, "",
+ &CGM.getModule());
+ Fn->takeName(OldFn);
+ OldFn->replaceAllUsesWith(Fn);
+ OldFn->eraseFromParent();
+
+ // Replace the cached function in the map.
+ I->second = Fn;
+ return Fn;
}
void CGObjCGNU::GenerateDirectMethodPrologue(CodeGenFunction &CGF,
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index ea6645a39e83..4855e7410a01 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -1044,6 +1044,13 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
? CGM.getLangOpts().OMPHostIRFile
: StringRef{});
OMPBuilder.setConfig(Config);
+
+ // The user forces the compiler to behave as if omp requires
+ // unified_shared_memory was given.
+ if (CGM.getLangOpts().OpenMPForceUSM) {
+ HasRequiresUnifiedSharedMemory = true;
+ OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(true);
+ }
}
void CGOpenMPRuntime::clear() {
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp
index b89017de0bcf..beff0ad9da27 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp
@@ -2399,9 +2399,9 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
Tmp = Builder.CreatePtrToInt(
Tmp, llvm::IntegerType::get(CTX, (unsigned)TmpSize));
Tmp = Builder.CreateTrunc(Tmp, TruncTy);
- } else if (TruncTy->isIntegerTy()) {
+ } else if (Tmp->getType()->isIntegerTy() && TruncTy->isIntegerTy()) {
Tmp = Builder.CreateZExtOrTrunc(Tmp, TruncTy);
- } else if (TruncTy->isVectorTy()) {
+ } else if (Tmp->getType()->isVectorTy() || TruncTy->isVectorTy()) {
Tmp = Builder.CreateBitCast(Tmp, TruncTy);
}
}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp
index 27a2cab4f753..8dee3f74b44b 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp
@@ -793,7 +793,7 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder,
llvm::Constant *fnPtr;
// Pure virtual member functions.
- if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) {
+ if (cast<CXXMethodDecl>(GD.getDecl())->isPureVirtual()) {
if (!PureVirtualFn)
PureVirtualFn =
getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName());
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
index ad6fc71c1e50..1280bcd36de9 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
@@ -229,7 +229,8 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
ABIFLen = 32;
else if (ABIStr.ends_with("d"))
ABIFLen = 64;
- return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen);
+ bool EABI = ABIStr.ends_with("e");
+ return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen, EABI);
}
case llvm::Triple::systemz: {
@@ -721,43 +722,70 @@ void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags,
}
}
+static std::optional<llvm::GlobalValue::VisibilityTypes>
+getLLVMVisibility(clang::LangOptions::VisibilityFromDLLStorageClassKinds K) {
+ // Map to LLVM visibility.
+ switch (K) {
+ case clang::LangOptions::VisibilityFromDLLStorageClassKinds::Keep:
+ return std::nullopt;
+ case clang::LangOptions::VisibilityFromDLLStorageClassKinds::Default:
+ return llvm::GlobalValue::DefaultVisibility;
+ case clang::LangOptions::VisibilityFromDLLStorageClassKinds::Hidden:
+ return llvm::GlobalValue::HiddenVisibility;
+ case clang::LangOptions::VisibilityFromDLLStorageClassKinds::Protected:
+ return llvm::GlobalValue::ProtectedVisibility;
+ }
+ llvm_unreachable("unknown option value!");
+}
+
+void setLLVMVisibility(llvm::GlobalValue &GV,
+ std::optional<llvm::GlobalValue::VisibilityTypes> V) {
+ if (!V)
+ return;
+
+ // Reset DSO locality before setting the visibility. This removes
+ // any effects that visibility options and annotations may have
+ // had on the DSO locality. Setting the visibility will implicitly set
+ // appropriate globals to DSO Local; however, this will be pessimistic
+ // w.r.t. to the normal compiler IRGen.
+ GV.setDSOLocal(false);
+ GV.setVisibility(*V);
+}
+
static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO,
llvm::Module &M) {
if (!LO.VisibilityFromDLLStorageClass)
return;
- llvm::GlobalValue::VisibilityTypes DLLExportVisibility =
- CodeGenModule::GetLLVMVisibility(LO.getDLLExportVisibility());
- llvm::GlobalValue::VisibilityTypes NoDLLStorageClassVisibility =
- CodeGenModule::GetLLVMVisibility(LO.getNoDLLStorageClassVisibility());
- llvm::GlobalValue::VisibilityTypes ExternDeclDLLImportVisibility =
- CodeGenModule::GetLLVMVisibility(LO.getExternDeclDLLImportVisibility());
- llvm::GlobalValue::VisibilityTypes ExternDeclNoDLLStorageClassVisibility =
- CodeGenModule::GetLLVMVisibility(
- LO.getExternDeclNoDLLStorageClassVisibility());
+ std::optional<llvm::GlobalValue::VisibilityTypes> DLLExportVisibility =
+ getLLVMVisibility(LO.getDLLExportVisibility());
+
+ std::optional<llvm::GlobalValue::VisibilityTypes>
+ NoDLLStorageClassVisibility =
+ getLLVMVisibility(LO.getNoDLLStorageClassVisibility());
+
+ std::optional<llvm::GlobalValue::VisibilityTypes>
+ ExternDeclDLLImportVisibility =
+ getLLVMVisibility(LO.getExternDeclDLLImportVisibility());
+
+ std::optional<llvm::GlobalValue::VisibilityTypes>
+ ExternDeclNoDLLStorageClassVisibility =
+ getLLVMVisibility(LO.getExternDeclNoDLLStorageClassVisibility());
for (llvm::GlobalValue &GV : M.global_values()) {
if (GV.hasAppendingLinkage() || GV.hasLocalLinkage())
continue;
- // Reset DSO locality before setting the visibility. This removes
- // any effects that visibility options and annotations may have
- // had on the DSO locality. Setting the visibility will implicitly set
- // appropriate globals to DSO Local; however, this will be pessimistic
- // w.r.t. to the normal compiler IRGen.
- GV.setDSOLocal(false);
-
- if (GV.isDeclarationForLinker()) {
- GV.setVisibility(GV.getDLLStorageClass() ==
- llvm::GlobalValue::DLLImportStorageClass
- ? ExternDeclDLLImportVisibility
- : ExternDeclNoDLLStorageClassVisibility);
- } else {
- GV.setVisibility(GV.getDLLStorageClass() ==
- llvm::GlobalValue::DLLExportStorageClass
- ? DLLExportVisibility
- : NoDLLStorageClassVisibility);
- }
+ if (GV.isDeclarationForLinker())
+ setLLVMVisibility(GV, GV.getDLLStorageClass() ==
+ llvm::GlobalValue::DLLImportStorageClass
+ ? ExternDeclDLLImportVisibility
+ : ExternDeclNoDLLStorageClassVisibility);
+ else
+ setLLVMVisibility(GV, GV.getDLLStorageClass() ==
+ llvm::GlobalValue::DLLExportStorageClass
+ ? DLLExportVisibility
+ : NoDLLStorageClassVisibility);
GV.setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
}
@@ -1201,7 +1229,7 @@ void CodeGenModule::Release() {
llvm::CodeModel::Model codeModel = static_cast<llvm::CodeModel::Model>(CM);
getModule().setCodeModel(codeModel);
- if (CM == llvm::CodeModel::Medium &&
+ if ((CM == llvm::CodeModel::Medium || CM == llvm::CodeModel::Large) &&
Context.getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86_64) {
getModule().setLargeDataThreshold(getCodeGenOpts().LargeDataThreshold);
@@ -1688,8 +1716,10 @@ static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM,
static void AppendTargetVersionMangling(const CodeGenModule &CGM,
const TargetVersionAttr *Attr,
raw_ostream &Out) {
- if (Attr->isDefaultVersion())
+ if (Attr->isDefaultVersion()) {
+ Out << ".default";
return;
+ }
Out << "._";
const TargetInfo &TI = CGM.getTarget();
llvm::SmallVector<StringRef, 8> Feats;
@@ -1752,8 +1782,10 @@ static void AppendTargetClonesMangling(const CodeGenModule &CGM,
const TargetInfo &TI = CGM.getTarget();
if (TI.getTriple().isAArch64()) {
StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
- if (FeatureStr == "default")
+ if (FeatureStr == "default") {
+ Out << ".default";
return;
+ }
Out << "._";
SmallVector<StringRef, 8> Features;
FeatureStr.split(Features, "+");
@@ -2380,8 +2412,12 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (D->hasAttr<ArmLocallyStreamingAttr>())
B.addAttribute("aarch64_pstate_sm_body");
- if (D->hasAttr<ArmNewZAAttr>())
- B.addAttribute("aarch64_pstate_za_new");
+ if (auto *Attr = D->getAttr<ArmNewAttr>()) {
+ if (Attr->isNewZA())
+ B.addAttribute("aarch64_pstate_za_new");
+ if (Attr->isNewZT0())
+ B.addAttribute("aarch64_new_zt0");
+ }
// Track whether we need to add the optnone LLVM attribute,
// starting with the default for this optimization level.
@@ -3999,6 +4035,8 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD,
EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
// Ensure that the resolver function is also emitted.
GetOrCreateMultiVersionResolver(GD);
+ } else if (FD->hasAttr<TargetVersionAttr>()) {
+ GetOrCreateMultiVersionResolver(GD);
} else
EmitGlobalFunctionDefinition(GD, GV);
}
@@ -4180,14 +4218,7 @@ void CodeGenModule::emitMultiVersionFunctions() {
llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD);
if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
ResolverConstant = IFunc->getResolver();
- // In Aarch64, default versions of multiversioned functions are mangled to
- // their 'normal' assembly name. This deviates from other targets which
- // append a '.default' string. As a result we need to continue appending
- // .ifunc in Aarch64.
- // FIXME: Should Aarch64 mangling for 'default' multiversion function and
- // in turn ifunc function match that of other targets?
- if (FD->isTargetClonesMultiVersion() &&
- !getTarget().getTriple().isAArch64()) {
+ if (FD->isTargetClonesMultiVersion()) {
const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI);
std::string MangledName = getMangledNameImpl(
@@ -4368,14 +4399,7 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
// a separate resolver).
std::string ResolverName = MangledName;
if (getTarget().supportsIFunc()) {
- // In Aarch64, default versions of multiversioned functions are mangled to
- // their 'normal' assembly name. This deviates from other targets which
- // append a '.default' string. As a result we need to continue appending
- // .ifunc in Aarch64.
- // FIXME: Should Aarch64 mangling for 'default' multiversion function and
- // in turn ifunc function match that of other targets?
- if (!FD->isTargetClonesMultiVersion() ||
- getTarget().getTriple().isAArch64())
+ if (!FD->isTargetClonesMultiVersion())
ResolverName += ".ifunc";
} else if (FD->isTargetMultiVersion()) {
ResolverName += ".resolver";
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenPGO.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenPGO.cpp
index d68844d476eb..5d7c38477457 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -28,6 +28,8 @@ static llvm::cl::opt<bool>
llvm::cl::desc("Enable value profiling"),
llvm::cl::Hidden, llvm::cl::init(false));
+extern llvm::cl::opt<bool> SystemHeadersCoverage;
+
using namespace clang;
using namespace CodeGen;
@@ -1022,7 +1024,7 @@ bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) {
// Don't map the functions in system headers.
const auto &SM = CGM.getContext().getSourceManager();
auto Loc = D->getBody()->getBeginLoc();
- return SM.isInSystemHeader(Loc);
+ return !SystemHeadersCoverage && SM.isInSystemHeader(Loc);
}
void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp b/contrib/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp
index b245abd16c3f..5eca00f22bb8 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -37,7 +37,7 @@ static llvm::cl::opt<bool> EmptyLineCommentCoverage(
"disable it on test)"),
llvm::cl::init(true), llvm::cl::Hidden);
-static llvm::cl::opt<bool> SystemHeadersCoverage(
+llvm::cl::opt<bool> SystemHeadersCoverage(
"system-headers-coverage",
llvm::cl::desc("Enable collecting coverage from system headers"),
llvm::cl::init(false), llvm::cl::Hidden);
@@ -119,12 +119,16 @@ class SourceMappingRegion {
/// as the line execution count if there are no other regions on the line.
bool GapRegion;
+ /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
+ /// branch, or anything skipped but not empty line / comments)
+ bool SkippedRegion;
+
public:
SourceMappingRegion(Counter Count, std::optional<SourceLocation> LocStart,
std::optional<SourceLocation> LocEnd,
bool GapRegion = false)
- : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {
- }
+ : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+ SkippedRegion(false) {}
SourceMappingRegion(Counter Count, std::optional<Counter> FalseCount,
MCDCParameters MCDCParams,
@@ -132,13 +136,14 @@ public:
std::optional<SourceLocation> LocEnd,
bool GapRegion = false)
: Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
- LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {}
+ LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
+ SkippedRegion(false) {}
SourceMappingRegion(MCDCParameters MCDCParams,
std::optional<SourceLocation> LocStart,
std::optional<SourceLocation> LocEnd)
: MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
- GapRegion(false) {}
+ GapRegion(false), SkippedRegion(false) {}
const Counter &getCounter() const { return Count; }
@@ -174,6 +179,10 @@ public:
void setGap(bool Gap) { GapRegion = Gap; }
+ bool isSkipped() const { return SkippedRegion; }
+
+ void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
+
bool isBranch() const { return FalseCount.has_value(); }
bool isMCDCDecision() const { return MCDCParams.NumConditions != 0; }
@@ -468,6 +477,10 @@ public:
MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
SR.LineEnd, SR.ColumnEnd));
+ } else if (Region.isSkipped()) {
+ MappingRegions.push_back(CounterMappingRegion::makeSkipped(
+ *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
+ SR.ColumnEnd));
} else if (Region.isBranch()) {
MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
Region.getCounter(), Region.getFalseCounter(),
@@ -573,6 +586,11 @@ struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
/// creation.
struct MCDCCoverageBuilder {
+ struct DecisionIDPair {
+ MCDCConditionID TrueID = 0;
+ MCDCConditionID FalseID = 0;
+ };
+
/// The AST walk recursively visits nested logical-AND or logical-OR binary
/// operator nodes and then visits their LHS and RHS children nodes. As this
/// happens, the algorithm will assign IDs to each operator's LHS and RHS side
@@ -616,14 +634,14 @@ struct MCDCCoverageBuilder {
///
/// A node ID of '0' always means MC/DC isn't being tracked.
///
- /// As the AST walk proceeds recursively, the algorithm will also use stacks
+ /// As the AST walk proceeds recursively, the algorithm will also use a stack
/// to track the IDs of logical-AND and logical-OR operations on the RHS so
/// that it can be determined which nodes are executed next, depending on how
/// a LHS or RHS of a logical-AND or logical-OR is evaluated. This
/// information relies on the assigned IDs and are embedded within the
/// coverage region IDs of each branch region associated with a leaf-level
/// condition. This information helps the visualization tool reconstruct all
- /// possible test vectors for the purposes of MC/DC analysis. if a "next" node
+ /// possible test vectors for the purposes of MC/DC analysis. If a "next" node
/// ID is '0', it means it's the end of the test vector. The following rules
/// are used:
///
@@ -663,54 +681,40 @@ struct MCDCCoverageBuilder {
private:
CodeGenModule &CGM;
- llvm::SmallVector<MCDCConditionID> AndRHS;
- llvm::SmallVector<MCDCConditionID> OrRHS;
- llvm::SmallVector<const BinaryOperator *> NestLevel;
+ llvm::SmallVector<DecisionIDPair> DecisionStack;
llvm::DenseMap<const Stmt *, MCDCConditionID> &CondIDs;
llvm::DenseMap<const Stmt *, unsigned> &MCDCBitmapMap;
MCDCConditionID NextID = 1;
bool NotMapped = false;
+ /// Represent a sentinel value of [0,0] for the bottom of DecisionStack.
+ static constexpr DecisionIDPair DecisionStackSentinel{0, 0};
+
/// Is this a logical-AND operation?
bool isLAnd(const BinaryOperator *E) const {
return E->getOpcode() == BO_LAnd;
}
- /// Push an ID onto the corresponding RHS stack.
- void pushRHS(const BinaryOperator *E) {
- llvm::SmallVector<MCDCConditionID> &rhs = isLAnd(E) ? AndRHS : OrRHS;
- rhs.push_back(CondIDs[CodeGenFunction::stripCond(E->getRHS())]);
- }
-
- /// Pop an ID from the corresponding RHS stack.
- void popRHS(const BinaryOperator *E) {
- llvm::SmallVector<MCDCConditionID> &rhs = isLAnd(E) ? AndRHS : OrRHS;
- if (!rhs.empty())
- rhs.pop_back();
- }
-
- /// If the expected ID is on top, pop it off the corresponding RHS stack.
- void popRHSifTop(const BinaryOperator *E) {
- if (!OrRHS.empty() && CondIDs[E] == OrRHS.back())
- OrRHS.pop_back();
- else if (!AndRHS.empty() && CondIDs[E] == AndRHS.back())
- AndRHS.pop_back();
- }
-
public:
MCDCCoverageBuilder(CodeGenModule &CGM,
llvm::DenseMap<const Stmt *, MCDCConditionID> &CondIDMap,
llvm::DenseMap<const Stmt *, unsigned> &MCDCBitmapMap)
- : CGM(CGM), CondIDs(CondIDMap), MCDCBitmapMap(MCDCBitmapMap) {}
+ : CGM(CGM), DecisionStack(1, DecisionStackSentinel), CondIDs(CondIDMap),
+ MCDCBitmapMap(MCDCBitmapMap) {}
- /// Return the ID of the RHS of the next, upper nest-level logical-OR.
- MCDCConditionID getNextLOrCondID() const {
- return OrRHS.empty() ? 0 : OrRHS.back();
- }
+ /// Return whether the build of the control flow map is at the top-level
+ /// (root) of a logical operator nest in a boolean expression prior to the
+ /// assignment of condition IDs.
+ bool isIdle() const { return (NextID == 1 && !NotMapped); }
- /// Return the ID of the RHS of the next, upper nest-level logical-AND.
- MCDCConditionID getNextLAndCondID() const {
- return AndRHS.empty() ? 0 : AndRHS.back();
+ /// Return whether any IDs have been assigned in the build of the control
+ /// flow map, indicating that the map is being generated for this boolean
+ /// expression.
+ bool isBuilding() const { return (NextID > 1); }
+
+ /// Set the given condition's ID.
+ void setCondID(const Expr *Cond, MCDCConditionID ID) {
+ CondIDs[CodeGenFunction::stripCond(Cond)] = ID;
}
/// Return the ID of a given condition.
@@ -722,6 +726,9 @@ public:
return I->second;
}
+ /// Return the LHS Decision ([0,0] if not set).
+ const DecisionIDPair &back() const { return DecisionStack.back(); }
+
/// Push the binary operator statement to track the nest level and assign IDs
/// to the operator's LHS and RHS. The RHS may be a larger subtree that is
/// broken up on successive levels.
@@ -730,68 +737,67 @@ public:
return;
// If binary expression is disqualified, don't do mapping.
- if (NestLevel.empty() && MCDCBitmapMap.find(CodeGenFunction::stripCond(
- E)) == MCDCBitmapMap.end())
+ if (!isBuilding() && !MCDCBitmapMap.contains(CodeGenFunction::stripCond(E)))
NotMapped = true;
- // Push Stmt on 'NestLevel' stack to keep track of nest location.
- NestLevel.push_back(E);
-
// Don't go any further if we don't need to map condition IDs.
if (NotMapped)
return;
+ const DecisionIDPair &ParentDecision = DecisionStack.back();
+
// If the operator itself has an assigned ID, this means it represents a
- // larger subtree. In this case, pop its ID out of the RHS stack and
- // assign that ID to its LHS node. Its RHS will receive a new ID.
- if (CondIDs.find(CodeGenFunction::stripCond(E)) != CondIDs.end()) {
- // If Stmt has an ID, assign its ID to LHS
- CondIDs[CodeGenFunction::stripCond(E->getLHS())] = CondIDs[E];
-
- // Since the operator's LHS assumes the operator's same ID, pop the
- // operator from the RHS stack so that if LHS short-circuits, it won't be
- // incorrectly re-used as the node executed next.
- popRHSifTop(E);
- } else {
- // Otherwise, assign ID+1 to LHS.
- CondIDs[CodeGenFunction::stripCond(E->getLHS())] = NextID++;
- }
+ // larger subtree. In this case, assign that ID to its LHS node. Its RHS
+ // will receive a new ID below. Otherwise, assign ID+1 to LHS.
+ if (CondIDs.contains(CodeGenFunction::stripCond(E)))
+ setCondID(E->getLHS(), getCondID(E));
+ else
+ setCondID(E->getLHS(), NextID++);
- // Assign ID+1 to RHS.
- CondIDs[CodeGenFunction::stripCond(E->getRHS())] = NextID++;
+ // Assign a ID+1 for the RHS.
+ MCDCConditionID RHSid = NextID++;
+ setCondID(E->getRHS(), RHSid);
- // Push ID of Stmt's RHS so that LHS nodes know about it
- pushRHS(E);
+ // Push the LHS decision IDs onto the DecisionStack.
+ if (isLAnd(E))
+ DecisionStack.push_back({RHSid, ParentDecision.FalseID});
+ else
+ DecisionStack.push_back({ParentDecision.TrueID, RHSid});
+ }
+
+ /// Pop and return the LHS Decision ([0,0] if not set).
+ DecisionIDPair pop() {
+ if (!CGM.getCodeGenOpts().MCDCCoverage || NotMapped)
+ return DecisionStack.front();
+
+ assert(DecisionStack.size() > 1);
+ DecisionIDPair D = DecisionStack.back();
+ DecisionStack.pop_back();
+ return D;
}
- /// Pop the binary operator from the next level. If the walk is at the top of
- /// the next, assign the total number of conditions.
- unsigned popAndReturnCondCount(const BinaryOperator *E) {
+ /// Return the total number of conditions and reset the state. The number of
+ /// conditions is zero if the expression isn't mapped.
+ unsigned getTotalConditionsAndReset(const BinaryOperator *E) {
if (!CGM.getCodeGenOpts().MCDCCoverage)
return 0;
- unsigned TotalConds = 0;
-
- // Pop Stmt from 'NestLevel' stack.
- assert(NestLevel.back() == E);
- NestLevel.pop_back();
+ assert(!isIdle());
+ assert(DecisionStack.size() == 1);
// Reset state if not doing mapping.
- if (NestLevel.empty() && NotMapped) {
+ if (NotMapped) {
NotMapped = false;
+ assert(NextID == 1);
return 0;
}
- // Pop RHS ID.
- popRHS(E);
+ // Set number of conditions and reset.
+ unsigned TotalConds = NextID - 1;
- // If at the parent (NestLevel=0), set conds and reset.
- if (NestLevel.empty()) {
- TotalConds = NextID - 1;
+ // Reset ID back to beginning.
+ NextID = 1;
- // Reset ID back to beginning.
- NextID = 1;
- }
return TotalConds;
}
};
@@ -1018,13 +1024,15 @@ struct CounterCoverageMappingBuilder
return (Cond->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext()));
}
+ using MCDCDecisionIDPair = MCDCCoverageBuilder::DecisionIDPair;
+
/// Create a Branch Region around an instrumentable condition for coverage
/// and add it to the function's SourceRegions. A branch region tracks a
/// "True" counter and a "False" counter for boolean expressions that
/// result in the generation of a branch.
- void createBranchRegion(const Expr *C, Counter TrueCnt, Counter FalseCnt,
- MCDCConditionID ID = 0, MCDCConditionID TrueID = 0,
- MCDCConditionID FalseID = 0) {
+ void
+ createBranchRegion(const Expr *C, Counter TrueCnt, Counter FalseCnt,
+ const MCDCDecisionIDPair &IDPair = MCDCDecisionIDPair()) {
// Check for NULL conditions.
if (!C)
return;
@@ -1034,6 +1042,10 @@ struct CounterCoverageMappingBuilder
// function's SourceRegions) because it doesn't apply to any other source
// code other than the Condition.
if (CodeGenFunction::isInstrumentedCondition(C)) {
+ MCDCConditionID ID = MCDCBuilder.getCondID(C);
+ MCDCConditionID TrueID = IDPair.TrueID;
+ MCDCConditionID FalseID = IDPair.FalseID;
+
// If a condition can fold to true or false, the corresponding branch
// will be removed. Create a region with both counters hard-coded to
// zero. This allows us to visualize them in a special way.
@@ -1252,6 +1264,69 @@ struct CounterCoverageMappingBuilder
popRegions(Index);
}
+ /// Find a valid range starting with \p StartingLoc and ending before \p
+ /// BeforeLoc.
+ std::optional<SourceRange> findAreaStartingFromTo(SourceLocation StartingLoc,
+ SourceLocation BeforeLoc) {
+ // If StartingLoc is in function-like macro, use its start location.
+ if (StartingLoc.isMacroID()) {
+ FileID FID = SM.getFileID(StartingLoc);
+ const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+ if (EI->isFunctionMacroExpansion())
+ StartingLoc = EI->getExpansionLocStart();
+ }
+
+ size_t StartDepth = locationDepth(StartingLoc);
+ size_t EndDepth = locationDepth(BeforeLoc);
+ while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
+ bool UnnestStart = StartDepth >= EndDepth;
+ bool UnnestEnd = EndDepth >= StartDepth;
+ if (UnnestEnd) {
+ assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+ BeforeLoc));
+
+ BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+ assert(BeforeLoc.isValid());
+ EndDepth--;
+ }
+ if (UnnestStart) {
+ assert(SM.isWrittenInSameFile(StartingLoc,
+ getStartOfFileOrMacro(StartingLoc)));
+
+ StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
+ assert(StartingLoc.isValid());
+ StartDepth--;
+ }
+ }
+ // If the start and end locations of the gap are both within the same macro
+ // file, the range may not be in source order.
+ if (StartingLoc.isMacroID() || BeforeLoc.isMacroID())
+ return std::nullopt;
+ if (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc) ||
+ !SpellingRegion(SM, StartingLoc, BeforeLoc).isInSourceOrder())
+ return std::nullopt;
+ return {{StartingLoc, BeforeLoc}};
+ }
+
+ void markSkipped(SourceLocation StartLoc, SourceLocation BeforeLoc) {
+ const auto Skipped = findAreaStartingFromTo(StartLoc, BeforeLoc);
+
+ if (!Skipped)
+ return;
+
+ const auto NewStartLoc = Skipped->getBegin();
+ const auto EndLoc = Skipped->getEnd();
+
+ if (NewStartLoc == EndLoc)
+ return;
+ assert(SpellingRegion(SM, NewStartLoc, EndLoc).isInSourceOrder());
+ handleFileExit(NewStartLoc);
+ size_t Index = pushRegion({}, NewStartLoc, EndLoc);
+ getRegion().setSkipped(true);
+ handleFileExit(EndLoc);
+ popRegions(Index);
+ }
+
/// Keep counts of breaks and continues inside loops.
struct BreakContinue {
Counter BreakCount;
@@ -1701,43 +1776,119 @@ struct CounterCoverageMappingBuilder
Visit(S->getSubStmt());
}
+ void coverIfConsteval(const IfStmt *S) {
+ assert(S->isConsteval());
+
+ const auto *Then = S->getThen();
+ const auto *Else = S->getElse();
+
+ // It's better for llvm-cov to create a new region with same counter
+ // so line-coverage can be properly calculated for lines containing
+ // a skipped region (without it the line is marked uncovered)
+ const Counter ParentCount = getRegion().getCounter();
+
+ extendRegion(S);
+
+ if (S->isNegatedConsteval()) {
+ // ignore 'if consteval'
+ markSkipped(S->getIfLoc(), getStart(Then));
+ propagateCounts(ParentCount, Then);
+
+ if (Else) {
+ // ignore 'else <else>'
+ markSkipped(getEnd(Then), getEnd(Else));
+ }
+ } else {
+ assert(S->isNonNegatedConsteval());
+ // ignore 'if consteval <then> [else]'
+ markSkipped(S->getIfLoc(), Else ? getStart(Else) : getEnd(Then));
+
+ if (Else)
+ propagateCounts(ParentCount, Else);
+ }
+ }
+
+ void coverIfConstexpr(const IfStmt *S) {
+ assert(S->isConstexpr());
+
+ // evaluate constant condition...
+ const auto *E = cast<ConstantExpr>(S->getCond());
+ const bool isTrue = E->getResultAsAPSInt().getExtValue();
+
+ extendRegion(S);
+
+ // I'm using 'propagateCounts' later as new region is better and allows me
+ // to properly calculate line coverage in llvm-cov utility
+ const Counter ParentCount = getRegion().getCounter();
+
+ // ignore 'if constexpr ('
+ SourceLocation startOfSkipped = S->getIfLoc();
+
+ if (const auto *Init = S->getInit()) {
+ const auto start = getStart(Init);
+ const auto end = getEnd(Init);
+
+ // this check is to make sure typedef here which doesn't have valid source
+ // location won't crash it
+ if (start.isValid() && end.isValid()) {
+ markSkipped(startOfSkipped, start);
+ propagateCounts(ParentCount, Init);
+ startOfSkipped = getEnd(Init);
+ }
+ }
+
+ const auto *Then = S->getThen();
+ const auto *Else = S->getElse();
+
+ if (isTrue) {
+ // ignore '<condition>)'
+ markSkipped(startOfSkipped, getStart(Then));
+ propagateCounts(ParentCount, Then);
+
+ if (Else)
+ // ignore 'else <else>'
+ markSkipped(getEnd(Then), getEnd(Else));
+ } else {
+ // ignore '<condition>) <then> [else]'
+ markSkipped(startOfSkipped, Else ? getStart(Else) : getEnd(Then));
+
+ if (Else)
+ propagateCounts(ParentCount, Else);
+ }
+ }
+
void VisitIfStmt(const IfStmt *S) {
+ // "if constexpr" and "if consteval" are not normal conditional statements,
+ // their discarded statement should be skipped
+ if (S->isConsteval())
+ return coverIfConsteval(S);
+ else if (S->isConstexpr())
+ return coverIfConstexpr(S);
+
extendRegion(S);
if (S->getInit())
Visit(S->getInit());
// Extend into the condition before we propagate through it below - this is
// needed to handle macros that generate the "if" but not the condition.
- if (!S->isConsteval())
- extendRegion(S->getCond());
+ extendRegion(S->getCond());
Counter ParentCount = getRegion().getCounter();
+ Counter ThenCount = getRegionCounter(S);
- // If this is "if !consteval" the then-branch will never be taken, we don't
- // need to change counter
- Counter ThenCount =
- S->isNegatedConsteval() ? ParentCount : getRegionCounter(S);
-
- if (!S->isConsteval()) {
- // Emitting a counter for the condition makes it easier to interpret the
- // counter for the body when looking at the coverage.
- propagateCounts(ParentCount, S->getCond());
+ // Emitting a counter for the condition makes it easier to interpret the
+ // counter for the body when looking at the coverage.
+ propagateCounts(ParentCount, S->getCond());
- // The 'then' count applies to the area immediately after the condition.
- std::optional<SourceRange> Gap =
- findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
- if (Gap)
- fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
- }
+ // The 'then' count applies to the area immediately after the condition.
+ std::optional<SourceRange> Gap =
+ findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
+ if (Gap)
+ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
extendRegion(S->getThen());
Counter OutCount = propagateCounts(ThenCount, S->getThen());
-
- // If this is "if consteval" the else-branch will never be taken, we don't
- // need to change counter
- Counter ElseCount = S->isNonNegatedConsteval()
- ? ParentCount
- : subtractCounters(ParentCount, ThenCount);
+ Counter ElseCount = subtractCounters(ParentCount, ThenCount);
if (const Stmt *Else = S->getElse()) {
bool ThenHasTerminateStmt = HasTerminateStmt;
@@ -1760,11 +1911,9 @@ struct CounterCoverageMappingBuilder
GapRegionCounter = OutCount;
}
- if (!S->isConsteval()) {
- // Create Branch Region around condition.
- createBranchRegion(S->getCond(), ThenCount,
- subtractCounters(ParentCount, ThenCount));
- }
+ // Create Branch Region around condition.
+ createBranchRegion(S->getCond(), ThenCount,
+ subtractCounters(ParentCount, ThenCount));
}
void VisitCXXTryStmt(const CXXTryStmt *S) {
@@ -1822,20 +1971,28 @@ struct CounterCoverageMappingBuilder
}
void VisitBinLAnd(const BinaryOperator *E) {
- // Keep track of Binary Operator and assign MCDC condition IDs
+ bool IsRootNode = MCDCBuilder.isIdle();
+
+ // Keep track of Binary Operator and assign MCDC condition IDs.
MCDCBuilder.pushAndAssignIDs(E);
extendRegion(E->getLHS());
propagateCounts(getRegion().getCounter(), E->getLHS());
handleFileExit(getEnd(E->getLHS()));
+ // Track LHS True/False Decision.
+ const auto DecisionLHS = MCDCBuilder.pop();
+
// Counter tracks the right hand side of a logical and operator.
extendRegion(E->getRHS());
propagateCounts(getRegionCounter(E), E->getRHS());
- // Process Binary Operator and create MCDC Decision Region if top-level
+ // Track RHS True/False Decision.
+ const auto DecisionRHS = MCDCBuilder.back();
+
+ // Create MCDC Decision Region if at top-level (root).
unsigned NumConds = 0;
- if ((NumConds = MCDCBuilder.popAndReturnCondCount(E)))
+ if (IsRootNode && (NumConds = MCDCBuilder.getTotalConditionsAndReset(E)))
createDecisionRegion(E, getRegionBitmap(E), NumConds);
// Extract the RHS's Execution Counter.
@@ -1847,30 +2004,13 @@ struct CounterCoverageMappingBuilder
// Extract the Parent Region Counter.
Counter ParentCnt = getRegion().getCounter();
- // Extract the MCDC condition IDs (returns 0 if not needed).
- MCDCConditionID NextOrID = MCDCBuilder.getNextLOrCondID();
- MCDCConditionID NextAndID = MCDCBuilder.getNextLAndCondID();
- MCDCConditionID LHSid = MCDCBuilder.getCondID(E->getLHS());
- MCDCConditionID RHSid = MCDCBuilder.getCondID(E->getRHS());
-
// Create Branch Region around LHS condition.
- // MC/DC: For "LHS && RHS"
- // - If LHS is TRUE, execution goes to the RHS.
- // - If LHS is FALSE, execution goes to the LHS of the next logical-OR.
- // If that does not exist, execution exits (ID == 0).
createBranchRegion(E->getLHS(), RHSExecCnt,
- subtractCounters(ParentCnt, RHSExecCnt), LHSid, RHSid,
- NextOrID);
+ subtractCounters(ParentCnt, RHSExecCnt), DecisionLHS);
// Create Branch Region around RHS condition.
- // MC/DC: For "LHS && RHS"
- // - If RHS is TRUE, execution goes to LHS of the next logical-AND.
- // If that does not exist, execution exits (ID == 0).
- // - If RHS is FALSE, execution goes to the LHS of the next logical-OR.
- // If that does not exist, execution exits (ID == 0).
createBranchRegion(E->getRHS(), RHSTrueCnt,
- subtractCounters(RHSExecCnt, RHSTrueCnt), RHSid,
- NextAndID, NextOrID);
+ subtractCounters(RHSExecCnt, RHSTrueCnt), DecisionRHS);
}
// Determine whether the right side of OR operation need to be visited.
@@ -1884,20 +2024,28 @@ struct CounterCoverageMappingBuilder
}
void VisitBinLOr(const BinaryOperator *E) {
- // Keep track of Binary Operator and assign MCDC condition IDs
+ bool IsRootNode = MCDCBuilder.isIdle();
+
+ // Keep track of Binary Operator and assign MCDC condition IDs.
MCDCBuilder.pushAndAssignIDs(E);
extendRegion(E->getLHS());
Counter OutCount = propagateCounts(getRegion().getCounter(), E->getLHS());
handleFileExit(getEnd(E->getLHS()));
+ // Track LHS True/False Decision.
+ const auto DecisionLHS = MCDCBuilder.pop();
+
// Counter tracks the right hand side of a logical or operator.
extendRegion(E->getRHS());
propagateCounts(getRegionCounter(E), E->getRHS());
- // Process Binary Operator and create MCDC Decision Region if top-level
+ // Track RHS True/False Decision.
+ const auto DecisionRHS = MCDCBuilder.back();
+
+ // Create MCDC Decision Region if at top-level (root).
unsigned NumConds = 0;
- if ((NumConds = MCDCBuilder.popAndReturnCondCount(E)))
+ if (IsRootNode && (NumConds = MCDCBuilder.getTotalConditionsAndReset(E)))
createDecisionRegion(E, getRegionBitmap(E), NumConds);
// Extract the RHS's Execution Counter.
@@ -1913,28 +2061,13 @@ struct CounterCoverageMappingBuilder
// Extract the Parent Region Counter.
Counter ParentCnt = getRegion().getCounter();
- // Extract the MCDC condition IDs (returns 0 if not needed).
- MCDCConditionID NextOrID = MCDCBuilder.getNextLOrCondID();
- MCDCConditionID NextAndID = MCDCBuilder.getNextLAndCondID();
- MCDCConditionID LHSid = MCDCBuilder.getCondID(E->getLHS());
- MCDCConditionID RHSid = MCDCBuilder.getCondID(E->getRHS());
-
// Create Branch Region around LHS condition.
- // MC/DC: For "LHS || RHS"
- // - If LHS is TRUE, execution goes to the LHS of the next logical-AND.
- // If that does not exist, execution exits (ID == 0).
- // - If LHS is FALSE, execution goes to the RHS.
createBranchRegion(E->getLHS(), subtractCounters(ParentCnt, RHSExecCnt),
- RHSExecCnt, LHSid, NextAndID, RHSid);
+ RHSExecCnt, DecisionLHS);
// Create Branch Region around RHS condition.
- // MC/DC: For "LHS || RHS"
- // - If RHS is TRUE, execution goes to LHS of the next logical-AND.
- // If that does not exist, execution exits (ID == 0).
- // - If RHS is FALSE, execution goes to the LHS of the next logical-OR.
- // If that does not exist, execution exits (ID == 0).
createBranchRegion(E->getRHS(), subtractCounters(RHSExecCnt, RHSFalseCnt),
- RHSFalseCnt, RHSid, NextAndID, NextOrID);
+ RHSFalseCnt, DecisionRHS);
}
void VisitLambdaExpr(const LambdaExpr *LE) {
diff --git a/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.h b/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.h
index 0c0781a2d5ab..7682f197041c 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.h
+++ b/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.h
@@ -496,7 +496,8 @@ createPPC64_SVR4_TargetCodeGenInfo(CodeGenModule &CGM, PPC64_SVR4_ABIKind Kind,
bool SoftFloatABI);
std::unique_ptr<TargetCodeGenInfo>
-createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen, unsigned FLen);
+createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen, unsigned FLen,
+ bool EABI);
std::unique_ptr<TargetCodeGenInfo>
createCommonSPIRTargetCodeGenInfo(CodeGenModule &CGM);
diff --git a/contrib/llvm-project/clang/lib/CodeGen/Targets/RISCV.cpp b/contrib/llvm-project/clang/lib/CodeGen/Targets/RISCV.cpp
index 1e1d249b37ac..0851d1993d0c 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -25,8 +25,9 @@ private:
// ISA might have a wider FLen than the selected ABI (e.g. an RV32IF target
// with soft float ABI has FLen==0).
unsigned FLen;
- static const int NumArgGPRs = 8;
- static const int NumArgFPRs = 8;
+ const int NumArgGPRs;
+ const int NumArgFPRs;
+ const bool EABI;
bool detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
llvm::Type *&Field1Ty,
CharUnits &Field1Off,
@@ -34,8 +35,10 @@ private:
CharUnits &Field2Off) const;
public:
- RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen)
- : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen) {}
+ RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen,
+ bool EABI)
+ : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen), NumArgGPRs(EABI ? 6 : 8),
+ NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}
// DefaultABIInfo's classifyReturnType and classifyArgumentType are
// non-virtual, but computeInfo is virtual, so we overload it.
@@ -86,7 +89,7 @@ void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
}
int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
- int ArgFPRsLeft = FLen ? NumArgFPRs : 0;
+ int ArgFPRsLeft = NumArgFPRs;
int NumFixedArgs = FI.getNumRequiredArgs();
int ArgNum = 0;
@@ -396,9 +399,12 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
// Determine the number of GPRs needed to pass the current argument
// according to the ABI. 2*XLen-aligned varargs are passed in "aligned"
// register pairs, so may consume 3 registers.
+ // TODO: To be compatible with GCC's behaviors, we don't align registers
+ // currently if we are using ILP32E calling convention. This behavior may be
+ // changed when RV32E/ILP32E is ratified.
int NeededArgGPRs = 1;
if (!IsFixed && NeededAlign == 2 * XLen)
- NeededArgGPRs = 2 + (ArgGPRsLeft % 2);
+ NeededArgGPRs = 2 + (EABI && XLen == 32 ? 0 : (ArgGPRsLeft % 2));
else if (Size > XLen && Size <= 2 * XLen)
NeededArgGPRs = 2;
@@ -480,6 +486,13 @@ Address RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
auto TInfo = getContext().getTypeInfoInChars(Ty);
+ // TODO: To be compatible with GCC's behaviors, we force arguments with
+ // 2×XLEN-bit alignment and size at most 2×XLEN bits like `long long`,
+ // `unsigned long long` and `double` to have 4-byte alignment. This
+ // behavior may be changed when RV32E/ILP32E is ratified.
+ if (EABI && XLen == 32)
+ TInfo.Align = std::min(TInfo.Align, CharUnits::fromQuantity(4));
+
// Arguments bigger than 2*Xlen bytes are passed indirectly.
bool IsIndirect = TInfo.Width > 2 * SlotSize;
@@ -499,8 +512,9 @@ namespace {
class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
public:
RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen,
- unsigned FLen)
- : TargetCodeGenInfo(std::make_unique<RISCVABIInfo>(CGT, XLen, FLen)) {}
+ unsigned FLen, bool EABI)
+ : TargetCodeGenInfo(
+ std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override {
@@ -526,6 +540,7 @@ public:
std::unique_ptr<TargetCodeGenInfo>
CodeGen::createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen,
- unsigned FLen) {
- return std::make_unique<RISCVTargetCodeGenInfo>(CGM.getTypes(), XLen, FLen);
+ unsigned FLen, bool EABI) {
+ return std::make_unique<RISCVTargetCodeGenInfo>(CGM.getTypes(), XLen, FLen,
+ EABI);
}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/Targets/X86.cpp b/contrib/llvm-project/clang/lib/CodeGen/Targets/X86.cpp
index d053f41ab168..2291c991fb11 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/Targets/X86.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/Targets/X86.cpp
@@ -40,6 +40,11 @@ static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
return llvm::Type::getX86_MMXTy(CGF.getLLVMContext());
}
+ if (Constraint == "k") {
+ llvm::Type *Int1Ty = llvm::Type::getInt1Ty(CGF.getLLVMContext());
+ return llvm::FixedVectorType::get(Int1Ty, Ty->getScalarSizeInBits());
+ }
+
// No operation needed
return Ty;
}