20#include "llvm/Support/SaveAndRestore.h"
36 if (!
cgm.getCodeGenOpts().OptimizationLevel)
43 mlir::Value sizeValue = builder.getConstInt(loc, builder.getSInt64Ty(),
44 static_cast<int64_t
>(width));
49 cir::LLVMIntrinsicCallOp::create(
50 builder, loc, builder.getStringAttr(
"invariant.start"), addr.getType(),
51 mlir::ValueRange{sizeValue, addr});
62 if (region.empty() || region.hasOneBlock())
65 mlir::OpBuilder::InsertionGuard guard(builder);
66 mlir::Block *wrapper = builder.createBlock(®ion, region.begin());
67 builder.setInsertionPointToStart(wrapper);
68 auto scope = cir::ScopeOp::create(builder, loc,
69 [](mlir::OpBuilder &, mlir::Location) {});
73 mlir::Region &scopeRegion = scope.getRegion();
74 scopeRegion.getBlocks().clear();
75 scopeRegion.getBlocks().splice(scopeRegion.end(), region.getBlocks(),
76 std::next(region.begin()), region.end());
78 builder.setInsertionPointToEnd(wrapper);
79 cir::YieldOp::create(builder, loc);
83 cir::GlobalOp globalOp, mlir::Region &ctorRegion) {
84 assert((
varDecl->hasGlobalStorage() ||
87 "VarDecl must have global or local (in the case of OpenCL) storage!");
88 assert(!
varDecl->getType()->isReferenceType() &&
89 "Should not call emitDeclInit on a reference!");
94 mlir::OpBuilder::InsertionGuard guard(builder);
95 mlir::Block *block = builder.createBlock(&ctorRegion);
97 builder.getInsertionBlock()};
99 builder.setInsertionPointToStart(block);
126 builder.setInsertionPointToEnd(builder.getInsertionBlock());
127 cir::YieldOp::create(builder, globalOp.getLoc());
131 cir::GlobalOp addr, mlir::Region &dtorRegion) {
153 assert(!vd->
getTLSKind() &&
"should have rejected this");
161 mlir::OpBuilder::InsertionGuard guard(builder);
164 mlir::Block *block = dtorRegion.empty() ? builder.createBlock(&dtorRegion)
165 : &dtorRegion.front();
168 builder.setInsertionPointToStart(block);
178 bool canRegisterDestructor =
179 record && (!cgm.
getCXXABI().hasThisReturn(
187 if (record && (canRegisterDestructor || cgm.
getCodeGenOpts().CXAAtExit)) {
204 cir::PointerType realPtrTy = cir::PointerType::get(
206 mlir::cast<cir::PointerType>(thisAddr.getType()).getAddrSpace());
207 if (realPtrTy != thisAddr.getType())
208 thisAddr = builder.
createBitcast(thisAddr.getLoc(), thisAddr, realPtrTy);
211 mlir::ValueRange{thisAddr}, {},
213 fnOp.getCallingConv());
214 assert(fnOp &&
"expected cir.func");
228 globalVal.getDefiningOp<cir::GetGlobalOp>().setStaticLocal(
235 builder.setInsertionPointToEnd(block);
236 if (block->empty()) {
239 builder.clearInsertionPoint();
240 }
else if (!block->mightHaveTerminator()) {
242 cir::YieldOp::create(builder, addr.getLoc());
256 mlir::OpBuilder::InsertionGuard guard(builder);
261 setNonAliasAttributes(gd, fn);
277 return cir::TLSKind::None;
279 return cir::TLSKind::Static;
281 return cir::TLSKind::Dynamic;
283 llvm_unreachable(
"unknown TLSKind");
287static cir::TemplateSpecializationKind
291 return cir::TemplateSpecializationKind::Undeclared;
293 return cir::TemplateSpecializationKind::ImplicitInstantiation;
295 return cir::TemplateSpecializationKind::ExplicitSpecialization;
297 return cir::TemplateSpecializationKind::ExplicitInstantiationDeclaration;
299 return cir::TemplateSpecializationKind::ExplicitInstantiationDefinition;
301 llvm_unreachable(
"unknown clang::TemplateSpecializationKind");
308 mlir::Region &ctorRegion,
309 mlir::Region &dtorRegion) {
311 assert(curCGF &&
"Special var init only available inside of a function");
339 if (addr.getDynamicInitGuard().has_value())
340 addr.setDynamicInitInfoAttr(cir::DynamicInitInfoAttr::get(
344 varDecl->getTemplateSpecializationKind())));
351 bool isConstantStorage =
360 if (isConstantStorage) {
362 mlir::OpBuilder::InsertionGuard guard(builder);
364 if (!ctorRegion.empty()) {
365 mlir::Block *block = &ctorRegion.back();
367 mlir::Operation *yieldOp = block->getTerminator();
369 builder.setInsertionPoint(yieldOp);
374 }
else if (isConstantStorage) {
378 if (!isConstantStorage) {
385 mlir::OpBuilder::InsertionGuard guard(builder);
386 auto *block = builder.createBlock(&ctorRegion);
388 builder.getInsertionBlock()};
390 builder.setInsertionPointToStart(block);
391 mlir::Value getGlobal = builder.createGetGlobal(addr,
varDecl->getTLSKind());
395 getGlobal.getDefiningOp<cir::GetGlobalOp>().setStaticLocal(
396 addr.getDynamicInitGuard().has_value() &&
varDecl->isLocalVarDecl());
399 assert(performInit &&
"cannot have a constant initializer which needs "
400 "destruction for reference");
403 mlir::OpBuilder::InsertionGuard guard(builder);
404 mlir::Operation *rvalDefOp = rv.
getValue().getDefiningOp();
405 if (rvalDefOp && rvalDefOp->getBlock()) {
406 mlir::Block *rvalSrcBlock = rvalDefOp->getBlock();
409 mlir::Operation &front = rvalSrcBlock->front();
410 getGlobal.getDefiningOp()->moveBefore(&front);
418 builder.setInsertionPointToEnd(builder.getInsertionBlock());
419 cir::YieldOp::create(builder, addr->getLoc());
426 assert(!
varDecl->isStaticLocal());
432 curCGF->curFn = addr;
439 builder.setDefaultConstrainedRounding(rm);
440 builder.setDefaultConstrainedExcept(eb);
441 builder.setIsFPConstrained(
false);
443 rm != llvm::RoundingMode::NearestTiesToEven) {
444 builder.setIsFPConstrained(
true);
445 addr.setStrictfp(
true);
448 if (
const auto *ipa =
varDecl->getAttr<InitPriorityAttr>())
449 addr.setInitPriority(ipa->getPriority());
452 addr.getDtorRegion());
458 assert(
varDecl->isStaticLocal());
461 cir::LocalInitOp::create(builder, addr->getLoc(), addr.getSymNameAttr(),
465 initOp.getDtorRegion());
static void emitDeclInvariant(CIRGenFunction &cgf, const VarDecl *d)
Emit code to cause the variable at the given address to be considered as constant from this point onw...
static void wrapMultiBlockRegionInScope(CIRGenBuilderTy &builder, mlir::Region ®ion, mlir::Location loc)
The ctor and dtor regions of a global (or static local) hold a single block, but an initializer can h...
static cir::TemplateSpecializationKind getCIRTemplateSpecializationKind(clang::TemplateSpecializationKind kind)
static void emitDeclDestroy(CIRGenFunction &cgf, const VarDecl *vd, cir::GlobalOp addr, mlir::Region &dtorRegion)
static void emitDeclInit(CIRGenFunction &cgf, const VarDecl *varDecl, cir::GlobalOp globalOp, mlir::Region &ctorRegion)
static cir::TLSKind getCIRTLSKind(clang::VarDecl::TLSKind kind)
static constexpr bool needsDtor()
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={}, cir::CallingConv callingConv=cir::CallingConv::C)
cir::GetGlobalOp createGetGlobal(mlir::Location loc, cir::GlobalOp global, bool threadLocal=false)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
const LangOptions & getLangOpts() const
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
virtual void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor, mlir::Value addr)=0
Emit code to force the execution of a destructor during global teardown.
virtual bool canCallMismatchedFunctionType() const
Returns true if the target allows calling a function through a pointer with a different signature tha...
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
void emitInvariantStart(CharUnits size, mlir::Value addr, mlir::Location loc)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
void emitScalarInit(const clang::Expr *init, LValue lvalue, bool capturedByInit=false)
mlir::Type convertTypeForMem(QualType t)
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
CIRGenBuilderTy & getBuilder()
void emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
clang::ASTContext & getContext() const
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
This class organizes the cross-function state that is used while generating CIR code.
void emitCXXGlobalVarDeclInit(const VarDecl *varDecl, cir::GlobalOp addr, bool performInit)
Emit the function that initializes the specified global.
clang::ASTContext & getASTContext() const
cir::FuncOp getAddrOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
void emitCXXStaticLocalVarDeclInit(const VarDecl *varDecl, cir::GlobalOp addr, bool performInit)
Emit the function that initializes the specified static-local variable.
std::pair< cir::FuncType, cir::FuncOp > getAddrAndTypeOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
mlir::Value getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty={}, ForDefinition_t isForDefinition=NotForDefinition)
Return the mlir::Value for the address of the given global variable.
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
cir::FuncOp codegenCXXStructor(clang::GlobalDecl gd)
void setCIRFunctionAttributesForDefinition(const clang::Decl *decl, cir::FuncOp f)
Set extra attributes (inline, etc.) for a function.
mlir::MLIRContext & getMLIRContext()
CIRGenCXXABI & getCXXABI() const
void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f)
void emitCXXSpecialVarDeclInit(const VarDecl *varDecl, cir::GlobalOp addr, bool performInit, mlir::Region &ctorRegion, mlir::Region &dtorRegion)
Helper function for the below two that will create the constructor/destructor in specified regions,...
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
This trivial value class is used to represent the result of an expression that is evaluated.
mlir::Value getValue() const
Return the value of this scalar value.
Represents a C++ destructor within a class.
Represents a C++ struct/union/class.
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
This represents one expression.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
FPExceptionModeKind
Possible floating point exception behavior.
@ FPE_Ignore
Assume that floating-point exceptions are masked.
FPExceptionModeKind getDefaultExceptionMode() const
RoundingMode getDefaultRoundingMode() const
A (possibly-)qualified type.
@ DK_objc_strong_lifetime
bool isReferenceType() const
Represents a variable declaration or definition.
TLSKind getTLSKind() const
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
TLSKind
Kinds of thread-local storage.
@ TLS_Static
TLS with a known-constant initializer.
@ TLS_Dynamic
TLS with a dynamic initializer.
@ TLS_None
Not a TLS variable.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
@ Dtor_Complete
Complete object dtor.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
@ TSK_ExplicitSpecialization
This template specialization was declared or defined by an explicit specialization (C++ [temp....
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
@ TSK_Undeclared
This template specialization was formed from a template-id but has not yet been declared,...
U cast(CodeGen::Address addr)
static bool addressSpace()
static bool aggValueSlotGC()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...