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