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