clang 24.0.0git
CIRGenFunction.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// Internal per-function state used for AST-to-ClangIR code gen
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenFunction.h"
14
15#include "CIRGenCXXABI.h"
16#include "CIRGenCall.h"
17#include "CIRGenValue.h"
18#include "mlir/IR/Location.h"
19#include "clang/AST/Attr.h"
20#include "clang/AST/ExprCXX.h"
24#include "llvm/ADT/ScopeExit.h"
25#include "llvm/IR/FPEnv.h"
26
27#include <cassert>
28
29namespace clang::CIRGen {
30
32 bool suppressNewContext)
33 : CIRGenTypeCache(cgm), cgm{cgm}, builder(builder),
35 ehStack.setCGF(this);
36}
37
39
40// This is copied from clang/lib/CodeGen/CodeGenFunction.cpp
42 type = type.getCanonicalType();
43 while (true) {
44 switch (type->getTypeClass()) {
45#define TYPE(name, parent)
46#define ABSTRACT_TYPE(name, parent)
47#define NON_CANONICAL_TYPE(name, parent) case Type::name:
48#define DEPENDENT_TYPE(name, parent) case Type::name:
49#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(name, parent) case Type::name:
50#include "clang/AST/TypeNodes.inc"
51 llvm_unreachable("non-canonical or dependent type in IR-generation");
52
53 case Type::Auto:
54 case Type::DeducedTemplateSpecialization:
55 llvm_unreachable("undeduced type in IR-generation");
56
57 // Various scalar types.
58 case Type::Builtin:
59 case Type::Pointer:
60 case Type::BlockPointer:
61 case Type::LValueReference:
62 case Type::RValueReference:
63 case Type::MemberPointer:
64 case Type::Vector:
65 case Type::ExtVector:
66 case Type::ConstantMatrix:
67 case Type::FunctionProto:
68 case Type::FunctionNoProto:
69 case Type::Enum:
70 case Type::ObjCObjectPointer:
71 case Type::Pipe:
72 case Type::BitInt:
73 case Type::OverflowBehavior:
74 case Type::HLSLAttributedResource:
75 case Type::HLSLInlineSpirv:
76 return cir::TEK_Scalar;
77
78 // Complexes.
79 case Type::Complex:
80 return cir::TEK_Complex;
81
82 // Arrays, records, and Objective-C objects.
83 case Type::ConstantArray:
84 case Type::IncompleteArray:
85 case Type::VariableArray:
86 case Type::Record:
87 case Type::ObjCObject:
88 case Type::ObjCInterface:
89 case Type::ArrayParameter:
90 return cir::TEK_Aggregate;
91
92 // We operate on atomic values according to their underlying type.
93 case Type::Atomic:
94 type = cast<AtomicType>(type)->getValueType();
95 continue;
96 }
97 llvm_unreachable("unknown type kind!");
98 }
99}
100
102 return cgm.getTypes().convertTypeForMem(t);
103}
104
106 return cgm.getTypes().convertType(t);
107}
108
110 // Some AST nodes might contain invalid source locations (e.g.
111 // CXXDefaultArgExpr), workaround that to still get something out.
112 if (srcLoc.isValid()) {
114 PresumedLoc pLoc = sm.getPresumedLoc(srcLoc);
115 StringRef filename = pLoc.getFilename();
116 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
117 pLoc.getLine(), pLoc.getColumn());
118 }
119 // We expect to have a currSrcLoc set, so we assert here, but it isn't
120 // critical for the correctness of compilation, so in non-assert builds
121 // we fallback on using an unknown location.
122 assert(currSrcLoc && "expected to inherit some source location");
123 if (currSrcLoc)
124 return *currSrcLoc;
125 // We're brave, but time to give up.
126 return builder.getUnknownLoc();
127}
128
129mlir::Location CIRGenFunction::getLoc(SourceRange srcLoc) {
130 // Some AST nodes might contain invalid source locations (e.g.
131 // CXXDefaultArgExpr), workaround that to still get something out.
132 if (srcLoc.isValid()) {
133 mlir::Location beg = getLoc(srcLoc.getBegin());
134 mlir::Location end = getLoc(srcLoc.getEnd());
135 SmallVector<mlir::Location, 2> locs = {beg, end};
136 mlir::Attribute metadata;
137 return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());
138 }
139 // We expect to have a currSrcLoc set, so we assert here, but it isn't
140 // critical for the correctness of compilation, so in non-assert builds
141 // we fallback on using an unknown location.
142 assert(currSrcLoc && "expected to inherit some source location");
143 if (currSrcLoc)
144 return *currSrcLoc;
145 // We're brave, but time to give up.
146 return builder.getUnknownLoc();
147}
148
149mlir::Location CIRGenFunction::getLoc(mlir::Location lhs, mlir::Location rhs) {
150 SmallVector<mlir::Location, 2> locs = {lhs, rhs};
151 mlir::Attribute metadata;
152 return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());
153}
154
155bool CIRGenFunction::containsLabel(const Stmt *s, bool ignoreCaseStmts) {
156 // Null statement, not a label!
157 if (!s)
158 return false;
159
160 // If this is a label, we have to emit the code, consider something like:
161 // if (0) { ... foo: bar(); } goto foo;
162 //
163 // TODO: If anyone cared, we could track __label__'s, since we know that you
164 // can't jump to one from outside their declared region.
165 if (isa<LabelStmt>(s))
166 return true;
167
168 // If this is a case/default statement, and we haven't seen a switch, we
169 // have to emit the code.
170 if (isa<SwitchCase>(s) && !ignoreCaseStmts)
171 return true;
172
173 // If this is a switch statement, we want to ignore case statements when we
174 // recursively process the sub-statements of the switch. If we haven't
175 // encountered a switch statement, we treat case statements like labels, but
176 // if we are processing a switch statement, case statements are expected.
177 if (isa<SwitchStmt>(s))
178 ignoreCaseStmts = true;
179
180 // Scan subexpressions for verboten labels.
181 return std::any_of(s->child_begin(), s->child_end(),
182 [=](const Stmt *subStmt) {
183 return containsLabel(subStmt, ignoreCaseStmts);
184 });
185}
186
187/// If the specified expression does not fold to a constant, or if it does but
188/// contains a label, return false. If it constant folds return true and set
189/// the boolean result in Result.
190bool CIRGenFunction::constantFoldsToBool(const Expr *cond, bool &resultBool,
191 bool allowLabels) {
192 llvm::APSInt resultInt;
193 if (!constantFoldsToSimpleInteger(cond, resultInt, allowLabels))
194 return false;
195
196 resultBool = resultInt.getBoolValue();
197 return true;
198}
199
200/// If the specified expression does not fold to a constant, or if it does
201/// fold but contains a label, return false. If it constant folds, return
202/// true and set the folded value.
204 llvm::APSInt &resultInt,
205 bool allowLabels) {
206 // FIXME: Rename and handle conversion of other evaluatable things
207 // to bool.
208 Expr::EvalResult result;
209 if (!cond->EvaluateAsInt(result, getContext()))
210 return false; // Not foldable, not integer or not fully evaluatable.
211
212 llvm::APSInt intValue = result.Val.getInt();
213 if (!allowLabels && containsLabel(cond))
214 return false; // Contains a label.
215
216 resultInt = intValue;
217 return true;
218}
219
220void CIRGenFunction::emitAndUpdateRetAlloca(QualType type, mlir::Location loc,
221 CharUnits alignment) {
222 if (!type->isVoidType()) {
223 Address allocaAddr = Address::invalid();
224 returnValue = createMemTemp(type, alignment, loc, "__retval", &allocaAddr);
225 fnRetAlloca = allocaAddr.getPointer();
226 }
227}
228
229void CIRGenFunction::declare(mlir::Value addrVal, const Decl *var, QualType ty,
230 mlir::Location loc, CharUnits alignment,
231 bool isParam) {
232 assert(isa<NamedDecl>(var) && "Needs a named decl");
233 assert(!symbolTable.count(var) && "not supposed to be available just yet");
234
235 Address addr(addrVal, alignment);
236 cir::AllocaOp allocaOp = addr.getUnderlyingAllocaOp();
237 assert(allocaOp && "expected cir::AllocaOp");
238
239 if (isParam)
240 allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
241 if (ty->isReferenceType() || ty.isConstQualified())
242 allocaOp.setConstantAttr(mlir::UnitAttr::get(&getMLIRContext()));
243
244 symbolTable.insert(var, addrVal);
245}
246
248 CIRGenBuilderTy &builder = cgf.builder;
249 LexicalScope *localScope = cgf.curLexScope;
250
251 // Process all return blocks — emit cir.return ops.
252 // TODO(cir): Handle returning from a switch statement through a cleanup
253 // block. We can't simply jump to the cleanup block, because the cleanup block
254 // is not part of the case region. Either reemit all cleanups in the return
255 // block or wait for MLIR structured control flow to support early exits.
257 for (mlir::Block *retBlock : localScope->getRetBlocks()) {
258 mlir::OpBuilder::InsertionGuard guard(builder);
259 builder.setInsertionPointToEnd(retBlock);
260 retBlocks.push_back(retBlock);
261 mlir::Location retLoc = localScope->getRetLoc(retBlock);
262 emitReturn(retLoc);
263 }
264
265 // Pop cleanup scopes from the EH stack. In CIR, this emits cleanup code
266 // into the cleanup regions of cir.cleanup.scope ops — no CFG-level cleanup
267 // blocks or branches are needed.
268 if (performCleanup) {
270 forceCleanup();
271 }
272
273 mlir::Block *curBlock = builder.getBlock();
274 if (isGlobalInit() && !curBlock)
275 return;
276 if (curBlock->mightHaveTerminator() && curBlock->getTerminator())
277 return;
278
279 // Get rid of any empty block at the end of the scope. An empty non-entry
280 // block is created when a terminator (return/break/continue) is followed
281 // by unreachable code.
282 bool isEntryBlock = builder.getInsertionBlock()->isEntryBlock();
283 if (!isEntryBlock && curBlock->empty()) {
284 curBlock->erase();
285 for (mlir::Block *retBlock : retBlocks) {
286 if (retBlock->getUses().empty())
287 retBlock->erase();
288 }
289 return;
290 }
291
292 if (localScope->depth == 0) {
293 // Reached the end of the function.
294 if (localScope->getRetBlocks().size() == 1) {
295 mlir::Block *retBlock = localScope->getRetBlocks()[0];
296 mlir::Location retLoc = localScope->getRetLoc(retBlock);
297 if (retBlock->getUses().empty()) {
298 retBlock->erase();
299 } else {
300 cir::BrOp::create(builder, retLoc, retBlock);
301 return;
302 }
303 }
304 emitImplicitReturn();
305 return;
306 }
307
308 // End of any local scope != function.
309 // Ternary ops have to deal with matching arms for yielding types
310 // and do return a value, it must do its own cir.yield insertion.
311 if (!localScope->isTernary() && !curBlock->mightHaveTerminator()) {
312 !retVal ? cir::YieldOp::create(builder, localScope->endLoc)
313 : cir::YieldOp::create(builder, localScope->endLoc, retVal);
314 }
315}
316
317cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
318 CIRGenBuilderTy &builder = cgf.getBuilder();
319
320 auto fn = dyn_cast<cir::FuncOp>(cgf.curFn);
321 assert(fn && "emitReturn from non-function");
322
323 if (!fn.getFunctionType().hasVoidReturn()) {
324 // Load the value from `__retval` and return it via the `cir.return` op.
325 auto value = cir::LoadOp::create(
326 builder, loc, fn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);
327 return cir::ReturnOp::create(builder, loc,
328 llvm::ArrayRef(value.getResult()));
329 }
330 return cir::ReturnOp::create(builder, loc);
331}
332
333// This is copied from CodeGenModule::MayDropFunctionReturn. This is a
334// candidate for sharing between CIRGen and CodeGen.
335static bool mayDropFunctionReturn(const ASTContext &astContext,
336 QualType returnType) {
337 // We can't just discard the return value for a record type with a complex
338 // destructor or a non-trivially copyable type.
339 if (const auto *classDecl = returnType->getAsCXXRecordDecl())
340 return classDecl->hasTrivialDestructor();
341 return returnType.isTriviallyCopyableType(astContext);
342}
343
344static bool previousOpIsNonYieldingCleanup(mlir::Block *block) {
345 if (block->empty())
346 return false;
347 mlir::Operation *op = &block->back();
348 auto cleanupScopeOp = mlir::dyn_cast<cir::CleanupScopeOp>(op);
349 if (!cleanupScopeOp)
350 return false;
351
352 // Check whether the body region of the cleanup scope exits via cir.yield.
353 // Exits via cir.return or cir.goto do not fall through to the operation
354 // following the cleanup scope, and exits via break, continue, and resume
355 // are not expected here.
356 for (mlir::Block &bodyBlock : cleanupScopeOp.getBodyRegion()) {
357 if (bodyBlock.mightHaveTerminator()) {
358 if (mlir::isa<cir::YieldOp>(bodyBlock.getTerminator()))
359 return false;
360 assert(!mlir::isa<cir::BreakOp>(bodyBlock.getTerminator()) &&
361 !mlir::isa<cir::ContinueOp>(bodyBlock.getTerminator()) &&
362 !mlir::isa<cir::ResumeOp>(bodyBlock.getTerminator()));
363 }
364 }
365 return true;
366}
367
368void CIRGenFunction::LexicalScope::emitImplicitReturn() {
369 CIRGenBuilderTy &builder = cgf.getBuilder();
370 LexicalScope *localScope = cgf.curLexScope;
371
372 const auto *fd = cast<clang::FunctionDecl>(cgf.curGD.getDecl());
373
374 // In C++, flowing off the end of a non-void function is always undefined
375 // behavior. In C, flowing off the end of a non-void function is undefined
376 // behavior only if the non-existent return value is used by the caller.
377 // That influences whether the terminating op is trap, unreachable, or
378 // return.
379 if (cgf.getLangOpts().CPlusPlus && !fd->hasImplicitReturnZero() &&
380 !cgf.sawAsmBlock && !fd->getReturnType()->isVoidType() &&
381 builder.getInsertionBlock() &&
382 !previousOpIsNonYieldingCleanup(builder.getInsertionBlock())) {
383 bool shouldEmitUnreachable =
384 cgf.cgm.getCodeGenOpts().StrictReturn ||
385 !mayDropFunctionReturn(fd->getASTContext(), fd->getReturnType());
386
387 if (shouldEmitUnreachable) {
389 if (cgf.cgm.getCodeGenOpts().OptimizationLevel == 0)
390 cir::TrapOp::create(builder, localScope->endLoc);
391 else
392 cir::UnreachableOp::create(builder, localScope->endLoc);
393 builder.clearInsertionPoint();
394 return;
395 }
396 }
397
398 (void)emitReturn(localScope->endLoc);
399}
400
402 LexicalScope *scope = this;
403 while (scope) {
404 if (scope->isTry())
405 return scope->getTry();
406 scope = scope->parentScope;
407 }
408 return nullptr;
409}
410
411/// An argument came in as a promoted argument; demote it back to its
412/// declared type.
413static mlir::Value emitArgumentDemotion(CIRGenFunction &cgf, const VarDecl *var,
414 mlir::Value value) {
415 mlir::Type ty = cgf.convertType(var->getType());
416
417 // This can happen with promotions that actually don't change the
418 // underlying type, like the enum promotions.
419 if (value.getType() == ty)
420 return value;
421
422 assert((mlir::isa<cir::IntType>(ty) || cir::isAnyFloatingPointType(ty)) &&
423 "unexpected promotion type");
424
425 if (mlir::isa<cir::IntType>(ty))
426 return cgf.getBuilder().CIRBaseBuilderTy::createIntCast(value, ty);
427
428 return cgf.getBuilder().createFloatingCast(value, ty);
429}
430
432 mlir::Block *entryBB,
433 const FunctionDecl *fd,
434 SourceLocation bodyBeginLoc) {
435 // Naked functions don't have prologues.
436 if (fd && fd->hasAttr<NakedAttr>()) {
437 cgm.errorNYI(bodyBeginLoc, "naked function decl");
438 }
439
440 // Declare all the function arguments in the symbol table.
441 for (const auto nameValue : llvm::zip(args, entryBB->getArguments())) {
442 const VarDecl *paramVar = std::get<0>(nameValue);
443 mlir::Value paramVal = std::get<1>(nameValue);
444 CharUnits alignment = getContext().getDeclAlign(paramVar);
445 mlir::Location paramLoc = getLoc(paramVar->getSourceRange());
446 paramVal.setLoc(paramLoc);
447
448 mlir::Value addrVal =
449 emitAlloca(cast<NamedDecl>(paramVar)->getName(),
450 convertType(paramVar->getType()), paramLoc, alignment,
451 /*insertIntoFnEntryBlock=*/true);
452
453 declare(addrVal, paramVar, paramVar->getType(), paramLoc, alignment,
454 /*isParam=*/true);
455
456 setAddrOfLocalVar(paramVar, Address(addrVal, alignment));
457
458 bool isPromoted = isa<ParmVarDecl>(paramVar) &&
459 cast<ParmVarDecl>(paramVar)->isKNRPromoted();
461 if (isPromoted)
462 paramVal = emitArgumentDemotion(*this, paramVar, paramVal);
463
464 // Location of the store to the param storage tracked as beginning of
465 // the function body.
466 mlir::Location fnBodyBegin = getLoc(bodyBeginLoc);
467 builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal, addrVal);
468 }
469 assert(builder.getInsertionBlock() && "Should be valid");
470}
471
473 cir::FuncOp fn, cir::FuncType funcType,
475 SourceLocation startLoc) {
476 assert(!curFn &&
477 "CIRGenFunction can only be used for one function at a time");
478
479 curFn = fn;
480
481 const Decl *d = gd.getDecl();
482
483 didCallStackSave = false;
484 curCodeDecl = d;
485 const auto *fd = dyn_cast_or_null<FunctionDecl>(d);
486 curFuncDecl = (d ? d->getNonClosureContext() : nullptr);
487
488 // This is an artifact of the legacy handling of constrained floating-point
489 // modes. The rounding mode and exception behavior tracked in
490 // clang::LangOptions don't correspond directly to the representation we
491 // use in CIR, but the CIR settings can be derived from them. We track the
492 // default state using the legacy settings because it keeps the tracking in
493 // sync with classic codegen.
494 llvm::RoundingMode rm = getLangOpts().getDefaultRoundingMode();
496 builder.setDefaultConstrainedRounding(rm);
497 builder.setDefaultConstrainedExcept(eb);
498 builder.setIsFPConstrained(false);
499 if ((fd && (fd->UsesFPIntrin() || fd->hasAttr<StrictFPAttr>())) ||
501 rm != llvm::RoundingMode::NearestTiesToEven))) {
502 builder.setIsFPConstrained(true);
503 fn->setAttr(cir::CIRDialect::getStrictFPAttrName(),
504 mlir::UnitAttr::get(fn.getContext()));
505 }
506 prologueCleanupDepth = ehStack.stable_begin();
507
508 mlir::Block *entryBB = &fn.getBlocks().front();
509 builder.setInsertionPointToStart(entryBB);
510
511 // Determine the function body begin location for the prolog.
512 // If fd is null or has no body, use startLoc as fallback.
513 SourceLocation bodyBeginLoc = startLoc;
514 if (fd) {
515 if (Stmt *body = fd->getBody())
516 bodyBeginLoc = body->getBeginLoc();
517 else
518 bodyBeginLoc = fd->getLocation();
519 }
520
521 emitFunctionProlog(args, entryBB, fd, bodyBeginLoc);
522
523 // When the current function is not void, create an address to store the
524 // result value.
525 if (!returnType->isVoidType()) {
526 // Determine the function body end location.
527 // If fd is null or has no body, use loc as fallback.
528 SourceLocation bodyEndLoc = loc;
529 if (fd) {
530 if (Stmt *body = fd->getBody())
531 bodyEndLoc = body->getEndLoc();
532 else
533 bodyEndLoc = fd->getLocation();
534 }
535 emitAndUpdateRetAlloca(returnType, getLoc(bodyEndLoc),
536 getContext().getTypeAlignInChars(returnType));
537
538 // If this is an implicit-return-zero function, initialize the return
539 // value. This mirrors the implicit-return-zero handling in classic
540 // codegen's EmitFunctionProlog (CGCall.cpp). It is done here, after
541 // emitAndUpdateRetAlloca, because in CIR the return slot is created
542 // after the prolog (the opposite of classic codegen, where ReturnValue
543 // is set up before EmitFunctionProlog runs).
544 // TODO(cir): Align prolog handling with classic codegen.
545 if (fd && fd->hasImplicitReturnZero()) {
546 mlir::Type cirRetTy = convertType(returnType.getUnqualifiedType());
547 mlir::Location bodyBeginMLIRLoc = getLoc(bodyBeginLoc);
548 mlir::Value zero = builder.getNullValue(cirRetTy, bodyBeginMLIRLoc);
549 builder.CIRBaseBuilderTy::createStore(bodyBeginMLIRLoc, zero,
550 returnValue.getPointer());
551 }
552 }
553
554 // Only implicit-object member functions (without an explicit `this`
555 // parameter) receive an implicit `this` argument that the CXXABI prolog has
556 // to set up. C++23 explicit-object members (P0847R7) carry their object via a
557 // regular parameter and use the standard parameter prolog instead.
558 if (isa_and_nonnull<CXXMethodDecl>(d) &&
559 cast<CXXMethodDecl>(d)->isImplicitObjectMemberFunction()) {
560 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *this);
561
562 const auto *md = cast<CXXMethodDecl>(d);
563 if (md->getParent()->isLambda() && md->getOverloadedOperator() == OO_Call) {
564 // We're in a lambda.
565 auto fn = dyn_cast<cir::FuncOp>(curFn);
566 assert(fn && "lambda in non-function region");
567 fn.setLambda(true);
568
569 // Figure out the captures.
570 md->getParent()->getCaptureFields(lambdaCaptureFields,
573 // If the lambda captures the object referred to by '*this' - either by
574 // value or by reference, make sure CXXThisValue points to the correct
575 // object.
576
577 // Get the lvalue for the field (which is a copy of the enclosing object
578 // or contains the address of the enclosing object).
579 LValue thisFieldLValue =
581 if (!lambdaThisCaptureField->getType()->isPointerType()) {
582 // If the enclosing object was captured by value, just use its
583 // address. Sign this pointer.
584 cxxThisValue = thisFieldLValue.getPointer();
585 } else {
586 // Load the lvalue pointed to by the field, since '*this' was captured
587 // by reference.
589 emitLoadOfLValue(thisFieldLValue, SourceLocation()).getValue();
590 }
591 }
592 for (auto *fd : md->getParent()->fields()) {
593 if (fd->hasCapturedVLAType())
594 cgm.errorNYI(loc, "lambda captured VLA type");
595 }
596 } else {
597 // Not in a lambda; just use 'this' from the method.
598 // FIXME: Should we generate a new load for each use of 'this'? The fast
599 // register allocator would be happier...
601 }
602
605 }
606
607 // If any of the arguments have a variably modified type, make sure to
608 // emit the type size, but only if the function is not naked. Naked functions
609 // have no prolog to run this evaluation.
610 if (!fd || !fd->hasAttr<NakedAttr>()) {
611 for (const VarDecl *vd : args) {
612 // Dig out the type as written from ParmVarDecls; it's unclear whether
613 // the standard (C99 6.9.1p10) requires this, but we're following the
614 // precedent set by gcc.
615 QualType ty;
616 if (const auto *pvd = dyn_cast<ParmVarDecl>(vd))
617 ty = pvd->getOriginalType();
618 else
619 ty = vd->getType();
620 if (ty->isVariablyModifiedType())
622 }
623 }
624}
625
627 // Pop any cleanups that might have been associated with the
628 // parameters. Do this in whatever block we're currently in; it's
629 // important to do this before we enter the return block or return
630 // edges will be *really* confused.
631 // TODO(cir): Use prologueCleanupDepth here.
632 bool hasCleanups = ehStack.stable_begin() != prologueCleanupDepth;
633 if (hasCleanups) {
635 // FIXME(cir): should we clearInsertionPoint? breaks many testcases
637 }
638
639 assert(deferredConditionalCleanupStack.empty() &&
640 "deferred conditional cleanups were not consumed by a "
641 "FullExprCleanupScope");
642}
643
644mlir::LogicalResult CIRGenFunction::emitFunctionBody(const clang::Stmt *body) {
645 // We start with function level scope for variables.
647
648 if (const CompoundStmt *block = dyn_cast<CompoundStmt>(body))
649 return emitCompoundStmtWithoutScope(*block);
650
651 return emitStmt(body, /*useCurrentScope=*/true);
652}
653
654static void eraseEmptyAndUnusedBlocks(cir::FuncOp func) {
655 // Remove any leftover blocks that are unreachable and empty, since they do
656 // not represent unreachable code useful for warnings nor anything deemed
657 // useful in general.
658 SmallVector<mlir::Block *> blocksToDelete;
659 for (mlir::Block &block : func.getBlocks()) {
660 if (block.empty() && block.getUses().empty())
661 blocksToDelete.push_back(&block);
662 }
663 for (mlir::Block *block : blocksToDelete)
664 block->erase();
665}
666
667cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
668 cir::FuncType funcType) {
669 const auto *funcDecl = cast<FunctionDecl>(gd.getDecl());
670 curGD = gd;
671
672 if (funcDecl->isInlineBuiltinDeclaration()) {
673 // When generating code for a builtin with an inline declaration, use a
674 // mangled name to hold the actual body, while keeping an external
675 // declaration in case the function pointer is referenced somewhere.
676 std::string fdInlineName = (cgm.getMangledName(funcDecl) + ".inline").str();
677 cir::FuncOp clone =
678 mlir::cast_or_null<cir::FuncOp>(cgm.getGlobalValue(fdInlineName));
679 if (!clone) {
680 mlir::OpBuilder::InsertionGuard guard(builder);
681 builder.setInsertionPoint(fn);
682 clone = cir::FuncOp::create(builder, fn.getLoc(), fdInlineName,
683 fn.getFunctionType());
684 cgm.insertGlobalSymbol(clone);
685 clone.setLinkage(cir::GlobalLinkageKind::InternalLinkage);
686 clone.setSymVisibility("private");
687 clone.setInlineKind(cir::InlineKind::AlwaysInline);
688 }
689 fn.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
690 fn.setSymVisibility("private");
691 fn = clone;
692 } else {
693 // Detect the unusual situation where an inline version is shadowed by a
694 // non-inline version. In that case we should pick the external one
695 // everywhere. That's GCC behavior too.
696 for (const FunctionDecl *pd = funcDecl->getPreviousDecl(); pd;
697 pd = pd->getPreviousDecl()) {
698 if (LLVM_UNLIKELY(pd->isInlineBuiltinDeclaration())) {
699 std::string inlineName = funcDecl->getName().str() + ".inline";
700 if (auto inlineFn = mlir::cast_or_null<cir::FuncOp>(
701 cgm.getGlobalValue(inlineName))) {
702 // Replace all uses of the .inline function with the regular function
703 // FIXME: This performs a linear walk over the module. Introduce some
704 // caching here.
705 if (inlineFn
706 .replaceAllSymbolUses(fn.getSymNameAttr(), cgm.getModule())
707 .failed())
708 llvm_unreachable("Failed to replace inline builtin symbol uses");
709 cgm.eraseGlobalSymbol(inlineFn);
710 inlineFn.erase();
711 }
712 break;
713 }
714 }
715 }
716
717 SourceLocation loc = funcDecl->getLocation();
718 Stmt *body = funcDecl->getBody();
719 SourceRange bodyRange =
720 body ? body->getSourceRange() : funcDecl->getLocation();
721
722 SourceLocRAIIObject fnLoc{*this, loc.isValid() ? getLoc(loc)
723 : builder.getUnknownLoc()};
724
725 auto validMLIRLoc = [&](clang::SourceLocation clangLoc) {
726 return clangLoc.isValid() ? getLoc(clangLoc) : builder.getUnknownLoc();
727 };
728 const mlir::Location fusedLoc = mlir::FusedLoc::get(
730 {validMLIRLoc(bodyRange.getBegin()), validMLIRLoc(bodyRange.getEnd())});
731 mlir::Block *entryBB = fn.addEntryBlock();
732
733 FunctionArgList args;
734 QualType retTy = buildFunctionArgList(gd, args);
735
736 // Create a scope in the symbol table to hold variable declarations.
738 {
739 LexicalScope lexScope(*this, fusedLoc, entryBB);
740
741 // Emit the standard function prologue.
742 startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin());
743
744 // Save parameters for coroutine function.
745 if (body && isa_and_nonnull<CoroutineBodyStmt>(body))
746 llvm::append_range(fnArgs, funcDecl->parameters());
747
748 if (isa<CXXDestructorDecl>(funcDecl)) {
749 emitDestructorBody(args);
750 } else if (isa<CXXConstructorDecl>(funcDecl)) {
752 } else if (getLangOpts().CUDA && !getLangOpts().CUDAIsDevice &&
753 funcDecl->hasAttr<CUDAGlobalAttr>()) {
754 cgm.getCUDARuntime().emitDeviceStub(*this, fn, args);
755 } else if (isa<CXXMethodDecl>(funcDecl) &&
756 cast<CXXMethodDecl>(funcDecl)->isLambdaStaticInvoker()) {
757 // The lambda static invoker function is special, because it forwards or
758 // clones the body of the function call operator (but is actually
759 // static).
761 } else if (funcDecl->isDefaulted() && isa<CXXMethodDecl>(funcDecl) &&
762 (cast<CXXMethodDecl>(funcDecl)->isCopyAssignmentOperator() ||
763 cast<CXXMethodDecl>(funcDecl)->isMoveAssignmentOperator())) {
764 // Implicit copy-assignment gets the same special treatment as implicit
765 // copy-constructors.
767 } else if (body) {
768 // Emit standard function body.
769 if (mlir::failed(emitFunctionBody(body))) {
770 return nullptr;
771 }
772 } else {
773 // Anything without a body should have been handled above.
774 llvm_unreachable("no definition for normal function");
775 }
776
777 if (mlir::failed(fn.verifyBody()))
778 return nullptr;
779
780 finishFunction(bodyRange.getEnd());
781 }
782
784 return fn;
785}
786
789 const auto *ctor = cast<CXXConstructorDecl>(curGD.getDecl());
790 CXXCtorType ctorType = curGD.getCtorType();
791
792 assert((cgm.getTarget().getCXXABI().hasConstructorVariants() ||
793 ctorType == Ctor_Complete) &&
794 "can only generate complete ctor for this ABI");
795
796 cgm.setFuncInfoAttr(cast<cir::FuncOp>(curFn), ctor);
797
798 if (ctorType == Ctor_Complete && isConstructorDelegationValid(ctor) &&
799 cgm.getTarget().getCXXABI().hasConstructorVariants()) {
800 emitDelegateCXXConstructorCall(ctor, Ctor_Base, args, ctor->getEndLoc());
801 return;
802 }
803
804 const FunctionDecl *definition = nullptr;
805 Stmt *body = ctor->getBody(definition);
806 assert(definition == ctor && "emitting wrong constructor body");
807
808 bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
809
810 // A type that handles the emission of the constructor body, that can be
811 // called directly for cases where we don't have a try-body, or passed to
812 // emitCXXTryStmt.
813 struct ctorTryBodyEmitter final : cxxTryBodyEmitter {
814 const CXXConstructorDecl *ctor = nullptr;
815 CXXCtorType ctorType;
816 FunctionArgList &args;
817 Stmt *emitterBody = nullptr;
818 ctorTryBodyEmitter(const CXXConstructorDecl *ctor, CXXCtorType ctorType,
819 FunctionArgList &args, bool isTryBody, Stmt *b)
820 : ctor(ctor), ctorType(ctorType), args(args),
821 emitterBody(isTryBody ? cast<CXXTryStmt>(b)->getTryBlock() : b) {}
822 ~ctorTryBodyEmitter() override = default;
823
824 mlir::LogicalResult operator()(CIRGenFunction &cgf) override {
827
828 //// TODO: in restricted cases, we can emit the vbase initializers of a
829 //// complete ctor and then delegate to the base ctor.
830
831 cgf.emitCtorPrologue(ctor, ctorType, args);
832 return cgf.emitStmt(emitterBody, /*useCurrentScope=*/true);
833 }
834 };
835
836 ctorTryBodyEmitter emitter{ctor, ctorType, args, isTryBody, body};
837 mlir::LogicalResult bodyRes =
838 isTryBody ? emitCXXTryStmt(*cast<CXXTryStmt>(body), emitter)
839 : emitter(*this);
840
841 // TODO(cir): propagate this result via mlir::logical result. Just
842 // unreachable now just to have it handled.
843 if (bodyRes.failed())
844 cgm.errorNYI(ctor->getSourceRange(),
845 "emitConstructorBody: emit body statement failed.");
846}
847
848/// Emits the body of the current destructor.
850 const CXXDestructorDecl *dtor = cast<CXXDestructorDecl>(curGD.getDecl());
851 CXXDtorType dtorType = curGD.getDtorType();
852
853 cgm.setFuncInfoAttr(cast<cir::FuncOp>(curFn), dtor);
854
855 // For an abstract class, non-base destructors are never used (and can't
856 // be emitted in general, because vbase dtors may not have been validated
857 // by Sema), but the Itanium ABI doesn't make them optional and Clang may
858 // in fact emit references to them from other compilations, so emit them
859 // as functions containing a trap instruction.
860 if (dtorType != Dtor_Base && dtor->getParent()->isAbstract()) {
861 SourceLocation loc =
862 dtor->hasBody() ? dtor->getBody()->getBeginLoc() : dtor->getLocation();
863 emitTrap(getLoc(loc), true);
864 return;
865 }
866
867 Stmt *body = dtor->getBody();
869
870 // The call to operator delete in a deleting destructor happens
871 // outside of the function-try-block, which means it's always
872 // possible to delegate the destructor body to the complete
873 // destructor. Do so.
874 if (dtorType == Dtor_Deleting || dtorType == Dtor_VectorDeleting) {
876 cgm.errorNYI(dtor->getSourceRange(), "emitConditionalArrayDtorCall");
877 RunCleanupsScope dtorEpilogue(*this);
879 if (haveInsertPoint()) {
881 emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase=*/false,
882 /*delegating=*/false, loadCXXThisAddress(), thisTy);
883 }
884 return;
885 }
886
887 // If the body is a function-try-block, enter the try before
888 // anything else.
889 const bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
890 if (isTryBody)
891 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");
892
894
895 // Enter the epilogue cleanups.
896 RunCleanupsScope dtorEpilogue(*this);
897
898 // If this is the complete variant, just invoke the base variant;
899 // the epilogue will destruct the virtual bases. But we can't do
900 // this optimization if the body is a function-try-block, because
901 // we'd introduce *two* handler blocks. In the Microsoft ABI, we
902 // always delegate because we might not have a definition in this TU.
903 switch (dtorType) {
904 case Dtor_Unified:
905 llvm_unreachable("not expecting a unified dtor");
906 case Dtor_Comdat:
907 llvm_unreachable("not expecting a COMDAT");
908 case Dtor_Deleting:
910 llvm_unreachable("already handled deleting case");
911
912 case Dtor_Complete:
913 assert((body || getTarget().getCXXABI().isMicrosoft()) &&
914 "can't emit a dtor without a body for non-Microsoft ABIs");
915
916 // Enter the cleanup scopes for virtual bases.
918
919 if (!isTryBody) {
921 emitCXXDestructorCall(dtor, Dtor_Base, /*forVirtualBase=*/false,
922 /*delegating=*/false, loadCXXThisAddress(), thisTy);
923 break;
924 }
925
926 // Fallthrough: act like we're in the base variant.
927 [[fallthrough]];
928
929 case Dtor_Base:
930 assert(body);
931
932 // Enter the cleanup scopes for fields and non-virtual bases.
934
936
937 if (isTryBody) {
938 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");
939 } else if (body) {
940 (void)emitStmt(body, /*useCurrentScope=*/true);
941 } else {
942 assert(dtor->isImplicit() && "bodyless dtor not implicit");
943 // nothing to do besides what's in the epilogue
944 }
945 // -fapple-kext must inline any call to this dtor into
946 // the caller's body.
948
949 break;
950 }
951
952 // Jump out through the epilogue cleanups.
953 dtorEpilogue.forceCleanup();
954
955 // Exit the try if applicable.
956 if (isTryBody)
957 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");
958}
959
960/// Given a value of type T* that may not be to a complete object, construct
961/// an l-vlaue withi the natural pointee alignment of T.
963 QualType ty) {
964 // FIXME(cir): is it safe to assume Op->getResult(0) is valid? Perhaps
965 // assert on the result type first.
966 LValueBaseInfo baseInfo;
968 CharUnits align = cgm.getNaturalTypeAlignment(ty, &baseInfo);
969 return makeAddrLValue(Address(val, align), ty, baseInfo);
970}
971
973 QualType ty) {
974 LValueBaseInfo baseInfo;
975 CharUnits alignment = cgm.getNaturalTypeAlignment(ty, &baseInfo);
976 Address addr(val, convertTypeForMem(ty), alignment);
978 return makeAddrLValue(addr, ty, baseInfo);
979}
980
982 FunctionArgList &args) {
983 const auto *fd = cast<FunctionDecl>(gd.getDecl());
984 QualType retTy = fd->getReturnType();
985
986 // Only implicit-object member functions need the CXXABI-supplied `this`
987 // parameter prepended to the arg list. Explicit-object members carry the
988 // object as a regular parameter that fd->parameters() already enumerates.
989 const auto *md = dyn_cast<CXXMethodDecl>(fd);
990 if (md && md->isImplicitObjectMemberFunction()) {
991 if (cgm.getCXXABI().hasThisReturn(gd))
992 cgm.errorNYI(fd->getSourceRange(), "this return");
993 else if (cgm.getCXXABI().hasMostDerivedReturn(gd))
994 cgm.errorNYI(fd->getSourceRange(), "most derived return");
995 cgm.getCXXABI().buildThisParam(*this, args);
996 }
997
998 bool passedParams = true;
999 if (const auto *cd = dyn_cast<CXXConstructorDecl>(fd))
1000 if (auto inherited = cd->getInheritedConstructor())
1001 passedParams =
1002 getTypes().inheritingCtorHasParams(inherited, gd.getCtorType());
1003
1004 if (passedParams) {
1005 for (auto *param : fd->parameters()) {
1006 args.push_back(param);
1007 if (!param->hasAttr<PassObjectSizeAttr>())
1008 continue;
1009
1010 auto *implicit = ImplicitParamDecl::Create(
1011 getContext(), param->getDeclContext(), param->getLocation(),
1012 /*Id=*/nullptr, getContext().getSizeType(), ImplicitParamKind::Other);
1013 sizeArguments[param] = implicit;
1014 args.push_back(implicit);
1015 }
1016 }
1017
1018 if (md && (isa<CXXConstructorDecl>(md) || isa<CXXDestructorDecl>(md)))
1019 cgm.getCXXABI().addImplicitStructorParams(*this, retTy, args);
1020
1021 return retTy;
1022}
1023
1025 // Initializing an aggregate temporary in C++11: T{...}.
1026 if (!e->isGLValue())
1027 return emitAggExprToLValue(e);
1028
1029 // An lvalue initializer list must be initializing a reference.
1030 assert(e->isTransparent() && "non-transparent glvalue init list");
1031 return emitLValue(e->getInit(0));
1032}
1033
1034static std::variant<LValue, RValue>
1036 bool forLValue, AggValueSlot slot) {
1038 SmallVector<OVMD> opaques;
1039 llvm::scope_exit opaque_cleanup{
1040 [&]() { llvm::for_each(opaques, [&](OVMD &o) { o.unbind(cgf); }); }};
1041
1042 // Find the result expression, if any.
1043 const Expr *resultExpr = e->getResultExpr();
1044 std::variant<LValue, RValue> result;
1045
1046 for (const Expr *semantic : e->semantics()) {
1047 // If this semantic expression is an opaque value, bind it
1048 // to the result of its source expression.
1049 if (const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
1050
1051 // Skip unique OVEs.
1052 if (ov->isUnique()) {
1053 assert(ov != resultExpr &&
1054 "A unique OVE cannot be used as the result expression");
1055 continue;
1056 }
1057
1058 // If this is the result expression, we may need to evaluate
1059 // directly into the slot.
1060 OVMD opaqueData;
1061 if (ov == resultExpr && ov->isPRValue() && !forLValue &&
1063 cgf.cgm.errorNYI(e->getSourceRange(),
1064 "emitPseudoObjectExpr for RValue & aggregate kind");
1065 } else {
1066 opaqueData = OVMD::bind(cgf, ov, ov->getSourceExpr());
1067
1068 // If this is the result, also evaluate the result now.
1069 if (ov == resultExpr) {
1070 // FIXME: This doesn't really affect anything, but I cannot find a
1071 // test for this, so leave an ErrorNYI here until we can find one.
1072 cgf.cgm.errorNYI(e->getSourceRange(),
1073 "emitPseudoObjectExpr as result");
1074 if (forLValue)
1075 result = cgf.emitLValue(ov);
1076 else
1077 cgf.cgm.errorNYI(e->getSourceRange(),
1078 "emitPseudoObjectExpr as an RValue");
1079 }
1080 }
1081 opaques.push_back(opaqueData);
1082 } else if (semantic == resultExpr) {
1083 // Otherwise, if the expression is the result, evaluate it
1084 // and remember the result.
1085 if (forLValue)
1086 result = cgf.emitLValue(semantic);
1087 else
1088 result = cgf.emitAnyExpr(semantic, slot);
1089 } else {
1090 // FIXME: best I can tell, this is only reachable as an r-value, so this
1091 // isn't properly tested.
1092 cgf.cgm.errorNYI(e->getSourceRange(),
1093 "emitPseudoObjectExpr as an ignored value");
1094 // Otherwise, evaluate the expression in an ignored context.
1095 cgf.emitIgnoredExpr(semantic);
1096 }
1097 }
1098
1099 return result;
1100}
1101
1103 AggValueSlot slot) {
1104 return std::get<RValue>(
1105 emitPseudoObjectExpr(*this, e, /*forLValue=*/false, slot));
1106}
1107
1109 return std::get<LValue>(emitPseudoObjectExpr(*this, e, /*forLValue=*/true,
1111}
1112
1113/// Emit code to compute a designator that specifies the location
1114/// of the expression.
1115/// FIXME: document this function better.
1118 switch (e->getStmtClass()) {
1119 default:
1121 "emitLValue: unsupported l-value class");
1122 return LValue();
1123
1124 case Expr::ObjCPropertyRefExprClass:
1125 llvm_unreachable("cannot emit a property reference directly");
1126
1127 case Expr::ObjCSelectorExprClass:
1129 "emitLValue: ObjCSelectorExpr");
1130 return LValue();
1131 case Expr::ObjCIsaExprClass:
1132 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: ObjCIsaExpr");
1133 return LValue();
1134 case Expr::BinaryOperatorClass:
1136 case Expr::CompoundAssignOperatorClass: {
1137 QualType ty = e->getType();
1138 if (const AtomicType *at = ty->getAs<AtomicType>())
1139 ty = at->getValueType();
1140 if (!ty->isAnyComplexType())
1142
1144 }
1145 case Expr::CallExprClass:
1146 case Expr::CXXMemberCallExprClass:
1147 case Expr::CXXOperatorCallExprClass:
1148 case Expr::UserDefinedLiteralClass:
1150 case Expr::CXXRewrittenBinaryOperatorClass:
1152 "emitLValue: CXXRewrittenBinaryOperator");
1153 return LValue();
1154 case Expr::VAArgExprClass:
1155 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: VAArgExpr");
1156 return LValue();
1157 case Expr::DeclRefExprClass:
1159 case Expr::ConstantExprClass:
1160 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: ConstantExpr");
1161 return LValue();
1162 case Expr::ParenExprClass:
1163 return emitLValue(cast<ParenExpr>(e)->getSubExpr());
1164 case Expr::GenericSelectionExprClass:
1165 return emitLValue(cast<GenericSelectionExpr>(e)->getResultExpr());
1166 case Expr::PredefinedExprClass:
1168 case Expr::StringLiteralClass:
1170 case Expr::ObjCEncodeExprClass:
1172 "emitLValue: ObjCEncodeExpr");
1173 return LValue();
1174 case Expr::PseudoObjectExprClass:
1176 case Expr::InitListExprClass:
1178 case Expr::CXXTemporaryObjectExprClass:
1179 case Expr::CXXConstructExprClass:
1181 case Expr::CXXBindTemporaryExprClass:
1183 case Expr::CXXUuidofExprClass:
1185 "emitLValue: CXXUuidofExpr");
1186 return LValue();
1187 case Expr::LambdaExprClass:
1188 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: LambdaExpr");
1189 return LValue();
1190 case Expr::ExprWithCleanupsClass: {
1191 const auto *cleanups = cast<ExprWithCleanups>(e);
1192 FullExprCleanupScope scope(*this, cleanups->getSubExpr());
1193 LValue lv = emitLValue(cleanups->getSubExpr());
1194 if (lv.isSimple()) {
1195 // Defend against branches out of gnu statement expressions surrounded by
1196 // cleanups.
1197 Address addr = lv.getAddress();
1198 mlir::Value v = addr.getPointer();
1199 scope.exit({&v});
1200 return LValue::makeAddr(addr.withPointer(v), lv.getType(),
1201 lv.getBaseInfo());
1202 }
1203 // FIXME: Is it possible to create an ExprWithCleanups that produces a
1204 // bitfield lvalue or some other non-simple lvalue?
1205 return lv;
1206 }
1207 case Expr::CXXDefaultArgExprClass: {
1208 auto *dae = cast<CXXDefaultArgExpr>(e);
1209 CXXDefaultArgExprScope scope(*this, dae);
1210 return emitLValue(dae->getExpr());
1211 }
1212 case Expr::CXXDefaultInitExprClass: {
1213 auto *die = cast<CXXDefaultInitExpr>(e);
1214 CXXDefaultInitExprScope scope(*this, die);
1215 return emitLValue(die->getExpr());
1216 }
1217 case Expr::CXXTypeidExprClass:
1219 case Expr::ObjCMessageExprClass:
1221 "emitLValue: ObjCMessageExpr");
1222 return LValue();
1223 case Expr::ObjCIvarRefExprClass:
1225 "emitLValue: ObjCIvarRefExpr");
1226 return LValue();
1227 case Expr::StmtExprClass:
1228 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: StmtExpr");
1229 return LValue();
1230 case Expr::UnaryOperatorClass:
1232 case Expr::ArraySubscriptExprClass:
1234 case Expr::MatrixSingleSubscriptExprClass:
1236 "emitLValue: MatrixSingleSubscriptExpr");
1237 return LValue();
1238 case Expr::MatrixSubscriptExprClass:
1240 "emitLValue: MatrixSubscriptExpr");
1241 return LValue();
1242 case Expr::ArraySectionExprClass:
1244 "emitLValue: ArraySectionExpr");
1245 return LValue();
1246 case Expr::ExtVectorElementExprClass:
1248 case Expr::MatrixElementExprClass:
1250 "emitLValue: MatrixElementExpr");
1251 return LValue();
1252 case Expr::CXXThisExprClass:
1253 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: CXXThisExpr");
1254 return LValue();
1255 case Expr::MemberExprClass:
1257 case Expr::CompoundLiteralExprClass:
1259 case Expr::ConditionalOperatorClass:
1261 case Expr::BinaryConditionalOperatorClass:
1263 case Expr::ChooseExprClass:
1264 return emitLValue(cast<ChooseExpr>(e)->getChosenSubExpr());
1265 case Expr::OpaqueValueExprClass:
1267 case Expr::SubstNonTypeTemplateParmExprClass:
1268 return emitLValue(cast<SubstNonTypeTemplateParmExpr>(e)->getReplacement());
1269 case Expr::ImplicitCastExprClass:
1270 case Expr::CStyleCastExprClass:
1271 case Expr::CXXFunctionalCastExprClass:
1272 case Expr::CXXStaticCastExprClass:
1273 case Expr::CXXDynamicCastExprClass:
1274 case Expr::CXXReinterpretCastExprClass:
1275 case Expr::CXXConstCastExprClass:
1276 return emitCastLValue(cast<CastExpr>(e));
1277 case Expr::CXXAddrspaceCastExprClass:
1278 case Expr::ObjCBridgedCastExprClass:
1279 // TODO(cir): These can just be moved into the cast handling above, but
1280 // they need test cases.
1282 "emitLValue: addrspace or ObjC bridged cast");
1283 return LValue();
1284 case Expr::MaterializeTemporaryExprClass:
1286 case Expr::CoawaitExprClass:
1287 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: CoawaitExpr");
1288 return LValue();
1289 case Expr::CoyieldExprClass:
1290 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: CoyieldExpr");
1291 return LValue();
1292 case Expr::PackIndexingExprClass:
1294 "emitLValue: PackIndexingExpr");
1295 return LValue();
1296 case Expr::HLSLOutArgExprClass:
1297 llvm_unreachable("cannot emit a HLSL out argument directly");
1298 }
1299}
1300
1301static std::string getVersionedTmpName(llvm::StringRef name, unsigned cnt) {
1302 SmallString<256> buffer;
1303 llvm::raw_svector_ostream out(buffer);
1304 out << name << cnt;
1305 return std::string(out.str());
1306}
1307
1309 return getVersionedTmpName("ref.tmp", counterRefTmp++);
1310}
1311
1313 return getVersionedTmpName("agg.tmp", counterAggTmp++);
1314}
1315
1316void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,
1317 QualType ty) {
1318 // Ignore empty classes in C++.
1319 if (getLangOpts().CPlusPlus)
1320 if (const auto *rd = ty->getAsCXXRecordDecl(); rd && rd->isEmpty())
1321 return;
1322
1323 // Cast the dest ptr to the appropriate i8 pointer type.
1324 if (builder.isInt8Ty(destPtr.getElementType())) {
1325 cgm.errorNYI(loc, "Cast the dest ptr to the appropriate i8 pointer type");
1326 }
1327
1328 // Get size and alignment info for this aggregate.
1329 const CharUnits size = getContext().getTypeSizeInChars(ty);
1330 if (size.isZero()) {
1331 // But note that getTypeInfo returns 0 for a VLA.
1332 if (isa<VariableArrayType>(getContext().getAsArrayType(ty))) {
1333 cgm.errorNYI(loc,
1334 "emitNullInitialization for zero size VariableArrayType");
1335 } else {
1336 return;
1337 }
1338 }
1339
1340 // If the type contains a pointer to data member we can't memset it to zero.
1341 // Instead, create a null constant and copy it to the destination.
1342 // TODO: there are other patterns besides zero that we can usefully memset,
1343 // like -1, which happens to be the pattern used by member-pointers.
1344 if (!cgm.getTypes().isZeroInitializable(ty)) {
1345 // Only the pointer-to-data-member case is tested here; emitNullConstant
1346 // owns the NYIs for shapes it cannot build (virtual bases, non-zero-init
1347 // arrays).
1348 assert((ty->isMemberDataPointerType() || ty->isRecordType()) &&
1349 "emitNullInitialization: only pointer-to-data-member (directly or "
1350 "within a record) null initialization is implemented");
1351 mlir::Value nullVal = cgm.emitNullConstant(ty, loc);
1352 builder.createStore(loc, nullVal, destPtr);
1353 return;
1354 }
1355
1356 // In LLVM Codegen: otherwise, just memset the whole thing to zero using
1357 // Builder.CreateMemSet. In CIR just emit a store of #cir.zero to the
1358 // respective address.
1359 // Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, false);
1360 const mlir::Value zeroValue = builder.getNullValue(convertType(ty), loc);
1361 builder.createStore(loc, zeroValue, destPtr);
1362}
1363
1365 const clang::Expr *e)
1366 : cgf(cgf) {
1367 ConstructorHelper(e->getFPFeaturesInEffect(cgf.getLangOpts()));
1368}
1369
1371 FPOptions fpFeatures)
1372 : cgf(cgf) {
1373 ConstructorHelper(fpFeatures);
1374}
1375
1376void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper(
1377 FPOptions fpFeatures) {
1378 oldFPFeatures = cgf.curFPFeatures;
1379 cgf.curFPFeatures = fpFeatures;
1380
1381 oldExcept = cgf.builder.getDefaultConstrainedExcept();
1382 oldRounding = cgf.builder.getDefaultConstrainedRounding();
1383
1384 if (oldFPFeatures == fpFeatures)
1385 return;
1386
1387 // TODO(cir): create guard to restore fast math configurations.
1389
1390 llvm::RoundingMode newRoundingMode = fpFeatures.getRoundingMode();
1391 LangOptions::FPExceptionModeKind newExceptionBehavior =
1392 fpFeatures.getExceptionMode();
1393
1394 cgf.builder.setDefaultConstrainedRounding(newRoundingMode);
1395 cgf.builder.setDefaultConstrainedExcept(newExceptionBehavior);
1396
1397 // TODO(cir): override FP flags once FM configs are guarded.
1399
1400 assert((cgf.curFuncDecl == nullptr || cgf.builder.getIsFPConstrained() ||
1401 isa<CXXConstructorDecl>(cgf.curFuncDecl) ||
1402 isa<CXXDestructorDecl>(cgf.curFuncDecl) ||
1403 (newExceptionBehavior == LangOptions::FPE_Ignore &&
1404 newRoundingMode == llvm::RoundingMode::NearestTiesToEven)) &&
1405 "FPConstrained should be enabled on entire function");
1406
1407 // TODO(cir): mark CIR function with fast math attributes.
1409}
1410
1412 cgf.curFPFeatures = oldFPFeatures;
1413 cgf.builder.setDefaultConstrainedExcept(oldExcept);
1414 cgf.builder.setDefaultConstrainedRounding(oldRounding);
1415}
1416
1417// TODO(cir): should be shared with LLVM codegen.
1419 const Expr *e = ce->getSubExpr();
1420
1421 if (ce->getCastKind() == CK_UncheckedDerivedToBase)
1422 return false;
1423
1424 if (isa<CXXThisExpr>(e->IgnoreParens())) {
1425 // We always assume that 'this' is never null.
1426 return false;
1427 }
1428
1429 if (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(ce)) {
1430 // And that glvalue casts are never null.
1431 if (ice->isGLValue())
1432 return false;
1433 }
1434
1435 return true;
1436}
1437
1438/// Computes the length of an array in elements, as well as the base
1439/// element type and a properly-typed first element pointer.
1440mlir::Value
1442 QualType &baseType, Address &addr) {
1443 const clang::ArrayType *arrayType = origArrayType;
1444
1445 // If it's a VLA, we have to load the stored size. Note that
1446 // this is the size of the VLA in bytes, not its size in elements.
1447 mlir::Value numVLAElements = nullptr;
1450
1451 // Walk into all VLAs. This doesn't require changes to addr,
1452 // which has type T* where T is the first non-VLA element type.
1453 do {
1454 QualType elementType = arrayType->getElementType();
1455 arrayType = getContext().getAsArrayType(elementType);
1456
1457 // If we only have VLA components, 'addr' requires no adjustment.
1458 if (!arrayType) {
1459 baseType = elementType;
1460 return numVLAElements;
1461 }
1463
1464 // We get out here only if we find a constant array type
1465 // inside the VLA.
1466 }
1467
1468 // Classic codegen emits an all-zero inbounds GEP to convert addr from
1469 // [M x [N x T]]* to T*. CIR doesn't need this because callers handle
1470 // the array-to-element pointer conversion themselves (via array_to_ptrdecay
1471 // casts, ptr_bitcast, or manual array type peeling).
1472
1473 uint64_t countFromCLAs = 1;
1474 QualType eltType;
1475
1476 auto cirArrayType = mlir::dyn_cast<cir::ArrayType>(addr.getElementType());
1477
1478 while (cirArrayType) {
1480 countFromCLAs *= cirArrayType.getSize();
1481 eltType = arrayType->getElementType();
1482
1483 cirArrayType =
1484 mlir::dyn_cast<cir::ArrayType>(cirArrayType.getElementType());
1485
1486 arrayType = getContext().getAsArrayType(arrayType->getElementType());
1487 assert((!cirArrayType || arrayType) &&
1488 "CIR and Clang types are out-of-sync");
1489 }
1490
1491 if (arrayType) {
1492 // From this point onwards, the Clang array type has been emitted
1493 // as some other type (probably a packed struct). Compute the array
1494 // size, and just emit the 'begin' expression as a bitcast.
1495 cgm.errorNYI(*currSrcLoc, "length for non-array underlying types");
1496 }
1497
1498 baseType = eltType;
1499
1500 mlir::Value numElements =
1501 builder.getConstInt(*currSrcLoc, sizeTy, countFromCLAs);
1502
1503 // If we had any VLA dimensions, factor them in.
1504 if (numVLAElements)
1505 numElements =
1506 builder.createMul(numVLAElements.getLoc(), numVLAElements, numElements,
1508
1509 return numElements;
1510}
1511
1513 mlir::Value ptrValue, QualType ty, SourceLocation loc,
1514 SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue) {
1516 mlir::Location assumeLoc = getLoc(assumptionLoc);
1517 mlir::Value alignValue = builder.getUInt64(alignment, assumeLoc);
1518 mlir::Value cond = builder.getBool(true, assumeLoc);
1519 llvm::SmallVector<mlir::Value> bundleArgs{ptrValue, alignValue};
1520 if (offsetValue)
1521 bundleArgs.push_back(offsetValue);
1522 cir::AssumeOp::create(builder, assumeLoc, cond, cir::AssumeBundleKind::Align,
1523 bundleArgs);
1524 return ptrValue;
1525}
1526
1528 mlir::Value ptrValue, const Expr *expr, SourceLocation assumptionLoc,
1529 int64_t alignment, mlir::Value offsetValue) {
1530 QualType ty = expr->getType();
1531 SourceLocation loc = expr->getExprLoc();
1532 return emitAlignmentAssumption(ptrValue, ty, loc, assumptionLoc, alignment,
1533 offsetValue);
1534}
1535
1537 const VariableArrayType *vla =
1538 cgm.getASTContext().getAsVariableArrayType(type);
1539 assert(vla && "type was not a variable array type!");
1540 return getVLASize(vla);
1541}
1542
1545 // The number of elements so far; always size_t.
1546 mlir::Value numElements;
1547
1548 QualType elementType;
1549 do {
1550 elementType = type->getElementType();
1551 mlir::Value vlaSize = vlaSizeMap[type->getSizeExpr()];
1552 assert(vlaSize && "no size for VLA!");
1553 assert(vlaSize.getType() == sizeTy);
1554
1555 if (!numElements) {
1556 numElements = vlaSize;
1557 } else {
1558 // It's undefined behavior if this wraps around, so mark it that way.
1559 // FIXME: Teach -fsanitize=undefined to trap this.
1560
1561 numElements =
1562 builder.createMul(numElements.getLoc(), numElements, vlaSize,
1564 }
1565 } while ((type = getContext().getAsVariableArrayType(elementType)));
1566
1567 assert(numElements && "Undefined elements number");
1568 return {numElements, elementType};
1569}
1570
1573 mlir::Value vlaSize = vlaSizeMap[vla->getSizeExpr()];
1574 assert(vlaSize && "no size for VLA!");
1575 assert(vlaSize.getType() == sizeTy);
1576 return {vlaSize, vla->getElementType()};
1577}
1578
1579// TODO(cir): Most of this function can be shared between CIRGen
1580// and traditional LLVM codegen
1582 assert(type->isVariablyModifiedType() &&
1583 "Must pass variably modified type to EmitVLASizes!");
1584
1585 // We're going to walk down into the type and look for VLA
1586 // expressions.
1587 do {
1588 assert(type->isVariablyModifiedType());
1589
1590 const Type *ty = type.getTypePtr();
1591 switch (ty->getTypeClass()) {
1592 case Type::CountAttributed:
1593 case Type::PackIndexing:
1594 case Type::ArrayParameter:
1595 case Type::HLSLAttributedResource:
1596 case Type::HLSLInlineSpirv:
1597 case Type::PredefinedSugar:
1598 case Type::LateParsedAttr:
1599 cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType");
1600 break;
1601
1602#define TYPE(Class, Base)
1603#define ABSTRACT_TYPE(Class, Base)
1604#define NON_CANONICAL_TYPE(Class, Base)
1605#define DEPENDENT_TYPE(Class, Base) case Type::Class:
1606#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)
1607#include "clang/AST/TypeNodes.inc"
1608 llvm_unreachable(
1609 "dependent type must be resolved before the CIR codegen");
1610
1611 // These types are never variably-modified.
1612 case Type::Builtin:
1613 case Type::Complex:
1614 case Type::Vector:
1615 case Type::ExtVector:
1616 case Type::ConstantMatrix:
1617 case Type::Record:
1618 case Type::Enum:
1619 case Type::Using:
1620 case Type::TemplateSpecialization:
1621 case Type::ObjCTypeParam:
1622 case Type::ObjCObject:
1623 case Type::ObjCInterface:
1624 case Type::ObjCObjectPointer:
1625 case Type::BitInt:
1626 case Type::OverflowBehavior:
1627 llvm_unreachable("type class is never variably-modified!");
1628
1629 case Type::Adjusted:
1630 type = cast<clang::AdjustedType>(ty)->getAdjustedType();
1631 break;
1632
1633 case Type::Decayed:
1634 type = cast<clang::DecayedType>(ty)->getPointeeType();
1635 break;
1636
1637 case Type::Pointer:
1638 type = cast<clang::PointerType>(ty)->getPointeeType();
1639 break;
1640
1641 case Type::BlockPointer:
1642 type = cast<clang::BlockPointerType>(ty)->getPointeeType();
1643 break;
1644
1645 case Type::LValueReference:
1646 case Type::RValueReference:
1647 type = cast<clang::ReferenceType>(ty)->getPointeeType();
1648 break;
1649
1650 case Type::MemberPointer:
1651 type = cast<clang::MemberPointerType>(ty)->getPointeeType();
1652 break;
1653
1654 case Type::ConstantArray:
1655 case Type::IncompleteArray:
1656 // Losing element qualification here is fine.
1657 type = cast<clang::ArrayType>(ty)->getElementType();
1658 break;
1659
1660 case Type::VariableArray: {
1661 // Losing element qualification here is fine.
1663
1664 // Unknown size indication requires no size computation.
1665 // Otherwise, evaluate and record it.
1666 if (const Expr *sizeExpr = vat->getSizeExpr()) {
1667 // It's possible that we might have emitted this already,
1668 // e.g. with a typedef and a pointer to it.
1669 mlir::Value &entry = vlaSizeMap[sizeExpr];
1670 if (!entry) {
1671 mlir::Value size = emitScalarExpr(sizeExpr);
1673
1674 // Always zexting here would be wrong if it weren't
1675 // undefined behavior to have a negative bound.
1676 // FIXME: What about when size's type is larger than size_t?
1677 entry = builder.createBoolIntToIntCast(size, sizeTy);
1678 }
1679 }
1680 type = vat->getElementType();
1681 break;
1682 }
1683
1684 case Type::FunctionProto:
1685 case Type::FunctionNoProto:
1686 type = cast<clang::FunctionType>(ty)->getReturnType();
1687 break;
1688
1689 case Type::Paren:
1690 case Type::TypeOf:
1691 case Type::UnaryTransform:
1692 case Type::Attributed:
1693 case Type::BTFTagAttributed:
1694 case Type::SubstTemplateTypeParm:
1695 case Type::MacroQualified:
1696 // Keep walking after single level desugaring.
1697 type = type.getSingleStepDesugaredType(getContext());
1698 break;
1699
1700 case Type::Typedef:
1701 case Type::Decltype:
1702 case Type::Auto:
1703 case Type::DeducedTemplateSpecialization:
1704 // Stop walking: nothing to do.
1705 return;
1706
1707 case Type::TypeOfExpr:
1708 // Stop walking: emit typeof expression.
1709 emitIgnoredExpr(cast<clang::TypeOfExprType>(ty)->getUnderlyingExpr());
1710 return;
1711
1712 case Type::Atomic:
1713 type = cast<clang::AtomicType>(ty)->getValueType();
1714 break;
1715
1716 case Type::Pipe:
1717 type = cast<clang::PipeType>(ty)->getElementType();
1718 break;
1719 }
1720 } while (type->isVariablyModifiedType());
1721}
1722
1724 if (getContext().getBuiltinVaListType()->isArrayType())
1725 return emitPointerWithAlignment(e);
1726 return emitLValue(e).getAddress();
1727}
1728
1729} // namespace clang::CIRGen
Defines the clang::Expr interface and subclasses for C++ expressions.
APSInt & getInt()
Definition APValue.h:511
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
SourceManager & getSourceManager()
Definition ASTContext.h:884
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.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3836
QualType getElementType() const
Definition TypeBase.h:3848
Address withPointer(mlir::Value newPtr) const
Return address with different pointer, but same element type and alignment.
Definition Address.h:83
mlir::Value getPointer() const
Definition Address.h:98
mlir::Type getElementType() const
Definition Address.h:125
static Address invalid()
Definition Address.h:76
An aggregate value slot.
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
mlir::Value createFloatingCast(mlir::Value v, mlir::Type destType)
CIRGenFPOptionsRAII(CIRGenFunction &cgf, FPOptions FPFeatures)
void exit(ArrayRef< mlir::Value * > valuesToReload={})
A non-RAII class containing all the information about a bound opaque value.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void forceCleanup(ArrayRef< mlir::Value * > valuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
static bool isConstructorDelegationValid(const clang::CXXConstructorDecl *ctor)
Checks whether the given constructor is a valid subject for the complete-to-base constructor delegati...
void emitFunctionProlog(const FunctionArgList &args, mlir::Block *entryBB, const FunctionDecl *fd, SourceLocation bodyBeginLoc)
Emit the function prologue: declare function arguments in the symbol table.
mlir::Type convertType(clang::QualType t)
LValue emitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *e)
LValue emitOpaqueValueLValue(const OpaqueValueExpr *e)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
EHScopeStack::stable_iterator prologueCleanupDepth
The cleanup depth enclosing all the cleanups associated with the parameters.
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
CIRGenTypes & getTypes() const
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
void emitVariablyModifiedType(QualType ty)
RValue emitLoadOfLValue(LValue lv, SourceLocation loc)
Given an expression that represents a value lvalue, this method emits the address of the lvalue,...
const clang::LangOptions & getLangOpts() const
void emitTrap(mlir::Location loc, bool createNewBlock)
Emit a trap instruction, which is used to abort the program in an abnormal way, usually for debugging...
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t)
Given a value of type T* that may not be to a complete object, construct an l-vlaue withi the natural...
LValue emitMemberExpr(const MemberExpr *e)
const TargetInfo & getTarget() const
LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr)
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
const clang::Decl * curFuncDecl
LValue emitLValueForLambdaField(const FieldDecl *field)
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
llvm::DenseMap< const Expr *, mlir::Value > vlaSizeMap
bool constantFoldsToSimpleInteger(const clang::Expr *cond, llvm::APSInt &resultInt, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does fold but contains a label,...
LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
void emitDelegateCXXConstructorCall(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, const FunctionArgList &args, clang::SourceLocation loc)
VlaSizePair getVLAElements1D(const VariableArrayType *vla)
Return the number of elements for a single dimension for the given array type.
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...
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
LValue emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e)
llvm::ScopedHashTableScope< const clang::Decl *, mlir::Value > SymTableScopeTy
mlir::Operation * curFn
The current function or global initializer that is generated code for.
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void enterDtorCleanups(const CXXDestructorDecl *dtor, CXXDtorType type)
Enter the cleanups necessary to complete the given phase of destruction for a destructor.
llvm::SmallVector< const ParmVarDecl * > fnArgs
Save Parameter Decl for coroutine.
llvm::SmallVector< PendingCleanupEntry > deferredConditionalCleanupStack
std::optional< mlir::Value > fnRetAlloca
The compiler-generated variable that holds the return value.
void emitImplicitAssignmentOperatorBody(FunctionArgList &args)
mlir::Type convertTypeForMem(QualType t)
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback)
clang::QualType buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args)
void emitCtorPrologue(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, FunctionArgList &args)
This routine generates necessary code to initialize base classes and non-static data members belongin...
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, mlir::Location loc, clang::CharUnits alignment, bool insertIntoFnEntryBlock, mlir::Value arraySize=nullptr)
LValue emitAggExprToLValue(const Expr *e)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
Address returnValue
The temporary alloca to hold the return value.
static bool hasAggregateEvaluationKind(clang::QualType type)
void finishFunction(SourceLocation endLoc)
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body)
LValue emitUnaryOpLValue(const clang::UnaryOperator *e)
clang::FieldDecl * lambdaThisCaptureField
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
void emitConstructorBody(FunctionArgList &args)
LValue emitCallExprLValue(const clang::CallExpr *e)
bool haveInsertPoint() const
True if an insertion point is defined.
LValue emitStringLiteralLValue(const StringLiteral *e, llvm::StringRef name=".str")
llvm::SmallDenseMap< const ParmVarDecl *, const ImplicitParamDecl * > sizeArguments
If a ParmVarDecl had the pass_object_size attribute, this will contain a mapping from said ParmVarDec...
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
LValue emitPseudoObjectLValue(const PseudoObjectExpr *E)
void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth, ArrayRef< mlir::Value * > valuesToReload={})
Takes the old cleanup stack size and emits the cleanup blocks that have been added.
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
bool didCallStackSave
Whether a cir.stacksave operation has been added.
LValue emitBinaryOperatorLValue(const BinaryOperator *e)
void startFunction(clang::GlobalDecl gd, clang::QualType returnType, cir::FuncOp fn, cir::FuncType funcType, FunctionArgList args, clang::SourceLocation loc, clang::SourceLocation startLoc)
Emit code for the start of a function.
unsigned counterRefTmp
Hold counters for incrementally naming temporaries.
mlir::MLIRContext & getMLIRContext()
void emitDestructorBody(FunctionArgList &args)
Emits the body of the current destructor.
LValue emitInitListLValue(const InitListExpr *e)
LValue emitCastLValue(const CastExpr *e)
Casts are never lvalues unless that cast is to a reference type.
LValue emitCXXTypeidLValue(const CXXTypeidExpr *e)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
RValue emitPseudoObjectRValue(const PseudoObjectExpr *e, AggValueSlot slot=AggValueSlot::ignored())
LValue emitDeclRefLValue(const clang::DeclRefExpr *e)
llvm::DenseMap< const clang::ValueDecl *, clang::FieldDecl * > lambdaCaptureFields
mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty, SourceLocation loc, SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue=nullptr)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
LValue emitPredefinedLValue(const PredefinedExpr *e)
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
Emit code to compute the specified expression which can have any type.
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
void emitLambdaStaticInvokeBody(const CXXMethodDecl *md)
CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e)
LValue emitExtVectorElementExpr(const ExtVectorElementExpr *e)
clang::ASTContext & getContext() const
void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
Set the address of a local variable.
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
Address emitVAListRef(const Expr *e)
Build a "reference" to a va_list; this is either the address or the value of the expression,...
mlir::LogicalResult emitCompoundStmtWithoutScope(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
LValue emitCXXConstructLValue(const CXXConstructExpr *e)
LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e)
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
bool inheritingCtorHasParams(const InheritedConstructor &inherited, CXXCtorType type)
Determine if a C++ inheriting constructor should have parameters matching those of its inherited cons...
Type for representing both the decl and type of parameters to a function.
Definition CIRGenCall.h:193
Address getAddress() const
static LValue makeAddr(Address address, clang::QualType t, LValueBaseInfo baseInfo)
clang::QualType getType() const
mlir::Value getPointer() const
LValueBaseInfo getBaseInfo() const
bool isSimple() const
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:57
Represents a C++ constructor within a class.
Definition DeclCXX.h:2637
Represents a C++ destructor within a class.
Definition DeclCXX.h:2902
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2288
QualType getFunctionObjectParameterType() const
Definition DeclCXX.h:2312
bool isAbstract() const
Determine whether this class has a pure virtual function.
Definition DeclCXX.h:1226
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
Definition DeclCXX.h:1191
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3687
CastKind getCastKind() const
Definition Expr.h:3731
Expr * getSubExpr()
Definition Expr.h:3737
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1749
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:601
Decl * getNonClosureContext()
Find the innermost non-closure ancestor of this declaration, walking up through blocks,...
SourceLocation getLocation() const
Definition DeclBase.h:447
bool hasAttr() const
Definition DeclBase.h:585
This represents one expression.
Definition Expr.h:112
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isGLValue() const
Definition Expr.h:287
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Returns the set of floating point options that apply to this expression.
Definition Expr.cpp:4002
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3097
bool isPRValue() const
Definition Expr.h:285
QualType getType() const
Definition Expr.h:144
LangOptions::FPExceptionModeKind getExceptionMode() const
RoundingMode getRoundingMode() const
Represents a function declaration or definition.
Definition Decl.h:2058
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition Decl.cpp:3267
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4612
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3187
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
CXXCtorType getCtorType() const
Definition GlobalDecl.h:108
const Decl * getDecl() const
Definition GlobalDecl.h:106
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition Expr.h:3864
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Definition Decl.cpp:5665
Describes an C or C++ initializer list.
Definition Expr.h:5319
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
Definition Expr.cpp:2473
const Expr * getInit(unsigned Init) const
Definition Expr.h:5374
FPExceptionModeKind
Possible floating point exception behavior.
@ FPE_Ignore
Assume that floating-point exceptions are masked.
FPExceptionModeKind getDefaultExceptionMode() const
RoundingMode getDefaultRoundingMode() const
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition Expr.h:6821
Expr * getResultExpr()
Return the result-bearing expression, or null if there is none.
Definition Expr.h:6869
ArrayRef< Expr * > semantics()
Definition Expr.h:6893
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:2996
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8598
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
Definition Stmt.h:85
child_iterator child_begin()
Definition Stmt.h:1600
StmtClass getStmtClass() const
Definition Stmt.h:1502
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
child_iterator child_end()
Definition Stmt.h:1601
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
bool isVoidType() const
Definition TypeBase.h:9113
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isMemberDataPointerType() const
Definition TypeBase.h:8833
bool isAnyComplexType() const
Definition TypeBase.h:8876
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2877
TypeClass getTypeClass() const
Definition TypeBase.h:2449
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9340
bool isRecordType() const
Definition TypeBase.h:8868
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2171
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4080
Expr * getSizeExpr() const
Definition TypeBase.h:4094
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
static bool previousOpIsNonYieldingCleanup(mlir::Block *block)
static std::string getVersionedTmpName(llvm::StringRef name, unsigned cnt)
static bool mayDropFunctionReturn(const ASTContext &astContext, QualType returnType)
static mlir::Value emitArgumentDemotion(CIRGenFunction &cgf, const VarDecl *var, mlir::Value value)
An argument came in as a promoted argument; demote it back to its declared type.
static void eraseEmptyAndUnusedBlocks(cir::FuncOp func)
static std::variant< LValue, RValue > emitPseudoObjectExpr(CIRGenFunction &cgf, const PseudoObjectExpr *e, bool forLValue, AggValueSlot slot)
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
CXXCtorType
C++ constructor types.
Definition ABI.h:24
@ Ctor_Base
Base object ctor.
Definition ABI.h:26
@ Ctor_Complete
Complete object ctor.
Definition ABI.h:25
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus
CXXDtorType
C++ destructor types.
Definition ABI.h:34
@ Dtor_VectorDeleting
Vector deleting dtor.
Definition ABI.h:40
@ Dtor_Comdat
The COMDAT used for dtors.
Definition ABI.h:38
@ Dtor_Unified
GCC-style unified dtor.
Definition ABI.h:39
@ Dtor_Base
Base object dtor.
Definition ABI.h:37
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
@ Dtor_Deleting
Deleting dtor.
Definition ABI.h:35
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Other
Other implicit parameter.
Definition Decl.h:1774
static bool fastMathFuncAttributes()
static bool vtableInitialization()
static bool constructABIArgDirectExtend()
static bool runCleanupsScope()
static bool emitTypeCheck()
static bool fastMathGuard()
static bool fastMathFlags()
static bool generateDebugInfo()
static bool incrementProfileCounter()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
llvm::ArrayRef< mlir::Block * > getRetBlocks()
LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
mlir::Location getRetLoc(mlir::Block *b)
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:657
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:659