15#include "mlir/IR/Location.h"
28 mlir::OpBuilder::InsertPoint ip) {
39 "emitAutoVarDecl: decl escaping by reference");
55 nullptr,
nullptr, ip);
58 emission.
Addr = address;
72 if (constructor->isTrivial() && constructor->isDefaultConstructor() &&
73 !construct->requiresZeroInitialization())
81 assert(emission.
Variable &&
"emission was not valid!");
97 if (!init &&
type.isNonTrivialToPrimitiveDefaultInitialize() ==
100 "emitAutoVarInit: non-trivial to default initialize");
115 : (d.
getAttr<UninitializedAttr>()
119 auto initializeWhatIsTechnicallyUninitialized = [&](
Address addr) {
120 if (trivialAutoVarInit ==
128 initializeWhatIsTechnicallyUninitialized(addr);
132 mlir::Attribute constant;
141 if (constant && !mlir::isa<cir::ZeroAttr>(constant) &&
142 (trivialAutoVarInit !=
153 if (!constant || isa<CXXTemporaryObjectExpr>(init)) {
154 initializeWhatIsTechnicallyUninitialized(addr);
162 assert(val &&
"Should have an address");
163 auto allocaOp = val.getDefiningOp<cir::AllocaOp>();
164 assert(allocaOp &&
"Address should come straight out of the alloca");
166 if (!allocaOp.use_empty())
174 auto typedConstant = mlir::dyn_cast<mlir::TypedAttr>(constant);
175 assert(typedConstant &&
"expected typed attribute");
179 assert(init &&
"expected initializer");
226 cir::GlobalLinkageKind linkage =
241 CIRGenFunction::VarDeclContext varDeclCtx{*
this, &d};
251 std::string contextName;
253 if (
auto *cd = dyn_cast<CapturedDecl>(dc))
254 dc = cast<DeclContext>(cd->getNonClosureContext());
255 if (
const auto *fd = dyn_cast<FunctionDecl>(dc))
257 else if (isa<BlockDecl>(dc))
259 else if (isa<ObjCMethodDecl>(dc))
272 cir::GlobalLinkageKind linkage) {
292 if (d.
hasAttr<LoaderUninitializedAttr>() || d.
hasAttr<CUDASharedAttr>())
294 "getOrCreateStaticVarDecl: LoaderUninitializedAttr");
303 gv.setInitialValueAttr(init);
304 gv.setAlignment(
getASTContext().getDeclAlign(&d).getAsAlign().value());
328 if (isa<BlockDecl>(dc) || isa<CapturedDecl>(dc)) {
336 if (isa<CXXConstructorDecl>(dc))
338 else if (isa<CXXDestructorDecl>(dc))
340 else if (
const auto *fd = dyn_cast<FunctionDecl>(dc))
345 assert(isa<ObjCMethodDecl>(dc) &&
"unexpected parent code decl");
359 const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr) {
361 mlir::TypedAttr init =
380 if (gv.getSymType() != init.getType()) {
381 gv.setSymType(init.getType());
389 gvAddr.getAddr().setType(builder.
getPointerTo(init.getType()));
396 gv.setInitialValueAttr(init);
411 cir::GlobalLinkageKind linkage) {
419 auto getAddrOp = addr.getDefiningOp<cir::GetGlobalOp>();
420 assert(getAddrOp &&
"expected cir::GetGlobalOp");
434 "emitStaticVarDecl: variably modified type");
438 mlir::Type expectedType = addr.getType();
440 cir::GlobalOp var = globalOp;
448 var.setAlignment(alignment.
getAsAlign().value());
464 mlir::Value castedAddr =
474 LValue lvalue,
bool capturedByInit) {
479 if (capturedByInit) {
488 LValue lvalue,
bool capturedByInit) {
490 if (capturedByInit) {
497 if (
type->isReferenceType()) {
512 "emitExprAsInit: complex type captured by init");
527 llvm_unreachable(
"bad evaluation kind");
532 case Decl::BuiltinTemplate:
533 case Decl::TranslationUnit:
534 case Decl::ExternCContext:
535 case Decl::Namespace:
536 case Decl::UnresolvedUsingTypename:
537 case Decl::ClassTemplateSpecialization:
538 case Decl::ClassTemplatePartialSpecialization:
539 case Decl::VarTemplateSpecialization:
540 case Decl::VarTemplatePartialSpecialization:
541 case Decl::TemplateTypeParm:
542 case Decl::UnresolvedUsingValue:
543 case Decl::NonTypeTemplateParm:
544 case Decl::CXXDeductionGuide:
545 case Decl::CXXMethod:
546 case Decl::CXXConstructor:
547 case Decl::CXXDestructor:
548 case Decl::CXXConversion:
550 case Decl::MSProperty:
551 case Decl::IndirectField:
553 case Decl::ObjCAtDefsField:
555 case Decl::ImplicitParam:
556 case Decl::ClassTemplate:
557 case Decl::VarTemplate:
558 case Decl::FunctionTemplate:
559 case Decl::TypeAliasTemplate:
560 case Decl::TemplateTemplateParm:
561 case Decl::ObjCMethod:
562 case Decl::ObjCCategory:
563 case Decl::ObjCProtocol:
564 case Decl::ObjCInterface:
565 case Decl::ObjCCategoryImpl:
566 case Decl::ObjCImplementation:
567 case Decl::ObjCProperty:
568 case Decl::ObjCCompatibleAlias:
569 case Decl::PragmaComment:
570 case Decl::PragmaDetectMismatch:
571 case Decl::AccessSpec:
572 case Decl::LinkageSpec:
574 case Decl::ObjCPropertyImpl:
575 case Decl::FileScopeAsm:
577 case Decl::FriendTemplate:
579 case Decl::OutlinedFunction:
581 case Decl::UsingShadow:
582 case Decl::ConstructorUsingShadow:
583 case Decl::ObjCTypeParam:
585 case Decl::UnresolvedUsingIfExists:
586 case Decl::HLSLBuffer:
587 case Decl::HLSLRootSignature:
588 llvm_unreachable(
"Declaration should not be in declstmts!");
591 case Decl::EnumConstant:
592 case Decl::StaticAssert:
596 case Decl::TemplateParamObject:
597 case Decl::OMPThreadPrivate:
598 case Decl::OMPAllocate:
599 case Decl::OMPCapturedExpr:
600 case Decl::OMPRequires:
603 case Decl::LifetimeExtendedTemporary:
604 case Decl::RequiresExprBody:
605 case Decl::UnnamedGlobalConstant:
611 case Decl::CXXRecord:
612 case Decl::NamespaceAlias:
614 case Decl::UsingEnum:
615 case Decl::UsingDirective:
619 case Decl::Decomposition: {
620 const VarDecl &vd = cast<VarDecl>(d);
622 "Should not see file-scope variables inside a function!");
624 if (evaluateConditionDecl)
628 case Decl::OpenACCDeclare:
631 case Decl::OpenACCRoutine:
635 case Decl::TypeAlias: {
636 QualType ty = cast<TypedefNameDecl>(d).getUnderlyingType();
642 case Decl::ImplicitConceptSpecialization:
643 case Decl::TopLevelStmt:
644 case Decl::UsingPack:
645 case Decl::OMPDeclareReduction:
646 case Decl::OMPDeclareMapper:
648 std::string(
"emitDecl: unhandled decl type: ") +
655 if (!
sanOpts.
has(SanitizerKind::NullabilityAssign))
665 : addr(addr),
type(
type), destroyer(destroyer) {}
676 size_t getSize()
const override {
678 return sizeof(DestroyObject);
685 pushFullExprCleanup<DestroyObject>(cleanupKind, addr,
type, destroyer);
698 Destroyer *destroyer) {
704 cir::PointerType ptrToElmType = builder.
getPointerTo(cirElementType);
707 cir::ArrayDtor::create(
708 builder, *
currSrcLoc, begin, [&](mlir::OpBuilder &
b, mlir::Location loc) {
709 auto arg =
b.getInsertionBlock()->addArgument(ptrToElmType, loc);
714 destroyer(*
this, curAddr, elementType);
716 cir::YieldOp::create(builder, loc);
728 Destroyer *destroyer) {
731 return destroyer(*
this, addr,
type);
738 auto constantCount =
length.getDefiningOp<cir::ConstantOp>();
739 if (!constantCount) {
741 cgm.
errorNYI(
"emitDestroy: variable length array");
745 auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());
747 if (constIntAttr && constIntAttr.getUInt() == 0)
755 if (constantCount.use_empty())
756 constantCount.erase();
763 llvm_unreachable(
"no destroyer for trivial dtor");
769 cgm.
errorNYI(
"getDestroyer: other destruction kind");
772 llvm_unreachable(
"Unknown DestructionKind");
793 llvm_unreachable(
"no cleanup for trivially-destructible variable");
799 cgm.
errorNYI(var->getSourceRange(),
"emitAutoVarTypeCleanup: NRVO");
809 "emitAutoVarTypeCleanup: other dtor kind");
818 ehStack.pushCleanup<DestroyObject>(cleanupKind, addr,
type, destroyer);
822 if (
auto *dd = dyn_cast_if_present<DecompositionDecl>(vd)) {
823 for (
auto *
b : dd->flat_bindings())
824 if (
auto *hd =
b->getHoldingVar())
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static std::string getStaticDeclName(CIRGenModule &cgm, const VarDecl &d)
This file defines OpenACC nodes for declarative directives.
Defines the clang::Expr interface and subclasses for C++ expressions.
mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::TypedAttr getZeroInitAttr(mlir::Type ty)
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.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
mlir::Value getPointer() const
clang::CharUnits getAlignment() const
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
cir::GlobalOp createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage)
Creates a versioned global variable.
void emitOpenACCRoutine(const OpenACCRoutineDecl &d)
cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr)
Add the initializer for 'd' to the global variable that has already been created for it.
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d, mlir::OpBuilder::InsertPoint ip={})
void emitAutoVarTypeCleanup(const AutoVarEmission &emission, clang::QualType::DestructionKind dtorKind)
Enter a destroy cleanup for the given local variable.
cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, bool insertIntoFnEntryBlock=false)
This creates an alloca and inserts it into the entry block if ArraySize is nullptr,...
void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
bool isTrivialInitializer(const Expr *init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void emitOpenACCDeclare(const OpenACCDeclareDecl &d)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitArrayDestroy(mlir::Value begin, mlir::Value end, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Destroys all the elements of the given array, beginning from last to first.
void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d, LValue lvalue, bool capturedByInit=false)
Emit an expression as an initializer for an object (variable, field, etc.) at the given location.
mlir::Value emitArrayLength(const clang::ArrayType *arrayType, QualType &baseType, Address &addr)
Computes the length of an array in elements, as well as the base element type and a properly-typed fi...
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Type convertTypeForMem(QualType t)
void emitVarDecl(const clang::VarDecl &d)
This method handles emission of any variable declaration inside a function, including static vars etc...
static Destroyer destroyCXXObject
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit)
void emitScalarInit(const clang::Expr *init, mlir::Location loc, LValue lvalue, bool capturedByInit=false)
mlir::Value emitScalarExpr(const clang::Expr *e)
Emit the computation of the specified expression of scalar type.
void emitAutoVarInit(const AutoVarEmission &emission)
Emit the initializer for an allocated variable.
void maybeEmitDeferredVarDeclInit(const VarDecl *vd)
void emitAutoVarDecl(const clang::VarDecl &d)
Emit code and set up symbol table for a variable declaration with auto, register, or no storage class...
void pushDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer)
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
void emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
mlir::MLIRContext & getMLIRContext()
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty)
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
clang::ASTContext & getContext() const
void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
Set the address of a local variable.
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
void emitAutoVarCleanups(const AutoVarEmission &emission)
This class organizes the cross-function state that is used while generating CIR code.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
mlir::Type convertType(clang::QualType type)
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const
Set visibility, dllimport/dllexport and dso_local.
static mlir::SymbolTable::Visibility getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK)
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
void setStaticLocalDeclAddress(const VarDecl *d, cir::GlobalOp c)
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::ModuleOp getModule() const
bool supportsCOMDAT() const
cir::GlobalOp getStaticLocalDeclAddress(const VarDecl *d)
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant)
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
void finalize(cir::GlobalOp gv)
mlir::Attribute tryEmitForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
Information for lazily generating a cleanup.
Address getAddress() const
This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(mlir::Value v)
Represents a call to a C++ constructor.
Represents a C++ constructor within a class.
CharUnits - This is an opaque type for sizes expressed in character units.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Decl - This represents one declaration (or definition), e.g.
Decl * getNonClosureContext()
Find the innermost non-closure ancestor of this declaration, walking up through blocks,...
SourceLocation getLocation() const
const char * getDeclKindName() const
DeclContext * getDeclContext()
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
bool isExternallyVisible() const
A (possibly-)qualified type.
@ DK_objc_strong_lifetime
@ PDIK_Struct
The type is a struct containing a field whose type is not PCK_Trivial.
LangAS getAddressSpace() const
Return the address space of this type.
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool mightBeUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value might be usable in a constant expression, according to the re...
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
bool isEscapingByref() const
Indicates the capture is a __block variable that is captured by a block that can potentially escape (...
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
Matches all kinds of arrays.
The JSON file list parser is used to communicate input to InstallAPI.
@ SD_Automatic
Automatic storage duration (most local variables).
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
static bool opGlobalConstant()
static bool objCLifetime()
static bool addressSpace()
static bool emitNullabilityCheck()
static bool ehCleanupFlags()
static bool ehCleanupScope()
static bool opGlobalThreadLocal()
static bool aggValueSlotMayOverlap()
static bool dtorCleanups()
static bool dataLayoutTypeAllocSize()
static bool opAllocaCaptureByInit()
static bool opAllocaPreciseLifetime()
static bool cudaSupport()
static bool generateDebugInfo()
bool wasEmittedAsGlobal() const
const clang::VarDecl * Variable
bool IsEscapingByRef
True if the variable is a __block variable that is captured by an escaping block.
bool wasEmittedAsOffloadClause() const
Address getObjectAddress(CIRGenFunction &cgf) const
Returns the address of the object within this declaration.
Address Addr
The address of the alloca for languages with explicit address space (e.g.
bool IsConstantAggregate
True if the variable is of aggregate type and has a constant initializer.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.