Thanks to visit codestin.com
Credit goes to clang.llvm.org

clang 22.0.0git
CIRGenCXX.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code dealing with C++ code generation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenFunction.h"
14#include "CIRGenModule.h"
15
18#include "llvm/Support/SaveAndRestore.h"
19
20using namespace clang;
21using namespace clang::CIRGen;
22
23static void emitDeclInit(CIRGenFunction &cgf, const VarDecl *varDecl,
24 cir::GlobalOp globalOp) {
25 assert((varDecl->hasGlobalStorage() ||
26 (varDecl->hasLocalStorage() &&
27 cgf.getContext().getLangOpts().OpenCLCPlusPlus)) &&
28 "VarDecl must have global or local (in the case of OpenCL) storage!");
29 assert(!varDecl->getType()->isReferenceType() &&
30 "Should not call emitDeclInit on a reference!");
31
32 CIRGenBuilderTy &builder = cgf.getBuilder();
33
34 // Set up the ctor region.
35 mlir::OpBuilder::InsertionGuard guard(builder);
36 mlir::Block *block = builder.createBlock(&globalOp.getCtorRegion());
37 CIRGenFunction::LexicalScope lexScope{cgf, globalOp.getLoc(),
38 builder.getInsertionBlock()};
39 lexScope.setAsGlobalInit();
40 builder.setInsertionPointToStart(block);
41
44
45 QualType type = varDecl->getType();
46 LValue lv = cgf.makeAddrLValue(declAddr, type);
47
48 const Expr *init = varDecl->getInit();
50 case cir::TEK_Scalar:
52 cgf.emitScalarInit(init, cgf.getLoc(varDecl->getLocation()), lv, false);
53 break;
55 cgf.cgm.errorNYI(varDecl->getSourceRange(), "complex global initializer");
56 break;
59 cgf.emitAggExpr(init,
63 break;
64 }
65
66 // Finish the ctor region.
67 builder.setInsertionPointToEnd(block);
68 cir::YieldOp::create(builder, globalOp.getLoc());
69}
70
71static void emitDeclDestroy(CIRGenFunction &cgf, const VarDecl *vd,
72 cir::GlobalOp addr) {
73 // Honor __attribute__((no_destroy)) and bail instead of attempting
74 // to emit a reference to a possibly nonexistent destructor, which
75 // in turn can cause a crash. This will result in a global constructor
76 // that isn't balanced out by a destructor call as intended by the
77 // attribute. This also checks for -fno-c++-static-destructors and
78 // bails even if the attribute is not present.
80
81 // FIXME: __attribute__((cleanup)) ?
82
83 switch (dtorKind) {
85 return;
86
88 break;
89
93 // We don't care about releasing objects during process teardown.
94 assert(!vd->getTLSKind() && "should have rejected this");
95 return;
96 }
97
98 cgf.cgm.errorNYI(vd->getSourceRange(), "global with destructor");
99}
100
102 const CIRGenFunctionInfo &fnInfo =
104 cir::FuncType funcType = getTypes().getFunctionType(fnInfo);
105 cir::FuncOp fn = getAddrOfCXXStructor(gd, &fnInfo, /*FnType=*/nullptr,
106 /*DontDefer=*/true, ForDefinition);
107 setFunctionLinkage(gd, fn);
108 CIRGenFunction cgf{*this, builder};
109 curCGF = &cgf;
110 {
111 mlir::OpBuilder::InsertionGuard guard(builder);
112 cgf.generateCode(gd, fn, funcType);
113 }
114 curCGF = nullptr;
115
116 setNonAliasAttributes(gd, fn);
118 return fn;
119}
120
121// Global variables requiring non-trivial initialization are handled
122// differently in CIR than in classic codegen. Classic codegen emits
123// a global init function (__cxx_global_var_init) and inserts
124// initialization for each global there. In CIR, we attach a ctor
125// region to the global variable and insert the initialization code
126// into the ctor region. This will be moved into the
127// __cxx_global_var_init function during the LoweringPrepare pass.
129 cir::GlobalOp addr,
130 bool performInit) {
131 QualType ty = varDecl->getType();
132
133 // TODO: handle address space
134 // The address space of a static local variable (addr) may be different
135 // from the address space of the "this" argument of the constructor. In that
136 // case, we need an addrspacecast before calling the constructor.
137 //
138 // struct StructWithCtor {
139 // __device__ StructWithCtor() {...}
140 // };
141 // __device__ void foo() {
142 // __shared__ StructWithCtor s;
143 // ...
144 // }
145 //
146 // For example, in the above CUDA code, the static local variable s has a
147 // "shared" address space qualifier, but the constructor of StructWithCtor
148 // expects "this" in the "generic" address space.
150
151 // Create a CIRGenFunction to emit the initializer. While this isn't a true
152 // function, the handling works the same way.
153 CIRGenFunction cgf{*this, builder, true};
154 llvm::SaveAndRestore<CIRGenFunction *> savedCGF(curCGF, &cgf);
155 curCGF->curFn = addr;
156
158 getLoc(varDecl->getLocation())};
159
161
162 if (!ty->isReferenceType()) {
164
165 bool needsDtor = varDecl->needsDestruction(getASTContext()) ==
167 // PerformInit, constant store invariant / destroy handled below.
168 if (performInit)
169 emitDeclInit(cgf, varDecl, addr);
170
171 if (varDecl->getType().isConstantStorage(getASTContext(), true, !needsDtor))
172 errorNYI(varDecl->getSourceRange(), "global with constant storage");
173 else
174 emitDeclDestroy(cgf, varDecl, addr);
175 return;
176 }
177
178 errorNYI(varDecl->getSourceRange(), "global with reference type");
179}
static void emitDeclDestroy(CIRGenFunction &cgf, const VarDecl *vd, cir::GlobalOp addr)
Definition CIRGenCXX.cpp:71
static void emitDeclInit(CIRGenFunction &cgf, const VarDecl *varDecl, cir::GlobalOp globalOp)
Definition CIRGenCXX.cpp:23
const LangOptions & getLangOpts() const
Definition ASTContext.h:926
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
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)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitScalarInit(const clang::Expr *init, mlir::Location loc, LValue lvalue, bool capturedByInit=false)
CIRGenBuilderTy & getBuilder()
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
clang::ASTContext & getContext() const
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
void emitCXXGlobalVarDeclInit(const VarDecl *varDecl, cir::GlobalOp addr, bool performInit)
Emit the function that initializes the specified global.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
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)
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.
cir::FuncOp codegenCXXStructor(clang::GlobalDecl gd)
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f)
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
This represents one expression.
Definition Expr.h:112
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isReferenceType() const
Definition TypeBase.h:8548
Represents a variable declaration or definition.
Definition Decl.h:925
TLSKind getTLSKind() const
Definition Decl.cpp:2168
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2190
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2851
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
static bool addressSpace()
static bool aggValueSlotGC()
static bool opFuncAttributesForDefinition()
static bool astVarDeclInterface()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...