18#include "mlir/IR/Location.h"
26#include "llvm/ADT/ScopeExit.h"
27#include "llvm/IR/FPEnv.h"
48 bool suppressNewContext)
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");
72 case Type::DeducedTemplateSpecialization:
73 llvm_unreachable(
"undeduced type in IR-generation");
78 case Type::BlockPointer:
79 case Type::LValueReference:
80 case Type::RValueReference:
81 case Type::MemberPointer:
84 case Type::ConstantMatrix:
85 case Type::FunctionProto:
86 case Type::FunctionNoProto:
88 case Type::ObjCObjectPointer:
91 case Type::OverflowBehavior:
92 case Type::HLSLAttributedResource:
93 case Type::HLSLInlineSpirv:
101 case Type::ConstantArray:
102 case Type::IncompleteArray:
103 case Type::VariableArray:
105 case Type::ObjCObject:
106 case Type::ObjCInterface:
107 case Type::ArrayParameter:
115 llvm_unreachable(
"unknown type kind!");
120 return cgm.getTypes().convertTypeForMem(t);
124 return cgm.getTypes().convertType(t);
134 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
143 return builder.getUnknownLoc();
168 return builder.getUnknownLoc();
173 mlir::Attribute metadata;
200 ignoreCaseStmts =
true;
204 [=](
const Stmt *subStmt) {
205 return containsLabel(subStmt, ignoreCaseStmts);
214 llvm::APSInt resultInt;
218 resultBool = resultInt.getBoolValue();
226 llvm::APSInt &resultInt,
234 llvm::APSInt intValue = result.
Val.
getInt();
238 resultInt = intValue;
242void CIRGenFunction::emitAndUpdateRetAlloca(
QualType type, mlir::Location loc,
244 if (!
type->isVoidType()) {
251void CIRGenFunction::declare(mlir::Value addrVal,
const Decl *var, QualType ty,
252 mlir::Location loc, CharUnits alignment,
255 assert(!
symbolTable.count(var) &&
"not supposed to be available just yet");
257 Address addr(addrVal, alignment);
258 cir::AllocaOp allocaOp = addr.getUnderlyingAllocaOp();
259 assert(allocaOp &&
"expected cir::AllocaOp");
263 if (ty->isReferenceType() || ty.isConstQualified())
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);
295 mlir::Block *curBlock = builder.getBlock();
298 if (curBlock->mightHaveTerminator() && curBlock->getTerminator())
304 bool isEntryBlock = builder.getInsertionBlock()->isEntryBlock();
305 if (!isEntryBlock && curBlock->empty()) {
307 for (mlir::Block *retBlock : retBlocks) {
308 if (retBlock->getUses().empty())
314 if (localScope->
depth == 0) {
318 mlir::Location retLoc = localScope->
getRetLoc(retBlock);
319 if (retBlock->getUses().empty()) {
322 cir::BrOp::create(builder, retLoc, retBlock);
326 emitImplicitReturn();
333 if (!localScope->
isTernary() && !curBlock->mightHaveTerminator()) {
334 !retVal ? cir::YieldOp::create(builder, localScope->endLoc)
335 : cir::YieldOp::create(builder, localScope->endLoc, retVal);
339cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
342 auto fn = dyn_cast<cir::FuncOp>(cgf.curFn);
343 assert(fn &&
"emitReturn from non-function");
345 if (!fn.getFunctionType().hasVoidReturn()) {
347 auto value = cir::LoadOp::create(
348 builder, loc, fn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);
349 return cir::ReturnOp::create(builder, loc,
352 return cir::ReturnOp::create(builder, loc);
362 return classDecl->hasTrivialDestructor();
369 mlir::Operation *op = &block->back();
370 auto cleanupScopeOp = mlir::dyn_cast<cir::CleanupScopeOp>(op);
378 for (mlir::Block &bodyBlock : cleanupScopeOp.getBodyRegion()) {
379 if (bodyBlock.mightHaveTerminator()) {
380 if (mlir::isa<cir::YieldOp>(bodyBlock.getTerminator()))
382 assert(!mlir::isa<cir::BreakOp>(bodyBlock.getTerminator()) &&
383 !mlir::isa<cir::ContinueOp>(bodyBlock.getTerminator()) &&
384 !mlir::isa<cir::ResumeOp>(bodyBlock.getTerminator()));
390void CIRGenFunction::LexicalScope::emitImplicitReturn() {
391 CIRGenBuilderTy &builder = cgf.getBuilder();
392 LexicalScope *localScope = cgf.curLexScope;
397 const auto *fd = dyn_cast_or_null<clang::FunctionDecl>(cgf.curGD.getDecl());
404 if (fd && cgf.getLangOpts().CPlusPlus && !fd->hasImplicitReturnZero() &&
405 !cgf.sawAsmBlock && !fd->getReturnType()->isVoidType() &&
406 builder.getInsertionBlock() &&
408 bool shouldEmitUnreachable =
409 cgf.cgm.getCodeGenOpts().StrictReturn ||
412 if (shouldEmitUnreachable) {
414 if (cgf.cgm.getCodeGenOpts().OptimizationLevel == 0)
415 cir::TrapOp::create(builder, localScope->endLoc);
417 cir::UnreachableOp::create(builder, localScope->endLoc);
418 builder.clearInsertionPoint();
423 (void)emitReturn(localScope->endLoc);
431 scope = scope->parentScope;
444 if (value.getType() == ty)
447 assert((mlir::isa<cir::IntType>(ty) || cir::isAnyFloatingPointType(ty)) &&
448 "unexpected promotion type");
450 if (mlir::isa<cir::IntType>(ty))
451 return cgf.
getBuilder().CIRBaseBuilderTy::createIntCast(value, ty);
457 mlir::Block *entryBB,
461 if (fd && fd->
hasAttr<NakedAttr>()) {
462 cgm.errorNYI(bodyBeginLoc,
"naked function decl");
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);
471 paramVal.setLoc(paramLoc);
473 mlir::Value addrVal =
478 mlir::ptr::MemorySpaceAttrInterface destAddrSpace =
498 mlir::Location fnBodyBegin =
getLoc(bodyBeginLoc);
499 builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal, addrVal);
501 assert(builder.getInsertionBlock() &&
"Should be valid");
505 cir::FuncOp fn, cir::FuncType funcType,
509 "CIRGenFunction can only be used for one function at a time");
517 const auto *fd = dyn_cast_or_null<FunctionDecl>(d);
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()));
538 mlir::Block *entryBB = &fn.getBlocks().front();
539 builder.setInsertionPointToStart(entryBB);
551 if (
Stmt *body = fd->getBody())
552 bodyBeginLoc = body->getBeginLoc();
554 bodyBeginLoc = fd->getLocation();
566 if (
Stmt *body = fd->getBody())
567 bodyEndLoc = body->getEndLoc();
569 bodyEndLoc = fd->getLocation();
571 emitAndUpdateRetAlloca(returnType,
getLoc(bodyEndLoc),
572 getContext().getTypeAlignInChars(returnType));
581 if (fd && fd->hasImplicitReturnZero()) {
583 mlir::Location bodyBeginMLIRLoc =
getLoc(bodyBeginLoc);
584 mlir::Value zero = builder.getNullValue(cirRetTy, bodyBeginMLIRLoc);
585 builder.CIRBaseBuilderTy::createStore(bodyBeginMLIRLoc, zero,
590 if (
const auto *md = dyn_cast_if_present<CXXMethodDecl>(d);
591 md && !md->isStatic()) {
593 md->getParent()->isLambda() && md->getOverloadedOperator() == OO_Call;
595 if (md->isImplicitObjectMemberFunction())
596 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *
this);
625 for (
auto *fd : md->getParent()->fields()) {
626 if (fd->hasCapturedVLAType())
627 cgm.errorNYI(loc,
"lambda captured VLA type");
629 }
else if (md->isImplicitObjectMemberFunction()) {
643 if (!fd || !fd->hasAttr<NakedAttr>()) {
644 for (
const VarDecl *vd : args) {
649 if (
const auto *pvd = dyn_cast<ParmVarDecl>(vd))
650 ty = pvd->getOriginalType();
673 "deferred conditional cleanups were not consumed by a "
674 "FullExprCleanupScope");
683 if (
const CompoundStmt *block = dyn_cast<CompoundStmt>(body))
694 for (mlir::Block &block : func.getBlocks()) {
695 if (block.empty() && block.getUses().empty())
696 blocksToDelete.push_back(&block);
698 for (mlir::Block *block : blocksToDelete)
703 cir::FuncType funcType) {
707 if (funcDecl->isInlineBuiltinDeclaration()) {
711 std::string fdInlineName = (
cgm.getMangledName(funcDecl) +
".inline").str();
713 mlir::cast_or_null<cir::FuncOp>(
cgm.getGlobalValue(fdInlineName));
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);
724 fn.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
725 fn.setSymVisibility(
"private");
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))) {
741 .replaceAllSymbolUses(fn.getSymNameAttr(),
cgm.getModule())
743 llvm_unreachable(
"Failed to replace inline builtin symbol uses");
744 cgm.eraseGlobalSymbol(inlineFn);
753 Stmt *body = funcDecl->getBody();
760 return clangLoc.isValid() ?
getLoc(clangLoc) : builder.getUnknownLoc();
762 const mlir::Location fusedLoc = mlir::FusedLoc::get(
764 {validMLIRLoc(bodyRange.
getBegin()), validMLIRLoc(bodyRange.
getEnd())});
765 mlir::Block *entryBB = fn.addEntryBlock();
779 if (body && isa_and_nonnull<CoroutineBodyStmt>(body))
780 llvm::append_range(
fnArgs, funcDecl->parameters());
782 if (shouldEmitLifetimeMarkers)
790 funcDecl->hasAttr<CUDAGlobalAttr>()) {
791 cgm.getCUDARuntime().emitDeviceStub(*
this, fn, args);
811 llvm_unreachable(
"no definition for normal function");
818 if (mlir::failed(fn.verifyBody()))
823 cgm.emitOpenCLKernelArgMetadata(fn, funcDecl);
834 assert((
cgm.getTarget().getCXXABI().hasConstructorVariants() ||
836 "can only generate complete ctor for this ABI");
841 cgm.getTarget().getCXXABI().hasConstructorVariants()) {
847 Stmt *body = ctor->getBody(definition);
848 assert(definition == ctor &&
"emitting wrong constructor body");
850 bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
859 Stmt *emitterBody =
nullptr;
862 : ctor(ctor), ctorType(ctorType), args(args),
864 ~ctorTryBodyEmitter()
override =
default;
874 return cgf.
emitStmt(emitterBody,
true);
878 ctorTryBodyEmitter emitter{ctor, ctorType, args, isTryBody, body};
879 mlir::LogicalResult bodyRes =
885 if (bodyRes.failed())
886 cgm.errorNYI(ctor->getSourceRange(),
887 "emitConstructorBody: emit body statement failed.");
930 const bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
946 llvm_unreachable(
"not expecting a unified dtor");
948 llvm_unreachable(
"not expecting a COMDAT");
951 llvm_unreachable(
"already handled deleting case");
954 assert((body ||
getTarget().getCXXABI().isMicrosoft()) &&
955 "can't emit a dtor without a body for non-Microsoft ABIs");
973 bool needsVTableInit =
976 if (needsVTableInit &&
cgm.getCodeGenOpts().StrictVTablePointers &&
977 cgm.getCodeGenOpts().OptimizationLevel > 0) {
994 assert(dtor->
isImplicit() &&
"bodyless dtor not implicit");
1020 CharUnits align =
cgm.getNaturalTypeAlignment(ty, &baseInfo);
1027 CharUnits alignment =
cgm.getNaturalTypeAlignment(ty, &baseInfo);
1036 QualType retTy = fd->getReturnType();
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);
1050 bool passedParams =
true;
1051 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(fd))
1052 if (
auto inherited = cd->getInheritedConstructor())
1057 for (
auto *param : fd->parameters()) {
1058 args.push_back(param);
1059 if (!param->hasAttr<PassObjectSizeAttr>())
1063 getContext(), param->getDeclContext(), param->getLocation(),
1066 args.push_back(implicit);
1071 cgm.getCXXABI().addImplicitStructorParams(*
this, retTy, args);
1082 assert(e->
isTransparent() &&
"non-transparent glvalue init list");
1086static std::variant<LValue, RValue>
1091 llvm::scope_exit opaque_cleanup{
1092 [&]() { llvm::for_each(opaques, [&](OVMD &o) { o.unbind(cgf); }); }};
1096 std::variant<LValue, RValue> result;
1101 if (
const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
1104 if (ov->isUnique()) {
1105 assert(ov != resultExpr &&
1106 "A unique OVE cannot be used as the result expression");
1113 if (ov == resultExpr && ov->
isPRValue() && !forLValue &&
1116 "emitPseudoObjectExpr for RValue & aggregate kind");
1118 opaqueData = OVMD::bind(cgf, ov, ov->getSourceExpr());
1121 if (ov == resultExpr) {
1125 "emitPseudoObjectExpr as result");
1130 "emitPseudoObjectExpr as an RValue");
1133 opaques.push_back(opaqueData);
1134 }
else if (semantic == resultExpr) {
1145 "emitPseudoObjectExpr as an ignored value");
1156 return std::get<RValue>(
1173 "emitLValue: unsupported l-value class");
1176 case Expr::ObjCPropertyRefExprClass:
1177 llvm_unreachable(
"cannot emit a property reference directly");
1179 case Expr::ObjCSelectorExprClass:
1181 "emitLValue: ObjCSelectorExpr");
1183 case Expr::ObjCIsaExprClass:
1186 case Expr::BinaryOperatorClass:
1188 case Expr::CompoundAssignOperatorClass: {
1191 ty = at->getValueType();
1197 case Expr::CallExprClass:
1198 case Expr::CXXMemberCallExprClass:
1199 case Expr::CXXOperatorCallExprClass:
1200 case Expr::UserDefinedLiteralClass:
1202 case Expr::CXXRewrittenBinaryOperatorClass:
1205 case Expr::VAArgExprClass:
1208 case Expr::DeclRefExprClass:
1210 case Expr::ConstantExprClass:
1213 case Expr::ParenExprClass:
1215 case Expr::GenericSelectionExprClass:
1217 case Expr::PredefinedExprClass:
1219 case Expr::StringLiteralClass:
1221 case Expr::ObjCEncodeExprClass:
1223 "emitLValue: ObjCEncodeExpr");
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");
1238 case Expr::LambdaExprClass:
1241 case Expr::ExprWithCleanupsClass: {
1258 case Expr::CXXDefaultArgExprClass: {
1263 case Expr::CXXDefaultInitExprClass: {
1268 case Expr::CXXTypeidExprClass:
1270 case Expr::ObjCMessageExprClass:
1272 "emitLValue: ObjCMessageExpr");
1274 case Expr::ObjCIvarRefExprClass:
1276 "emitLValue: ObjCIvarRefExpr");
1278 case Expr::StmtExprClass:
1281 case Expr::UnaryOperatorClass:
1283 case Expr::ArraySubscriptExprClass:
1285 case Expr::MatrixSingleSubscriptExprClass:
1287 "emitLValue: MatrixSingleSubscriptExpr");
1289 case Expr::MatrixSubscriptExprClass:
1291 "emitLValue: MatrixSubscriptExpr");
1293 case Expr::ArraySectionExprClass:
1295 "emitLValue: ArraySectionExpr");
1297 case Expr::ExtVectorElementExprClass:
1299 case Expr::MatrixElementExprClass:
1301 "emitLValue: MatrixElementExpr");
1303 case Expr::CXXThisExprClass:
1306 case Expr::MemberExprClass:
1308 case Expr::CompoundLiteralExprClass:
1310 case Expr::ConditionalOperatorClass:
1312 case Expr::BinaryConditionalOperatorClass:
1314 case Expr::ChooseExprClass:
1316 case Expr::OpaqueValueExprClass:
1318 case Expr::SubstNonTypeTemplateParmExprClass:
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:
1328 case Expr::CXXAddrspaceCastExprClass:
1329 case Expr::ObjCBridgedCastExprClass:
1333 "emitLValue: addrspace or ObjC bridged cast");
1335 case Expr::MaterializeTemporaryExprClass:
1337 case Expr::CoawaitExprClass:
1340 case Expr::CoyieldExprClass:
1343 case Expr::PackIndexingExprClass:
1345 "emitLValue: PackIndexingExpr");
1347 case Expr::HLSLOutArgExprClass:
1348 llvm_unreachable(
"cannot emit a HLSL out argument directly");
1354 llvm::raw_svector_ostream
out(buffer);
1356 return std::string(
out.str());
1379 mlir::IntegerAttr sizeVal;
1383 if (isa_and_nonnull<VariableArrayType>(
getContext().getAsArrayType(ty))) {
1385 "emitNullInitialization for zero size VariableArrayType");
1390 sizeVal =
cgm.getSize(size);
1397 if (!
cgm.getTypes().isZeroInitializable(ty)) {
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);
1413 mlir::Value zero = builder.getNullValue(builder.getUInt8Ty(), loc);
1414 mlir::Value sizeValue =
1415 builder.getConstAPInt(loc,
cgm.uInt64Ty, sizeVal.getValue());
1417 builder.createMemSet(loc, destPtr, zero, sizeValue);
1429 ConstructorHelper(fpFeatures);
1432void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper(
1434 oldFPFeatures = cgf.curFPFeatures;
1435 cgf.curFPFeatures = fpFeatures;
1437 oldExcept = cgf.builder.getDefaultConstrainedExcept();
1438 oldRounding = cgf.builder.getDefaultConstrainedRounding();
1440 if (oldFPFeatures == fpFeatures)
1450 cgf.builder.setDefaultConstrainedRounding(newRoundingMode);
1451 cgf.builder.setDefaultConstrainedExcept(newExceptionBehavior);
1456 assert((cgf.curFuncDecl ==
nullptr || cgf.builder.getIsFPConstrained() ||
1460 newRoundingMode == llvm::RoundingMode::NearestTiesToEven)) &&
1461 "FPConstrained should be enabled on entire function");
1468 cgf.curFPFeatures = oldFPFeatures;
1469 cgf.builder.setDefaultConstrainedExcept(oldExcept);
1470 cgf.builder.setDefaultConstrainedRounding(oldRounding);
1477 if (ce->
getCastKind() == CK_UncheckedDerivedToBase)
1487 if (ice->isGLValue())
1503 mlir::Value numVLAElements =
nullptr;
1515 baseType = elementType;
1516 return numVLAElements;
1529 uint64_t countFromCLAs = 1;
1532 auto cirArrayType = mlir::dyn_cast<cir::ArrayType>(addr.
getElementType());
1534 while (cirArrayType) {
1536 countFromCLAs *= cirArrayType.getSize();
1540 mlir::dyn_cast<cir::ArrayType>(cirArrayType.getElementType());
1544 "CIR and Clang types are out-of-sync");
1551 cgm.errorNYI(*
currSrcLoc,
"length for non-array underlying types");
1556 mlir::Value numElements =
1562 builder.createMul(numVLAElements.getLoc(), numVLAElements, numElements,
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);
1577 bundleArgs.push_back(offsetValue);
1578 cir::AssumeOp::create(builder, assumeLoc, cond, cir::AssumeBundleKind::Align,
1585 int64_t alignment, mlir::Value offsetValue) {
1594 cgm.getASTContext().getAsVariableArrayType(
type);
1595 assert(vla &&
"type was not a variable array type!");
1602 mlir::Value numElements;
1606 elementType =
type->getElementType();
1608 assert(vlaSize &&
"no size for VLA!");
1609 assert(vlaSize.getType() ==
sizeTy);
1612 numElements = vlaSize;
1618 builder.createMul(numElements.getLoc(), numElements, vlaSize,
1621 }
while ((
type =
getContext().getAsVariableArrayType(elementType)));
1623 assert(numElements &&
"Undefined elements number");
1624 return {numElements, elementType};
1630 assert(vlaSize &&
"no size for VLA!");
1631 assert(vlaSize.getType() ==
sizeTy);
1638 assert(
type->isVariablyModifiedType() &&
1639 "Must pass variably modified type to EmitVLASizes!");
1644 assert(
type->isVariablyModifiedType());
1646 const Type *ty =
type.getTypePtr();
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");
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"
1665 "dependent type must be resolved before the CIR codegen");
1671 case Type::ExtVector:
1672 case Type::ConstantMatrix:
1676 case Type::TemplateSpecialization:
1677 case Type::ObjCTypeParam:
1678 case Type::ObjCObject:
1679 case Type::ObjCInterface:
1680 case Type::ObjCObjectPointer:
1682 case Type::OverflowBehavior:
1683 llvm_unreachable(
"type class is never variably-modified!");
1685 case Type::Adjusted:
1697 case Type::BlockPointer:
1701 case Type::LValueReference:
1702 case Type::RValueReference:
1706 case Type::MemberPointer:
1710 case Type::ConstantArray:
1711 case Type::IncompleteArray:
1716 case Type::VariableArray: {
1733 entry = builder.createBoolIntToIntCast(size,
sizeTy);
1740 case Type::FunctionProto:
1741 case Type::FunctionNoProto:
1747 case Type::UnaryTransform:
1748 case Type::Attributed:
1749 case Type::BTFTagAttributed:
1750 case Type::SubstTemplateTypeParm:
1751 case Type::MacroQualified:
1757 case Type::Decltype:
1759 case Type::DeducedTemplateSpecialization:
1763 case Type::TypeOfExpr:
1776 }
while (
type->isVariablyModifiedType());
1780 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
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
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,...
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
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.
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)
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)
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::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
SourceLocation getBeginLoc() const LLVM_READONLY
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.
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)
LangAS getAddressSpace() const
Return the address space of this type.
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
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.
@ 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 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)
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.