17#include "mlir/IR/Builders.h"
23#include "llvm/IR/Value.h"
39 if (
const DeclRefExpr *dre = dyn_cast<DeclRefExpr>(e)) {
40 const VarDecl *
var = dyn_cast<VarDecl>(dre->getDecl());
41 return (var &&
var->hasAttr<BlocksAttr>());
50 if (op->isAssignmentOp() || op->isPtrMemOp())
54 if (op->getOpcode() == BO_Comma)
62 dyn_cast<AbstractConditionalOperator>(e)) {
68 if (
const Expr *src = op->getSourceExpr())
75 }
else if (
const CastExpr *
cast = dyn_cast<CastExpr>(e)) {
76 if (
cast->getCastKind() == CK_LValueToRValue)
82 }
else if (
const UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
86 }
else if (
const MemberExpr *mem = dyn_cast<MemberExpr>(e)) {
97class AggExprEmitter :
public StmtVisitor<AggExprEmitter> {
108 void withReturnValueSlot(
const Expr *e,
109 llvm::function_ref<RValue(ReturnValueSlot)> fn);
111 AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
112 if (!dest.isIgnored())
114 return cgf.createAggTemp(t, loc,
"agg.tmp.ensured");
117 void ensureDest(mlir::Location loc, QualType ty) {
118 if (!dest.isIgnored())
120 dest = cgf.createAggTemp(ty, loc,
"agg.tmp.ensured");
124 AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
125 : cgf(cgf), dest(dest) {}
130 void emitAggLoadOfLValue(
const Expr *e);
132 void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
133 Expr *exprToVisit, ArrayRef<Expr *> args,
136 void emitFinalDestCopy(QualType
type, RValue src);
139 void emitFinalDestCopy(QualType
type,
const LValue &src,
143 void emitCopy(QualType
type,
const AggValueSlot &dest,
144 const AggValueSlot &src);
146 void emitInitializationToLValue(Expr *e, LValue lv);
148 void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
150 void emitComparisonResult(
const Expr *e, mlir::Location loc,
151 const ComparisonCategoryInfo &cmpInfo,
152 mlir::Value resultValue);
154 void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
156 void VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
157 emitAggLoadOfLValue(e);
160 void VisitCallExpr(
const CallExpr *e);
161 void VisitStmtExpr(
const StmtExpr *e) {
162 CIRGenFunction::StmtExprEvaluation eval(cgf);
165 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca, dest);
168 void VisitBinAssign(
const BinaryOperator *e) {
171 assert(cgf.getContext().hasSameUnqualifiedType(e->
getLHS()->
getType(),
173 "Invalid assignment");
178 "block var reference with side effects");
182 LValue lhs = cgf.emitLValue(e->
getLHS());
186 if (lhs.getType()->isAtomicType() ||
187 cgf.isLValueSuitableForInlineAtomic(lhs)) {
190 cgf.emitAtomicStore(dest.asRValue(), lhs,
false);
204 cgf.emitAggExpr(e->
getRHS(), lhsSlot);
207 emitFinalDestCopy(e->
getType(), lhs);
209 if (!dest.isIgnored() && !dest.isExternallyDestructed() &&
215 void VisitDeclRefExpr(DeclRefExpr *e) { emitAggLoadOfLValue(e); }
217 void VisitInitListExpr(InitListExpr *e);
218 void VisitCXXConstructExpr(
const CXXConstructExpr *e);
220 void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
221 FieldDecl *initializedFieldInUnion,
223 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
224 CIRGenFunction::CXXDefaultInitExprScope Scope(cgf, die);
227 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *e) {
230 bool wasExternallyDestructed = dest.isExternallyDestructed();
234 dest.setExternallyDestructed();
239 if (!wasExternallyDestructed)
243 void VisitExprWithCleanups(ExprWithCleanups *e);
249 if (
auto *castE = dyn_cast<CastExpr>(op)) {
250 if (castE->getCastKind() ==
kind)
251 return castE->getSubExpr();
259 case CK_LValueToRValueBitCast: {
260 if (dest.isIgnored()) {
266 LValue sourceLV = cgf.emitLValue(e->
getSubExpr());
268 sourceLV.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
270 dest.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
272 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
274 mlir::Value sizeVal = cgf.getBuilder().getConstInt(
276 cgf.getContext().getTypeSizeInChars(e->
getType()).getQuantity());
277 cgf.getBuilder().createMemCpy(loc, destAddress.
getPointer(),
283 case CK_NonAtomicToAtomic:
284 case CK_AtomicToNonAtomic: {
285 bool isToAtomic = (e->
getCastKind() == CK_NonAtomicToAtomic);
289 QualType valueType = e->
getType();
294 assert(cgf.getContext().hasSameUnqualifiedType(
295 valueType,
atomicType->castAs<AtomicType>()->getValueType()));
299 if (dest.isIgnored() || !cgf.cgm.isPaddedAtomicType(
atomicType))
304 (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic);
309 assert(cgf.getContext().hasSameUnqualifiedType(op->
getType(),
311 "peephole significantly changed types?");
318 AggValueSlot valueDest = dest;
322 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
323 if (!dest.isZeroed())
324 cgf.emitNullInitialization(loc, dest.getAddress(),
atomicType);
326 Address valueAddr = cgf.getBuilder().createGetMember(
327 loc, valueDest.
getAddress(),
"value_addr", 0);
341 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
342 AggValueSlot atomicSlot = cgf.createAggTemp(
atomicType, loc);
345 Address valueAddr = cgf.getBuilder().createGetMember(
346 loc, atomicSlot.
getAddress(),
"value_addr", 0);
348 return emitFinalDestCopy(valueType, rvalue);
350 case CK_LValueToRValue:
355 "AggExprEmitter: volatile lvalue-to-rvalue cast");
358 case CK_UserDefinedConversion:
359 case CK_ConstructorConversion:
362 "Implicit cast types must be compatible");
366 if (dest.isIgnored()) {
372 Address castPtr = dest.getAddress().withElementType(cgf.getBuilder(),
373 cgf.convertType(ty));
375 cgf.makeAddrLValue(castPtr, ty));
380 std::string(
"AggExprEmitter: VisitCastExpr: ") +
385 void VisitStmt(Stmt *s) {
387 std::string(
"AggExprEmitter::VisitStmt: ") +
390 void VisitParenExpr(ParenExpr *pe) { Visit(pe->
getSubExpr()); }
391 void VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
394 void VisitCoawaitExpr(CoawaitExpr *e) {
395 cgf.cgm.errorNYI(e->
getSourceRange(),
"AggExprEmitter: VisitCoawaitExpr");
397 void VisitCoyieldExpr(CoyieldExpr *e) {
398 cgf.cgm.errorNYI(e->
getSourceRange(),
"AggExprEmitter: VisitCoyieldExpr");
400 void VisitUnaryCoawait(UnaryOperator *e) {
401 cgf.cgm.errorNYI(e->
getSourceRange(),
"AggExprEmitter: VisitUnaryCoawait");
403 void VisitUnaryExtension(UnaryOperator *e) { Visit(e->
getSubExpr()); }
404 void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
406 "AggExprEmitter: VisitSubstNonTypeTemplateParmExpr");
408 void VisitConstantExpr(ConstantExpr *e) {
411 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
412 mlir::Value resultVal = cgf.getBuilder().getConstant(
413 cgf.getLoc(e->
getSourceRange()), mlir::cast<mlir::TypedAttr>(result));
414 LValue destLVal = cgf.makeAddrLValue(dest.getAddress(), e->
getType());
415 cgf.emitStoreThroughLValue(
RValue::get(resultVal), destLVal);
423 void VisitMemberExpr(MemberExpr *e) { emitAggLoadOfLValue(e); }
424 void VisitUnaryDeref(UnaryOperator *e) { emitAggLoadOfLValue(e); }
425 void VisitStringLiteral(StringLiteral *e) { emitAggLoadOfLValue(e); }
426 void VisitCompoundLiteralExpr(CompoundLiteralExpr *e);
428 void VisitPredefinedExpr(
const PredefinedExpr *e) { emitAggLoadOfLValue(e); }
429 void VisitBinaryOperator(
const BinaryOperator *e) {
431 "AggExprEmitter: VisitBinaryOperator");
433 void VisitPointerToDataMemberBinaryOperator(
const BinaryOperator *e) {
435 "AggExprEmitter: VisitPointerToDataMemberBinaryOperator");
437 void VisitBinComma(
const BinaryOperator *e) {
438 cgf.emitIgnoredExpr(e->
getLHS());
441 void VisitBinCmp(
const BinaryOperator *e) {
444 const ComparisonCategoryInfo &cmpInfo =
445 cgf.getContext().CompCategories.getInfoForType(e->
getType());
447 "cannot copy non-trivially copyable aggregate");
454 cgf.cgm.errorNYI(e->
getBeginLoc(),
"aggregate three-way comparison");
457 CIRGenBuilderTy &builder = cgf.getBuilder();
460 cgf.cgm.errorNYI(e->
getBeginLoc(),
"VisitBinCmp: complex type");
463 cgf.cgm.errorNYI(e->
getBeginLoc(),
"VisitBinCmp: aggregate type");
465 mlir::Value lhs = cgf.emitAnyExpr(e->
getLHS()).getValue();
466 mlir::Value rhs = cgf.emitAnyExpr(e->
getRHS()).getValue();
468 mlir::Value resultScalar;
477 cir::CmpOrdering ordering = cmpInfo.
isStrong()
478 ? cir::CmpOrdering::Strong
479 : cir::CmpOrdering::Weak;
481 loc, lhs, rhs, ltRes, eqRes, gtRes, ordering);
486 loc, lhs, rhs, ltRes, eqRes, gtRes, unorderedRes);
490 emitComparisonResult(e, loc, cmpInfo, resultScalar);
493 void VisitTypeTraitExpr(
const TypeTraitExpr *e) {
495 "expected a strong_ordering type trait with a stored value");
497 const ComparisonCategoryInfo &cmpInfo =
498 cgf.getContext().CompCategories.getInfoForType(e->
getType());
502 mlir::Value resultValue = cgf.getBuilder().getConstInt(
505 emitComparisonResult(e, loc, cmpInfo, resultValue);
508 void VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
511 void VisitObjCMessageExpr(ObjCMessageExpr *e) {
513 "AggExprEmitter: VisitObjCMessageExpr");
515 void VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
517 "AggExprEmitter: VisitObjCIVarRefExpr");
520 void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e) {
522 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->
getType());
523 emitInitializationToLValue(e->
getBase(), destLV);
526 void VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e) {
529 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
530 CIRGenFunction::ConditionalEvaluation eval(cgf);
533 bool isExternallyDestructed = dest.isExternallyDestructed();
534 bool destructNonTrivialCStruct =
535 !isExternallyDestructed &&
537 isExternallyDestructed |= destructNonTrivialCStruct;
541 cgf.emitIfOnBoolExpr(
544 [&](mlir::OpBuilder &b, mlir::Location loc) {
545 eval.beginEvaluation();
547 CIRGenFunction::LexicalScope lexScope{cgf, loc,
548 b.getInsertionBlock()};
549 cgf.curLexScope->setAsTernary();
550 dest.setExternallyDestructed(isExternallyDestructed);
551 assert(!cir::MissingFeatures::incrementProfileCounter());
552 Visit(e->getTrueExpr());
554 eval.endEvaluation();
558 [&](mlir::OpBuilder &b, mlir::Location loc) {
559 eval.beginEvaluation();
561 CIRGenFunction::LexicalScope lexScope{cgf, loc,
562 b.getInsertionBlock()};
563 cgf.curLexScope->setAsTernary();
569 dest.setExternallyDestructed(isExternallyDestructed);
573 eval.endEvaluation();
577 if (destructNonTrivialCStruct)
580 "Abstract conditional aggregate: destructNonTrivialCStruct");
591 uint64_t numElements = e->
getArraySize().getZExtValue();
600 "VisitArrayInitLoopExpr: Non-constant array");
605 emitArrayInit(dest, arrayTy, e->
getType(),
613 emitNullInitializationToLValue(loc,
639 assert(array.isSimple() &&
"initializer_list array not a simple lvalue");
640 Address arrayPtr = array.getAddress();
644 assert(
arrayType &&
"std::initializer_list constructed from non-array");
647 assert(record->getNumFields() == 2 &&
648 "Expected std::initializer_list to only have two fields");
651 assert(field != record->field_end() &&
652 ctx.
hasSameType(field->getType()->getPointeeType(),
654 "Expected std::initializer_list first field to be const E *");
665 assert(field != record->field_end() &&
666 "Expected std::initializer_list to have two fields");
676 assert(field->getType()->isPointerType() &&
677 ctx.
hasSameType(field->getType()->getPointeeType(),
679 "Expected std::initializer_list second field to be const E *");
687 "AggExprEmitter: VisitCXXScalarValueInitExpr");
689 void VisitCXXTypeidExpr(
CXXTypeidExpr *e) { emitAggLoadOfLValue(e); }
695 "AggExprEmitter: VisitOpaqueValueExpr");
700 "AggExprEmitter: VisitPseudoObjectExpr");
706 mlir::Value vaArgValue = cgf.
emitVAArg(e);
719 emitFinalDestCopy(e->
getType(), tmpLValue);
725 emitFinalDestCopy(e->
getType(), result);
738 if (
auto *ile = dyn_cast<InitListExpr>(e)) {
739 if (ile->getNumInits())
744 if (
const auto *cons = dyn_cast_or_null<CXXConstructExpr>(e))
745 return cons->getConstructor()->isDefaultConstructor() &&
746 cons->getConstructor()->isTrivial();
753void AggExprEmitter::emitAggLoadOfLValue(
const Expr *e) {
762 emitFinalDestCopy(e->
getType(), lv);
765void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
769 emitAggLoadOfLValue(e);
790void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
791 QualType arrayQTy, Expr *e,
792 ArrayRef<Expr *> args, Expr *arrayFiller) {
796 const uint64_t numInitElements = args.size();
800 const QualType elementType =
805 const mlir::Type cirElementType = cgf.
convertType(elementType);
806 const cir::PointerType cirElementPtrType =
809 auto begin = cir::CastOp::create(builder, loc, cirElementPtrType,
810 cir::CastKind::array_to_ptrdecay,
813 const CharUnits elementSize =
815 const CharUnits elementAlign =
826 loc,
"arrayinit.endOfInit");
839 mlir::Value element = begin;
846 for (uint64_t i = 0; i != numInitElements; ++i) {
857 const Address address =
Address(element, cirElementType, elementAlign);
858 const LValue elementLV = cgf.
makeAddrLValue(address, elementType);
859 emitInitializationToLValue(args[i], elementLV);
862 const uint64_t numArrayElements = arrayTy.getSize();
870 if (numInitElements != numArrayElements &&
871 !(dest.
isZeroed() && hasTrivialFiller &&
874 if (numInitElements) {
876 element = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
891 cir::ConstantOp numArrayElementsConst = builder.
getConstInt(
892 loc, mlir::cast<cir::IntType>(cgf.
ptrDiffTy), numArrayElements);
893 mlir::Value end = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
894 begin, numArrayElementsConst);
899 [&](mlir::OpBuilder &b, mlir::Location loc) {
900 cir::LoadOp currentElement = builder.
createLoad(loc, tmpAddr);
901 cir::CmpOp cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
902 currentElement, end);
906 [&](mlir::OpBuilder &b, mlir::Location loc) {
907 cir::LoadOp currentElement = builder.
createLoad(loc, tmpAddr);
911 Address(currentElement, cirElementType, elementAlign),
915 if (setArrayInitLoopExprScope)
916 idx = cir::PtrDiffOp::create(b, loc, cgf.
ptrDiffTy, currentElement,
919 CIRGenFunction::ArrayInitLoopExprScope loopExprScope(
920 cgf, setArrayInitLoopExprScope, idx);
923 emitInitializationToLValue(arrayFiller, elementLV);
925 emitNullInitializationToLValue(loc, elementLV);
929 loc, mlir::cast<cir::IntType>(cgf.
ptrDiffTy), 1);
930 auto nextElement = cir::PtrStrideOp::create(
931 builder, loc, cirElementPtrType, currentElement, one);
945void AggExprEmitter::emitFinalDestCopy(QualType
type, RValue src) {
946 assert(src.
isAggregate() &&
"value must be aggregate value!");
952void AggExprEmitter::emitFinalDestCopy(
953 QualType
type,
const LValue &src,
964 cgf.
cgm.
errorNYI(
"emitFinalDestCopy: EVK_RValue & PCK_Struct");
968 cgf.
cgm.
errorNYI(
"emitFinalDestCopy: !EVK_RValue & PCK_Struct");
979 emitCopy(
type, dest, srcAgg);
986void AggExprEmitter::emitCopy(QualType
type,
const AggValueSlot &dest,
987 const AggValueSlot &src) {
1000void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
1001 const QualType
type = lv.getType();
1007 return emitNullInitializationToLValue(loc, lv);
1013 if (
type->isReferenceType()) {
1038void AggExprEmitter::VisitCXXConstructExpr(
const CXXConstructExpr *e) {
1043void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
1045 const QualType
type = lv.getType();
1055 if (lv.isSimple()) {
1070void AggExprEmitter::emitComparisonResult(
const Expr *e, mlir::Location loc,
1071 const ComparisonCategoryInfo &cmpInfo,
1072 mlir::Value resultValue) {
1074 ensureDest(loc, e->
getType());
1081 destLVal, resultField, resultField->
getName());
1085void AggExprEmitter::VisitLambdaExpr(
LambdaExpr *e) {
1092 CIRGenFunction::CleanupDeactivationScope deactivationScope(cgf);
1094 for (
auto [curField, capture, captureInit] : llvm::zip(
1097 llvm::StringRef fieldName = curField->getName();
1098 if (capture.capturesVariable()) {
1099 assert(!curField->isBitField() &&
"lambdas don't have bitfield members!");
1100 ValueDecl *v = capture.getCapturedVar();
1103 }
else if (capture.capturesThis()) {
1113 if (curField->hasCapturedVLAType())
1116 emitInitializationToLValue(captureInit, lv);
1120 curField->getType().isDestructedType()) {
1121 assert(lv.isSimple());
1123 curField->getType(),
1129void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1130 CIRGenFunction::FullExprCleanupScope fullExprScope(cgf, e->
getSubExpr());
1134void AggExprEmitter::VisitCallExpr(
const CallExpr *e) {
1140 withReturnValueSlot(
1141 e, [&](ReturnValueSlot slot) {
return cgf.
emitCallExpr(e, slot); });
1144void AggExprEmitter::withReturnValueSlot(
1145 const Expr *e, llvm::function_ref<RValue(ReturnValueSlot)> fn) {
1146 QualType retTy = e->
getType();
1149 bool requiresDestruction =
1151 if (requiresDestruction)
1154 "withReturnValueSlot: return value requiring destruction is NYI");
1169 fn(ReturnValueSlot(retAddr));
1172void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
1174 llvm_unreachable(
"GNU array range designator extension");
1179 visitCXXParenListOrInitListExpr(
1183void AggExprEmitter::visitCXXParenListOrInitListExpr(
1184 Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,
1185 Expr *arrayFiller) {
1188 const AggValueSlot dest = ensureSlot(loc, e->
getType());
1191 cir::ArrayType arrayTy =
1198 "visitCXXParenListOrInitListExpr variable array type");
1204 "visitCXXParenListOrInitListExpr array type");
1214 unsigned numInitElements = args.size();
1219 CIRGenFunction::CleanupDeactivationScope deactivateCleanups(cgf);
1221 unsigned curInitIndex = 0;
1224 if (
auto *cxxrd = dyn_cast<CXXRecordDecl>(record)) {
1225 assert(numInitElements >= cxxrd->getNumBases() &&
1226 "missing initializer for base class");
1227 for (
auto &base : cxxrd->bases()) {
1228 assert(!base.isVirtual() &&
"should not see vbases here");
1229 CXXRecordDecl *baseRD = base.getType()->getAsCXXRecordDecl();
1241 base.getType().isDestructedType())
1247 CIRGenFunction::FieldConstructionScope fcScope(cgf, dest.
getAddress());
1251 if (record->isUnion()) {
1254 if (!initializedFieldInUnion) {
1259 assert(llvm::all_of(record->fields(),
1260 [](
const FieldDecl *f) {
1261 return f->isUnnamedBitField() ||
1262 f->isAnonymousStructOrUnion();
1264 "Only unnamed bitfields or anonymous class allowed");
1269 FieldDecl *initedField = initializedFieldInUnion;
1272 destLV, initedField, initedField->
getName());
1274 if (numInitElements) {
1276 emitInitializationToLValue(args[0], fieldLV);
1279 emitNullInitializationToLValue(loc, fieldLV);
1286 for (
const FieldDecl *field : record->fields()) {
1288 if (field->getType()->isIncompleteArrayType())
1292 if (field->isUnnamedBitField())
1298 if (curInitIndex == numInitElements && dest.
isZeroed() &&
1306 if (curInitIndex < numInitElements) {
1308 CIRGenFunction::SourceLocRAIIObject loc{
1309 cgf, cgf.
getLoc(record->getSourceRange())};
1310 emitInitializationToLValue(args[curInitIndex++], lv);
1320 field->getType().isDestructedType()) {
1321 assert(lv.isSimple());
1347 getContext().getASTRecordLayout(baseRD).getSize() <=
1356 AggExprEmitter(*
this, slot).Visit(
const_cast<Expr *
>(e));
1371 assert((record->hasTrivialCopyConstructor() ||
1372 record->hasTrivialCopyAssignment() ||
1373 record->hasTrivialMoveConstructor() ||
1374 record->hasTrivialMoveAssignment() ||
1375 record->hasAttr<TrivialABIAttr>() || record->isUnion()) &&
1376 "Trying to aggregate-copy a type without a trivial copy/move "
1377 "constructor or assignment operator");
1379 if (record->isEmpty())
1402 typeInfo =
getContext().getTypeInfoDataSizeInChars(ty);
1404 typeInfo =
getContext().getTypeInfoInChars(ty);
1410 cgm.errorNYI(
"emitAggregateCopy: GC");
1416 bool skipTailPadding =
1417 mayOverlap && dataSize !=
getContext().getTypeSizeInChars(ty);
1421 builder.createCopy(destPtr, srcPtr, isVolatile, skipTailPadding);
static Expr * findPeephole(Expr *op, CastKind kind, const ASTContext &ctx)
Attempt to look through various unimportant expressions to find a cast of the given kind.
static bool isBlockVarRef(const Expr *E)
Is the value of the given expression possibly a reference to or into a __block variable?
static bool isTrivialFiller(Expr *e)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::ConditionOp createCondition(mlir::Value condition)
Create a loop condition.
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)
cir::PointerType getPointerTo(mlir::Type ty)
cir::DoWhileOp createDoWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder)
Create a do-while operation.
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
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.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Represents a loop initializing the elements of an array.
llvm::APInt getArraySize() const
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Expr * getSubExpr() const
Get the initializer to use for each array element.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
QualType getElementType() const
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
A builtin binary operation expression such as "x + y" or "x <= y".
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getExprLoc() const
mlir::Value getPointer() const
mlir::Type getElementType() const
clang::CharUnits getAlignment() const
mlir::Value emitRawPointer() const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
IsZeroed_t isZeroed() const
Overlap_t mayOverlap() const
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
IsDestructed_t isExternallyDestructed() const
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
Address getAddress() const
void setExternallyDestructed(bool destructed=true)
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
IsAliased_t isPotentiallyAliased() const
clang::Qualifiers getQualifiers() const
void setVolatile(bool flag)
cir::CmpThreeWayOp createThreeWayCmpTotalOrdering(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, const llvm::APSInt <Res, const llvm::APSInt &eqRes, const llvm::APSInt >Res, cir::CmpOrdering ordering)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::CmpThreeWayOp createThreeWayCmpPartialOrdering(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, const llvm::APSInt <Res, const llvm::APSInt &eqRes, const llvm::APSInt >Res, const llvm::APSInt &unorderedRes)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
static bool hasScalarEvaluationKind(clang::QualType type)
mlir::Type convertType(clang::QualType t)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
CIRGenTypes & getTypes() const
const clang::LangOptions & getLangOpts() const
cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, bool insertIntoFnEntryBlock=false)
This creates an alloca and inserts it into the entry block if ArraySize is nullptr,...
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap, bool isVolatile=false)
Emit an aggregate copy.
void pushIrregularPartialArrayCleanup(mlir::Value arrayBegin, Address arrayEndPointer, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Push an EH cleanup to destroy already-constructed elements of the given array.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitAggregateStore(mlir::Value value, Address dest)
RValue emitAtomicExpr(AtomicExpr *e)
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
void pushDestroyAndDeferDeactivation(QualType::DestructionKind dtorKind, Address addr, QualType type)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, AggValueSlot slot=AggValueSlot::ignored())
void emitCXXConstructExpr(const clang::CXXConstructExpr *e, AggValueSlot dest)
LValue emitAggExprToLValue(const Expr *e)
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
static bool hasAggregateEvaluationKind(clang::QualType type)
void emitScalarInit(const clang::Expr *init, mlir::Location loc, LValue lvalue, bool capturedByInit=false)
LValue emitLValueForFieldInitialization(LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName)
Like emitLValueForField, excpet that if the Field is a reference, this will return the address of the...
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
Address getAddressOfDirectBaseInCompleteClass(mlir::Location loc, Address value, const CXXRecordDecl *derived, const CXXRecordDecl *base, bool baseIsVirtual)
Convert the given pointer to a complete class to the given direct base.
CIRGenBuilderTy & getBuilder()
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual)
Determine whether a base class initialization may overlap some other object.
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
void emitCXXThrowExpr(const CXXThrowExpr *e)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
clang::ASTContext & getContext() const
void emitInheritedCXXConstructorCall(const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr, bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e)
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
bool isLValueSuitableForInlineAtomic(LValue lv)
An LValue is a candidate for having its loads and stores be made atomic if we are operating under /vo...
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...
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
mlir::Value emitVAArg(VAArgExpr *ve)
Generate code to get an argument from the passed in pointer and update it accordingly.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
llvm::DenseMap< const clang::FieldDecl *, llvm::StringRef > lambdaFieldToName
Keep a map between lambda fields and names, this needs to be per module since lambdas might get gener...
bool isZeroInitializable(clang::QualType ty)
Return whether a type can be zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
Address getAddress() const
This trivial value class is used to represent the result of an expression that is evaluated.
Address getAggregateAddress() const
Return the value of the address of the aggregate.
static RValue get(mlir::Value v)
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
CXXTemporary * getTemporary()
const Expr * getSubExpr() const
A default argument (C++ [dcl.fct.default]).
Expr * getExpr()
Get the initialization expression that will be used.
Represents a call to an inherited base class constructor from an inheriting constructor.
bool constructsVBase() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will call.
bool inheritedFromVBase() const
Determine whether the inherited constructor is inherited from a virtual base of the object we constru...
Represents a list-initialization with parenthesis.
MutableArrayRef< Expr * > getInitExprs()
FieldDecl * getInitializedFieldInUnion()
Represents a C++ struct/union/class.
bool isTriviallyCopyable() const
Determine whether this class is considered trivially copyable per (C++11 [class]p6).
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
An expression "T()" which creates an rvalue of a non-class type T.
Implicit construction of a std::initializer_list<T> object from an array temporary within list-initia...
A C++ throw-expression (C++ [except.throw]).
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
static const char * getCastKindName(CastKind CK)
CharUnits - This is an opaque type for sizes expressed in character units.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
bool isPartial() const
True iff the comparison is not totally ordered.
const ValueInfo * getLess() const
const ValueInfo * getUnordered() const
const CXXRecordDecl * Record
The declaration for the comparison category type from the standard library.
const ValueInfo * getValueInfo(ComparisonCategoryResult ValueKind) const
bool isStrong() const
True iff the comparison is "strong".
const ValueInfo * getGreater() const
const ValueInfo * getEqualOrEquiv() const
const Expr * getInitializer() const
Represents the canonical version of C arrays with a specified constant size.
A reference to a declared variable, function, enum, etc.
InitListExpr * getUpdater() const
This represents one expression.
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
const Expr * getSubExpr() const
Expr * getResultExpr()
Return the result expression of this controlling expression.
Represents an implicitly-generated value initialization of an object of a given type.
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
bool hadArrayRangeDesignator() const
Expr * getArrayFiller()
If this initializer list initializes an array with more elements than there are initializers in the l...
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits() const
llvm::iterator_range< capture_init_iterator > capture_inits()
Retrieve the initialization expressions for this lambda's captures.
capture_range captures() const
Retrieve this lambda's captures.
CXXRecordDecl * getLambdaClass() const
Retrieve the class that corresponds to the lambda.
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Represents a place-holder for an object not to be initialized by anything.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
const Expr * getSubExpr() const
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
@ PCK_Struct
The type is a struct containing a field whose type is neither PCK_Trivial nor PCK_VolatileTrivial.
Represents a struct/union/class.
field_range fields() const
specific_decl_iterator< FieldDecl > field_iterator
field_iterator field_begin() const
CompoundStmt * getSubStmt()
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const char * getStmtClassName() const
bool isStoredAsComparisonResult() const
const APValue & getAPValue() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool isPointerType() const
bool isReferenceType() const
bool isVariableArrayType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
bool isMemberPointerType() const
bool isRealFloatingType() const
Floating point categories.
bool isNullPtrType() const
bool isRecordType() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
Represents a call to the builtin function __builtin_va_arg.
Represents a variable declaration or definition.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
const AstTypeMatcher< AtomicType > atomicType
constexpr Variable var(Literal L)
Returns the variable of L.
@ Address
A pointer to a ValueDecl.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
CastKind
CastKind - The kind of operation required for a conversion.
U cast(CodeGen::Address addr)
static bool emitLifetimeMarkers()
static bool aggValueSlotDestructedFlag()
static bool aggValueSlotGC()
static bool aggValueSlotAlias()
static bool aggEmitFinalDestCopyRValue()
static bool cleanupDeactivationScope()
static bool aggValueSlotVolatile()
static bool cudaSupport()
static bool incrementProfileCounter()
clang::CharUnits getPointerAlign() const
llvm::APSInt getIntValue() const
Get the constant integer value used by this variable to represent the comparison category result type...