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