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 // Declare all the function arguments in the symbol table.
466 for (const auto nameValue : llvm::zip(args, entryBB->getArguments())) {
467 const VarDecl *paramVar = std::get<0>(nameValue);
468 mlir::Value paramVal = std::get<1>(nameValue);
469 CharUnits alignment = getContext().getDeclAlign(paramVar);
470 mlir::Location paramLoc = getLoc(paramVar->getSourceRange());
471 paramVal.setLoc(paramLoc);
472
473 mlir::Value addrVal =
474 emitAlloca(cast<NamedDecl>(paramVar)->getName(),
475 convertType(paramVar->getType()), paramLoc, alignment,
476 /*insertIntoFnEntryBlock=*/true);
477
478 mlir::ptr::MemorySpaceAttrInterface destAddrSpace =
480 paramVar->getType().getAddressSpace());
481 Address addr = Address(addrVal, alignment);
482 addr = maybeCastStackAddressSpace(addr, destAddrSpace);
483
484 declare(addr.getPointer(), paramVar, paramVar->getType(), paramLoc,
485 alignment,
486 /*isParam=*/true);
487
488 setAddrOfLocalVar(paramVar, addr);
489
490 bool isPromoted = isa<ParmVarDecl>(paramVar) &&
491 cast<ParmVarDecl>(paramVar)->isKNRPromoted();
493 if (isPromoted)
494 paramVal = emitArgumentDemotion(*this, paramVar, paramVal);
495
496 // Location of the store to the param storage tracked as beginning of
497 // the function body.
498 mlir::Location fnBodyBegin = getLoc(bodyBeginLoc);
499 builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal,
500 addr.getPointer());
501 }
502 assert(builder.getInsertionBlock() && "Should be valid");
503}
504
506 cir::FuncOp fn, cir::FuncType funcType,
508 SourceLocation startLoc) {
509 assert(!curFn &&
510 "CIRGenFunction can only be used for one function at a time");
511
512 curFn = fn;
513
514 const Decl *d = gd.getDecl();
515
516 didCallStackSave = false;
517 curCodeDecl = d;
518 const auto *fd = dyn_cast_or_null<FunctionDecl>(d);
519 curFuncDecl = (d ? d->getNonClosureContext() : nullptr);
520
521 // Recursion is disallowed for C++ main, OpenCL, HLSL, SYCL device code and
522 // CUDA/HIP kernels.
523 if (fd &&
524 ((getLangOpts().CPlusPlus && fd->isMain()) || getLangOpts().OpenCL ||
525 getLangOpts().HLSL || getLangOpts().SYCLIsDevice ||
526 (getLangOpts().CUDA && fd->hasAttr<CUDAGlobalAttr>())))
527 fn->setAttr(cir::CIRDialect::getNoRecurseAttrName(),
528 mlir::UnitAttr::get(fn.getContext()));
529
530 // This is an artifact of the legacy handling of constrained floating-point
531 // modes. The rounding mode and exception behavior tracked in
532 // clang::LangOptions don't correspond directly to the representation we
533 // use in CIR, but the CIR settings can be derived from them. We track the
534 // default state using the legacy settings because it keeps the tracking in
535 // sync with classic codegen.
536 llvm::RoundingMode rm = getLangOpts().getDefaultRoundingMode();
538 builder.setDefaultConstrainedRounding(rm);
539 builder.setDefaultConstrainedExcept(eb);
540 builder.setIsFPConstrained(false);
541 if ((fd && (fd->UsesFPIntrin() || fd->hasAttr<StrictFPAttr>())) ||
543 rm != llvm::RoundingMode::NearestTiesToEven))) {
544 builder.setIsFPConstrained(true);
545 fn->setAttr(cir::CIRDialect::getStrictFPAttrName(),
546 mlir::UnitAttr::get(fn.getContext()));
547 }
548 mlir::Block *entryBB = &fn.getBlocks().front();
549 builder.setInsertionPointToStart(entryBB);
550
551 // Wrap the rest of the function in a filter try when this declaration has
552 // a dynamic exception specification. Parameter cleanups are pushed after
553 // this so they nest inside the specification, matching classic codegen.
555 prologueCleanupDepth = ehStack.stable_begin();
556
557 // Determine the function body begin location for the prolog.
558 // If fd is null or has no body, use startLoc as fallback.
559 SourceLocation bodyBeginLoc = startLoc;
560 if (fd) {
561 if (Stmt *body = fd->getBody())
562 bodyBeginLoc = body->getBeginLoc();
563 else
564 bodyBeginLoc = fd->getLocation();
565 }
566
567 emitFunctionProlog(args, entryBB, fd, bodyBeginLoc);
568
569 // When the current function is not void, create an address to store the
570 // result value.
571 if (!returnType->isVoidType()) {
572 // Determine the function body end location.
573 // If fd is null or has no body, use loc as fallback.
574 SourceLocation bodyEndLoc = loc;
575 if (fd) {
576 if (Stmt *body = fd->getBody())
577 bodyEndLoc = body->getEndLoc();
578 else
579 bodyEndLoc = fd->getLocation();
580 }
581 emitAndUpdateRetAlloca(returnType, getLoc(bodyEndLoc),
582 getContext().getTypeAlignInChars(returnType));
583
584 // If this is an implicit-return-zero function, initialize the return
585 // value. This mirrors the implicit-return-zero handling in classic
586 // codegen's EmitFunctionProlog (CGCall.cpp). It is done here, after
587 // emitAndUpdateRetAlloca, because in CIR the return slot is created
588 // after the prolog (the opposite of classic codegen, where ReturnValue
589 // is set up before EmitFunctionProlog runs).
590 // TODO(cir): Align prolog handling with classic codegen.
591 if (fd && fd->hasImplicitReturnZero()) {
592 mlir::Type cirRetTy = convertType(returnType.getUnqualifiedType());
593 mlir::Location bodyBeginMLIRLoc = getLoc(bodyBeginLoc);
594 mlir::Value zero = builder.getNullValue(cirRetTy, bodyBeginMLIRLoc);
595 builder.CIRBaseBuilderTy::createStore(bodyBeginMLIRLoc, zero,
596 returnValue.getPointer());
597 }
598 }
599
600 if (const auto *md = dyn_cast_if_present<CXXMethodDecl>(d);
601 md && !md->isStatic()) {
602 bool isInLambda =
603 md->getParent()->isLambda() && md->getOverloadedOperator() == OO_Call;
604
605 if (md->isImplicitObjectMemberFunction())
606 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *this);
607
608 if (isInLambda) {
609 // We're in a lambda; figure out the captures.
610 auto fn = cast<cir::FuncOp>(curFn);
611 fn.setLambda(true);
612
613 md->getParent()->getCaptureFields(lambdaCaptureFields,
616 // If the lambda captures the object referred to by '*this' - either by
617 // value or by reference, make sure CXXThisValue points to the correct
618 // object.
619
620 // Get the lvalue for the field (which is a copy of the enclosing object
621 // or contains the address of the enclosing object).
622 LValue thisFieldLValue =
624 if (!lambdaThisCaptureField->getType()->isPointerType()) {
625 // If the enclosing object was captured by value, just use its
626 // address. Sign this pointer.
627 cxxThisValue = thisFieldLValue.getPointer();
628 } else {
629 // Load the lvalue pointed to by the field, since '*this' was captured
630 // by reference.
632 emitLoadOfLValue(thisFieldLValue, SourceLocation()).getValue();
633 }
634 }
635 for (auto *fd : md->getParent()->fields()) {
636 if (fd->hasCapturedVLAType())
637 cgm.errorNYI(loc, "lambda captured VLA type");
638 }
639 } else if (md->isImplicitObjectMemberFunction()) {
640 // Not in a lambda; just use 'this' from the method.
641 // FIXME: Should we generate a new load for each use of 'this'? The fast
642 // register allocator would be happier...
644 }
645
648 }
649
650 // If any of the arguments have a variably modified type, make sure to
651 // emit the type size, but only if the function is not naked. Naked functions
652 // have no prolog to run this evaluation.
653 if (!fd || !fd->hasAttr<NakedAttr>()) {
654 for (const VarDecl *vd : args) {
655 // Dig out the type as written from ParmVarDecls; it's unclear whether
656 // the standard (C99 6.9.1p10) requires this, but we're following the
657 // precedent set by gcc.
658 QualType ty;
659 if (const auto *pvd = dyn_cast<ParmVarDecl>(vd))
660 ty = pvd->getOriginalType();
661 else
662 ty = vd->getType();
663 if (ty->isVariablyModifiedType())
665 }
666 }
667}
668
670 // Pop any cleanups that might have been associated with the
671 // parameters. Do this in whatever block we're currently in; it's
672 // important to do this before we enter the return block or return
673 // edges will be *really* confused.
674 // TODO(cir): Use prologueCleanupDepth here.
675 bool hasCleanups = ehStack.stable_begin() != prologueCleanupDepth;
676 if (hasCleanups) {
678 // FIXME(cir): should we clearInsertionPoint? breaks many testcases
680 }
681
682 assert(deferredConditionalCleanupStack.empty() &&
683 "deferred conditional cleanups were not consumed by a "
684 "FullExprCleanupScope");
685
687}
688
689mlir::LogicalResult CIRGenFunction::emitFunctionBody(const clang::Stmt *body) {
690 // We start with function level scope for variables.
692
693 if (const CompoundStmt *block = dyn_cast<CompoundStmt>(body))
694 return emitCompoundStmtWithoutScope(*block);
695
696 return emitStmt(body, /*useCurrentScope=*/true);
697}
698
700 // Remove any leftover blocks that are unreachable and empty, since they do
701 // not represent unreachable code useful for warnings nor anything deemed
702 // useful in general.
703 SmallVector<mlir::Block *> blocksToDelete;
704 for (mlir::Block &block : func.getBlocks()) {
705 if (block.empty() && block.getUses().empty())
706 blocksToDelete.push_back(&block);
707 }
708 for (mlir::Block *block : blocksToDelete)
709 block->erase();
710}
711
712cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
713 cir::FuncType funcType) {
714 const auto *funcDecl = cast<FunctionDecl>(gd.getDecl());
715 curGD = gd;
716
717 if (funcDecl->isInlineBuiltinDeclaration()) {
718 // When generating code for a builtin with an inline declaration, use a
719 // mangled name to hold the actual body, while keeping an external
720 // declaration in case the function pointer is referenced somewhere.
721 std::string fdInlineName = (cgm.getMangledName(funcDecl) + ".inline").str();
722 cir::FuncOp clone =
723 mlir::cast_or_null<cir::FuncOp>(cgm.getGlobalValue(fdInlineName));
724 if (!clone) {
725 mlir::OpBuilder::InsertionGuard guard(builder);
726 builder.setInsertionPoint(fn);
727 clone = cir::FuncOp::create(builder, fn.getLoc(), fdInlineName,
728 fn.getFunctionType());
729 cgm.insertGlobalSymbol(clone);
730 clone.setLinkage(cir::GlobalLinkageKind::InternalLinkage);
731 clone.setSymVisibility("private");
732 clone.setInlineKind(cir::InlineKind::AlwaysInline);
733 }
734 fn.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
735 fn.setSymVisibility("private");
736 fn = clone;
737 } else {
738 // Detect the unusual situation where an inline version is shadowed by a
739 // non-inline version. In that case we should pick the external one
740 // everywhere. That's GCC behavior too.
741 for (const FunctionDecl *pd = funcDecl->getPreviousDecl(); pd;
742 pd = pd->getPreviousDecl()) {
743 if (LLVM_UNLIKELY(pd->isInlineBuiltinDeclaration())) {
744 std::string inlineName = funcDecl->getName().str() + ".inline";
745 if (auto inlineFn = mlir::cast_or_null<cir::FuncOp>(
746 cgm.getGlobalValue(inlineName))) {
747 // Replace all uses of the .inline function with the regular function
748 // FIXME: This performs a linear walk over the module. Introduce some
749 // caching here.
750 if (inlineFn
751 .replaceAllSymbolUses(fn.getSymNameAttr(), cgm.getModule())
752 .failed())
753 llvm_unreachable("Failed to replace inline builtin symbol uses");
754 cgm.eraseGlobalSymbol(inlineFn);
755 inlineFn.erase();
756 }
757 break;
758 }
759 }
760 }
761
762 SourceLocation loc = funcDecl->getLocation();
763 Stmt *body = funcDecl->getBody();
764 SourceRange bodyRange =
765 body ? body->getSourceRange() : funcDecl->getLocation();
766
767 SourceLocRAIIObject fnLoc{*this, funcDecl->getSourceRange()};
768
769 auto validMLIRLoc = [&](clang::SourceLocation clangLoc) {
770 return clangLoc.isValid() ? getLoc(clangLoc) : builder.getUnknownLoc();
771 };
772 const mlir::Location fusedLoc = mlir::FusedLoc::get(
774 {validMLIRLoc(bodyRange.getBegin()), validMLIRLoc(bodyRange.getEnd())});
775 mlir::Block *entryBB = fn.addEntryBlock();
776
777 FunctionArgList args;
778 QualType retTy = buildFunctionArgList(gd, args);
779
780 // Create a scope in the symbol table to hold variable declarations.
782 {
783 LexicalScope lexScope(*this, fusedLoc, entryBB);
784
785 // Emit the standard function prologue.
786 startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin());
787
788 // Save parameters for coroutine function.
789 if (body && isa_and_nonnull<CoroutineBodyStmt>(body))
790 llvm::append_range(fnArgs, funcDecl->parameters());
791
793 fn->setAttr(cir::CIRDialect::getMustProgressAttrName(),
794 mlir::UnitAttr::get(&getMLIRContext()));
795
796 if (shouldEmitLifetimeMarkers)
797 fnHasBypassStmt = functionMightHaveBypass(body);
798
799 if (isa<CXXDestructorDecl>(funcDecl)) {
800 emitDestructorBody(args);
801 } else if (isa<CXXConstructorDecl>(funcDecl)) {
803 } else if (getLangOpts().CUDA && !getLangOpts().CUDAIsDevice &&
804 funcDecl->hasAttr<CUDAGlobalAttr>()) {
805 cgm.getCUDARuntime().emitDeviceStub(*this, fn, args);
806 } else if (isa<CXXMethodDecl>(funcDecl) &&
807 cast<CXXMethodDecl>(funcDecl)->isLambdaStaticInvoker()) {
808 // The lambda static invoker function is special, because it forwards or
809 // clones the body of the function call operator (but is actually
810 // static).
812 } else if (funcDecl->isDefaulted() && isa<CXXMethodDecl>(funcDecl) &&
813 (cast<CXXMethodDecl>(funcDecl)->isCopyAssignmentOperator() ||
814 cast<CXXMethodDecl>(funcDecl)->isMoveAssignmentOperator())) {
815 // Implicit copy-assignment gets the same special treatment as implicit
816 // copy-constructors.
818 } else if (body) {
819 // Emit standard function body.
820 if (mlir::failed(emitFunctionBody(body))) {
821 return nullptr;
822 }
823 } else {
824 // Anything without a body should have been handled above.
825 llvm_unreachable("no definition for normal function");
826 }
827
828 // Finish the function (including closing a dynamic exception
829 // specification try) before verifying so the try body is terminated.
830 finishFunction(bodyRange.getEnd());
831
832 if (mlir::failed(fn.verifyBody()))
833 return nullptr;
834 }
835
836 if (getLangOpts().OpenCL && funcDecl->hasAttr<DeviceKernelAttr>())
837 cgm.emitOpenCLKernelArgMetadata(fn, funcDecl);
838
840 return fn;
841}
842
845 const auto *ctor = cast<CXXConstructorDecl>(curGD.getDecl());
846 CXXCtorType ctorType = curGD.getCtorType();
847
848 assert((cgm.getTarget().getCXXABI().hasConstructorVariants() ||
849 ctorType == Ctor_Complete) &&
850 "can only generate complete ctor for this ABI");
851
852 cgm.setFuncInfoAttr(cast<cir::FuncOp>(curFn), ctor);
853
854 if (ctorType == Ctor_Complete && isConstructorDelegationValid(ctor) &&
855 cgm.getTarget().getCXXABI().hasConstructorVariants()) {
856 emitDelegateCXXConstructorCall(ctor, Ctor_Base, args, ctor->getEndLoc());
857 return;
858 }
859
860 const FunctionDecl *definition = nullptr;
861 Stmt *body = ctor->getBody(definition);
862 assert(definition == ctor && "emitting wrong constructor body");
863
864 bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
865
866 // A type that handles the emission of the constructor body, that can be
867 // called directly for cases where we don't have a try-body, or passed to
868 // emitCXXTryStmt.
869 struct ctorTryBodyEmitter final : cxxTryBodyEmitter {
870 const CXXConstructorDecl *ctor = nullptr;
871 CXXCtorType ctorType;
872 FunctionArgList &args;
873 Stmt *emitterBody = nullptr;
874 ctorTryBodyEmitter(const CXXConstructorDecl *ctor, CXXCtorType ctorType,
875 FunctionArgList &args, bool isTryBody, Stmt *b)
876 : ctor(ctor), ctorType(ctorType), args(args),
877 emitterBody(isTryBody ? cast<CXXTryStmt>(b)->getTryBlock() : b) {}
878 ~ctorTryBodyEmitter() override = default;
879
880 mlir::LogicalResult operator()(CIRGenFunction &cgf) override {
883
884 //// TODO: in restricted cases, we can emit the vbase initializers of a
885 //// complete ctor and then delegate to the base ctor.
886
887 cgf.emitCtorPrologue(ctor, ctorType, args);
888 return cgf.emitStmt(emitterBody, /*useCurrentScope=*/true);
889 }
890 };
891
892 ctorTryBodyEmitter emitter{ctor, ctorType, args, isTryBody, body};
893 mlir::LogicalResult bodyRes =
894 isTryBody ? emitCXXTryStmt(*cast<CXXTryStmt>(body), emitter,
895 /*isFnTryBlock=*/true)
896 : emitter(*this);
897
898 // TODO(cir): propagate this result via mlir::logical result. Just
899 // unreachable now just to have it handled.
900 if (bodyRes.failed())
901 cgm.errorNYI(ctor->getSourceRange(),
902 "emitConstructorBody: emit body statement failed.");
903}
904
905/// Emits the body of the current destructor.
907 const CXXDestructorDecl *dtor = cast<CXXDestructorDecl>(curGD.getDecl());
908 CXXDtorType dtorType = curGD.getDtorType();
909
910 cgm.setFuncInfoAttr(cast<cir::FuncOp>(curFn), dtor);
911
912 // For an abstract class, non-base destructors are never used (and can't
913 // be emitted in general, because vbase dtors may not have been validated
914 // by Sema), but the Itanium ABI doesn't make them optional and Clang may
915 // in fact emit references to them from other compilations, so emit them
916 // as functions containing a trap instruction.
917 Stmt *body = dtor->getBody();
918 if (dtorType != Dtor_Base && dtor->getParent()->isAbstract()) {
919 SourceLocation loc = body ? body->getBeginLoc() : dtor->getLocation();
920 emitTrap(getLoc(loc), true);
921 return;
922 }
923
925
926 // The call to operator delete in a deleting destructor happens
927 // outside of the function-try-block, which means it's always
928 // possible to delegate the destructor body to the complete
929 // destructor. Do so.
930 if (dtorType == Dtor_Deleting || dtorType == Dtor_VectorDeleting) {
932 cgm.errorNYI(dtor->getSourceRange(), "emitConditionalArrayDtorCall");
933
934 // A destroying operator delete destroys the object and deallocates its
935 // storage, so the deleting destructor only calls the operator delete.
936 const FunctionDecl *operatorDelete = dtor->getOperatorDelete();
937 if (operatorDelete->isDestroyingOperatorDelete()) {
939 // The implicit parameter of a deleting destructor is the Microsoft ABI.
940 cgm.errorNYI(dtor->getSourceRange(), "emitConditionalArrayDtorCall");
941 }
942 emitDeleteCall(operatorDelete, loadThisForDtorDelete(dtor),
943 getContext().getCanonicalTagType(dtor->getParent()));
944 return;
945 }
946
947 RunCleanupsScope dtorEpilogue(*this);
950 emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase=*/false,
951 /*delegating=*/false, loadCXXThisAddress(), thisTy);
952 return;
953 }
954
955 // If the body is a function-try-block, enter the try before
956 // anything else.
957 const bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
958 if (isTryBody)
959 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");
960
962
963 // Enter the epilogue cleanups.
964 RunCleanupsScope dtorEpilogue(*this);
965
966 // If this is the complete variant, just invoke the base variant;
967 // the epilogue will destruct the virtual bases. But we can't do
968 // this optimization if the body is a function-try-block, because
969 // we'd introduce *two* handler blocks. In the Microsoft ABI, we
970 // always delegate because we might not have a definition in this TU.
971 switch (dtorType) {
972 case Dtor_Unified:
973 llvm_unreachable("not expecting a unified dtor");
974 case Dtor_Comdat:
975 llvm_unreachable("not expecting a COMDAT");
976 case Dtor_Deleting:
978 llvm_unreachable("already handled deleting case");
979
980 case Dtor_Complete:
981 assert((body || getTarget().getCXXABI().isMicrosoft()) &&
982 "can't emit a dtor without a body for non-Microsoft ABIs");
983
984 // Enter the cleanup scopes for virtual bases.
986
987 if (!isTryBody) {
989 emitCXXDestructorCall(dtor, Dtor_Base, /*forVirtualBase=*/false,
990 /*delegating=*/false, loadCXXThisAddress(), thisTy);
991 break;
992 }
993
994 // Fallthrough: act like we're in the base variant.
995 [[fallthrough]];
996
997 case Dtor_Base:
998 assert(body);
999
1000 bool needsVTableInit =
1002 // Launder 'this' if necessary.
1003 if (needsVTableInit && cgm.getCodeGenOpts().StrictVTablePointers &&
1004 cgm.getCodeGenOpts().OptimizationLevel > 0) {
1005 cxxThisValue = cir::LaunderOp::create(
1006 builder, getLoc(dtor->getBeginLoc()), loadCXXThis());
1007 }
1008
1009 // Enter the cleanup scopes for fields and non-virtual bases.
1011
1012 // Initialize the vtable pointers before entering the body.
1013 if (needsVTableInit)
1015
1016 if (isTryBody) {
1017 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");
1018 } else if (body) {
1019 (void)emitStmt(body, /*useCurrentScope=*/true);
1020 } else {
1021 assert(dtor->isImplicit() && "bodyless dtor not implicit");
1022 // nothing to do besides what's in the epilogue
1023 }
1024 // -fapple-kext must inline any call to this dtor into
1025 // the caller's body.
1027
1028 break;
1029 }
1030
1031 // Jump out through the epilogue cleanups.
1032 dtorEpilogue.forceCleanup();
1033
1034 // Exit the try if applicable.
1035 if (isTryBody)
1036 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");
1037}
1038
1039/// Given a value of type T* that may not be to a complete object, construct
1040/// an l-vlaue withi the natural pointee alignment of T.
1042 QualType ty) {
1043 // FIXME(cir): is it safe to assume Op->getResult(0) is valid? Perhaps
1044 // assert on the result type first.
1045 LValueBaseInfo baseInfo;
1047 CharUnits align = cgm.getNaturalTypeAlignment(ty, &baseInfo);
1048 return makeAddrLValue(Address(val, align), ty, baseInfo);
1049}
1050
1052 QualType ty) {
1053 LValueBaseInfo baseInfo;
1054 CharUnits alignment = cgm.getNaturalTypeAlignment(ty, &baseInfo);
1055 Address addr(val, convertTypeForMem(ty), alignment);
1057 return makeAddrLValue(addr, ty, baseInfo);
1058}
1059
1061 FunctionArgList &args) {
1062 const auto *fd = cast<FunctionDecl>(gd.getDecl());
1063 QualType retTy = fd->getReturnType();
1064
1065 // Only implicit-object member functions need the CXXABI-supplied `this`
1066 // parameter prepended to the arg list. Explicit-object members carry the
1067 // object as a regular parameter that fd->parameters() already enumerates.
1068 const auto *md = dyn_cast<CXXMethodDecl>(fd);
1069 if (md && md->isImplicitObjectMemberFunction()) {
1070 if (cgm.getCXXABI().hasThisReturn(gd))
1071 cgm.errorNYI(fd->getSourceRange(), "this return");
1072 else if (cgm.getCXXABI().hasMostDerivedReturn(gd))
1073 cgm.errorNYI(fd->getSourceRange(), "most derived return");
1074 cgm.getCXXABI().buildThisParam(*this, args);
1075 }
1076
1077 bool passedParams = true;
1078 if (const auto *cd = dyn_cast<CXXConstructorDecl>(fd))
1079 if (auto inherited = cd->getInheritedConstructor())
1080 passedParams =
1081 getTypes().inheritingCtorHasParams(inherited, gd.getCtorType());
1082
1083 if (passedParams) {
1084 for (auto *param : fd->parameters()) {
1085 args.push_back(param);
1086 if (!param->hasAttr<PassObjectSizeAttr>())
1087 continue;
1088
1089 auto *implicit = ImplicitParamDecl::Create(
1090 getContext(), param->getDeclContext(), param->getLocation(),
1091 /*Id=*/nullptr, getContext().getSizeType(), ImplicitParamKind::Other);
1092 sizeArguments[param] = implicit;
1093 args.push_back(implicit);
1094 }
1095 }
1096
1097 if (md && (isa<CXXConstructorDecl>(md) || isa<CXXDestructorDecl>(md)))
1098 cgm.getCXXABI().addImplicitStructorParams(*this, retTy, args);
1099
1100 return retTy;
1101}
1102
1104 // Initializing an aggregate temporary in C++11: T{...}.
1105 if (!e->isGLValue())
1106 return emitAggExprToLValue(e);
1107
1108 // An lvalue initializer list must be initializing a reference.
1109 assert(e->isTransparent() && "non-transparent glvalue init list");
1110 return emitLValue(e->getInit(0));
1111}
1112
1113static std::variant<LValue, RValue>
1115 bool forLValue, AggValueSlot slot) {
1117 SmallVector<OVMD> opaques;
1118 llvm::scope_exit opaque_cleanup{
1119 [&]() { llvm::for_each(opaques, [&](OVMD &o) { o.unbind(cgf); }); }};
1120
1121 // Find the result expression, if any.
1122 const Expr *resultExpr = e->getResultExpr();
1123 std::variant<LValue, RValue> result;
1124
1125 for (const Expr *semantic : e->semantics()) {
1126 // If this semantic expression is an opaque value, bind it
1127 // to the result of its source expression.
1128 if (const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
1129
1130 // Skip unique OVEs.
1131 if (ov->isUnique()) {
1132 assert(ov != resultExpr &&
1133 "A unique OVE cannot be used as the result expression");
1134 continue;
1135 }
1136
1137 // If this is the result expression, we may need to evaluate
1138 // directly into the slot.
1139 OVMD opaqueData;
1140 if (ov == resultExpr && ov->isPRValue() && !forLValue &&
1142 cgf.cgm.errorNYI(e->getSourceRange(),
1143 "emitPseudoObjectExpr for RValue & aggregate kind");
1144 } else {
1145 opaqueData = OVMD::bind(cgf, ov, ov->getSourceExpr());
1146
1147 // If this is the result, also evaluate the result now.
1148 if (ov == resultExpr) {
1149 // FIXME: This doesn't really affect anything, but I cannot find a
1150 // test for this, so leave an ErrorNYI here until we can find one.
1151 cgf.cgm.errorNYI(e->getSourceRange(),
1152 "emitPseudoObjectExpr as result");
1153 if (forLValue)
1154 result = cgf.emitLValue(ov);
1155 else
1156 cgf.cgm.errorNYI(e->getSourceRange(),
1157 "emitPseudoObjectExpr as an RValue");
1158 }
1159 }
1160 opaques.push_back(opaqueData);
1161 } else if (semantic == resultExpr) {
1162 // Otherwise, if the expression is the result, evaluate it
1163 // and remember the result.
1164 if (forLValue)
1165 result = cgf.emitLValue(semantic);
1166 else
1167 result = cgf.emitAnyExpr(semantic, slot);
1168 } else {
1169 // FIXME: best I can tell, this is only reachable as an r-value, so this
1170 // isn't properly tested.
1171 cgf.cgm.errorNYI(e->getSourceRange(),
1172 "emitPseudoObjectExpr as an ignored value");
1173 // Otherwise, evaluate the expression in an ignored context.
1174 cgf.emitIgnoredExpr(semantic);
1175 }
1176 }
1177
1178 return result;
1179}
1180
1182 AggValueSlot slot) {
1183 return std::get<RValue>(
1184 emitPseudoObjectExpr(*this, e, /*forLValue=*/false, slot));
1185}
1186
1188 return std::get<LValue>(emitPseudoObjectExpr(*this, e, /*forLValue=*/true,
1190}
1191
1192/// Emit code to compute a designator that specifies the location
1193/// of the expression.
1194/// FIXME: document this function better.
1197 switch (e->getStmtClass()) {
1198 default:
1200 "emitLValue: unsupported l-value class");
1201 return LValue();
1202
1203 case Expr::ObjCPropertyRefExprClass:
1204 llvm_unreachable("cannot emit a property reference directly");
1205
1206 case Expr::ObjCSelectorExprClass:
1208 "emitLValue: ObjCSelectorExpr");
1209 return LValue();
1210 case Expr::ObjCIsaExprClass:
1211 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: ObjCIsaExpr");
1212 return LValue();
1213 case Expr::BinaryOperatorClass:
1215 case Expr::CompoundAssignOperatorClass: {
1216 QualType ty = e->getType();
1217 if (const AtomicType *at = ty->getAs<AtomicType>())
1218 ty = at->getValueType();
1219 if (!ty->isAnyComplexType())
1221
1223 }
1224 case Expr::CallExprClass:
1225 case Expr::CXXMemberCallExprClass:
1226 case Expr::CXXOperatorCallExprClass:
1227 case Expr::UserDefinedLiteralClass:
1229 case Expr::CXXRewrittenBinaryOperatorClass:
1231 return emitLValue(cast<CXXRewrittenBinaryOperator>(e)->getSemanticForm());
1232 case Expr::VAArgExprClass:
1233 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: VAArgExpr");
1234 return LValue();
1235 case Expr::DeclRefExprClass:
1237 case Expr::ConstantExprClass:
1238 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: ConstantExpr");
1239 return LValue();
1240 case Expr::ParenExprClass:
1241 return emitLValue(cast<ParenExpr>(e)->getSubExpr());
1242 case Expr::GenericSelectionExprClass:
1243 return emitLValue(cast<GenericSelectionExpr>(e)->getResultExpr());
1244 case Expr::PredefinedExprClass:
1246 case Expr::StringLiteralClass:
1248 case Expr::ObjCEncodeExprClass:
1250 "emitLValue: ObjCEncodeExpr");
1251 return LValue();
1252 case Expr::PseudoObjectExprClass:
1254 case Expr::InitListExprClass:
1256 case Expr::CXXTemporaryObjectExprClass:
1257 case Expr::CXXConstructExprClass:
1259 case Expr::CXXBindTemporaryExprClass:
1261 case Expr::CXXUuidofExprClass:
1263 "emitLValue: CXXUuidofExpr");
1264 return LValue();
1265 case Expr::LambdaExprClass:
1266 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: LambdaExpr");
1267 return LValue();
1268 case Expr::ExprWithCleanupsClass: {
1269 const auto *cleanups = cast<ExprWithCleanups>(e);
1270 FullExprCleanupScope scope(*this, cleanups->getSubExpr());
1271 LValue lv = emitLValue(cleanups->getSubExpr());
1272 if (lv.isSimple()) {
1273 // Defend against branches out of gnu statement expressions surrounded by
1274 // cleanups.
1275 Address addr = lv.getAddress();
1276 mlir::Value v = addr.getPointer();
1277 scope.exit({&v});
1278 return LValue::makeAddr(addr.withPointer(v), lv.getType(),
1279 lv.getBaseInfo());
1280 }
1281 // FIXME: Is it possible to create an ExprWithCleanups that produces a
1282 // bitfield lvalue or some other non-simple lvalue?
1283 return lv;
1284 }
1285 case Expr::CXXDefaultArgExprClass: {
1286 auto *dae = cast<CXXDefaultArgExpr>(e);
1287 CXXDefaultArgExprScope scope(*this, dae);
1288 return emitLValue(dae->getExpr());
1289 }
1290 case Expr::CXXDefaultInitExprClass: {
1291 auto *die = cast<CXXDefaultInitExpr>(e);
1292 CXXDefaultInitExprScope scope(*this, die);
1293 return emitLValue(die->getExpr());
1294 }
1295 case Expr::CXXTypeidExprClass:
1297 case Expr::ObjCMessageExprClass:
1299 "emitLValue: ObjCMessageExpr");
1300 return LValue();
1301 case Expr::ObjCIvarRefExprClass:
1303 "emitLValue: ObjCIvarRefExpr");
1304 return LValue();
1305 case Expr::StmtExprClass:
1306 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: StmtExpr");
1307 return LValue();
1308 case Expr::UnaryOperatorClass:
1310 case Expr::ArraySubscriptExprClass:
1312 case Expr::MatrixSingleSubscriptExprClass:
1314 "emitLValue: MatrixSingleSubscriptExpr");
1315 return LValue();
1316 case Expr::MatrixSubscriptExprClass:
1318 "emitLValue: MatrixSubscriptExpr");
1319 return LValue();
1320 case Expr::ArraySectionExprClass:
1322 "emitLValue: ArraySectionExpr");
1323 return LValue();
1324 case Expr::ExtVectorElementExprClass:
1326 case Expr::MatrixElementExprClass:
1328 "emitLValue: MatrixElementExpr");
1329 return LValue();
1330 case Expr::CXXThisExprClass:
1332 case Expr::MemberExprClass:
1334 case Expr::CompoundLiteralExprClass:
1336 case Expr::ConditionalOperatorClass:
1338 case Expr::BinaryConditionalOperatorClass:
1340 case Expr::ChooseExprClass:
1341 return emitLValue(cast<ChooseExpr>(e)->getChosenSubExpr());
1342 case Expr::OpaqueValueExprClass:
1344 case Expr::SubstNonTypeTemplateParmExprClass:
1345 return emitLValue(cast<SubstNonTypeTemplateParmExpr>(e)->getReplacement());
1346 case Expr::ImplicitCastExprClass:
1347 case Expr::CStyleCastExprClass:
1348 case Expr::CXXFunctionalCastExprClass:
1349 case Expr::CXXStaticCastExprClass:
1350 case Expr::CXXDynamicCastExprClass:
1351 case Expr::CXXReinterpretCastExprClass:
1352 case Expr::CXXConstCastExprClass:
1353 return emitCastLValue(cast<CastExpr>(e));
1354 case Expr::CXXAddrspaceCastExprClass:
1355 case Expr::ObjCBridgedCastExprClass:
1356 // TODO(cir): These can just be moved into the cast handling above, but
1357 // they need test cases.
1359 "emitLValue: addrspace or ObjC bridged cast");
1360 return LValue();
1361 case Expr::MaterializeTemporaryExprClass:
1363 case Expr::CoawaitExprClass:
1364 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: CoawaitExpr");
1365 return LValue();
1366 case Expr::CoyieldExprClass:
1367 getCIRGenModule().errorNYI(e->getSourceRange(), "emitLValue: CoyieldExpr");
1368 return LValue();
1369 case Expr::PackIndexingExprClass:
1370 return emitLValue(cast<PackIndexingExpr>(e)->getSelectedExpr());
1371 case Expr::HLSLOutArgExprClass:
1372 llvm_unreachable("cannot emit a HLSL out argument directly");
1373 }
1374}
1375
1376static std::string getVersionedTmpName(llvm::StringRef name, unsigned cnt) {
1377 SmallString<256> buffer;
1378 llvm::raw_svector_ostream out(buffer);
1379 out << name << cnt;
1380 return std::string(out.str());
1381}
1382
1384 return getVersionedTmpName("ref.tmp", counterRefTmp++);
1385}
1386
1388 return getVersionedTmpName("agg.tmp", counterAggTmp++);
1389}
1390
1391void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,
1392 QualType ty) {
1393 // Ignore empty classes in C++.
1394 if (getLangOpts().CPlusPlus)
1395 if (const auto *rd = ty->getAsCXXRecordDecl(); rd && rd->isEmpty())
1396 return;
1397
1398 // Cast the dest ptr to the appropriate i8 pointer type.
1399 if (!builder.isInt8Ty(destPtr.getElementType()))
1400 destPtr = destPtr.withElementType(builder, uInt8Ty);
1401
1402 // Get size and alignment info for this aggregate.
1403 mlir::IntegerAttr sizeVal;
1404 const CharUnits size = getContext().getTypeSizeInChars(ty);
1405 if (size.isZero()) {
1406 // But note that getTypeInfo returns 0 for a VLA.
1407 if (isa_and_nonnull<VariableArrayType>(getContext().getAsArrayType(ty))) {
1408 cgm.errorNYI(loc,
1409 "emitNullInitialization for zero size VariableArrayType");
1410 } else {
1411 return;
1412 }
1413 } else {
1414 sizeVal = cgm.getSize(size);
1415 }
1416
1417 // If the type contains a pointer to data member we can't memset it to zero.
1418 // Instead, create a null constant and copy it to the destination.
1419 // TODO: there are other patterns besides zero that we can usefully memset,
1420 // like -1, which happens to be the pattern used by member-pointers.
1421 if (!cgm.getTypes().isZeroInitializable(ty)) {
1422 // Only the pointer-to-data-member case is tested here; emitNullConstant
1423 // owns the NYIs for shapes it cannot build (virtual bases, non-zero-init
1424 // arrays).
1425 assert((ty->isMemberDataPointerType() || ty->isRecordType()) &&
1426 "emitNullInitialization: only pointer-to-data-member (directly or "
1427 "within a record) null initialization is implemented");
1428 mlir::Value nullVal = cgm.emitNullConstant(ty, loc);
1429 builder.createStore(loc, nullVal, destPtr);
1430 return;
1431 }
1432
1433 // Otherwise, just memset the whole thing to zero. This is legal
1434 // because in LLVM, all default initializers (other than the ones we just
1435 // handled above, and the case handled below) are guaranteed to have a bit
1436 // pattern of all zeros.
1437 mlir::Value zero = builder.getNullValue(builder.getUInt8Ty(), loc);
1438 mlir::Value sizeValue =
1439 builder.getConstAPInt(loc, cgm.uInt64Ty, sizeVal.getValue());
1440 destPtr = destPtr.withElementType(builder, cgm.voidTy);
1441 builder.createMemSet(loc, destPtr, zero, sizeValue);
1442}
1443
1445 const clang::Expr *e)
1446 : cgf(cgf) {
1447 ConstructorHelper(e->getFPFeaturesInEffect(cgf.getLangOpts()));
1448}
1449
1451 FPOptions fpFeatures)
1452 : cgf(cgf) {
1453 ConstructorHelper(fpFeatures);
1454}
1455
1456void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper(
1457 FPOptions fpFeatures) {
1458 oldFPFeatures = cgf.curFPFeatures;
1459 cgf.curFPFeatures = fpFeatures;
1460
1461 oldExcept = cgf.builder.getDefaultConstrainedExcept();
1462 oldRounding = cgf.builder.getDefaultConstrainedRounding();
1463
1464 if (oldFPFeatures == fpFeatures)
1465 return;
1466
1467 // TODO(cir): create guard to restore fast math configurations.
1469
1470 llvm::RoundingMode newRoundingMode = fpFeatures.getRoundingMode();
1471 LangOptions::FPExceptionModeKind newExceptionBehavior =
1472 fpFeatures.getExceptionMode();
1473
1474 cgf.builder.setDefaultConstrainedRounding(newRoundingMode);
1475 cgf.builder.setDefaultConstrainedExcept(newExceptionBehavior);
1476
1477 // TODO(cir): override FP flags once FM configs are guarded.
1479
1480 assert((cgf.curFuncDecl == nullptr || cgf.builder.getIsFPConstrained() ||
1481 isa<CXXConstructorDecl>(cgf.curFuncDecl) ||
1482 isa<CXXDestructorDecl>(cgf.curFuncDecl) ||
1483 (newExceptionBehavior == LangOptions::FPE_Ignore &&
1484 newRoundingMode == llvm::RoundingMode::NearestTiesToEven)) &&
1485 "FPConstrained should be enabled on entire function");
1486
1487 // TODO(cir): mark CIR function with fast math attributes.
1489}
1490
1492 cgf.curFPFeatures = oldFPFeatures;
1493 cgf.builder.setDefaultConstrainedExcept(oldExcept);
1494 cgf.builder.setDefaultConstrainedRounding(oldRounding);
1495}
1496
1498 cir::FastMathFlags flags = cir::FastMathFlags::none;
1499 if (curFPFeatures.getAllowFPReassociate())
1500 flags |= cir::FastMathFlags::reassoc;
1501 if (curFPFeatures.getNoHonorNaNs())
1502 flags |= cir::FastMathFlags::nnan;
1503 if (curFPFeatures.getNoHonorInfs())
1504 flags |= cir::FastMathFlags::ninf;
1505 if (curFPFeatures.getNoSignedZero())
1506 flags |= cir::FastMathFlags::nsz;
1507 if (curFPFeatures.getAllowReciprocal())
1508 flags |= cir::FastMathFlags::arcp;
1509 if (curFPFeatures.getAllowApproxFunc())
1510 flags |= cir::FastMathFlags::afn;
1511 if (curFPFeatures.allowFPContractAcrossStatement())
1512 flags |= cir::FastMathFlags::contract;
1513
1514 return flags;
1515}
1516
1517cir::FastMathFlagsAttr
1518CIRGenFunction::getFastMathFlagsAttr(cir::FastMathFlags fastMathFlags) {
1519 if (fastMathFlags == cir::FastMathFlags::none)
1520 return {};
1521 return cir::FastMathFlagsAttr::get(&getMLIRContext(), fastMathFlags);
1522}
1523
1524// TODO(cir): should be shared with LLVM codegen.
1526 const Expr *e = ce->getSubExpr();
1527
1528 if (ce->getCastKind() == CK_UncheckedDerivedToBase)
1529 return false;
1530
1531 if (isa<CXXThisExpr>(e->IgnoreParens())) {
1532 // We always assume that 'this' is never null.
1533 return false;
1534 }
1535
1536 if (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(ce)) {
1537 // And that glvalue casts are never null.
1538 if (ice->isGLValue())
1539 return false;
1540 }
1541
1542 return true;
1543}
1544
1545/// Computes the length of an array in elements, as well as the base
1546/// element type and a properly-typed first element pointer.
1547mlir::Value
1549 QualType &baseType, Address &addr) {
1550 const clang::ArrayType *arrayType = origArrayType;
1551
1552 // If it's a VLA, we have to load the stored size. Note that
1553 // this is the size of the VLA in bytes, not its size in elements.
1554 mlir::Value numVLAElements = nullptr;
1557
1558 // Walk into all VLAs. This doesn't require changes to addr,
1559 // which has type T* where T is the first non-VLA element type.
1560 do {
1561 QualType elementType = arrayType->getElementType();
1562 arrayType = getContext().getAsArrayType(elementType);
1563
1564 // If we only have VLA components, 'addr' requires no adjustment.
1565 if (!arrayType) {
1566 baseType = elementType;
1567 return numVLAElements;
1568 }
1570
1571 // We get out here only if we find a constant array type
1572 // inside the VLA.
1573 }
1574
1575 // Classic codegen emits an all-zero inbounds GEP to convert addr from
1576 // [M x [N x T]]* to T*. CIR doesn't need this because callers handle
1577 // the array-to-element pointer conversion themselves (via array_to_ptrdecay
1578 // casts, ptr_bitcast, or manual array type peeling).
1579
1580 uint64_t countFromCLAs = 1;
1581 QualType eltType;
1582
1583 auto cirArrayType = mlir::dyn_cast<cir::ArrayType>(addr.getElementType());
1584
1585 while (cirArrayType) {
1587 countFromCLAs *= cirArrayType.getSize();
1588 eltType = arrayType->getElementType();
1589
1590 cirArrayType =
1591 mlir::dyn_cast<cir::ArrayType>(cirArrayType.getElementType());
1592
1593 arrayType = getContext().getAsArrayType(arrayType->getElementType());
1594 assert((!cirArrayType || arrayType) &&
1595 "CIR and Clang types are out-of-sync");
1596 }
1597
1598 if (arrayType) {
1599 // From this point onwards, the Clang array type has been emitted
1600 // as some other type (probably a packed struct). Compute the array
1601 // size, and just emit the 'begin' expression as a bitcast.
1602 cgm.errorNYI(*currSrcLoc, "length for non-array underlying types");
1603 }
1604
1605 baseType = eltType;
1606
1607 mlir::Value numElements =
1608 builder.getConstInt(getLoc(*currSrcLoc), sizeTy, countFromCLAs);
1609
1610 // If we had any VLA dimensions, factor them in.
1611 if (numVLAElements)
1612 numElements =
1613 builder.createMul(numVLAElements.getLoc(), numVLAElements, numElements,
1615
1616 return numElements;
1617}
1618
1620 mlir::Value ptrValue, QualType ty, SourceLocation loc,
1621 SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue) {
1623 mlir::Location assumeLoc = getLoc(assumptionLoc);
1624 mlir::Value alignValue = builder.getUInt64(alignment, assumeLoc);
1625 mlir::Value cond = builder.getBool(true, assumeLoc);
1626 llvm::SmallVector<mlir::Value> bundleArgs{ptrValue, alignValue};
1627 if (offsetValue)
1628 bundleArgs.push_back(offsetValue);
1629 cir::AssumeOp::create(builder, assumeLoc, cond, cir::AssumeBundleKind::Align,
1630 bundleArgs);
1631 return ptrValue;
1632}
1633
1635 mlir::Value ptrValue, const Expr *expr, SourceLocation assumptionLoc,
1636 int64_t alignment, mlir::Value offsetValue) {
1637 QualType ty = expr->getType();
1638 SourceLocation loc = expr->getExprLoc();
1639 return emitAlignmentAssumption(ptrValue, ty, loc, assumptionLoc, alignment,
1640 offsetValue);
1641}
1642
1644 const VariableArrayType *vla =
1645 cgm.getASTContext().getAsVariableArrayType(type);
1646 assert(vla && "type was not a variable array type!");
1647 return getVLASize(vla);
1648}
1649
1652 // The number of elements so far; always size_t.
1653 mlir::Value numElements;
1654
1655 QualType elementType;
1656 do {
1657 elementType = type->getElementType();
1658 mlir::Value vlaSize = vlaSizeMap[type->getSizeExpr()];
1659 assert(vlaSize && "no size for VLA!");
1660 assert(vlaSize.getType() == sizeTy);
1661
1662 if (!numElements) {
1663 numElements = vlaSize;
1664 } else {
1665 // It's undefined behavior if this wraps around, so mark it that way.
1666 // FIXME: Teach -fsanitize=undefined to trap this.
1667
1668 numElements =
1669 builder.createMul(numElements.getLoc(), numElements, vlaSize,
1671 }
1672 } while ((type = getContext().getAsVariableArrayType(elementType)));
1673
1674 assert(numElements && "Undefined elements number");
1675 return {numElements, elementType};
1676}
1677
1680 mlir::Value vlaSize = vlaSizeMap[vla->getSizeExpr()];
1681 assert(vlaSize && "no size for VLA!");
1682 assert(vlaSize.getType() == sizeTy);
1683 return {vlaSize, vla->getElementType()};
1684}
1685
1686// TODO(cir): Most of this function can be shared between CIRGen
1687// and traditional LLVM codegen
1689 assert(type->isVariablyModifiedType() &&
1690 "Must pass variably modified type to EmitVLASizes!");
1691
1692 // We're going to walk down into the type and look for VLA
1693 // expressions.
1694 do {
1695 assert(type->isVariablyModifiedType());
1696
1697 const Type *ty = type.getTypePtr();
1698 switch (ty->getTypeClass()) {
1699 case Type::CountAttributed:
1700 case Type::PackIndexing:
1701 case Type::ArrayParameter:
1702 case Type::HLSLAttributedResource:
1703 case Type::HLSLInlineSpirv:
1704 case Type::PredefinedSugar:
1705 case Type::LateParsedAttr:
1706 cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType");
1707 break;
1708
1709#define TYPE(Class, Base)
1710#define ABSTRACT_TYPE(Class, Base)
1711#define NON_CANONICAL_TYPE(Class, Base)
1712#define DEPENDENT_TYPE(Class, Base) case Type::Class:
1713#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)
1714#include "clang/AST/TypeNodes.inc"
1715 llvm_unreachable(
1716 "dependent type must be resolved before the CIR codegen");
1717
1718 // These types are never variably-modified.
1719 case Type::Builtin:
1720 case Type::Complex:
1721 case Type::Vector:
1722 case Type::ExtVector:
1723 case Type::ConstantMatrix:
1724 case Type::Record:
1725 case Type::Enum:
1726 case Type::Using:
1727 case Type::TemplateSpecialization:
1728 case Type::ObjCTypeParam:
1729 case Type::ObjCObject:
1730 case Type::ObjCInterface:
1731 case Type::ObjCObjectPointer:
1732 case Type::BitInt:
1733 case Type::OverflowBehavior:
1734 llvm_unreachable("type class is never variably-modified!");
1735
1736 case Type::Adjusted:
1737 type = cast<clang::AdjustedType>(ty)->getAdjustedType();
1738 break;
1739
1740 case Type::Decayed:
1741 type = cast<clang::DecayedType>(ty)->getPointeeType();
1742 break;
1743
1744 case Type::Pointer:
1745 type = cast<clang::PointerType>(ty)->getPointeeType();
1746 break;
1747
1748 case Type::BlockPointer:
1749 type = cast<clang::BlockPointerType>(ty)->getPointeeType();
1750 break;
1751
1752 case Type::LValueReference:
1753 case Type::RValueReference:
1754 type = cast<clang::ReferenceType>(ty)->getPointeeType();
1755 break;
1756
1757 case Type::MemberPointer:
1758 type = cast<clang::MemberPointerType>(ty)->getPointeeType();
1759 break;
1760
1761 case Type::ConstantArray:
1762 case Type::IncompleteArray:
1763 // Losing element qualification here is fine.
1764 type = cast<clang::ArrayType>(ty)->getElementType();
1765 break;
1766
1767 case Type::VariableArray: {
1768 // Losing element qualification here is fine.
1770
1771 // Unknown size indication requires no size computation.
1772 // Otherwise, evaluate and record it.
1773 if (const Expr *sizeExpr = vat->getSizeExpr()) {
1774 // It's possible that we might have emitted this already,
1775 // e.g. with a typedef and a pointer to it.
1776 mlir::Value &entry = vlaSizeMap[sizeExpr];
1777 if (!entry) {
1778 mlir::Value size = emitScalarExpr(sizeExpr);
1780
1781 // Always zexting here would be wrong if it weren't
1782 // undefined behavior to have a negative bound.
1783 // FIXME: What about when size's type is larger than size_t?
1784 entry = builder.createBoolIntToIntCast(size, sizeTy);
1785 }
1786 }
1787 type = vat->getElementType();
1788 break;
1789 }
1790
1791 case Type::FunctionProto:
1792 case Type::FunctionNoProto:
1793 type = cast<clang::FunctionType>(ty)->getReturnType();
1794 break;
1795
1796 case Type::Paren:
1797 case Type::TypeOf:
1798 case Type::UnaryTransform:
1799 case Type::Attributed:
1800 case Type::BTFTagAttributed:
1801 case Type::SubstTemplateTypeParm:
1802 case Type::MacroQualified:
1803 // Keep walking after single level desugaring.
1804 type = type.getSingleStepDesugaredType(getContext());
1805 break;
1806
1807 case Type::Typedef:
1808 case Type::Decltype:
1809 case Type::Auto:
1810 case Type::DeducedTemplateSpecialization:
1811 // Stop walking: nothing to do.
1812 return;
1813
1814 case Type::TypeOfExpr:
1815 // Stop walking: emit typeof expression.
1816 emitIgnoredExpr(cast<clang::TypeOfExprType>(ty)->getUnderlyingExpr());
1817 return;
1818
1819 case Type::Atomic:
1820 type = cast<clang::AtomicType>(ty)->getValueType();
1821 break;
1822
1823 case Type::Pipe:
1824 type = cast<clang::PipeType>(ty)->getElementType();
1825 break;
1826 }
1827 } while (type->isVariablyModifiedType());
1828}
1829
1831 if (getContext().getBuiltinVaListType()->isArrayType())
1832 return emitPointerWithAlignment(e);
1833 return emitLValue(e).getAddress();
1834}
1835
1836} // 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:239
SourceManager & getSourceManager()
Definition ASTContext.h:911
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: declare function arguments in the symbol table.
mlir::Type convertType(clang::QualType t)
LValue emitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *e)
LValue emitOpaqueValueLValue(const OpaqueValueExpr *e)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
EHScopeStack::stable_iterator prologueCleanupDepth
The cleanup depth enclosing all the cleanups associated with the parameters.
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
CIRGenTypes & getTypes() const
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
void emitVariablyModifiedType(QualType ty)
RValue emitLoadOfLValue(LValue lv, SourceLocation loc)
Given an expression that represents a value lvalue, this method emits the address of the lvalue,...
const clang::LangOptions & getLangOpts() const
void emitTrap(mlir::Location loc, bool createNewBlock)
Emit a trap instruction, which is used to abort the program in an abnormal way, usually for debugging...
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
mlir::Value loadCXXThis()
Load the value for 'this'.
LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t)
Given a value of type T* that may not be to a complete object, construct an l-vlaue withi the natural...
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)
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
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4613
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:5678
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