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