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