18#include "mlir/IR/Location.h"
24#include "llvm/ADT/ScopeExit.h"
25#include "llvm/IR/FPEnv.h"
32 bool suppressNewContext)
44 switch (
type->getTypeClass()) {
45#define TYPE(name, parent)
46#define ABSTRACT_TYPE(name, parent)
47#define NON_CANONICAL_TYPE(name, parent) case Type::name:
48#define DEPENDENT_TYPE(name, parent) case Type::name:
49#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(name, parent) case Type::name:
50#include "clang/AST/TypeNodes.inc"
51 llvm_unreachable(
"non-canonical or dependent type in IR-generation");
54 case Type::DeducedTemplateSpecialization:
55 llvm_unreachable(
"undeduced type in IR-generation");
60 case Type::BlockPointer:
61 case Type::LValueReference:
62 case Type::RValueReference:
63 case Type::MemberPointer:
66 case Type::ConstantMatrix:
67 case Type::FunctionProto:
68 case Type::FunctionNoProto:
70 case Type::ObjCObjectPointer:
73 case Type::OverflowBehavior:
74 case Type::HLSLAttributedResource:
75 case Type::HLSLInlineSpirv:
83 case Type::ConstantArray:
84 case Type::IncompleteArray:
85 case Type::VariableArray:
87 case Type::ObjCObject:
88 case Type::ObjCInterface:
89 case Type::ArrayParameter:
97 llvm_unreachable(
"unknown type kind!");
102 return cgm.getTypes().convertTypeForMem(t);
106 return cgm.getTypes().convertType(t);
116 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
122 assert(
currSrcLoc &&
"expected to inherit some source location");
126 return builder.getUnknownLoc();
136 mlir::Attribute metadata;
142 assert(
currSrcLoc &&
"expected to inherit some source location");
146 return builder.getUnknownLoc();
151 mlir::Attribute metadata;
178 ignoreCaseStmts =
true;
182 [=](
const Stmt *subStmt) {
183 return containsLabel(subStmt, ignoreCaseStmts);
192 llvm::APSInt resultInt;
196 resultBool = resultInt.getBoolValue();
204 llvm::APSInt &resultInt,
212 llvm::APSInt intValue = result.
Val.
getInt();
216 resultInt = intValue;
220void CIRGenFunction::emitAndUpdateRetAlloca(
QualType type, mlir::Location loc,
222 if (!
type->isVoidType()) {
229void CIRGenFunction::declare(mlir::Value addrVal,
const Decl *var, QualType ty,
230 mlir::Location loc, CharUnits alignment,
233 assert(!
symbolTable.count(var) &&
"not supposed to be available just yet");
235 Address addr(addrVal, alignment);
236 cir::AllocaOp allocaOp = addr.getUnderlyingAllocaOp();
237 assert(allocaOp &&
"expected cir::AllocaOp");
241 if (ty->isReferenceType() || ty.isConstQualified())
257 for (mlir::Block *retBlock : localScope->
getRetBlocks()) {
258 mlir::OpBuilder::InsertionGuard guard(builder);
259 builder.setInsertionPointToEnd(retBlock);
260 retBlocks.push_back(retBlock);
261 mlir::Location retLoc = localScope->
getRetLoc(retBlock);
273 mlir::Block *curBlock = builder.getBlock();
276 if (curBlock->mightHaveTerminator() && curBlock->getTerminator())
282 bool isEntryBlock = builder.getInsertionBlock()->isEntryBlock();
283 if (!isEntryBlock && curBlock->empty()) {
285 for (mlir::Block *retBlock : retBlocks) {
286 if (retBlock->getUses().empty())
292 if (localScope->
depth == 0) {
296 mlir::Location retLoc = localScope->
getRetLoc(retBlock);
297 if (retBlock->getUses().empty()) {
300 cir::BrOp::create(builder, retLoc, retBlock);
304 emitImplicitReturn();
311 if (!localScope->
isTernary() && !curBlock->mightHaveTerminator()) {
312 !retVal ? cir::YieldOp::create(builder, localScope->endLoc)
313 : cir::YieldOp::create(builder, localScope->endLoc, retVal);
317cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
320 auto fn = dyn_cast<cir::FuncOp>(cgf.curFn);
321 assert(fn &&
"emitReturn from non-function");
323 if (!fn.getFunctionType().hasVoidReturn()) {
325 auto value = cir::LoadOp::create(
326 builder, loc, fn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);
327 return cir::ReturnOp::create(builder, loc,
330 return cir::ReturnOp::create(builder, loc);
340 return classDecl->hasTrivialDestructor();
347 mlir::Operation *op = &block->back();
348 auto cleanupScopeOp = mlir::dyn_cast<cir::CleanupScopeOp>(op);
356 for (mlir::Block &bodyBlock : cleanupScopeOp.getBodyRegion()) {
357 if (bodyBlock.mightHaveTerminator()) {
358 if (mlir::isa<cir::YieldOp>(bodyBlock.getTerminator()))
360 assert(!mlir::isa<cir::BreakOp>(bodyBlock.getTerminator()) &&
361 !mlir::isa<cir::ContinueOp>(bodyBlock.getTerminator()) &&
362 !mlir::isa<cir::ResumeOp>(bodyBlock.getTerminator()));
368void CIRGenFunction::LexicalScope::emitImplicitReturn() {
369 CIRGenBuilderTy &builder = cgf.getBuilder();
370 LexicalScope *localScope = cgf.curLexScope;
379 if (cgf.getLangOpts().CPlusPlus && !fd->hasImplicitReturnZero() &&
380 !cgf.sawAsmBlock && !fd->getReturnType()->isVoidType() &&
381 builder.getInsertionBlock() &&
383 bool shouldEmitUnreachable =
384 cgf.cgm.getCodeGenOpts().StrictReturn ||
387 if (shouldEmitUnreachable) {
389 if (cgf.cgm.getCodeGenOpts().OptimizationLevel == 0)
390 cir::TrapOp::create(builder, localScope->endLoc);
392 cir::UnreachableOp::create(builder, localScope->endLoc);
393 builder.clearInsertionPoint();
398 (void)emitReturn(localScope->endLoc);
406 scope = scope->parentScope;
419 if (value.getType() == ty)
422 assert((mlir::isa<cir::IntType>(ty) || cir::isAnyFloatingPointType(ty)) &&
423 "unexpected promotion type");
425 if (mlir::isa<cir::IntType>(ty))
426 return cgf.
getBuilder().CIRBaseBuilderTy::createIntCast(value, ty);
432 mlir::Block *entryBB,
436 if (fd && fd->
hasAttr<NakedAttr>()) {
437 cgm.errorNYI(bodyBeginLoc,
"naked function decl");
441 for (
const auto nameValue : llvm::zip(args, entryBB->getArguments())) {
442 const VarDecl *paramVar = std::get<0>(nameValue);
443 mlir::Value paramVal = std::get<1>(nameValue);
446 paramVal.setLoc(paramLoc);
448 mlir::Value addrVal =
453 declare(addrVal, paramVar, paramVar->
getType(), paramLoc, alignment,
466 mlir::Location fnBodyBegin =
getLoc(bodyBeginLoc);
467 builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal, addrVal);
469 assert(builder.getInsertionBlock() &&
"Should be valid");
473 cir::FuncOp fn, cir::FuncType funcType,
477 "CIRGenFunction can only be used for one function at a time");
485 const auto *fd = dyn_cast_or_null<FunctionDecl>(d);
496 builder.setDefaultConstrainedRounding(rm);
497 builder.setDefaultConstrainedExcept(eb);
498 builder.setIsFPConstrained(
false);
499 if ((fd && (fd->UsesFPIntrin() || fd->hasAttr<StrictFPAttr>())) ||
501 rm != llvm::RoundingMode::NearestTiesToEven))) {
502 builder.setIsFPConstrained(
true);
503 fn->setAttr(cir::CIRDialect::getStrictFPAttrName(),
504 mlir::UnitAttr::get(fn.getContext()));
508 mlir::Block *entryBB = &fn.getBlocks().front();
509 builder.setInsertionPointToStart(entryBB);
515 if (
Stmt *body = fd->getBody())
516 bodyBeginLoc = body->getBeginLoc();
518 bodyBeginLoc = fd->getLocation();
530 if (
Stmt *body = fd->getBody())
531 bodyEndLoc = body->getEndLoc();
533 bodyEndLoc = fd->getLocation();
535 emitAndUpdateRetAlloca(returnType,
getLoc(bodyEndLoc),
536 getContext().getTypeAlignInChars(returnType));
545 if (fd && fd->hasImplicitReturnZero()) {
547 mlir::Location bodyBeginMLIRLoc =
getLoc(bodyBeginLoc);
548 mlir::Value zero = builder.getNullValue(cirRetTy, bodyBeginMLIRLoc);
549 builder.CIRBaseBuilderTy::createStore(bodyBeginMLIRLoc, zero,
558 if (isa_and_nonnull<CXXMethodDecl>(d) &&
560 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *
this);
563 if (md->getParent()->isLambda() && md->getOverloadedOperator() == OO_Call) {
565 auto fn = dyn_cast<cir::FuncOp>(
curFn);
566 assert(fn &&
"lambda in non-function region");
592 for (
auto *fd : md->getParent()->fields()) {
593 if (fd->hasCapturedVLAType())
594 cgm.errorNYI(loc,
"lambda captured VLA type");
610 if (!fd || !fd->hasAttr<NakedAttr>()) {
611 for (
const VarDecl *vd : args) {
616 if (
const auto *pvd = dyn_cast<ParmVarDecl>(vd))
617 ty = pvd->getOriginalType();
640 "deferred conditional cleanups were not consumed by a "
641 "FullExprCleanupScope");
648 if (
const CompoundStmt *block = dyn_cast<CompoundStmt>(body))
659 for (mlir::Block &block : func.getBlocks()) {
660 if (block.empty() && block.getUses().empty())
661 blocksToDelete.push_back(&block);
663 for (mlir::Block *block : blocksToDelete)
668 cir::FuncType funcType) {
672 if (funcDecl->isInlineBuiltinDeclaration()) {
676 std::string fdInlineName = (
cgm.getMangledName(funcDecl) +
".inline").str();
678 mlir::cast_or_null<cir::FuncOp>(
cgm.getGlobalValue(fdInlineName));
680 mlir::OpBuilder::InsertionGuard guard(builder);
681 builder.setInsertionPoint(fn);
682 clone = cir::FuncOp::create(builder, fn.getLoc(), fdInlineName,
683 fn.getFunctionType());
684 cgm.insertGlobalSymbol(clone);
685 clone.setLinkage(cir::GlobalLinkageKind::InternalLinkage);
686 clone.setSymVisibility(
"private");
687 clone.setInlineKind(cir::InlineKind::AlwaysInline);
689 fn.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
690 fn.setSymVisibility(
"private");
698 if (LLVM_UNLIKELY(pd->isInlineBuiltinDeclaration())) {
699 std::string inlineName = funcDecl->getName().str() +
".inline";
700 if (
auto inlineFn = mlir::cast_or_null<cir::FuncOp>(
701 cgm.getGlobalValue(inlineName))) {
706 .replaceAllSymbolUses(fn.getSymNameAttr(),
cgm.getModule())
708 llvm_unreachable(
"Failed to replace inline builtin symbol uses");
709 cgm.eraseGlobalSymbol(inlineFn);
718 Stmt *body = funcDecl->getBody();
723 : builder.getUnknownLoc()};
726 return clangLoc.isValid() ?
getLoc(clangLoc) : builder.getUnknownLoc();
728 const mlir::Location fusedLoc = mlir::FusedLoc::get(
730 {validMLIRLoc(bodyRange.
getBegin()), validMLIRLoc(bodyRange.
getEnd())});
731 mlir::Block *entryBB = fn.addEntryBlock();
745 if (body && isa_and_nonnull<CoroutineBodyStmt>(body))
746 llvm::append_range(
fnArgs, funcDecl->parameters());
753 funcDecl->hasAttr<CUDAGlobalAttr>()) {
754 cgm.getCUDARuntime().emitDeviceStub(*
this, fn, args);
774 llvm_unreachable(
"no definition for normal function");
777 if (mlir::failed(fn.verifyBody()))
792 assert((
cgm.getTarget().getCXXABI().hasConstructorVariants() ||
794 "can only generate complete ctor for this ABI");
799 cgm.getTarget().getCXXABI().hasConstructorVariants()) {
805 Stmt *body = ctor->getBody(definition);
806 assert(definition == ctor &&
"emitting wrong constructor body");
808 bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
817 Stmt *emitterBody =
nullptr;
820 : ctor(ctor), ctorType(ctorType), args(args),
822 ~ctorTryBodyEmitter()
override =
default;
832 return cgf.
emitStmt(emitterBody,
true);
836 ctorTryBodyEmitter emitter{ctor, ctorType, args, isTryBody, body};
837 mlir::LogicalResult bodyRes =
843 if (bodyRes.failed())
844 cgm.errorNYI(ctor->getSourceRange(),
845 "emitConstructorBody: emit body statement failed.");
889 const bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
905 llvm_unreachable(
"not expecting a unified dtor");
907 llvm_unreachable(
"not expecting a COMDAT");
910 llvm_unreachable(
"already handled deleting case");
913 assert((body ||
getTarget().getCXXABI().isMicrosoft()) &&
914 "can't emit a dtor without a body for non-Microsoft ABIs");
942 assert(dtor->
isImplicit() &&
"bodyless dtor not implicit");
968 CharUnits align =
cgm.getNaturalTypeAlignment(ty, &baseInfo);
975 CharUnits alignment =
cgm.getNaturalTypeAlignment(ty, &baseInfo);
984 QualType retTy = fd->getReturnType();
989 const auto *md = dyn_cast<CXXMethodDecl>(fd);
990 if (md && md->isImplicitObjectMemberFunction()) {
991 if (
cgm.getCXXABI().hasThisReturn(gd))
992 cgm.errorNYI(fd->getSourceRange(),
"this return");
993 else if (
cgm.getCXXABI().hasMostDerivedReturn(gd))
994 cgm.errorNYI(fd->getSourceRange(),
"most derived return");
995 cgm.getCXXABI().buildThisParam(*
this, args);
998 bool passedParams =
true;
999 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(fd))
1000 if (
auto inherited = cd->getInheritedConstructor())
1005 for (
auto *param : fd->parameters()) {
1006 args.push_back(param);
1007 if (!param->hasAttr<PassObjectSizeAttr>())
1011 getContext(), param->getDeclContext(), param->getLocation(),
1014 args.push_back(implicit);
1019 cgm.getCXXABI().addImplicitStructorParams(*
this, retTy, args);
1030 assert(e->
isTransparent() &&
"non-transparent glvalue init list");
1034static std::variant<LValue, RValue>
1039 llvm::scope_exit opaque_cleanup{
1040 [&]() { llvm::for_each(opaques, [&](OVMD &o) { o.unbind(cgf); }); }};
1044 std::variant<LValue, RValue> result;
1049 if (
const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
1052 if (ov->isUnique()) {
1053 assert(ov != resultExpr &&
1054 "A unique OVE cannot be used as the result expression");
1061 if (ov == resultExpr && ov->
isPRValue() && !forLValue &&
1064 "emitPseudoObjectExpr for RValue & aggregate kind");
1066 opaqueData = OVMD::bind(cgf, ov, ov->getSourceExpr());
1069 if (ov == resultExpr) {
1073 "emitPseudoObjectExpr as result");
1078 "emitPseudoObjectExpr as an RValue");
1081 opaques.push_back(opaqueData);
1082 }
else if (semantic == resultExpr) {
1093 "emitPseudoObjectExpr as an ignored value");
1104 return std::get<RValue>(
1121 "emitLValue: unsupported l-value class");
1124 case Expr::ObjCPropertyRefExprClass:
1125 llvm_unreachable(
"cannot emit a property reference directly");
1127 case Expr::ObjCSelectorExprClass:
1129 "emitLValue: ObjCSelectorExpr");
1131 case Expr::ObjCIsaExprClass:
1134 case Expr::BinaryOperatorClass:
1136 case Expr::CompoundAssignOperatorClass: {
1139 ty = at->getValueType();
1145 case Expr::CallExprClass:
1146 case Expr::CXXMemberCallExprClass:
1147 case Expr::CXXOperatorCallExprClass:
1148 case Expr::UserDefinedLiteralClass:
1150 case Expr::CXXRewrittenBinaryOperatorClass:
1152 "emitLValue: CXXRewrittenBinaryOperator");
1154 case Expr::VAArgExprClass:
1157 case Expr::DeclRefExprClass:
1159 case Expr::ConstantExprClass:
1162 case Expr::ParenExprClass:
1164 case Expr::GenericSelectionExprClass:
1166 case Expr::PredefinedExprClass:
1168 case Expr::StringLiteralClass:
1170 case Expr::ObjCEncodeExprClass:
1172 "emitLValue: ObjCEncodeExpr");
1174 case Expr::PseudoObjectExprClass:
1176 case Expr::InitListExprClass:
1178 case Expr::CXXTemporaryObjectExprClass:
1179 case Expr::CXXConstructExprClass:
1181 case Expr::CXXBindTemporaryExprClass:
1183 case Expr::CXXUuidofExprClass:
1185 "emitLValue: CXXUuidofExpr");
1187 case Expr::LambdaExprClass:
1190 case Expr::ExprWithCleanupsClass: {
1207 case Expr::CXXDefaultArgExprClass: {
1212 case Expr::CXXDefaultInitExprClass: {
1217 case Expr::CXXTypeidExprClass:
1219 case Expr::ObjCMessageExprClass:
1221 "emitLValue: ObjCMessageExpr");
1223 case Expr::ObjCIvarRefExprClass:
1225 "emitLValue: ObjCIvarRefExpr");
1227 case Expr::StmtExprClass:
1230 case Expr::UnaryOperatorClass:
1232 case Expr::ArraySubscriptExprClass:
1234 case Expr::MatrixSingleSubscriptExprClass:
1236 "emitLValue: MatrixSingleSubscriptExpr");
1238 case Expr::MatrixSubscriptExprClass:
1240 "emitLValue: MatrixSubscriptExpr");
1242 case Expr::ArraySectionExprClass:
1244 "emitLValue: ArraySectionExpr");
1246 case Expr::ExtVectorElementExprClass:
1248 case Expr::MatrixElementExprClass:
1250 "emitLValue: MatrixElementExpr");
1252 case Expr::CXXThisExprClass:
1255 case Expr::MemberExprClass:
1257 case Expr::CompoundLiteralExprClass:
1259 case Expr::ConditionalOperatorClass:
1261 case Expr::BinaryConditionalOperatorClass:
1263 case Expr::ChooseExprClass:
1265 case Expr::OpaqueValueExprClass:
1267 case Expr::SubstNonTypeTemplateParmExprClass:
1269 case Expr::ImplicitCastExprClass:
1270 case Expr::CStyleCastExprClass:
1271 case Expr::CXXFunctionalCastExprClass:
1272 case Expr::CXXStaticCastExprClass:
1273 case Expr::CXXDynamicCastExprClass:
1274 case Expr::CXXReinterpretCastExprClass:
1275 case Expr::CXXConstCastExprClass:
1277 case Expr::CXXAddrspaceCastExprClass:
1278 case Expr::ObjCBridgedCastExprClass:
1282 "emitLValue: addrspace or ObjC bridged cast");
1284 case Expr::MaterializeTemporaryExprClass:
1286 case Expr::CoawaitExprClass:
1289 case Expr::CoyieldExprClass:
1292 case Expr::PackIndexingExprClass:
1294 "emitLValue: PackIndexingExpr");
1296 case Expr::HLSLOutArgExprClass:
1297 llvm_unreachable(
"cannot emit a HLSL out argument directly");
1303 llvm::raw_svector_ostream
out(buffer);
1305 return std::string(
out.str());
1325 cgm.errorNYI(loc,
"Cast the dest ptr to the appropriate i8 pointer type");
1334 "emitNullInitialization for zero size VariableArrayType");
1344 if (!
cgm.getTypes().isZeroInitializable(ty)) {
1349 "emitNullInitialization: only pointer-to-data-member (directly or "
1350 "within a record) null initialization is implemented");
1351 mlir::Value nullVal =
cgm.emitNullConstant(ty, loc);
1352 builder.createStore(loc, nullVal, destPtr);
1360 const mlir::Value zeroValue = builder.getNullValue(
convertType(ty), loc);
1361 builder.createStore(loc, zeroValue, destPtr);
1373 ConstructorHelper(fpFeatures);
1376void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper(
1378 oldFPFeatures = cgf.curFPFeatures;
1379 cgf.curFPFeatures = fpFeatures;
1381 oldExcept = cgf.builder.getDefaultConstrainedExcept();
1382 oldRounding = cgf.builder.getDefaultConstrainedRounding();
1384 if (oldFPFeatures == fpFeatures)
1394 cgf.builder.setDefaultConstrainedRounding(newRoundingMode);
1395 cgf.builder.setDefaultConstrainedExcept(newExceptionBehavior);
1400 assert((cgf.curFuncDecl ==
nullptr || cgf.builder.getIsFPConstrained() ||
1404 newRoundingMode == llvm::RoundingMode::NearestTiesToEven)) &&
1405 "FPConstrained should be enabled on entire function");
1412 cgf.curFPFeatures = oldFPFeatures;
1413 cgf.builder.setDefaultConstrainedExcept(oldExcept);
1414 cgf.builder.setDefaultConstrainedRounding(oldRounding);
1421 if (ce->
getCastKind() == CK_UncheckedDerivedToBase)
1431 if (ice->isGLValue())
1447 mlir::Value numVLAElements =
nullptr;
1459 baseType = elementType;
1460 return numVLAElements;
1473 uint64_t countFromCLAs = 1;
1476 auto cirArrayType = mlir::dyn_cast<cir::ArrayType>(addr.
getElementType());
1478 while (cirArrayType) {
1480 countFromCLAs *= cirArrayType.getSize();
1484 mlir::dyn_cast<cir::ArrayType>(cirArrayType.getElementType());
1488 "CIR and Clang types are out-of-sync");
1495 cgm.errorNYI(*
currSrcLoc,
"length for non-array underlying types");
1500 mlir::Value numElements =
1506 builder.createMul(numVLAElements.getLoc(), numVLAElements, numElements,
1514 SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue) {
1516 mlir::Location assumeLoc =
getLoc(assumptionLoc);
1517 mlir::Value alignValue = builder.getUInt64(alignment, assumeLoc);
1518 mlir::Value cond = builder.getBool(
true, assumeLoc);
1521 bundleArgs.push_back(offsetValue);
1522 cir::AssumeOp::create(builder, assumeLoc, cond, cir::AssumeBundleKind::Align,
1529 int64_t alignment, mlir::Value offsetValue) {
1538 cgm.getASTContext().getAsVariableArrayType(
type);
1539 assert(vla &&
"type was not a variable array type!");
1546 mlir::Value numElements;
1550 elementType =
type->getElementType();
1552 assert(vlaSize &&
"no size for VLA!");
1553 assert(vlaSize.getType() ==
sizeTy);
1556 numElements = vlaSize;
1562 builder.createMul(numElements.getLoc(), numElements, vlaSize,
1565 }
while ((
type =
getContext().getAsVariableArrayType(elementType)));
1567 assert(numElements &&
"Undefined elements number");
1568 return {numElements, elementType};
1574 assert(vlaSize &&
"no size for VLA!");
1575 assert(vlaSize.getType() ==
sizeTy);
1582 assert(
type->isVariablyModifiedType() &&
1583 "Must pass variably modified type to EmitVLASizes!");
1588 assert(
type->isVariablyModifiedType());
1590 const Type *ty =
type.getTypePtr();
1592 case Type::CountAttributed:
1593 case Type::PackIndexing:
1594 case Type::ArrayParameter:
1595 case Type::HLSLAttributedResource:
1596 case Type::HLSLInlineSpirv:
1597 case Type::PredefinedSugar:
1598 case Type::LateParsedAttr:
1599 cgm.errorNYI(
"CIRGenFunction::emitVariablyModifiedType");
1602#define TYPE(Class, Base)
1603#define ABSTRACT_TYPE(Class, Base)
1604#define NON_CANONICAL_TYPE(Class, Base)
1605#define DEPENDENT_TYPE(Class, Base) case Type::Class:
1606#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)
1607#include "clang/AST/TypeNodes.inc"
1609 "dependent type must be resolved before the CIR codegen");
1615 case Type::ExtVector:
1616 case Type::ConstantMatrix:
1620 case Type::TemplateSpecialization:
1621 case Type::ObjCTypeParam:
1622 case Type::ObjCObject:
1623 case Type::ObjCInterface:
1624 case Type::ObjCObjectPointer:
1626 case Type::OverflowBehavior:
1627 llvm_unreachable(
"type class is never variably-modified!");
1629 case Type::Adjusted:
1641 case Type::BlockPointer:
1645 case Type::LValueReference:
1646 case Type::RValueReference:
1650 case Type::MemberPointer:
1654 case Type::ConstantArray:
1655 case Type::IncompleteArray:
1660 case Type::VariableArray: {
1677 entry = builder.createBoolIntToIntCast(size,
sizeTy);
1684 case Type::FunctionProto:
1685 case Type::FunctionNoProto:
1691 case Type::UnaryTransform:
1692 case Type::Attributed:
1693 case Type::BTFTagAttributed:
1694 case Type::SubstTemplateTypeParm:
1695 case Type::MacroQualified:
1701 case Type::Decltype:
1703 case Type::DeducedTemplateSpecialization:
1707 case Type::TypeOfExpr:
1720 }
while (
type->isVariablyModifiedType());
1724 if (
getContext().getBuiltinVaListType()->isArrayType())
Defines the clang::Expr interface and subclasses for C++ expressions.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
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.
QualType getElementType() const
Address withPointer(mlir::Value newPtr) const
Return address with different pointer, but same element type and alignment.
mlir::Value getPointer() const
mlir::Type getElementType() const
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)
The scope of a CXXDefaultInitExpr.
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
mlir::Value cxxStructorImplicitParamValue
void emitTrap(mlir::Location loc, bool createNewBlock)
Emit a trap instruction, which is used to abort the program in an abnormal way, usually for debugging...
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t)
Given a value of type T* that may not be to a complete object, construct an l-vlaue withi the natural...
LValue emitMemberExpr(const MemberExpr *e)
const TargetInfo & getTarget() const
LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr)
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
const clang::Decl * curFuncDecl
clang::FPOptions curFPFeatures
Address loadCXXThisAddress()
LValue emitLValueForLambdaField(const FieldDecl *field)
std::string getCounterRefTmpAsString()
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
llvm::DenseMap< const Expr *, mlir::Value > vlaSizeMap
bool constantFoldsToSimpleInteger(const clang::Expr *cond, llvm::APSInt &resultInt, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does fold but contains a label,...
LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
void emitDelegateCXXConstructorCall(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, const FunctionArgList &args, clang::SourceLocation loc)
VlaSizePair getVLAElements1D(const VariableArrayType *vla)
Return the number of elements for a single dimension for the given array type.
mlir::Value emitArrayLength(const clang::ArrayType *arrayType, QualType &baseType, Address &addr)
Computes the length of an array in elements, as well as the base element type and a properly-typed fi...
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
LValue emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e)
llvm::ScopedHashTableScope< const clang::Decl *, mlir::Value > SymTableScopeTy
mlir::Operation * curFn
The current function or global initializer that is generated code for.
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void enterDtorCleanups(const CXXDestructorDecl *dtor, CXXDtorType type)
Enter the cleanups necessary to complete the given phase of destruction for a destructor.
llvm::SmallVector< const ParmVarDecl * > fnArgs
Save Parameter Decl for coroutine.
llvm::SmallVector< PendingCleanupEntry > deferredConditionalCleanupStack
std::optional< mlir::Value > fnRetAlloca
The compiler-generated variable that holds the return value.
void emitImplicitAssignmentOperatorBody(FunctionArgList &args)
mlir::Type convertTypeForMem(QualType t)
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback)
clang::QualType buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args)
void emitCtorPrologue(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, FunctionArgList &args)
This routine generates necessary code to initialize base classes and non-static data members belongin...
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, mlir::Location loc, clang::CharUnits alignment, bool insertIntoFnEntryBlock, mlir::Value arraySize=nullptr)
LValue emitAggExprToLValue(const Expr *e)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
Address returnValue
The temporary alloca to hold the return value.
static bool hasAggregateEvaluationKind(clang::QualType type)
void finishFunction(SourceLocation endLoc)
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body)
std::string getCounterAggTmpAsString()
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.
CIRGenModule & getCIRGenModule()
unsigned counterRefTmp
Hold counters for incrementally naming temporaries.
mlir::MLIRContext & getMLIRContext()
void emitDestructorBody(FunctionArgList &args)
Emits the body of the current destructor.
LValue emitInitListLValue(const InitListExpr *e)
LValue emitCastLValue(const CastExpr *e)
Casts are never lvalues unless that cast is to a reference type.
LValue emitCXXTypeidLValue(const CXXTypeidExpr *e)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
RValue emitPseudoObjectRValue(const PseudoObjectExpr *e, AggValueSlot slot=AggValueSlot::ignored())
LValue emitDeclRefLValue(const clang::DeclRefExpr *e)
llvm::DenseMap< const clang::ValueDecl *, clang::FieldDecl * > lambdaCaptureFields
mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty, SourceLocation loc, SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue=nullptr)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
LValue emitPredefinedLValue(const PredefinedExpr *e)
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
Emit code to compute the specified expression which can have any type.
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
void emitLambdaStaticInvokeBody(const CXXMethodDecl *md)
CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e)
LValue emitExtVectorElementExpr(const ExtVectorElementExpr *e)
clang::ASTContext & getContext() const
void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
Set the address of a local variable.
mlir::Value cxxabiThisValue
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.
Address getAddress() const
static LValue makeAddr(Address address, clang::QualType t, LValueBaseInfo baseInfo)
clang::QualType getType() const
mlir::Value getPointer() const
LValueBaseInfo getBaseInfo() const
This trivial value class is used to represent the result of an expression that is evaluated.
mlir::Value getValue() const
Return the value of this scalar value.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getFunctionObjectParameterType() const
bool isAbstract() const
Determine whether this class has a pure virtual function.
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
CompoundStmt - This represents a group of statements like { stmt stmt }.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Decl * getNonClosureContext()
Find the innermost non-closure ancestor of this declaration, walking up through blocks,...
SourceLocation getLocation() const
This represents one expression.
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,...
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Returns the set of floating point options that apply to this expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
LangOptions::FPExceptionModeKind getExceptionMode() const
RoundingMode getRoundingMode() const
Represents a function declaration or definition.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
CXXCtorType getCtorType() const
const Decl * getDecl() const
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Describes an C or C++ initializer list.
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
const Expr * getInit(unsigned Init) const
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.
Expr * getResultExpr()
Return the result-bearing expression, or null if there is none.
ArrayRef< Expr * > semantics()
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
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.
child_iterator child_begin()
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
child_iterator child_end()
SourceLocation getBeginLoc() const LLVM_READONLY
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isMemberDataPointerType() const
bool isAnyComplexType() const
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
TypeClass getTypeClass() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represents a variable declaration or definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
static bool previousOpIsNonYieldingCleanup(mlir::Block *block)
static std::string getVersionedTmpName(llvm::StringRef name, unsigned cnt)
static bool mayDropFunctionReturn(const ASTContext &astContext, QualType returnType)
static mlir::Value emitArgumentDemotion(CIRGenFunction &cgf, const VarDecl *var, mlir::Value value)
An argument came in as a promoted argument; demote it back to its declared type.
static void eraseEmptyAndUnusedBlocks(cir::FuncOp func)
static std::variant< LValue, RValue > emitPseudoObjectExpr(CIRGenFunction &cgf, const PseudoObjectExpr *e, bool forLValue, AggValueSlot slot)
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.
@ Ctor_Base
Base object ctor.
@ Ctor_Complete
Complete object ctor.
bool isa(CodeGen::Address addr)
CXXDtorType
C++ destructor types.
@ Dtor_VectorDeleting
Vector deleting dtor.
@ Dtor_Comdat
The COMDAT used for dtors.
@ Dtor_Unified
GCC-style unified dtor.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
U cast(CodeGen::Address addr)
@ Other
Other implicit parameter.
static bool fastMathFuncAttributes()
static bool vtableInitialization()
static bool constructABIArgDirectExtend()
static bool runCleanupsScope()
static bool emitTypeCheck()
static bool fastMathGuard()
static bool fastMathFlags()
static bool generateDebugInfo()
static bool incrementProfileCounter()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
llvm::ArrayRef< mlir::Block * > getRetBlocks()
LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
cir::TryOp getClosestTryParent()
mlir::Location getRetLoc(mlir::Block *b)
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.