1*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // Internal per-function state used for AST-to-ClangIR code gen
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric
13*700637cbSDimitry Andric #include "CIRGenFunction.h"
14*700637cbSDimitry Andric
15*700637cbSDimitry Andric #include "CIRGenCXXABI.h"
16*700637cbSDimitry Andric #include "CIRGenCall.h"
17*700637cbSDimitry Andric #include "CIRGenValue.h"
18*700637cbSDimitry Andric #include "mlir/IR/Location.h"
19*700637cbSDimitry Andric #include "clang/AST/ExprCXX.h"
20*700637cbSDimitry Andric #include "clang/AST/GlobalDecl.h"
21*700637cbSDimitry Andric #include "clang/CIR/MissingFeatures.h"
22*700637cbSDimitry Andric
23*700637cbSDimitry Andric #include <cassert>
24*700637cbSDimitry Andric
25*700637cbSDimitry Andric namespace clang::CIRGen {
26*700637cbSDimitry Andric
CIRGenFunction(CIRGenModule & cgm,CIRGenBuilderTy & builder,bool suppressNewContext)27*700637cbSDimitry Andric CIRGenFunction::CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder,
28*700637cbSDimitry Andric bool suppressNewContext)
29*700637cbSDimitry Andric : CIRGenTypeCache(cgm), cgm{cgm}, builder(builder) {}
30*700637cbSDimitry Andric
~CIRGenFunction()31*700637cbSDimitry Andric CIRGenFunction::~CIRGenFunction() {}
32*700637cbSDimitry Andric
33*700637cbSDimitry Andric // This is copied from clang/lib/CodeGen/CodeGenFunction.cpp
getEvaluationKind(QualType type)34*700637cbSDimitry Andric cir::TypeEvaluationKind CIRGenFunction::getEvaluationKind(QualType type) {
35*700637cbSDimitry Andric type = type.getCanonicalType();
36*700637cbSDimitry Andric while (true) {
37*700637cbSDimitry Andric switch (type->getTypeClass()) {
38*700637cbSDimitry Andric #define TYPE(name, parent)
39*700637cbSDimitry Andric #define ABSTRACT_TYPE(name, parent)
40*700637cbSDimitry Andric #define NON_CANONICAL_TYPE(name, parent) case Type::name:
41*700637cbSDimitry Andric #define DEPENDENT_TYPE(name, parent) case Type::name:
42*700637cbSDimitry Andric #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(name, parent) case Type::name:
43*700637cbSDimitry Andric #include "clang/AST/TypeNodes.inc"
44*700637cbSDimitry Andric llvm_unreachable("non-canonical or dependent type in IR-generation");
45*700637cbSDimitry Andric
46*700637cbSDimitry Andric case Type::Auto:
47*700637cbSDimitry Andric case Type::DeducedTemplateSpecialization:
48*700637cbSDimitry Andric llvm_unreachable("undeduced type in IR-generation");
49*700637cbSDimitry Andric
50*700637cbSDimitry Andric // Various scalar types.
51*700637cbSDimitry Andric case Type::Builtin:
52*700637cbSDimitry Andric case Type::Pointer:
53*700637cbSDimitry Andric case Type::BlockPointer:
54*700637cbSDimitry Andric case Type::LValueReference:
55*700637cbSDimitry Andric case Type::RValueReference:
56*700637cbSDimitry Andric case Type::MemberPointer:
57*700637cbSDimitry Andric case Type::Vector:
58*700637cbSDimitry Andric case Type::ExtVector:
59*700637cbSDimitry Andric case Type::ConstantMatrix:
60*700637cbSDimitry Andric case Type::FunctionProto:
61*700637cbSDimitry Andric case Type::FunctionNoProto:
62*700637cbSDimitry Andric case Type::Enum:
63*700637cbSDimitry Andric case Type::ObjCObjectPointer:
64*700637cbSDimitry Andric case Type::Pipe:
65*700637cbSDimitry Andric case Type::BitInt:
66*700637cbSDimitry Andric case Type::HLSLAttributedResource:
67*700637cbSDimitry Andric case Type::HLSLInlineSpirv:
68*700637cbSDimitry Andric return cir::TEK_Scalar;
69*700637cbSDimitry Andric
70*700637cbSDimitry Andric // Complexes.
71*700637cbSDimitry Andric case Type::Complex:
72*700637cbSDimitry Andric return cir::TEK_Complex;
73*700637cbSDimitry Andric
74*700637cbSDimitry Andric // Arrays, records, and Objective-C objects.
75*700637cbSDimitry Andric case Type::ConstantArray:
76*700637cbSDimitry Andric case Type::IncompleteArray:
77*700637cbSDimitry Andric case Type::VariableArray:
78*700637cbSDimitry Andric case Type::Record:
79*700637cbSDimitry Andric case Type::ObjCObject:
80*700637cbSDimitry Andric case Type::ObjCInterface:
81*700637cbSDimitry Andric case Type::ArrayParameter:
82*700637cbSDimitry Andric return cir::TEK_Aggregate;
83*700637cbSDimitry Andric
84*700637cbSDimitry Andric // We operate on atomic values according to their underlying type.
85*700637cbSDimitry Andric case Type::Atomic:
86*700637cbSDimitry Andric type = cast<AtomicType>(type)->getValueType();
87*700637cbSDimitry Andric continue;
88*700637cbSDimitry Andric }
89*700637cbSDimitry Andric llvm_unreachable("unknown type kind!");
90*700637cbSDimitry Andric }
91*700637cbSDimitry Andric }
92*700637cbSDimitry Andric
convertTypeForMem(QualType t)93*700637cbSDimitry Andric mlir::Type CIRGenFunction::convertTypeForMem(QualType t) {
94*700637cbSDimitry Andric return cgm.getTypes().convertTypeForMem(t);
95*700637cbSDimitry Andric }
96*700637cbSDimitry Andric
convertType(QualType t)97*700637cbSDimitry Andric mlir::Type CIRGenFunction::convertType(QualType t) {
98*700637cbSDimitry Andric return cgm.getTypes().convertType(t);
99*700637cbSDimitry Andric }
100*700637cbSDimitry Andric
getLoc(SourceLocation srcLoc)101*700637cbSDimitry Andric mlir::Location CIRGenFunction::getLoc(SourceLocation srcLoc) {
102*700637cbSDimitry Andric // Some AST nodes might contain invalid source locations (e.g.
103*700637cbSDimitry Andric // CXXDefaultArgExpr), workaround that to still get something out.
104*700637cbSDimitry Andric if (srcLoc.isValid()) {
105*700637cbSDimitry Andric const SourceManager &sm = getContext().getSourceManager();
106*700637cbSDimitry Andric PresumedLoc pLoc = sm.getPresumedLoc(srcLoc);
107*700637cbSDimitry Andric StringRef filename = pLoc.getFilename();
108*700637cbSDimitry Andric return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
109*700637cbSDimitry Andric pLoc.getLine(), pLoc.getColumn());
110*700637cbSDimitry Andric }
111*700637cbSDimitry Andric // Do our best...
112*700637cbSDimitry Andric assert(currSrcLoc && "expected to inherit some source location");
113*700637cbSDimitry Andric return *currSrcLoc;
114*700637cbSDimitry Andric }
115*700637cbSDimitry Andric
getLoc(SourceRange srcLoc)116*700637cbSDimitry Andric mlir::Location CIRGenFunction::getLoc(SourceRange srcLoc) {
117*700637cbSDimitry Andric // Some AST nodes might contain invalid source locations (e.g.
118*700637cbSDimitry Andric // CXXDefaultArgExpr), workaround that to still get something out.
119*700637cbSDimitry Andric if (srcLoc.isValid()) {
120*700637cbSDimitry Andric mlir::Location beg = getLoc(srcLoc.getBegin());
121*700637cbSDimitry Andric mlir::Location end = getLoc(srcLoc.getEnd());
122*700637cbSDimitry Andric SmallVector<mlir::Location, 2> locs = {beg, end};
123*700637cbSDimitry Andric mlir::Attribute metadata;
124*700637cbSDimitry Andric return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());
125*700637cbSDimitry Andric }
126*700637cbSDimitry Andric if (currSrcLoc) {
127*700637cbSDimitry Andric return *currSrcLoc;
128*700637cbSDimitry Andric }
129*700637cbSDimitry Andric // We're brave, but time to give up.
130*700637cbSDimitry Andric return builder.getUnknownLoc();
131*700637cbSDimitry Andric }
132*700637cbSDimitry Andric
getLoc(mlir::Location lhs,mlir::Location rhs)133*700637cbSDimitry Andric mlir::Location CIRGenFunction::getLoc(mlir::Location lhs, mlir::Location rhs) {
134*700637cbSDimitry Andric SmallVector<mlir::Location, 2> locs = {lhs, rhs};
135*700637cbSDimitry Andric mlir::Attribute metadata;
136*700637cbSDimitry Andric return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());
137*700637cbSDimitry Andric }
138*700637cbSDimitry Andric
containsLabel(const Stmt * s,bool ignoreCaseStmts)139*700637cbSDimitry Andric bool CIRGenFunction::containsLabel(const Stmt *s, bool ignoreCaseStmts) {
140*700637cbSDimitry Andric // Null statement, not a label!
141*700637cbSDimitry Andric if (!s)
142*700637cbSDimitry Andric return false;
143*700637cbSDimitry Andric
144*700637cbSDimitry Andric // If this is a label, we have to emit the code, consider something like:
145*700637cbSDimitry Andric // if (0) { ... foo: bar(); } goto foo;
146*700637cbSDimitry Andric //
147*700637cbSDimitry Andric // TODO: If anyone cared, we could track __label__'s, since we know that you
148*700637cbSDimitry Andric // can't jump to one from outside their declared region.
149*700637cbSDimitry Andric if (isa<LabelStmt>(s))
150*700637cbSDimitry Andric return true;
151*700637cbSDimitry Andric
152*700637cbSDimitry Andric // If this is a case/default statement, and we haven't seen a switch, we
153*700637cbSDimitry Andric // have to emit the code.
154*700637cbSDimitry Andric if (isa<SwitchCase>(s) && !ignoreCaseStmts)
155*700637cbSDimitry Andric return true;
156*700637cbSDimitry Andric
157*700637cbSDimitry Andric // If this is a switch statement, we want to ignore case statements when we
158*700637cbSDimitry Andric // recursively process the sub-statements of the switch. If we haven't
159*700637cbSDimitry Andric // encountered a switch statement, we treat case statements like labels, but
160*700637cbSDimitry Andric // if we are processing a switch statement, case statements are expected.
161*700637cbSDimitry Andric if (isa<SwitchStmt>(s))
162*700637cbSDimitry Andric ignoreCaseStmts = true;
163*700637cbSDimitry Andric
164*700637cbSDimitry Andric // Scan subexpressions for verboten labels.
165*700637cbSDimitry Andric return std::any_of(s->child_begin(), s->child_end(),
166*700637cbSDimitry Andric [=](const Stmt *subStmt) {
167*700637cbSDimitry Andric return containsLabel(subStmt, ignoreCaseStmts);
168*700637cbSDimitry Andric });
169*700637cbSDimitry Andric }
170*700637cbSDimitry Andric
171*700637cbSDimitry Andric /// If the specified expression does not fold to a constant, or if it does but
172*700637cbSDimitry Andric /// contains a label, return false. If it constant folds return true and set
173*700637cbSDimitry Andric /// the boolean result in Result.
constantFoldsToBool(const Expr * cond,bool & resultBool,bool allowLabels)174*700637cbSDimitry Andric bool CIRGenFunction::constantFoldsToBool(const Expr *cond, bool &resultBool,
175*700637cbSDimitry Andric bool allowLabels) {
176*700637cbSDimitry Andric llvm::APSInt resultInt;
177*700637cbSDimitry Andric if (!constantFoldsToSimpleInteger(cond, resultInt, allowLabels))
178*700637cbSDimitry Andric return false;
179*700637cbSDimitry Andric
180*700637cbSDimitry Andric resultBool = resultInt.getBoolValue();
181*700637cbSDimitry Andric return true;
182*700637cbSDimitry Andric }
183*700637cbSDimitry Andric
184*700637cbSDimitry Andric /// If the specified expression does not fold to a constant, or if it does
185*700637cbSDimitry Andric /// fold but contains a label, return false. If it constant folds, return
186*700637cbSDimitry Andric /// true and set the folded value.
constantFoldsToSimpleInteger(const Expr * cond,llvm::APSInt & resultInt,bool allowLabels)187*700637cbSDimitry Andric bool CIRGenFunction::constantFoldsToSimpleInteger(const Expr *cond,
188*700637cbSDimitry Andric llvm::APSInt &resultInt,
189*700637cbSDimitry Andric bool allowLabels) {
190*700637cbSDimitry Andric // FIXME: Rename and handle conversion of other evaluatable things
191*700637cbSDimitry Andric // to bool.
192*700637cbSDimitry Andric Expr::EvalResult result;
193*700637cbSDimitry Andric if (!cond->EvaluateAsInt(result, getContext()))
194*700637cbSDimitry Andric return false; // Not foldable, not integer or not fully evaluatable.
195*700637cbSDimitry Andric
196*700637cbSDimitry Andric llvm::APSInt intValue = result.Val.getInt();
197*700637cbSDimitry Andric if (!allowLabels && containsLabel(cond))
198*700637cbSDimitry Andric return false; // Contains a label.
199*700637cbSDimitry Andric
200*700637cbSDimitry Andric resultInt = intValue;
201*700637cbSDimitry Andric return true;
202*700637cbSDimitry Andric }
203*700637cbSDimitry Andric
emitAndUpdateRetAlloca(QualType type,mlir::Location loc,CharUnits alignment)204*700637cbSDimitry Andric void CIRGenFunction::emitAndUpdateRetAlloca(QualType type, mlir::Location loc,
205*700637cbSDimitry Andric CharUnits alignment) {
206*700637cbSDimitry Andric if (!type->isVoidType()) {
207*700637cbSDimitry Andric fnRetAlloca = emitAlloca("__retval", convertType(type), loc, alignment,
208*700637cbSDimitry Andric /*insertIntoFnEntryBlock=*/false);
209*700637cbSDimitry Andric }
210*700637cbSDimitry Andric }
211*700637cbSDimitry Andric
declare(mlir::Value addrVal,const Decl * var,QualType ty,mlir::Location loc,CharUnits alignment,bool isParam)212*700637cbSDimitry Andric void CIRGenFunction::declare(mlir::Value addrVal, const Decl *var, QualType ty,
213*700637cbSDimitry Andric mlir::Location loc, CharUnits alignment,
214*700637cbSDimitry Andric bool isParam) {
215*700637cbSDimitry Andric const auto *namedVar = dyn_cast_or_null<NamedDecl>(var);
216*700637cbSDimitry Andric assert(namedVar && "Needs a named decl");
217*700637cbSDimitry Andric assert(!cir::MissingFeatures::cgfSymbolTable());
218*700637cbSDimitry Andric
219*700637cbSDimitry Andric auto allocaOp = cast<cir::AllocaOp>(addrVal.getDefiningOp());
220*700637cbSDimitry Andric if (isParam)
221*700637cbSDimitry Andric allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
222*700637cbSDimitry Andric if (ty->isReferenceType() || ty.isConstQualified())
223*700637cbSDimitry Andric allocaOp.setConstantAttr(mlir::UnitAttr::get(&getMLIRContext()));
224*700637cbSDimitry Andric }
225*700637cbSDimitry Andric
cleanup()226*700637cbSDimitry Andric void CIRGenFunction::LexicalScope::cleanup() {
227*700637cbSDimitry Andric CIRGenBuilderTy &builder = cgf.builder;
228*700637cbSDimitry Andric LexicalScope *localScope = cgf.curLexScope;
229*700637cbSDimitry Andric
230*700637cbSDimitry Andric if (returnBlock != nullptr) {
231*700637cbSDimitry Andric // Write out the return block, which loads the value from `__retval` and
232*700637cbSDimitry Andric // issues the `cir.return`.
233*700637cbSDimitry Andric mlir::OpBuilder::InsertionGuard guard(builder);
234*700637cbSDimitry Andric builder.setInsertionPointToEnd(returnBlock);
235*700637cbSDimitry Andric (void)emitReturn(*returnLoc);
236*700637cbSDimitry Andric }
237*700637cbSDimitry Andric
238*700637cbSDimitry Andric mlir::Block *curBlock = builder.getBlock();
239*700637cbSDimitry Andric if (isGlobalInit() && !curBlock)
240*700637cbSDimitry Andric return;
241*700637cbSDimitry Andric if (curBlock->mightHaveTerminator() && curBlock->getTerminator())
242*700637cbSDimitry Andric return;
243*700637cbSDimitry Andric
244*700637cbSDimitry Andric // Get rid of any empty block at the end of the scope.
245*700637cbSDimitry Andric bool entryBlock = builder.getInsertionBlock()->isEntryBlock();
246*700637cbSDimitry Andric if (!entryBlock && curBlock->empty()) {
247*700637cbSDimitry Andric curBlock->erase();
248*700637cbSDimitry Andric if (returnBlock != nullptr && returnBlock->getUses().empty())
249*700637cbSDimitry Andric returnBlock->erase();
250*700637cbSDimitry Andric return;
251*700637cbSDimitry Andric }
252*700637cbSDimitry Andric
253*700637cbSDimitry Andric // Reached the end of the scope.
254*700637cbSDimitry Andric {
255*700637cbSDimitry Andric mlir::OpBuilder::InsertionGuard guard(builder);
256*700637cbSDimitry Andric builder.setInsertionPointToEnd(curBlock);
257*700637cbSDimitry Andric
258*700637cbSDimitry Andric if (localScope->depth == 0) {
259*700637cbSDimitry Andric // Reached the end of the function.
260*700637cbSDimitry Andric if (returnBlock != nullptr) {
261*700637cbSDimitry Andric if (returnBlock->getUses().empty())
262*700637cbSDimitry Andric returnBlock->erase();
263*700637cbSDimitry Andric else {
264*700637cbSDimitry Andric builder.create<cir::BrOp>(*returnLoc, returnBlock);
265*700637cbSDimitry Andric return;
266*700637cbSDimitry Andric }
267*700637cbSDimitry Andric }
268*700637cbSDimitry Andric emitImplicitReturn();
269*700637cbSDimitry Andric return;
270*700637cbSDimitry Andric }
271*700637cbSDimitry Andric // Reached the end of a non-function scope. Some scopes, such as those
272*700637cbSDimitry Andric // used with the ?: operator, can return a value.
273*700637cbSDimitry Andric if (!localScope->isTernary() && !curBlock->mightHaveTerminator()) {
274*700637cbSDimitry Andric !retVal ? builder.create<cir::YieldOp>(localScope->endLoc)
275*700637cbSDimitry Andric : builder.create<cir::YieldOp>(localScope->endLoc, retVal);
276*700637cbSDimitry Andric }
277*700637cbSDimitry Andric }
278*700637cbSDimitry Andric }
279*700637cbSDimitry Andric
emitReturn(mlir::Location loc)280*700637cbSDimitry Andric cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
281*700637cbSDimitry Andric CIRGenBuilderTy &builder = cgf.getBuilder();
282*700637cbSDimitry Andric
283*700637cbSDimitry Andric if (!cgf.curFn.getFunctionType().hasVoidReturn()) {
284*700637cbSDimitry Andric // Load the value from `__retval` and return it via the `cir.return` op.
285*700637cbSDimitry Andric auto value = builder.create<cir::LoadOp>(
286*700637cbSDimitry Andric loc, cgf.curFn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);
287*700637cbSDimitry Andric return builder.create<cir::ReturnOp>(loc,
288*700637cbSDimitry Andric llvm::ArrayRef(value.getResult()));
289*700637cbSDimitry Andric }
290*700637cbSDimitry Andric return builder.create<cir::ReturnOp>(loc);
291*700637cbSDimitry Andric }
292*700637cbSDimitry Andric
293*700637cbSDimitry Andric // This is copied from CodeGenModule::MayDropFunctionReturn. This is a
294*700637cbSDimitry Andric // candidate for sharing between CIRGen and CodeGen.
mayDropFunctionReturn(const ASTContext & astContext,QualType returnType)295*700637cbSDimitry Andric static bool mayDropFunctionReturn(const ASTContext &astContext,
296*700637cbSDimitry Andric QualType returnType) {
297*700637cbSDimitry Andric // We can't just discard the return value for a record type with a complex
298*700637cbSDimitry Andric // destructor or a non-trivially copyable type.
299*700637cbSDimitry Andric if (const RecordType *recordType =
300*700637cbSDimitry Andric returnType.getCanonicalType()->getAs<RecordType>()) {
301*700637cbSDimitry Andric if (const auto *classDecl = dyn_cast<CXXRecordDecl>(recordType->getDecl()))
302*700637cbSDimitry Andric return classDecl->hasTrivialDestructor();
303*700637cbSDimitry Andric }
304*700637cbSDimitry Andric return returnType.isTriviallyCopyableType(astContext);
305*700637cbSDimitry Andric }
306*700637cbSDimitry Andric
emitImplicitReturn()307*700637cbSDimitry Andric void CIRGenFunction::LexicalScope::emitImplicitReturn() {
308*700637cbSDimitry Andric CIRGenBuilderTy &builder = cgf.getBuilder();
309*700637cbSDimitry Andric LexicalScope *localScope = cgf.curLexScope;
310*700637cbSDimitry Andric
311*700637cbSDimitry Andric const auto *fd = cast<clang::FunctionDecl>(cgf.curGD.getDecl());
312*700637cbSDimitry Andric
313*700637cbSDimitry Andric // In C++, flowing off the end of a non-void function is always undefined
314*700637cbSDimitry Andric // behavior. In C, flowing off the end of a non-void function is undefined
315*700637cbSDimitry Andric // behavior only if the non-existent return value is used by the caller.
316*700637cbSDimitry Andric // That influences whether the terminating op is trap, unreachable, or
317*700637cbSDimitry Andric // return.
318*700637cbSDimitry Andric if (cgf.getLangOpts().CPlusPlus && !fd->hasImplicitReturnZero() &&
319*700637cbSDimitry Andric !cgf.sawAsmBlock && !fd->getReturnType()->isVoidType() &&
320*700637cbSDimitry Andric builder.getInsertionBlock()) {
321*700637cbSDimitry Andric bool shouldEmitUnreachable =
322*700637cbSDimitry Andric cgf.cgm.getCodeGenOpts().StrictReturn ||
323*700637cbSDimitry Andric !mayDropFunctionReturn(fd->getASTContext(), fd->getReturnType());
324*700637cbSDimitry Andric
325*700637cbSDimitry Andric if (shouldEmitUnreachable) {
326*700637cbSDimitry Andric if (cgf.cgm.getCodeGenOpts().OptimizationLevel == 0)
327*700637cbSDimitry Andric builder.create<cir::TrapOp>(localScope->endLoc);
328*700637cbSDimitry Andric else
329*700637cbSDimitry Andric builder.create<cir::UnreachableOp>(localScope->endLoc);
330*700637cbSDimitry Andric builder.clearInsertionPoint();
331*700637cbSDimitry Andric return;
332*700637cbSDimitry Andric }
333*700637cbSDimitry Andric }
334*700637cbSDimitry Andric
335*700637cbSDimitry Andric (void)emitReturn(localScope->endLoc);
336*700637cbSDimitry Andric }
337*700637cbSDimitry Andric
startFunction(GlobalDecl gd,QualType returnType,cir::FuncOp fn,cir::FuncType funcType,FunctionArgList args,SourceLocation loc,SourceLocation startLoc)338*700637cbSDimitry Andric void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType,
339*700637cbSDimitry Andric cir::FuncOp fn, cir::FuncType funcType,
340*700637cbSDimitry Andric FunctionArgList args, SourceLocation loc,
341*700637cbSDimitry Andric SourceLocation startLoc) {
342*700637cbSDimitry Andric assert(!curFn &&
343*700637cbSDimitry Andric "CIRGenFunction can only be used for one function at a time");
344*700637cbSDimitry Andric
345*700637cbSDimitry Andric curFn = fn;
346*700637cbSDimitry Andric
347*700637cbSDimitry Andric const Decl *d = gd.getDecl();
348*700637cbSDimitry Andric const auto *fd = dyn_cast_or_null<FunctionDecl>(d);
349*700637cbSDimitry Andric curFuncDecl = d->getNonClosureContext();
350*700637cbSDimitry Andric
351*700637cbSDimitry Andric mlir::Block *entryBB = &fn.getBlocks().front();
352*700637cbSDimitry Andric builder.setInsertionPointToStart(entryBB);
353*700637cbSDimitry Andric
354*700637cbSDimitry Andric // TODO(cir): this should live in `emitFunctionProlog
355*700637cbSDimitry Andric // Declare all the function arguments in the symbol table.
356*700637cbSDimitry Andric for (const auto nameValue : llvm::zip(args, entryBB->getArguments())) {
357*700637cbSDimitry Andric const VarDecl *paramVar = std::get<0>(nameValue);
358*700637cbSDimitry Andric mlir::Value paramVal = std::get<1>(nameValue);
359*700637cbSDimitry Andric CharUnits alignment = getContext().getDeclAlign(paramVar);
360*700637cbSDimitry Andric mlir::Location paramLoc = getLoc(paramVar->getSourceRange());
361*700637cbSDimitry Andric paramVal.setLoc(paramLoc);
362*700637cbSDimitry Andric
363*700637cbSDimitry Andric mlir::Value addrVal =
364*700637cbSDimitry Andric emitAlloca(cast<NamedDecl>(paramVar)->getName(),
365*700637cbSDimitry Andric convertType(paramVar->getType()), paramLoc, alignment,
366*700637cbSDimitry Andric /*insertIntoFnEntryBlock=*/true);
367*700637cbSDimitry Andric
368*700637cbSDimitry Andric declare(addrVal, paramVar, paramVar->getType(), paramLoc, alignment,
369*700637cbSDimitry Andric /*isParam=*/true);
370*700637cbSDimitry Andric
371*700637cbSDimitry Andric setAddrOfLocalVar(paramVar, Address(addrVal, alignment));
372*700637cbSDimitry Andric
373*700637cbSDimitry Andric bool isPromoted = isa<ParmVarDecl>(paramVar) &&
374*700637cbSDimitry Andric cast<ParmVarDecl>(paramVar)->isKNRPromoted();
375*700637cbSDimitry Andric assert(!cir::MissingFeatures::constructABIArgDirectExtend());
376*700637cbSDimitry Andric if (isPromoted)
377*700637cbSDimitry Andric cgm.errorNYI(fd->getSourceRange(), "Function argument demotion");
378*700637cbSDimitry Andric
379*700637cbSDimitry Andric // Location of the store to the param storage tracked as beginning of
380*700637cbSDimitry Andric // the function body.
381*700637cbSDimitry Andric mlir::Location fnBodyBegin = getLoc(fd->getBody()->getBeginLoc());
382*700637cbSDimitry Andric builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal, addrVal);
383*700637cbSDimitry Andric }
384*700637cbSDimitry Andric assert(builder.getInsertionBlock() && "Should be valid");
385*700637cbSDimitry Andric
386*700637cbSDimitry Andric // When the current function is not void, create an address to store the
387*700637cbSDimitry Andric // result value.
388*700637cbSDimitry Andric if (!returnType->isVoidType())
389*700637cbSDimitry Andric emitAndUpdateRetAlloca(returnType, getLoc(fd->getBody()->getEndLoc()),
390*700637cbSDimitry Andric getContext().getTypeAlignInChars(returnType));
391*700637cbSDimitry Andric
392*700637cbSDimitry Andric if (isa_and_nonnull<CXXMethodDecl>(d) &&
393*700637cbSDimitry Andric cast<CXXMethodDecl>(d)->isInstance()) {
394*700637cbSDimitry Andric cgm.getCXXABI().emitInstanceFunctionProlog(loc, *this);
395*700637cbSDimitry Andric
396*700637cbSDimitry Andric const auto *md = cast<CXXMethodDecl>(d);
397*700637cbSDimitry Andric if (md->getParent()->isLambda() && md->getOverloadedOperator() == OO_Call) {
398*700637cbSDimitry Andric cgm.errorNYI(loc, "lambda call operator");
399*700637cbSDimitry Andric } else {
400*700637cbSDimitry Andric // Not in a lambda; just use 'this' from the method.
401*700637cbSDimitry Andric // FIXME: Should we generate a new load for each use of 'this'? The fast
402*700637cbSDimitry Andric // register allocator would be happier...
403*700637cbSDimitry Andric cxxThisValue = cxxabiThisValue;
404*700637cbSDimitry Andric }
405*700637cbSDimitry Andric
406*700637cbSDimitry Andric assert(!cir::MissingFeatures::sanitizers());
407*700637cbSDimitry Andric assert(!cir::MissingFeatures::emitTypeCheck());
408*700637cbSDimitry Andric }
409*700637cbSDimitry Andric }
410*700637cbSDimitry Andric
finishFunction(SourceLocation endLoc)411*700637cbSDimitry Andric void CIRGenFunction::finishFunction(SourceLocation endLoc) {}
412*700637cbSDimitry Andric
emitFunctionBody(const clang::Stmt * body)413*700637cbSDimitry Andric mlir::LogicalResult CIRGenFunction::emitFunctionBody(const clang::Stmt *body) {
414*700637cbSDimitry Andric auto result = mlir::LogicalResult::success();
415*700637cbSDimitry Andric if (const CompoundStmt *block = dyn_cast<CompoundStmt>(body))
416*700637cbSDimitry Andric emitCompoundStmtWithoutScope(*block);
417*700637cbSDimitry Andric else
418*700637cbSDimitry Andric result = emitStmt(body, /*useCurrentScope=*/true);
419*700637cbSDimitry Andric
420*700637cbSDimitry Andric return result;
421*700637cbSDimitry Andric }
422*700637cbSDimitry Andric
eraseEmptyAndUnusedBlocks(cir::FuncOp func)423*700637cbSDimitry Andric static void eraseEmptyAndUnusedBlocks(cir::FuncOp func) {
424*700637cbSDimitry Andric // Remove any leftover blocks that are unreachable and empty, since they do
425*700637cbSDimitry Andric // not represent unreachable code useful for warnings nor anything deemed
426*700637cbSDimitry Andric // useful in general.
427*700637cbSDimitry Andric SmallVector<mlir::Block *> blocksToDelete;
428*700637cbSDimitry Andric for (mlir::Block &block : func.getBlocks()) {
429*700637cbSDimitry Andric if (block.empty() && block.getUses().empty())
430*700637cbSDimitry Andric blocksToDelete.push_back(&block);
431*700637cbSDimitry Andric }
432*700637cbSDimitry Andric for (mlir::Block *block : blocksToDelete)
433*700637cbSDimitry Andric block->erase();
434*700637cbSDimitry Andric }
435*700637cbSDimitry Andric
generateCode(clang::GlobalDecl gd,cir::FuncOp fn,cir::FuncType funcType)436*700637cbSDimitry Andric cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
437*700637cbSDimitry Andric cir::FuncType funcType) {
438*700637cbSDimitry Andric const auto funcDecl = cast<FunctionDecl>(gd.getDecl());
439*700637cbSDimitry Andric curGD = gd;
440*700637cbSDimitry Andric
441*700637cbSDimitry Andric SourceLocation loc = funcDecl->getLocation();
442*700637cbSDimitry Andric Stmt *body = funcDecl->getBody();
443*700637cbSDimitry Andric SourceRange bodyRange =
444*700637cbSDimitry Andric body ? body->getSourceRange() : funcDecl->getLocation();
445*700637cbSDimitry Andric
446*700637cbSDimitry Andric SourceLocRAIIObject fnLoc{*this, loc.isValid() ? getLoc(loc)
447*700637cbSDimitry Andric : builder.getUnknownLoc()};
448*700637cbSDimitry Andric
449*700637cbSDimitry Andric auto validMLIRLoc = [&](clang::SourceLocation clangLoc) {
450*700637cbSDimitry Andric return clangLoc.isValid() ? getLoc(clangLoc) : builder.getUnknownLoc();
451*700637cbSDimitry Andric };
452*700637cbSDimitry Andric const mlir::Location fusedLoc = mlir::FusedLoc::get(
453*700637cbSDimitry Andric &getMLIRContext(),
454*700637cbSDimitry Andric {validMLIRLoc(bodyRange.getBegin()), validMLIRLoc(bodyRange.getEnd())});
455*700637cbSDimitry Andric mlir::Block *entryBB = fn.addEntryBlock();
456*700637cbSDimitry Andric
457*700637cbSDimitry Andric FunctionArgList args;
458*700637cbSDimitry Andric QualType retTy = buildFunctionArgList(gd, args);
459*700637cbSDimitry Andric
460*700637cbSDimitry Andric {
461*700637cbSDimitry Andric LexicalScope lexScope(*this, fusedLoc, entryBB);
462*700637cbSDimitry Andric
463*700637cbSDimitry Andric startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin());
464*700637cbSDimitry Andric
465*700637cbSDimitry Andric if (isa<CXXDestructorDecl>(funcDecl)) {
466*700637cbSDimitry Andric emitDestructorBody(args);
467*700637cbSDimitry Andric } else if (isa<CXXConstructorDecl>(funcDecl)) {
468*700637cbSDimitry Andric emitConstructorBody(args);
469*700637cbSDimitry Andric } else if (getLangOpts().CUDA && !getLangOpts().CUDAIsDevice &&
470*700637cbSDimitry Andric funcDecl->hasAttr<CUDAGlobalAttr>()) {
471*700637cbSDimitry Andric getCIRGenModule().errorNYI(bodyRange, "CUDA kernel");
472*700637cbSDimitry Andric } else if (isa<CXXMethodDecl>(funcDecl) &&
473*700637cbSDimitry Andric cast<CXXMethodDecl>(funcDecl)->isLambdaStaticInvoker()) {
474*700637cbSDimitry Andric getCIRGenModule().errorNYI(bodyRange, "Lambda static invoker");
475*700637cbSDimitry Andric } else if (funcDecl->isDefaulted() && isa<CXXMethodDecl>(funcDecl) &&
476*700637cbSDimitry Andric (cast<CXXMethodDecl>(funcDecl)->isCopyAssignmentOperator() ||
477*700637cbSDimitry Andric cast<CXXMethodDecl>(funcDecl)->isMoveAssignmentOperator())) {
478*700637cbSDimitry Andric // Implicit copy-assignment gets the same special treatment as implicit
479*700637cbSDimitry Andric // copy-constructors.
480*700637cbSDimitry Andric emitImplicitAssignmentOperatorBody(args);
481*700637cbSDimitry Andric } else if (body) {
482*700637cbSDimitry Andric if (mlir::failed(emitFunctionBody(body))) {
483*700637cbSDimitry Andric fn.erase();
484*700637cbSDimitry Andric return nullptr;
485*700637cbSDimitry Andric }
486*700637cbSDimitry Andric } else {
487*700637cbSDimitry Andric // Anything without a body should have been handled above.
488*700637cbSDimitry Andric llvm_unreachable("no definition for normal function");
489*700637cbSDimitry Andric }
490*700637cbSDimitry Andric
491*700637cbSDimitry Andric if (mlir::failed(fn.verifyBody()))
492*700637cbSDimitry Andric return nullptr;
493*700637cbSDimitry Andric
494*700637cbSDimitry Andric finishFunction(bodyRange.getEnd());
495*700637cbSDimitry Andric }
496*700637cbSDimitry Andric
497*700637cbSDimitry Andric eraseEmptyAndUnusedBlocks(fn);
498*700637cbSDimitry Andric return fn;
499*700637cbSDimitry Andric }
500*700637cbSDimitry Andric
emitConstructorBody(FunctionArgList & args)501*700637cbSDimitry Andric void CIRGenFunction::emitConstructorBody(FunctionArgList &args) {
502*700637cbSDimitry Andric assert(!cir::MissingFeatures::sanitizers());
503*700637cbSDimitry Andric const auto *ctor = cast<CXXConstructorDecl>(curGD.getDecl());
504*700637cbSDimitry Andric CXXCtorType ctorType = curGD.getCtorType();
505*700637cbSDimitry Andric
506*700637cbSDimitry Andric assert((cgm.getTarget().getCXXABI().hasConstructorVariants() ||
507*700637cbSDimitry Andric ctorType == Ctor_Complete) &&
508*700637cbSDimitry Andric "can only generate complete ctor for this ABI");
509*700637cbSDimitry Andric
510*700637cbSDimitry Andric if (ctorType == Ctor_Complete && isConstructorDelegationValid(ctor) &&
511*700637cbSDimitry Andric cgm.getTarget().getCXXABI().hasConstructorVariants()) {
512*700637cbSDimitry Andric emitDelegateCXXConstructorCall(ctor, Ctor_Base, args, ctor->getEndLoc());
513*700637cbSDimitry Andric return;
514*700637cbSDimitry Andric }
515*700637cbSDimitry Andric
516*700637cbSDimitry Andric const FunctionDecl *definition = nullptr;
517*700637cbSDimitry Andric Stmt *body = ctor->getBody(definition);
518*700637cbSDimitry Andric assert(definition == ctor && "emitting wrong constructor body");
519*700637cbSDimitry Andric
520*700637cbSDimitry Andric if (isa_and_nonnull<CXXTryStmt>(body)) {
521*700637cbSDimitry Andric cgm.errorNYI(ctor->getSourceRange(), "emitConstructorBody: try body");
522*700637cbSDimitry Andric return;
523*700637cbSDimitry Andric }
524*700637cbSDimitry Andric
525*700637cbSDimitry Andric assert(!cir::MissingFeatures::incrementProfileCounter());
526*700637cbSDimitry Andric assert(!cir::MissingFeatures::runCleanupsScope());
527*700637cbSDimitry Andric
528*700637cbSDimitry Andric // TODO: in restricted cases, we can emit the vbase initializers of a
529*700637cbSDimitry Andric // complete ctor and then delegate to the base ctor.
530*700637cbSDimitry Andric
531*700637cbSDimitry Andric // Emit the constructor prologue, i.e. the base and member initializers.
532*700637cbSDimitry Andric emitCtorPrologue(ctor, ctorType, args);
533*700637cbSDimitry Andric
534*700637cbSDimitry Andric // TODO(cir): propagate this result via mlir::logical result. Just unreachable
535*700637cbSDimitry Andric // now just to have it handled.
536*700637cbSDimitry Andric if (mlir::failed(emitStmt(body, true))) {
537*700637cbSDimitry Andric cgm.errorNYI(ctor->getSourceRange(),
538*700637cbSDimitry Andric "emitConstructorBody: emit body statement failed.");
539*700637cbSDimitry Andric return;
540*700637cbSDimitry Andric }
541*700637cbSDimitry Andric }
542*700637cbSDimitry Andric
543*700637cbSDimitry Andric /// Emits the body of the current destructor.
emitDestructorBody(FunctionArgList & args)544*700637cbSDimitry Andric void CIRGenFunction::emitDestructorBody(FunctionArgList &args) {
545*700637cbSDimitry Andric const CXXDestructorDecl *dtor = cast<CXXDestructorDecl>(curGD.getDecl());
546*700637cbSDimitry Andric CXXDtorType dtorType = curGD.getDtorType();
547*700637cbSDimitry Andric
548*700637cbSDimitry Andric // For an abstract class, non-base destructors are never used (and can't
549*700637cbSDimitry Andric // be emitted in general, because vbase dtors may not have been validated
550*700637cbSDimitry Andric // by Sema), but the Itanium ABI doesn't make them optional and Clang may
551*700637cbSDimitry Andric // in fact emit references to them from other compilations, so emit them
552*700637cbSDimitry Andric // as functions containing a trap instruction.
553*700637cbSDimitry Andric if (dtorType != Dtor_Base && dtor->getParent()->isAbstract()) {
554*700637cbSDimitry Andric cgm.errorNYI(dtor->getSourceRange(), "abstract base class destructors");
555*700637cbSDimitry Andric return;
556*700637cbSDimitry Andric }
557*700637cbSDimitry Andric
558*700637cbSDimitry Andric Stmt *body = dtor->getBody();
559*700637cbSDimitry Andric assert(body && !cir::MissingFeatures::incrementProfileCounter());
560*700637cbSDimitry Andric
561*700637cbSDimitry Andric // The call to operator delete in a deleting destructor happens
562*700637cbSDimitry Andric // outside of the function-try-block, which means it's always
563*700637cbSDimitry Andric // possible to delegate the destructor body to the complete
564*700637cbSDimitry Andric // destructor. Do so.
565*700637cbSDimitry Andric if (dtorType == Dtor_Deleting) {
566*700637cbSDimitry Andric cgm.errorNYI(dtor->getSourceRange(), "deleting destructor");
567*700637cbSDimitry Andric return;
568*700637cbSDimitry Andric }
569*700637cbSDimitry Andric
570*700637cbSDimitry Andric // If the body is a function-try-block, enter the try before
571*700637cbSDimitry Andric // anything else.
572*700637cbSDimitry Andric const bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
573*700637cbSDimitry Andric if (isTryBody)
574*700637cbSDimitry Andric cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");
575*700637cbSDimitry Andric
576*700637cbSDimitry Andric assert(!cir::MissingFeatures::sanitizers());
577*700637cbSDimitry Andric assert(!cir::MissingFeatures::dtorCleanups());
578*700637cbSDimitry Andric
579*700637cbSDimitry Andric // If this is the complete variant, just invoke the base variant;
580*700637cbSDimitry Andric // the epilogue will destruct the virtual bases. But we can't do
581*700637cbSDimitry Andric // this optimization if the body is a function-try-block, because
582*700637cbSDimitry Andric // we'd introduce *two* handler blocks. In the Microsoft ABI, we
583*700637cbSDimitry Andric // always delegate because we might not have a definition in this TU.
584*700637cbSDimitry Andric switch (dtorType) {
585*700637cbSDimitry Andric case Dtor_Comdat:
586*700637cbSDimitry Andric llvm_unreachable("not expecting a COMDAT");
587*700637cbSDimitry Andric case Dtor_Deleting:
588*700637cbSDimitry Andric llvm_unreachable("already handled deleting case");
589*700637cbSDimitry Andric
590*700637cbSDimitry Andric case Dtor_Complete:
591*700637cbSDimitry Andric assert((body || getTarget().getCXXABI().isMicrosoft()) &&
592*700637cbSDimitry Andric "can't emit a dtor without a body for non-Microsoft ABIs");
593*700637cbSDimitry Andric
594*700637cbSDimitry Andric assert(!cir::MissingFeatures::dtorCleanups());
595*700637cbSDimitry Andric
596*700637cbSDimitry Andric // TODO(cir): A complete destructor is supposed to call the base destructor.
597*700637cbSDimitry Andric // Since we have to emit both dtor kinds we just fall through for now and.
598*700637cbSDimitry Andric // As long as we don't support virtual bases this should be functionally
599*700637cbSDimitry Andric // equivalent.
600*700637cbSDimitry Andric assert(!cir::MissingFeatures::completeDtors());
601*700637cbSDimitry Andric
602*700637cbSDimitry Andric // Fallthrough: act like we're in the base variant.
603*700637cbSDimitry Andric [[fallthrough]];
604*700637cbSDimitry Andric
605*700637cbSDimitry Andric case Dtor_Base:
606*700637cbSDimitry Andric assert(body);
607*700637cbSDimitry Andric
608*700637cbSDimitry Andric assert(!cir::MissingFeatures::dtorCleanups());
609*700637cbSDimitry Andric assert(!cir::MissingFeatures::vtableInitialization());
610*700637cbSDimitry Andric
611*700637cbSDimitry Andric if (isTryBody) {
612*700637cbSDimitry Andric cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");
613*700637cbSDimitry Andric } else if (body) {
614*700637cbSDimitry Andric (void)emitStmt(body, /*useCurrentScope=*/true);
615*700637cbSDimitry Andric } else {
616*700637cbSDimitry Andric assert(dtor->isImplicit() && "bodyless dtor not implicit");
617*700637cbSDimitry Andric // nothing to do besides what's in the epilogue
618*700637cbSDimitry Andric }
619*700637cbSDimitry Andric // -fapple-kext must inline any call to this dtor into
620*700637cbSDimitry Andric // the caller's body.
621*700637cbSDimitry Andric assert(!cir::MissingFeatures::appleKext());
622*700637cbSDimitry Andric
623*700637cbSDimitry Andric break;
624*700637cbSDimitry Andric }
625*700637cbSDimitry Andric
626*700637cbSDimitry Andric assert(!cir::MissingFeatures::dtorCleanups());
627*700637cbSDimitry Andric
628*700637cbSDimitry Andric // Exit the try if applicable.
629*700637cbSDimitry Andric if (isTryBody)
630*700637cbSDimitry Andric cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");
631*700637cbSDimitry Andric }
632*700637cbSDimitry Andric
633*700637cbSDimitry Andric /// Given a value of type T* that may not be to a complete object, construct
634*700637cbSDimitry Andric /// an l-vlaue withi the natural pointee alignment of T.
makeNaturalAlignPointeeAddrLValue(mlir::Value val,QualType ty)635*700637cbSDimitry Andric LValue CIRGenFunction::makeNaturalAlignPointeeAddrLValue(mlir::Value val,
636*700637cbSDimitry Andric QualType ty) {
637*700637cbSDimitry Andric // FIXME(cir): is it safe to assume Op->getResult(0) is valid? Perhaps
638*700637cbSDimitry Andric // assert on the result type first.
639*700637cbSDimitry Andric LValueBaseInfo baseInfo;
640*700637cbSDimitry Andric assert(!cir::MissingFeatures::opTBAA());
641*700637cbSDimitry Andric CharUnits align = cgm.getNaturalTypeAlignment(ty, &baseInfo);
642*700637cbSDimitry Andric return makeAddrLValue(Address(val, align), ty, baseInfo);
643*700637cbSDimitry Andric }
644*700637cbSDimitry Andric
makeNaturalAlignAddrLValue(mlir::Value val,QualType ty)645*700637cbSDimitry Andric LValue CIRGenFunction::makeNaturalAlignAddrLValue(mlir::Value val,
646*700637cbSDimitry Andric QualType ty) {
647*700637cbSDimitry Andric LValueBaseInfo baseInfo;
648*700637cbSDimitry Andric CharUnits alignment = cgm.getNaturalTypeAlignment(ty, &baseInfo);
649*700637cbSDimitry Andric Address addr(val, convertTypeForMem(ty), alignment);
650*700637cbSDimitry Andric assert(!cir::MissingFeatures::opTBAA());
651*700637cbSDimitry Andric return makeAddrLValue(addr, ty, baseInfo);
652*700637cbSDimitry Andric }
653*700637cbSDimitry Andric
buildFunctionArgList(clang::GlobalDecl gd,FunctionArgList & args)654*700637cbSDimitry Andric clang::QualType CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd,
655*700637cbSDimitry Andric FunctionArgList &args) {
656*700637cbSDimitry Andric const auto *fd = cast<FunctionDecl>(gd.getDecl());
657*700637cbSDimitry Andric QualType retTy = fd->getReturnType();
658*700637cbSDimitry Andric
659*700637cbSDimitry Andric const auto *md = dyn_cast<CXXMethodDecl>(fd);
660*700637cbSDimitry Andric if (md && md->isInstance()) {
661*700637cbSDimitry Andric if (cgm.getCXXABI().hasThisReturn(gd))
662*700637cbSDimitry Andric cgm.errorNYI(fd->getSourceRange(), "this return");
663*700637cbSDimitry Andric else if (cgm.getCXXABI().hasMostDerivedReturn(gd))
664*700637cbSDimitry Andric cgm.errorNYI(fd->getSourceRange(), "most derived return");
665*700637cbSDimitry Andric cgm.getCXXABI().buildThisParam(*this, args);
666*700637cbSDimitry Andric }
667*700637cbSDimitry Andric
668*700637cbSDimitry Andric if (const auto *cd = dyn_cast<CXXConstructorDecl>(fd))
669*700637cbSDimitry Andric if (cd->getInheritedConstructor())
670*700637cbSDimitry Andric cgm.errorNYI(fd->getSourceRange(),
671*700637cbSDimitry Andric "buildFunctionArgList: inherited constructor");
672*700637cbSDimitry Andric
673*700637cbSDimitry Andric for (auto *param : fd->parameters())
674*700637cbSDimitry Andric args.push_back(param);
675*700637cbSDimitry Andric
676*700637cbSDimitry Andric if (md && (isa<CXXConstructorDecl>(md) || isa<CXXDestructorDecl>(md)))
677*700637cbSDimitry Andric assert(!cir::MissingFeatures::cxxabiStructorImplicitParam());
678*700637cbSDimitry Andric
679*700637cbSDimitry Andric return retTy;
680*700637cbSDimitry Andric }
681*700637cbSDimitry Andric
682*700637cbSDimitry Andric /// Emit code to compute a designator that specifies the location
683*700637cbSDimitry Andric /// of the expression.
684*700637cbSDimitry Andric /// FIXME: document this function better.
emitLValue(const Expr * e)685*700637cbSDimitry Andric LValue CIRGenFunction::emitLValue(const Expr *e) {
686*700637cbSDimitry Andric // FIXME: ApplyDebugLocation DL(*this, e);
687*700637cbSDimitry Andric switch (e->getStmtClass()) {
688*700637cbSDimitry Andric default:
689*700637cbSDimitry Andric getCIRGenModule().errorNYI(e->getSourceRange(),
690*700637cbSDimitry Andric std::string("l-value not implemented for '") +
691*700637cbSDimitry Andric e->getStmtClassName() + "'");
692*700637cbSDimitry Andric return LValue();
693*700637cbSDimitry Andric case Expr::ArraySubscriptExprClass:
694*700637cbSDimitry Andric return emitArraySubscriptExpr(cast<ArraySubscriptExpr>(e));
695*700637cbSDimitry Andric case Expr::UnaryOperatorClass:
696*700637cbSDimitry Andric return emitUnaryOpLValue(cast<UnaryOperator>(e));
697*700637cbSDimitry Andric case Expr::StringLiteralClass:
698*700637cbSDimitry Andric return emitStringLiteralLValue(cast<StringLiteral>(e));
699*700637cbSDimitry Andric case Expr::MemberExprClass:
700*700637cbSDimitry Andric return emitMemberExpr(cast<MemberExpr>(e));
701*700637cbSDimitry Andric case Expr::BinaryOperatorClass:
702*700637cbSDimitry Andric return emitBinaryOperatorLValue(cast<BinaryOperator>(e));
703*700637cbSDimitry Andric case Expr::CompoundAssignOperatorClass: {
704*700637cbSDimitry Andric QualType ty = e->getType();
705*700637cbSDimitry Andric if (ty->getAs<AtomicType>()) {
706*700637cbSDimitry Andric cgm.errorNYI(e->getSourceRange(),
707*700637cbSDimitry Andric "CompoundAssignOperator with AtomicType");
708*700637cbSDimitry Andric return LValue();
709*700637cbSDimitry Andric }
710*700637cbSDimitry Andric if (!ty->isAnyComplexType())
711*700637cbSDimitry Andric return emitCompoundAssignmentLValue(cast<CompoundAssignOperator>(e));
712*700637cbSDimitry Andric cgm.errorNYI(e->getSourceRange(),
713*700637cbSDimitry Andric "CompoundAssignOperator with ComplexType");
714*700637cbSDimitry Andric return LValue();
715*700637cbSDimitry Andric }
716*700637cbSDimitry Andric case Expr::CallExprClass:
717*700637cbSDimitry Andric case Expr::CXXMemberCallExprClass:
718*700637cbSDimitry Andric case Expr::CXXOperatorCallExprClass:
719*700637cbSDimitry Andric case Expr::UserDefinedLiteralClass:
720*700637cbSDimitry Andric return emitCallExprLValue(cast<CallExpr>(e));
721*700637cbSDimitry Andric case Expr::ParenExprClass:
722*700637cbSDimitry Andric return emitLValue(cast<ParenExpr>(e)->getSubExpr());
723*700637cbSDimitry Andric case Expr::DeclRefExprClass:
724*700637cbSDimitry Andric return emitDeclRefLValue(cast<DeclRefExpr>(e));
725*700637cbSDimitry Andric case Expr::CStyleCastExprClass:
726*700637cbSDimitry Andric case Expr::CXXStaticCastExprClass:
727*700637cbSDimitry Andric case Expr::CXXDynamicCastExprClass:
728*700637cbSDimitry Andric case Expr::ImplicitCastExprClass:
729*700637cbSDimitry Andric return emitCastLValue(cast<CastExpr>(e));
730*700637cbSDimitry Andric }
731*700637cbSDimitry Andric }
732*700637cbSDimitry Andric
getVersionedTmpName(llvm::StringRef name,unsigned cnt)733*700637cbSDimitry Andric static std::string getVersionedTmpName(llvm::StringRef name, unsigned cnt) {
734*700637cbSDimitry Andric SmallString<256> buffer;
735*700637cbSDimitry Andric llvm::raw_svector_ostream out(buffer);
736*700637cbSDimitry Andric out << name << cnt;
737*700637cbSDimitry Andric return std::string(out.str());
738*700637cbSDimitry Andric }
739*700637cbSDimitry Andric
getCounterAggTmpAsString()740*700637cbSDimitry Andric std::string CIRGenFunction::getCounterAggTmpAsString() {
741*700637cbSDimitry Andric return getVersionedTmpName("agg.tmp", counterAggTmp++);
742*700637cbSDimitry Andric }
743*700637cbSDimitry Andric
emitNullInitialization(mlir::Location loc,Address destPtr,QualType ty)744*700637cbSDimitry Andric void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,
745*700637cbSDimitry Andric QualType ty) {
746*700637cbSDimitry Andric // Ignore empty classes in C++.
747*700637cbSDimitry Andric if (getLangOpts().CPlusPlus) {
748*700637cbSDimitry Andric if (const RecordType *rt = ty->getAs<RecordType>()) {
749*700637cbSDimitry Andric if (cast<CXXRecordDecl>(rt->getDecl())->isEmpty())
750*700637cbSDimitry Andric return;
751*700637cbSDimitry Andric }
752*700637cbSDimitry Andric }
753*700637cbSDimitry Andric
754*700637cbSDimitry Andric // Cast the dest ptr to the appropriate i8 pointer type.
755*700637cbSDimitry Andric if (builder.isInt8Ty(destPtr.getElementType())) {
756*700637cbSDimitry Andric cgm.errorNYI(loc, "Cast the dest ptr to the appropriate i8 pointer type");
757*700637cbSDimitry Andric }
758*700637cbSDimitry Andric
759*700637cbSDimitry Andric // Get size and alignment info for this aggregate.
760*700637cbSDimitry Andric const CharUnits size = getContext().getTypeSizeInChars(ty);
761*700637cbSDimitry Andric if (size.isZero()) {
762*700637cbSDimitry Andric // But note that getTypeInfo returns 0 for a VLA.
763*700637cbSDimitry Andric if (isa<VariableArrayType>(getContext().getAsArrayType(ty))) {
764*700637cbSDimitry Andric cgm.errorNYI(loc,
765*700637cbSDimitry Andric "emitNullInitialization for zero size VariableArrayType");
766*700637cbSDimitry Andric } else {
767*700637cbSDimitry Andric return;
768*700637cbSDimitry Andric }
769*700637cbSDimitry Andric }
770*700637cbSDimitry Andric
771*700637cbSDimitry Andric // If the type contains a pointer to data member we can't memset it to zero.
772*700637cbSDimitry Andric // Instead, create a null constant and copy it to the destination.
773*700637cbSDimitry Andric // TODO: there are other patterns besides zero that we can usefully memset,
774*700637cbSDimitry Andric // like -1, which happens to be the pattern used by member-pointers.
775*700637cbSDimitry Andric if (!cgm.getTypes().isZeroInitializable(ty)) {
776*700637cbSDimitry Andric cgm.errorNYI(loc, "type is not zero initializable");
777*700637cbSDimitry Andric }
778*700637cbSDimitry Andric
779*700637cbSDimitry Andric // In LLVM Codegen: otherwise, just memset the whole thing to zero using
780*700637cbSDimitry Andric // Builder.CreateMemSet. In CIR just emit a store of #cir.zero to the
781*700637cbSDimitry Andric // respective address.
782*700637cbSDimitry Andric // Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, false);
783*700637cbSDimitry Andric const mlir::Value zeroValue = builder.getNullValue(convertType(ty), loc);
784*700637cbSDimitry Andric builder.createStore(loc, zeroValue, destPtr);
785*700637cbSDimitry Andric }
786*700637cbSDimitry Andric
787*700637cbSDimitry Andric // TODO(cir): should be shared with LLVM codegen.
shouldNullCheckClassCastValue(const CastExpr * ce)788*700637cbSDimitry Andric bool CIRGenFunction::shouldNullCheckClassCastValue(const CastExpr *ce) {
789*700637cbSDimitry Andric const Expr *e = ce->getSubExpr();
790*700637cbSDimitry Andric
791*700637cbSDimitry Andric if (ce->getCastKind() == CK_UncheckedDerivedToBase)
792*700637cbSDimitry Andric return false;
793*700637cbSDimitry Andric
794*700637cbSDimitry Andric if (isa<CXXThisExpr>(e->IgnoreParens())) {
795*700637cbSDimitry Andric // We always assume that 'this' is never null.
796*700637cbSDimitry Andric return false;
797*700637cbSDimitry Andric }
798*700637cbSDimitry Andric
799*700637cbSDimitry Andric if (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(ce)) {
800*700637cbSDimitry Andric // And that glvalue casts are never null.
801*700637cbSDimitry Andric if (ice->isGLValue())
802*700637cbSDimitry Andric return false;
803*700637cbSDimitry Andric }
804*700637cbSDimitry Andric
805*700637cbSDimitry Andric return true;
806*700637cbSDimitry Andric }
807*700637cbSDimitry Andric
808*700637cbSDimitry Andric } // namespace clang::CIRGen
809