18#include "mlir/IR/Location.h"
23#include "llvm/ADT/ScopeExit.h"
24#include "llvm/IR/FPEnv.h"
31 bool suppressNewContext)
42 switch (
type->getTypeClass()) {
43#define TYPE(name, parent)
44#define ABSTRACT_TYPE(name, parent)
45#define NON_CANONICAL_TYPE(name, parent) case Type::name:
46#define DEPENDENT_TYPE(name, parent) case Type::name:
47#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(name, parent) case Type::name:
48#include "clang/AST/TypeNodes.inc"
49 llvm_unreachable(
"non-canonical or dependent type in IR-generation");
52 case Type::DeducedTemplateSpecialization:
53 llvm_unreachable(
"undeduced type in IR-generation");
58 case Type::BlockPointer:
59 case Type::LValueReference:
60 case Type::RValueReference:
61 case Type::MemberPointer:
64 case Type::ConstantMatrix:
65 case Type::FunctionProto:
66 case Type::FunctionNoProto:
68 case Type::ObjCObjectPointer:
71 case Type::OverflowBehavior:
72 case Type::HLSLAttributedResource:
73 case Type::HLSLInlineSpirv:
81 case Type::ConstantArray:
82 case Type::IncompleteArray:
83 case Type::VariableArray:
85 case Type::ObjCObject:
86 case Type::ObjCInterface:
87 case Type::ArrayParameter:
95 llvm_unreachable(
"unknown type kind!");
100 return cgm.getTypes().convertTypeForMem(t);
104 return cgm.getTypes().convertType(t);
114 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
120 assert(
currSrcLoc &&
"expected to inherit some source location");
124 return builder.getUnknownLoc();
134 mlir::Attribute metadata;
140 assert(
currSrcLoc &&
"expected to inherit some source location");
144 return builder.getUnknownLoc();
149 mlir::Attribute metadata;
176 ignoreCaseStmts =
true;
179 return std::any_of(
s->child_begin(),
s->child_end(),
180 [=](
const Stmt *subStmt) {
181 return containsLabel(subStmt, ignoreCaseStmts);
190 llvm::APSInt resultInt;
194 resultBool = resultInt.getBoolValue();
202 llvm::APSInt &resultInt,
210 llvm::APSInt intValue = result.
Val.
getInt();
214 resultInt = intValue;
218void CIRGenFunction::emitAndUpdateRetAlloca(
QualType type, mlir::Location loc,
220 if (!
type->isVoidType()) {
228void CIRGenFunction::declare(mlir::Value addrVal,
const Decl *var, QualType ty,
229 mlir::Location loc, CharUnits alignment,
232 assert(!
symbolTable.count(var) &&
"not supposed to be available just yet");
234 auto allocaOp = addrVal.getDefiningOp<cir::AllocaOp>();
235 assert(allocaOp &&
"expected cir::AllocaOp");
239 if (ty->isReferenceType() || ty.isConstQualified())
255 for (mlir::Block *retBlock : localScope->
getRetBlocks()) {
256 mlir::OpBuilder::InsertionGuard guard(builder);
257 builder.setInsertionPointToEnd(retBlock);
258 retBlocks.push_back(retBlock);
259 mlir::Location retLoc = localScope->
getRetLoc(retBlock);
271 mlir::Block *curBlock = builder.getBlock();
274 if (curBlock->mightHaveTerminator() && curBlock->getTerminator())
280 bool isEntryBlock = builder.getInsertionBlock()->isEntryBlock();
281 if (!isEntryBlock && curBlock->empty()) {
283 for (mlir::Block *retBlock : retBlocks) {
284 if (retBlock->getUses().empty())
290 if (localScope->
depth == 0) {
294 mlir::Location retLoc = localScope->
getRetLoc(retBlock);
295 if (retBlock->getUses().empty()) {
298 cir::BrOp::create(builder, retLoc, retBlock);
302 emitImplicitReturn();
309 if (!localScope->
isTernary() && !curBlock->mightHaveTerminator()) {
310 !retVal ? cir::YieldOp::create(builder, localScope->endLoc)
311 : cir::YieldOp::create(builder, localScope->endLoc, retVal);
315cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
318 auto fn = dyn_cast<cir::FuncOp>(cgf.curFn);
319 assert(fn &&
"emitReturn from non-function");
322 if (fn.getCoroutine())
323 cgf.emitCoroEndBuiltinCall(loc,
324 builder.getNullPtr(builder.getVoidPtrTy(), loc));
325 if (!fn.getFunctionType().hasVoidReturn()) {
327 auto value = cir::LoadOp::create(
328 builder, loc, fn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);
329 return cir::ReturnOp::create(builder, loc,
332 return cir::ReturnOp::create(builder, loc);
342 return classDecl->hasTrivialDestructor();
349 mlir::Operation *op = &block->back();
350 auto cleanupScopeOp = mlir::dyn_cast<cir::CleanupScopeOp>(op);
358 for (mlir::Block &bodyBlock : cleanupScopeOp.getBodyRegion()) {
359 if (bodyBlock.mightHaveTerminator()) {
360 if (mlir::isa<cir::YieldOp>(bodyBlock.getTerminator()))
362 assert(!mlir::isa<cir::BreakOp>(bodyBlock.getTerminator()) &&
363 !mlir::isa<cir::ContinueOp>(bodyBlock.getTerminator()) &&
364 !mlir::isa<cir::ResumeOp>(bodyBlock.getTerminator()));
370void CIRGenFunction::LexicalScope::emitImplicitReturn() {
371 CIRGenBuilderTy &builder = cgf.getBuilder();
372 LexicalScope *localScope = cgf.curLexScope;
381 if (cgf.getLangOpts().CPlusPlus && !fd->hasImplicitReturnZero() &&
382 !cgf.sawAsmBlock && !fd->getReturnType()->isVoidType() &&
383 builder.getInsertionBlock() &&
385 bool shouldEmitUnreachable =
386 cgf.cgm.getCodeGenOpts().StrictReturn ||
389 if (shouldEmitUnreachable) {
391 if (cgf.cgm.getCodeGenOpts().OptimizationLevel == 0)
392 cir::TrapOp::create(builder, localScope->endLoc);
394 cir::UnreachableOp::create(builder, localScope->endLoc);
395 builder.clearInsertionPoint();
400 (void)emitReturn(localScope->endLoc);
408 scope = scope->parentScope;
421 if (value.getType() == ty)
424 assert((mlir::isa<cir::IntType>(ty) || cir::isAnyFloatingPointType(ty)) &&
425 "unexpected promotion type");
427 if (mlir::isa<cir::IntType>(ty))
428 return cgf.
getBuilder().CIRBaseBuilderTy::createIntCast(value, ty);
434 mlir::Block *entryBB,
438 if (fd && fd->
hasAttr<NakedAttr>()) {
439 cgm.errorNYI(bodyBeginLoc,
"naked function decl");
443 for (
const auto nameValue : llvm::zip(args, entryBB->getArguments())) {
444 const VarDecl *paramVar = std::get<0>(nameValue);
445 mlir::Value paramVal = std::get<1>(nameValue);
448 paramVal.setLoc(paramLoc);
450 mlir::Value addrVal =
455 declare(addrVal, paramVar, paramVar->
getType(), paramLoc, alignment,
468 mlir::Location fnBodyBegin =
getLoc(bodyBeginLoc);
469 builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal, addrVal);
471 assert(builder.getInsertionBlock() &&
"Should be valid");
475 cir::FuncOp fn, cir::FuncType funcType,
479 "CIRGenFunction can only be used for one function at a time");
487 const auto *fd = dyn_cast_or_null<FunctionDecl>(d);
492 mlir::Block *entryBB = &fn.getBlocks().front();
493 builder.setInsertionPointToStart(entryBB);
499 if (
Stmt *body = fd->getBody())
500 bodyBeginLoc = body->getBeginLoc();
502 bodyBeginLoc = fd->getLocation();
514 if (
Stmt *body = fd->getBody())
515 bodyEndLoc = body->getEndLoc();
517 bodyEndLoc = fd->getLocation();
519 emitAndUpdateRetAlloca(returnType,
getLoc(bodyEndLoc),
520 getContext().getTypeAlignInChars(returnType));
523 if (isa_and_nonnull<CXXMethodDecl>(d) &&
525 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *
this);
528 if (md->getParent()->isLambda() && md->getOverloadedOperator() == OO_Call) {
530 auto fn = dyn_cast<cir::FuncOp>(
curFn);
531 assert(fn &&
"lambda in non-function region");
557 for (
auto *fd : md->getParent()->fields()) {
558 if (fd->hasCapturedVLAType())
559 cgm.errorNYI(loc,
"lambda captured VLA type");
574 for (cir::BlockAddressOp &blockAddress :
cgm.unresolvedBlockAddressToLabel) {
575 cir::LabelOp labelOp =
576 cgm.lookupBlockAddressInfo(blockAddress.getBlockAddrInfo());
577 assert(labelOp &&
"expected cir.labelOp to already be emitted");
578 cgm.updateResolvedBlockAddress(blockAddress, labelOp);
580 cgm.unresolvedBlockAddressToLabel.clear();
588 mlir::OpBuilder::InsertionGuard guard(builder);
590 for (
auto &[blockAdd, labelOp] :
cgm.blockAddressToLabel) {
591 succesors.push_back(labelOp->getBlock());
592 rangeOperands.push_back(labelOp->getBlock()->getArguments());
594 cir::IndirectBrOp::create(builder, builder.getUnknownLoc(),
596 rangeOperands, succesors);
597 cgm.blockAddressToLabel.clear();
612 indrBr.setPoison(
true);
628 "deferred conditional cleanups were not consumed by a "
629 "FullExprCleanupScope");
636 if (
const CompoundStmt *block = dyn_cast<CompoundStmt>(body))
647 for (mlir::Block &block : func.getBlocks()) {
648 if (block.empty() && block.getUses().empty())
649 blocksToDelete.push_back(&block);
651 for (mlir::Block *block : blocksToDelete)
656 cir::FuncType funcType) {
660 if (funcDecl->isInlineBuiltinDeclaration()) {
664 std::string fdInlineName = (
cgm.getMangledName(funcDecl) +
".inline").str();
666 mlir::cast_or_null<cir::FuncOp>(
cgm.getGlobalValue(fdInlineName));
668 mlir::OpBuilder::InsertionGuard guard(builder);
669 builder.setInsertionPoint(fn);
670 clone = cir::FuncOp::create(builder, fn.getLoc(), fdInlineName,
671 fn.getFunctionType());
672 clone.setLinkage(cir::GlobalLinkageKind::InternalLinkage);
673 clone.setSymVisibility(
"private");
674 clone.setInlineKind(cir::InlineKind::AlwaysInline);
676 fn.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
677 fn.setSymVisibility(
"private");
685 if (LLVM_UNLIKELY(pd->isInlineBuiltinDeclaration())) {
686 std::string inlineName = funcDecl->getName().str() +
".inline";
687 if (
auto inlineFn = mlir::cast_or_null<cir::FuncOp>(
688 cgm.getGlobalValue(inlineName))) {
693 .replaceAllSymbolUses(fn.getSymNameAttr(),
cgm.getModule())
695 llvm_unreachable(
"Failed to replace inline builtin symbol uses");
704 Stmt *body = funcDecl->getBody();
709 : builder.getUnknownLoc()};
712 return clangLoc.isValid() ?
getLoc(clangLoc) : builder.getUnknownLoc();
714 const mlir::Location fusedLoc = mlir::FusedLoc::get(
716 {validMLIRLoc(bodyRange.
getBegin()), validMLIRLoc(bodyRange.
getEnd())});
717 mlir::Block *entryBB = fn.addEntryBlock();
731 if (body && isa_and_nonnull<CoroutineBodyStmt>(body))
732 llvm::append_range(
fnArgs, funcDecl->parameters());
739 funcDecl->hasAttr<CUDAGlobalAttr>()) {
740 cgm.getCUDARuntime().emitDeviceStub(*
this, fn, args);
760 llvm_unreachable(
"no definition for normal function");
763 if (mlir::failed(fn.verifyBody()))
778 assert((
cgm.getTarget().getCXXABI().hasConstructorVariants() ||
780 "can only generate complete ctor for this ABI");
785 cgm.getTarget().getCXXABI().hasConstructorVariants()) {
791 Stmt *body = ctor->getBody(definition);
792 assert(definition == ctor &&
"emitting wrong constructor body");
794 bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
803 Stmt *emitterBody =
nullptr;
806 : ctor(ctor), ctorType(ctorType), args(args),
808 ~ctorTryBodyEmitter()
override =
default;
818 return cgf.
emitStmt(emitterBody,
true);
822 ctorTryBodyEmitter emitter{ctor, ctorType, args, isTryBody, body};
823 mlir::LogicalResult bodyRes =
829 if (bodyRes.failed())
830 cgm.errorNYI(ctor->getSourceRange(),
831 "emitConstructorBody: emit body statement failed.");
875 const bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);
891 llvm_unreachable(
"not expecting a unified dtor");
893 llvm_unreachable(
"not expecting a COMDAT");
896 llvm_unreachable(
"already handled deleting case");
899 assert((body ||
getTarget().getCXXABI().isMicrosoft()) &&
900 "can't emit a dtor without a body for non-Microsoft ABIs");
928 assert(dtor->
isImplicit() &&
"bodyless dtor not implicit");
954 CharUnits align =
cgm.getNaturalTypeAlignment(ty, &baseInfo);
961 CharUnits alignment =
cgm.getNaturalTypeAlignment(ty, &baseInfo);
969static llvm::fp::ExceptionBehavior
973 return llvm::fp::ebIgnore;
975 return llvm::fp::ebMayTrap;
977 return llvm::fp::ebStrict;
979 llvm_unreachable(
"expected explicitly initialized exception behavior");
981 llvm_unreachable(
"unsupported FP exception behavior");
987 QualType retTy = fd->getReturnType();
989 const auto *md = dyn_cast<CXXMethodDecl>(fd);
990 if (md && md->isInstance()) {
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>())
1008 cgm.errorNYI(param->getSourceRange(),
"pass-object-size attribute");
1013 cgm.getCXXABI().addImplicitStructorParams(*
this, retTy, args);
1024 assert(e->
isTransparent() &&
"non-transparent glvalue init list");
1028static std::variant<LValue, RValue>
1033 llvm::scope_exit opaque_cleanup{
1034 [&]() { llvm::for_each(opaques, [&](OVMD &o) { o.unbind(cgf); }); }};
1038 std::variant<LValue, RValue> result;
1043 if (
const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
1046 if (ov->isUnique()) {
1050 "emitPseudoObjectExpr skipped for uniqueness");
1051 assert(ov != resultExpr &&
1052 "A unique OVE cannot be used as the result expression");
1059 if (ov == resultExpr && ov->
isPRValue() && !forLValue &&
1062 "emitPseudoObjectExpr for RValue & aggregate kind");
1064 opaqueData = OVMD::bind(cgf, ov, ov->getSourceExpr());
1067 if (ov == resultExpr) {
1071 "emitPseudoObjectExpr as result");
1076 "emitPseudoObjectExpr as an RValue");
1079 opaques.push_back(opaqueData);
1080 }
else if (semantic == resultExpr) {
1088 "emitPseudoObjectExpr as an RValue, when semantic is result");
1093 "emitPseudoObjectExpr as an ignored value");
1115 std::string(
"l-value not implemented for '") +
1118 case Expr::ConditionalOperatorClass:
1120 case Expr::BinaryConditionalOperatorClass:
1122 case Expr::ArraySubscriptExprClass:
1124 case Expr::ExtVectorElementExprClass:
1126 case Expr::UnaryOperatorClass:
1128 case Expr::StringLiteralClass:
1130 case Expr::MemberExprClass:
1132 case Expr::CompoundLiteralExprClass:
1134 case Expr::PredefinedExprClass:
1136 case Expr::BinaryOperatorClass:
1138 case Expr::CompoundAssignOperatorClass: {
1142 "CompoundAssignOperator with AtomicType");
1150 case Expr::CallExprClass:
1151 case Expr::CXXMemberCallExprClass:
1152 case Expr::CXXOperatorCallExprClass:
1153 case Expr::UserDefinedLiteralClass:
1155 case Expr::ExprWithCleanupsClass: {
1162 case Expr::CXXDefaultArgExprClass: {
1167 case Expr::CXXTypeidExprClass:
1169 case Expr::ParenExprClass:
1171 case Expr::GenericSelectionExprClass:
1173 case Expr::DeclRefExprClass:
1175 case Expr::ImplicitCastExprClass:
1176 case Expr::CStyleCastExprClass:
1177 case Expr::CXXStaticCastExprClass:
1178 case Expr::CXXDynamicCastExprClass:
1179 case Expr::CXXReinterpretCastExprClass:
1180 case Expr::CXXConstCastExprClass:
1181 case Expr::CXXFunctionalCastExprClass:
1185 case Expr::MaterializeTemporaryExprClass:
1187 case Expr::OpaqueValueExprClass:
1189 case Expr::ChooseExprClass:
1191 case Expr::SubstNonTypeTemplateParmExprClass:
1193 case Expr::InitListExprClass:
1195 case Expr::PseudoObjectExprClass:
1202 llvm::raw_svector_ostream
out(buffer);
1204 return std::string(
out.str());
1224 cgm.errorNYI(loc,
"Cast the dest ptr to the appropriate i8 pointer type");
1233 "emitNullInitialization for zero size VariableArrayType");
1243 if (!
cgm.getTypes().isZeroInitializable(ty)) {
1244 cgm.errorNYI(loc,
"type is not zero initializable");
1251 const mlir::Value zeroValue = builder.getNullValue(
convertType(ty), loc);
1252 builder.createStore(loc, zeroValue, destPtr);
1264 ConstructorHelper(fpFeatures);
1267void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper(
1269 oldFPFeatures = cgf.curFPFeatures;
1270 cgf.curFPFeatures = fpFeatures;
1272 oldExcept = cgf.builder.getDefaultConstrainedExcept();
1273 oldRounding = cgf.builder.getDefaultConstrainedRounding();
1275 if (oldFPFeatures == fpFeatures)
1281 [[maybe_unused]] llvm::RoundingMode newRoundingBehavior =
1284 [[maybe_unused]] llvm::fp::ExceptionBehavior newExceptionBehavior =
1292 assert((cgf.curFuncDecl ==
nullptr || cgf.builder.getIsFPConstrained() ||
1295 (newExceptionBehavior == llvm::fp::ebIgnore &&
1296 newRoundingBehavior == llvm::RoundingMode::NearestTiesToEven)) &&
1297 "FPConstrained should be enabled on entire function");
1304 cgf.curFPFeatures = oldFPFeatures;
1305 cgf.builder.setDefaultConstrainedExcept(oldExcept);
1306 cgf.builder.setDefaultConstrainedRounding(oldRounding);
1313 if (ce->
getCastKind() == CK_UncheckedDerivedToBase)
1323 if (ice->isGLValue())
1339 mlir::Value numVLAElements =
nullptr;
1351 baseType = elementType;
1352 return numVLAElements;
1365 uint64_t countFromCLAs = 1;
1368 auto cirArrayType = mlir::dyn_cast<cir::ArrayType>(addr.
getElementType());
1370 while (cirArrayType) {
1372 countFromCLAs *= cirArrayType.getSize();
1376 mlir::dyn_cast<cir::ArrayType>(cirArrayType.getElementType());
1380 "CIR and Clang types are out-of-sync");
1387 cgm.errorNYI(*
currSrcLoc,
"length for non-array underlying types");
1392 mlir::Value numElements =
1398 builder.createMul(numVLAElements.getLoc(), numVLAElements, numElements,
1409 mlir::OpBuilder::InsertionGuard guard(builder);
1411 builder.createBlock(builder.getBlock()->getParent(), {}, {voidPtrTy},
1412 {builder.getUnknownLoc()});
1417 SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue) {
1419 return cir::AssumeAlignedOp::create(builder,
getLoc(assumptionLoc), ptrValue,
1420 alignment, offsetValue);
1425 int64_t alignment, mlir::Value offsetValue) {
1434 cgm.getASTContext().getAsVariableArrayType(
type);
1435 assert(vla &&
"type was not a variable array type!");
1442 mlir::Value numElements;
1446 elementType =
type->getElementType();
1448 assert(vlaSize &&
"no size for VLA!");
1449 assert(vlaSize.getType() ==
sizeTy);
1452 numElements = vlaSize;
1458 builder.createMul(numElements.getLoc(), numElements, vlaSize,
1461 }
while ((
type =
getContext().getAsVariableArrayType(elementType)));
1463 assert(numElements &&
"Undefined elements number");
1464 return {numElements, elementType};
1470 assert(vlaSize &&
"no size for VLA!");
1471 assert(vlaSize.getType() ==
sizeTy);
1478 assert(
type->isVariablyModifiedType() &&
1479 "Must pass variably modified type to EmitVLASizes!");
1484 assert(
type->isVariablyModifiedType());
1486 const Type *ty =
type.getTypePtr();
1488 case Type::CountAttributed:
1489 case Type::PackIndexing:
1490 case Type::ArrayParameter:
1491 case Type::HLSLAttributedResource:
1492 case Type::HLSLInlineSpirv:
1493 case Type::PredefinedSugar:
1494 cgm.errorNYI(
"CIRGenFunction::emitVariablyModifiedType");
1497#define TYPE(Class, Base)
1498#define ABSTRACT_TYPE(Class, Base)
1499#define NON_CANONICAL_TYPE(Class, Base)
1500#define DEPENDENT_TYPE(Class, Base) case Type::Class:
1501#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)
1502#include "clang/AST/TypeNodes.inc"
1504 "dependent type must be resolved before the CIR codegen");
1510 case Type::ExtVector:
1511 case Type::ConstantMatrix:
1515 case Type::TemplateSpecialization:
1516 case Type::ObjCTypeParam:
1517 case Type::ObjCObject:
1518 case Type::ObjCInterface:
1519 case Type::ObjCObjectPointer:
1521 case Type::OverflowBehavior:
1522 llvm_unreachable(
"type class is never variably-modified!");
1524 case Type::Adjusted:
1536 case Type::BlockPointer:
1540 case Type::LValueReference:
1541 case Type::RValueReference:
1545 case Type::MemberPointer:
1549 case Type::ConstantArray:
1550 case Type::IncompleteArray:
1555 case Type::VariableArray: {
1572 entry = builder.createIntCast(size,
sizeTy);
1579 case Type::FunctionProto:
1580 case Type::FunctionNoProto:
1586 case Type::UnaryTransform:
1587 case Type::Attributed:
1588 case Type::BTFTagAttributed:
1589 case Type::SubstTemplateTypeParm:
1590 case Type::MacroQualified:
1596 case Type::Decltype:
1598 case Type::DeducedTemplateSpecialization:
1602 case Type::TypeOfExpr:
1615 }
while (
type->isVariablyModifiedType());
1619 if (
getContext().getBuiltinVaListType()->isArrayType())
Defines the clang::Expr interface and subclasses for C++ expressions.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
__device__ __2f16 float __ockl_bool s
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
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)
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 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
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::Block * indirectGotoBlock
IndirectBranch - The first time an indirect goto is seen we create a block reserved for the indirect ...
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.
void finishIndirectBranch()
LValue emitStringLiteralLValue(const StringLiteral *e, llvm::StringRef name=".str")
void resolveBlockAddresses()
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.
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)
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
void emitLambdaStaticInvokeBody(const CXXMethodDecl *md)
void instantiateIndirectGotoBlock()
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.
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
mlir::Value getPointer() const
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 ...
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_Default
Used internally to represent initial unspecified value.
@ FPE_Strict
Strictly preserve the floating-point exception semantics.
@ FPE_MayTrap
Transformations do not cause new exceptions but may hide some.
@ FPE_Ignore
Assume that floating-point exceptions are masked.
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)
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.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const char * getStmtClassName() const
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 isAnyComplexType() const
TypeClass getTypeClass() const
const T * getAs() const
Member-template getAs<specific type>'.
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)
static llvm::fp::ExceptionBehavior toConstrainedExceptMd(LangOptions::FPExceptionModeKind kind)
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)
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 cleanupWithPreservedValues()
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.