clang 24.0.0git
CIRGenExpr.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code to emit Expr nodes as CIR code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Address.h"
15#include "CIRGenFunction.h"
16#include "CIRGenModule.h"
17#include "CIRGenValue.h"
18#include "TargetInfo.h"
19#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
20#include "mlir/IR/BuiltinAttributes.h"
21#include "mlir/IR/Value.h"
22#include "clang/AST/Attr.h"
23#include "clang/AST/CharUnits.h"
24#include "clang/AST/Decl.h"
25#include "clang/AST/Expr.h"
26#include "clang/AST/ExprCXX.h"
33#include <optional>
34
35using namespace clang;
36using namespace clang::CIRGen;
37using namespace cir;
38
39/// Get the address of a zero-sized field within a record. Zero-sized fields
40/// (e.g. empty bases with [[no_unique_address]]) don't appear in the CIR
41/// record layout, so we compute their address using the ASTContext field
42/// offset and byte-level pointer arithmetic instead of cir.get_member.
44 const FieldDecl *field) {
45 CIRGenBuilderTy &builder = cgf.getBuilder();
47 cgf.getContext().getFieldOffset(field));
48 mlir::Type fieldType = cgf.convertType(field->getType());
49
50 if (offset.isZero()) {
51 return Address(builder.createPtrBitcast(base.getPointer(), fieldType),
52 base.getAlignment());
53 }
54
55 // Cast to byte pointer, stride by the field offset, then cast to the
56 // field pointer type (CIR pointers are typed, so we need explicit casts
57 // unlike OG's opaque-pointer GEP).
58 mlir::Location loc = cgf.getLoc(field->getLocation());
59 mlir::Value addr =
60 builder.createPtrBitcast(base.getPointer(), builder.getUInt8Ty());
61 addr = builder.createPtrStride(loc, addr,
62 builder.getUInt64(offset.getQuantity(), loc));
63 addr = builder.createPtrBitcast(addr, fieldType);
64 return Address(addr, base.getAlignment().alignmentAtOffset(offset));
65}
66
68 const FieldDecl *field,
69 llvm::StringRef fieldName,
70 unsigned fieldIndex) {
72 return emitAddrOfZeroSizeField(*this, base, field);
73
74 mlir::Location loc = getLoc(field->getLocation());
75
76 // Retrieve layout information for both type resolution and alignment.
77 const RecordDecl *rec = field->getParent();
78 const CIRGenRecordLayout &layout = cgm.getTypes().getCIRGenRecordLayout(rec);
79 unsigned idx = layout.getCIRFieldNo(field);
80
81 // For potentially-overlapping fields (e.g. [[no_unique_address]]), the
82 // record stores the base subobject type (without tail padding) rather than
83 // the complete object type. Use the record's member type for get_member,
84 // then bitcast to the complete type for downstream use.
85 //
86 // For unions, all fields map to index 0, so we use the field's declared type
87 // directly instead of looking up the member type from the layout.
88 mlir::Type fieldType = convertType(field->getType());
89 auto fieldPtr = cir::PointerType::get(fieldType);
90 bool needsBitcast = false;
91
92 if (!rec->isUnion() && field->isPotentiallyOverlapping()) {
93 mlir::Type memberType = layout.getCIRType().getMembers()[idx];
94 fieldPtr = cir::PointerType::get(memberType);
95 needsBitcast = true;
96 }
97
98 // For most cases fieldName is the same as field->getName() but for lambdas,
99 // which do not currently carry the name, so it can be passed down from the
100 // CaptureStmt.
101 mlir::Value addr = builder.createGetMember(loc, fieldPtr, base.getPointer(),
102 fieldName, fieldIndex);
103
104 // If the field is potentially overlapping, the record member uses the base
105 // subobject type. Cast to the complete object pointer type expected by
106 // callers (analogous to OG's opaque pointer behavior).
107 if (needsBitcast)
108 addr = builder.createPtrBitcast(addr, fieldType);
109
111 layout.getCIRType().getElementOffset(cgm.getDataLayout().layout, idx));
112 return Address(addr, base.getAlignment().alignmentAtOffset(offset));
113}
114
115/// Given an expression of pointer type, try to
116/// derive a more accurate bound on the alignment of the pointer.
118 LValueBaseInfo *baseInfo) {
119 // We allow this with ObjC object pointers because of fragile ABIs.
120 assert(expr->getType()->isPointerType() ||
121 expr->getType()->isObjCObjectPointerType());
122 expr = expr->IgnoreParens();
123
124 // Casts:
125 if (auto const *ce = dyn_cast<CastExpr>(expr)) {
126 if (const auto *ece = dyn_cast<ExplicitCastExpr>(ce))
127 cgm.emitExplicitCastExprType(ece);
128
129 switch (ce->getCastKind()) {
130 // Non-converting casts (but not C's implicit conversion from void*).
131 case CK_BitCast:
132 case CK_NoOp:
133 case CK_AddressSpaceConversion: {
134 if (const auto *ptrTy =
135 ce->getSubExpr()->getType()->getAs<PointerType>()) {
136 if (ptrTy->getPointeeType()->isVoidType())
137 break;
138
139 LValueBaseInfo innerBaseInfo;
141 Address addr =
142 emitPointerWithAlignment(ce->getSubExpr(), &innerBaseInfo);
143 if (baseInfo)
144 *baseInfo = innerBaseInfo;
145
146 if (isa<ExplicitCastExpr>(ce)) {
147 LValueBaseInfo targetTypeBaseInfo;
148
149 const QualType pointeeType = expr->getType()->getPointeeType();
150 const CharUnits align =
151 cgm.getNaturalTypeAlignment(pointeeType, &targetTypeBaseInfo);
152
153 // If the source l-value is opaque, honor the alignment of the
154 // casted-to type.
155 if (innerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) {
156 if (baseInfo)
157 baseInfo->mergeForCast(targetTypeBaseInfo);
158 addr = Address(addr.getPointer(), addr.getElementType(), align);
159 }
160 }
161
163
164 const mlir::Type eltTy =
165 convertTypeForMem(expr->getType()->getPointeeType());
166 addr = getBuilder().createElementBitCast(getLoc(expr->getSourceRange()),
167 addr, eltTy);
169
170 return addr;
171 }
172 break;
173 }
174
175 // Array-to-pointer decay. TODO(cir): BaseInfo and TBAAInfo.
176 case CK_ArrayToPointerDecay:
177 return emitArrayToPointerDecay(ce->getSubExpr(), baseInfo);
178
179 case CK_UncheckedDerivedToBase:
180 case CK_DerivedToBase: {
183 Address addr = emitPointerWithAlignment(ce->getSubExpr(), baseInfo);
184 const CXXRecordDecl *derived =
185 ce->getSubExpr()->getType()->getPointeeCXXRecordDecl();
186 return getAddressOfBaseClass(addr, derived, ce->path(),
188 ce->getExprLoc());
189 }
190
191 case CK_AnyPointerToBlockPointerCast:
192 case CK_BaseToDerived:
193 case CK_BaseToDerivedMemberPointer:
194 case CK_BlockPointerToObjCPointerCast:
195 case CK_BuiltinFnToFnPtr:
196 case CK_CPointerToObjCPointerCast:
197 case CK_DerivedToBaseMemberPointer:
198 case CK_Dynamic:
199 case CK_FunctionToPointerDecay:
200 case CK_IntegralToPointer:
201 case CK_LValueToRValue:
202 case CK_LValueToRValueBitCast:
203 case CK_NullToMemberPointer:
204 case CK_NullToPointer:
205 case CK_ReinterpretMemberPointer:
206 case CK_UserDefinedConversion:
207 // Common pointer conversions, nothing to do here.
208 // TODO: Is there any reason to treat base-to-derived conversions
209 // specially?
210 break;
211
212 case CK_ARCConsumeObject:
213 case CK_ARCExtendBlockObject:
214 case CK_ARCProduceObject:
215 case CK_ARCReclaimReturnedObject:
216 case CK_AtomicToNonAtomic:
217 case CK_BooleanToSignedIntegral:
218 case CK_ConstructorConversion:
219 case CK_CopyAndAutoreleaseBlockObject:
220 case CK_Dependent:
221 case CK_FixedPointCast:
222 case CK_FixedPointToBoolean:
223 case CK_FixedPointToFloating:
224 case CK_FixedPointToIntegral:
225 case CK_FloatingCast:
226 case CK_FloatingComplexCast:
227 case CK_FloatingComplexToBoolean:
228 case CK_FloatingComplexToIntegralComplex:
229 case CK_FloatingComplexToReal:
230 case CK_FloatingRealToComplex:
231 case CK_FloatingToBoolean:
232 case CK_FloatingToFixedPoint:
233 case CK_FloatingToIntegral:
234 case CK_HLSLAggregateSplatCast:
235 case CK_HLSLArrayRValue:
236 case CK_HLSLElementwiseCast:
237 case CK_HLSLVectorTruncation:
238 case CK_HLSLMatrixTruncation:
239 case CK_IntToOCLSampler:
240 case CK_IntegralCast:
241 case CK_IntegralComplexCast:
242 case CK_IntegralComplexToBoolean:
243 case CK_IntegralComplexToFloatingComplex:
244 case CK_IntegralComplexToReal:
245 case CK_IntegralRealToComplex:
246 case CK_IntegralToBoolean:
247 case CK_IntegralToFixedPoint:
248 case CK_IntegralToFloating:
249 case CK_LValueBitCast:
250 case CK_MatrixCast:
251 case CK_MemberPointerToBoolean:
252 case CK_NonAtomicToAtomic:
253 case CK_ObjCObjectLValueCast:
254 case CK_PointerToBoolean:
255 case CK_PointerToIntegral:
256 case CK_ToUnion:
257 case CK_ToVoid:
258 case CK_VectorSplat:
259 case CK_ZeroToOCLOpaqueType:
260 // Classic codegen has a default that does nothing. In CIR, we are issuing
261 // a diagnostic so we can examine casts that are reached here to be sure
262 // no action is needed. If nothing is needed, the cast can be moved to the
263 // group above that does nothing.
264 cgm.errorNYI(ce->getSourceRange(),
265 "unexpected cast for emitPointerWithAlignment: ",
266 ce->getCastKindName());
267 break;
268 }
269 }
270
271 // Unary &
272 if (const UnaryOperator *uo = dyn_cast<UnaryOperator>(expr)) {
273 // TODO(cir): maybe we should use a CIR unary op for pointers here instead.
274 if (uo->getOpcode() == UO_AddrOf) {
275 LValue lv = emitLValue(uo->getSubExpr());
276 if (baseInfo)
277 *baseInfo = lv.getBaseInfo();
279 return lv.getAddress();
280 }
281 }
282
283 // std::addressof and variants.
284 if (auto const *call = dyn_cast<CallExpr>(expr)) {
285 switch (call->getBuiltinCallee()) {
286 default:
287 break;
288 case Builtin::BIaddressof:
289 case Builtin::BI__addressof:
290 case Builtin::BI__builtin_addressof: {
291 LValue lv = emitLValue(call->getArg(0));
292 if (baseInfo)
293 *baseInfo = lv.getBaseInfo();
295 return lv.getAddress();
296 }
297 }
298 }
299
300 // Otherwise, use the alignment of the type.
302 emitScalarExpr(expr), expr->getType()->getPointeeType(), CharUnits(),
303 /*forPointeeType=*/true, baseInfo);
304}
305
307 LValue dst) {
308 auto getScalarSizeInBits = [&](mlir::Type ty) -> unsigned {
309 mlir::Type scalarTy = mlir::isa<cir::VectorType>(ty)
310 ? mlir::cast<cir::VectorType>(ty).getElementType()
311 : ty;
312 cir::CIRDataLayout dl = cgm.getDataLayout();
313 return dl.getTypeSizeInBits(scalarTy).getFixedValue();
314 };
315
316 mlir::Value srcVal = src.getValue();
317 Address dstAddr = dst.getExtVectorAddress();
318 if (getScalarSizeInBits(dstAddr.getElementType()) >
319 getScalarSizeInBits(srcVal.getType())) {
320 cgm.errorNYI(
321 dst.getPointer().getLoc(),
322 "emitStoreThroughExtVectorComponentLValue: dstTySize > srcTysize");
323 return;
324 }
325
326 if (getLangOpts().HLSL) {
327 cgm.errorNYI(dst.getPointer().getLoc(),
328 "emitStoreThroughExtVectorComponentLValue: HLSL");
329 return;
330 }
331
332 // This access turns into a read/modify/write of the vector. Load the input
333 // value now.
334 mlir::Location loc = dst.getExtVectorPointer().getLoc();
335
336 mlir::ArrayAttr elts = dst.getExtVectorElts();
337
338 mlir::Value vec = builder.createLoad(loc, dstAddr, dst.isVolatile());
339 if (const auto *vecTy = dst.getType()->getAs<clang::VectorType>()) {
340 unsigned numSrcElts = vecTy->getNumElements();
341 unsigned numDstElts = cast<cir::VectorType>(vec.getType()).getSize();
342 if (numDstElts == numSrcElts) {
343 // Use shuffle vector is the src and destination are the same number of
344 // elements and restore the vector mask since it is on the side it will be
345 // stored.
346 SmallVector<int64_t> mask(numDstElts);
347 for (unsigned i = 0; i != numDstElts; ++i)
348 mask[getAccessedFieldNo(i, elts)] = i;
349
350 vec = builder.createVecShuffle(loc, srcVal, mask);
351 } else if (numDstElts > numSrcElts) {
352 // Extended the source vector to the same length and then shuffle it
353 // into the destination.
354 // FIXME: since we're shuffling with undef, can we just use the indices
355 // into that? This could be simpler.
356 SmallVector<int64_t> extMask(numDstElts, -1);
357 std::iota(extMask.begin(), extMask.begin() + numSrcElts, 0);
358
359 mlir::Value extSrcVal = builder.createVecShuffle(loc, srcVal, extMask);
360
361 // build identity
362 SmallVector<int64_t> mask(numDstElts);
363 std::iota(mask.begin(), mask.begin() + numDstElts, 0);
364
365 // When the vector size is odd and .odd or .hi is used, the last element
366 // of the Elts constant array will be one past the size of the vector.
367 // Ignore the last element here, if it is greater than the mask size.
368 if ((unsigned)getAccessedFieldNo(numSrcElts - 1, elts) == mask.size())
369 numSrcElts--;
370
371 // modify when what gets shuffled in
372 for (unsigned i = 0; i != numSrcElts; ++i)
373 mask[getAccessedFieldNo(i, elts)] = i + numDstElts;
374
375 vec = builder.createVecShuffle(loc, vec, extSrcVal, mask);
376 } else {
377 // We should never shorten the vector
378 llvm_unreachable("unexpected shorten vector length");
379 }
380 } else {
381 // If the Src is a scalar (not a vector), and the target is a vector it
382 // must be updating one element.
383 unsigned inIdx = getAccessedFieldNo(0, elts);
384 cir::ConstantOp elt = builder.getSInt64(inIdx, loc);
385 vec = cir::VecInsertOp::create(builder, loc, vec, srcVal, elt);
386 }
387
388 builder.createStore(loc, vec, dst.getExtVectorAddress(),
389 dst.isVolatileQualified());
390}
391
393 bool isInit) {
394 if (!dst.isSimple()) {
395 if (dst.isVectorElt()) {
396 // Read/modify/write the vector, inserting the new element
397 const mlir::Location loc = dst.getVectorPointer().getLoc();
398 const mlir::Value vector =
399 builder.createLoad(loc, dst.getVectorAddress());
400 const mlir::Value newVector = cir::VecInsertOp::create(
401 builder, loc, vector, src.getValue(), dst.getVectorIdx());
402 builder.createStore(loc, newVector, dst.getVectorAddress());
403 return;
404 }
405
406 if (dst.isExtVectorElt())
408
409 if (dst.isMatrixElt()) {
410 cgm.errorNYI("emitStoreThroughLValue: !dst.isSimple() && isMatrixElt");
411 return;
412 }
413
414 if (dst.isMatrixRow()) {
415 cgm.errorNYI("emitStoreThroughLValue: !dst.isSimple() && isMatrixRow");
416 return;
417 }
418
419 assert(dst.isBitField() && "Unknown LValue type");
421 return;
422 }
423
426
427 assert(src.isScalar() && "Can't emit an aggregate store with this method");
428 emitStoreOfScalar(src.getValue(), dst, isInit);
429}
430
431static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e,
432 const VarDecl *vd) {
433 QualType t = e->getType();
434
435 // In classic codegen, thread-locals get a wrapper function here. Rather than
436 // doing that, we instead treat this as a normal 'global', and leave it to
437 // lowerng-prepare to correctly generate the wrapper/etc.
438
439 // Check if the variable is marked as declare target with link clause in
440 // device codegen.
441 if (cgf.getLangOpts().OpenMP)
442 cgf.cgm.errorNYI(e->getSourceRange(), "emitGlobalVarDeclLValue: OpenMP");
443
444 // Traditional LLVM codegen handles thread local separately, CIR handles
445 // as part of getAddrOfGlobalVar.
446 mlir::Value v = cgf.cgm.getAddrOfGlobalVar(vd);
447
448 mlir::Type realVarTy = cgf.convertTypeForMem(vd->getType());
449 cir::PointerType realPtrTy = cir::PointerType::get(
450 realVarTy, mlir::cast<cir::PointerType>(v.getType()).getAddrSpace());
451 if (realPtrTy != v.getType())
452 v = cgf.getBuilder().createBitcast(v.getLoc(), v, realPtrTy);
453
454 CharUnits alignment = cgf.getContext().getDeclAlign(vd);
455 Address addr(v, realVarTy, alignment);
456 LValue lv;
457 if (vd->getType()->isReferenceType())
458 lv = cgf.emitLoadOfReferenceLValue(addr, cgf.getLoc(e->getSourceRange()),
460 else
461 lv = cgf.makeAddrLValue(addr, t, AlignmentSource::Decl);
463 return lv;
464}
465
466void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
467 bool isVolatile, QualType ty,
468 LValueBaseInfo baseInfo, bool isInit,
469 bool isNontemporal) {
470
471 if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) {
472 // Handle vectors of size 3 like size 4 for better performance.
473 // TODO(CIR): Use `ABIInfo::getOptimalVectorMemoryType` once it upstreamed
475 if (clangVecTy->getNumElements() == 3 && !getLangOpts().PreserveVec3Type)
476 cgm.errorNYI(addr.getPointer().getLoc(),
477 "emitStoreOfScalar Vec3 & PreserveVec3Type disabled");
478 }
479
480 value = emitToMemory(value, ty);
481
483 LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo);
484 if (ty->isAtomicType() ||
485 (!isInit && isLValueSuitableForInlineAtomic(atomicLValue))) {
486 emitAtomicStore(RValue::get(value), atomicLValue, isInit);
487 return;
488 }
489
490 // Update the alloca with more info on initialization.
491 assert(addr.getPointer() && "expected pointer to exist");
492 cir::AllocaOp srcAlloca = addr.getUnderlyingAllocaOp();
493 if (currVarDecl && srcAlloca) {
494 const VarDecl *vd = currVarDecl;
495 assert(vd && "VarDecl expected");
496 if (vd->hasInit())
497 srcAlloca.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
498 }
499
500 assert(currSrcLoc && "must pass in source location");
501 builder.createStore(*currSrcLoc, value, addr, isVolatile, isNontemporal);
502
504}
505
506// TODO: Replace this with a proper TargetInfo function call.
507/// Helper method to check if the underlying ABI is AAPCS
508static bool isAAPCS(const TargetInfo &targetInfo) {
509 return targetInfo.getABI().starts_with("aapcs");
510}
511
513 LValue dst) {
514
515 const CIRGenBitFieldInfo &info = dst.getBitFieldInfo();
516 mlir::Type resLTy = convertTypeForMem(dst.getType());
517 Address ptr = dst.getBitFieldAddress();
518
519 bool useVoaltile = cgm.getCodeGenOpts().AAPCSBitfieldWidth &&
520 dst.isVolatileQualified() &&
521 info.volatileStorageSize != 0 && isAAPCS(cgm.getTarget());
522
523 assert(currSrcLoc && "must pass in source location");
524
525 return builder.createSetBitfield(*currSrcLoc, resLTy, ptr,
526 ptr.getElementType(), src.getValue(), info,
527 dst.isVolatileQualified(), useVoaltile);
528}
529
531 const CIRGenBitFieldInfo &info = lv.getBitFieldInfo();
532
533 // Get the output type.
534 mlir::Type resLTy = convertType(lv.getType());
535 Address ptr = lv.getBitFieldAddress();
536
537 bool useVoaltile = lv.isVolatileQualified() && info.volatileOffset != 0 &&
538 isAAPCS(cgm.getTarget());
539
540 mlir::Value field =
541 builder.createGetBitfield(getLoc(loc), resLTy, ptr, ptr.getElementType(),
542 info, lv.isVolatile(), useVoaltile);
544 return RValue::get(field);
545}
546
548 const FieldDecl *field,
549 mlir::Type fieldType,
550 unsigned index) {
551 mlir::Location loc = getLoc(field->getLocation());
552 cir::PointerType fieldPtr = cir::PointerType::get(fieldType);
554 cir::GetMemberOp sea = getBuilder().createGetMember(
555 loc, fieldPtr, base.getPointer(), field->getName(),
556 mlir::isa<cir::UnionType>(rec) ? field->getFieldIndex() : index);
558 rec.getElementOffset(cgm.getDataLayout().layout, index));
559 return Address(sea, base.getAlignment().alignmentAtOffset(offset));
560}
561
563 const FieldDecl *field) {
564 LValueBaseInfo baseInfo = base.getBaseInfo();
565 const CIRGenRecordLayout &layout =
566 cgm.getTypes().getCIRGenRecordLayout(field->getParent());
567 const CIRGenBitFieldInfo &info = layout.getBitFieldInfo(field);
568
570
571 unsigned idx = layout.getCIRFieldNo(field);
572 Address addr = getAddrOfBitFieldStorage(base, field, info.storageType, idx);
573
574 mlir::Location loc = getLoc(field->getLocation());
575 if (addr.getElementType() != info.storageType)
576 addr = builder.createElementBitCast(loc, addr, info.storageType);
577
578 QualType fieldType =
580 // TODO(cir): Support TBAA for bit fields.
582 LValueBaseInfo fieldBaseInfo(baseInfo.getAlignmentSource());
583 return LValue::makeBitfield(addr, info, fieldType, fieldBaseInfo);
584}
585
587 LValueBaseInfo baseInfo = base.getBaseInfo();
588
589 if (field->isBitField())
590 return emitLValueForBitField(base, field);
591
592 QualType fieldType = field->getType();
593 const RecordDecl *rec = field->getParent();
594 AlignmentSource baseAlignSource = baseInfo.getAlignmentSource();
595 LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(baseAlignSource));
597
598 Address addr = base.getAddress();
599 if (auto *classDecl = dyn_cast<CXXRecordDecl>(rec)) {
600 if (cgm.getCodeGenOpts().StrictVTablePointers &&
601 classDecl->isDynamicClass()) {
602 cgm.errorNYI(field->getSourceRange(),
603 "emitLValueForField: strict vtable for dynamic class");
604 }
605 }
606
607 unsigned recordCVR = base.getVRQualifiers();
608
609 llvm::StringRef fieldName = field->getName();
610 unsigned fieldIndex;
611 if (cgm.lambdaFieldToName.count(field))
612 fieldName = cgm.lambdaFieldToName[field];
613
614 // Empty fields don't have entries in the record layout, so handle them
615 // separately. They just use the base address directly with the right type.
616 if (!rec->isUnion() && isEmptyFieldForLayout(getContext(), field)) {
617 addr = emitAddrOfZeroSizeField(*this, addr, field);
618 LValue lv = makeAddrLValue(addr, fieldType, fieldBaseInfo);
619 lv.getQuals().addCVRQualifiers(recordCVR);
620 return lv;
621 }
622
623 if (rec->isUnion())
624 fieldIndex = field->getFieldIndex();
625 else {
626 const CIRGenRecordLayout &layout =
627 cgm.getTypes().getCIRGenRecordLayout(field->getParent());
628 fieldIndex = layout.getCIRFieldNo(field);
629 }
630
631 addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
633
634 // If this is a reference field, load the reference right now.
635 if (fieldType->isReferenceType()) {
637 LValue refLVal = makeAddrLValue(addr, fieldType, fieldBaseInfo);
638 if (recordCVR & Qualifiers::Volatile)
639 refLVal.getQuals().addVolatile();
640 addr = emitLoadOfReference(refLVal, getLoc(field->getSourceRange()),
641 &fieldBaseInfo);
642
643 // Qualifiers on the struct don't apply to the referencee.
644 recordCVR = 0;
645 fieldType = fieldType->getPointeeType();
646 }
647
648 if (field->hasAttr<AnnotateAttr>()) {
649 cgm.errorNYI(field->getSourceRange(), "emitLValueForField: AnnotateAttr");
650 return LValue();
651 }
652
653 LValue lv = makeAddrLValue(addr, fieldType, fieldBaseInfo);
654 lv.getQuals().addCVRQualifiers(recordCVR);
655
656 // __weak attribute on a field is ignored.
658 cgm.errorNYI(field->getSourceRange(),
659 "emitLValueForField: __weak attribute");
660 return LValue();
661 }
662
663 return lv;
664}
665
667 LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName) {
668 QualType fieldType = field->getType();
669
670 if (!fieldType->isReferenceType())
671 return emitLValueForField(base, field);
672
673 Address v = base.getAddress();
674 if (isEmptyFieldForLayout(getContext(), field)) {
675 v = emitAddrOfZeroSizeField(*this, v, field);
676 } else {
677 const CIRGenRecordLayout &layout =
678 cgm.getTypes().getCIRGenRecordLayout(field->getParent());
679 unsigned fieldIndex = layout.getCIRFieldNo(field);
680 v = emitAddrOfFieldStorage(v, field, fieldName, fieldIndex);
681 }
682
683 // Make sure that the address is pointing to the right type.
684 mlir::Type memTy = convertTypeForMem(fieldType);
685 v = builder.createElementBitCast(getLoc(field->getSourceRange()), v, memTy);
686
687 // TODO: Generate TBAA information that describes this access as a structure
688 // member access and not just an access to an object of the field's type. This
689 // should be similar to what we do in EmitLValueForField().
690 LValueBaseInfo baseInfo = base.getBaseInfo();
691 AlignmentSource fieldAlignSource = baseInfo.getAlignmentSource();
692 LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(fieldAlignSource));
694 return makeAddrLValue(v, fieldType, fieldBaseInfo);
695}
696
697/// Converts a scalar value from its primary IR type (as returned
698/// by ConvertType) to its load/store type.
699mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {
700 if (auto *atomicTy = ty->getAs<AtomicType>())
701 ty = atomicTy->getValueType();
702
703 if (ty->isConstantMatrixBoolType()) {
704 cgm.errorNYI("emitToMemory: ConstantMatrixBoolType");
705 return {};
706 }
707
708 // Unlike in classic codegen CIR, bools are kept as `cir.bool` and BitInts are
709 // kept as `cir.int<N>` until further lowering
710 return value;
711}
712
713mlir::Value CIRGenFunction::emitFromMemory(mlir::Value value, QualType ty) {
714 if (auto *atomicTy = ty->getAs<AtomicType>())
715 ty = atomicTy->getValueType();
716
718 cgm.errorNYI("emitFromMemory: PackedVectorBoolType");
719 }
720
721 return value;
722}
723
724void CIRGenFunction::emitStoreOfScalar(mlir::Value value, LValue lvalue,
725 bool isInit) {
726 if (lvalue.getType()->isConstantMatrixType()) {
727 assert(0 && "NYI: emitStoreOfScalar constant matrix type");
728 return;
729 }
730
731 emitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),
732 lvalue.getType(), lvalue.getBaseInfo(), isInit,
733 lvalue.isNontemporal());
734}
735
736mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile,
737 QualType ty, SourceLocation loc,
738 LValueBaseInfo baseInfo,
739 bool isNontemporal) {
740 // Traditional LLVM codegen handles thread local separately, CIR handles
741 // as part of getAddrOfGlobalVar (GetGlobalOp).
742 mlir::Type eltTy = addr.getElementType();
743 if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) {
744 // Handle vectors of size 3 like size 4 for better performance.
746 if (clangVecTy->getNumElements() == 3 && !getLangOpts().PreserveVec3Type)
747 cgm.errorNYI(addr.getPointer().getLoc(),
748 "emitLoadOfScalar Vec3 & PreserveVec3Type disabled");
749 }
750
752 LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo);
753 if (ty->isAtomicType() || isLValueSuitableForInlineAtomic(atomicLValue))
754 return emitAtomicLoad(atomicLValue, loc).getValue();
755
756 if (mlir::isa<cir::VoidType>(eltTy))
757 cgm.errorNYI(loc, "emitLoadOfScalar: void type");
758
760
761 mlir::Value loadOp =
762 builder.createLoad(getLoc(loc), addr, isVolatile, isNontemporal);
763
764 // Types with a boolean representation that are not the builtin bool (an enum
765 // whose underlying type is bool, or a _BitInt(1)) need no register/memory
766 // conversion here: like bool and _BitInt(N), CIR keeps them in their literal
767 // type until LowerToLLVM widens them to the in-memory integer type (see
768 // emitToMemory).
769 return loadOp;
770}
771
773 SourceLocation loc) {
775 return emitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),
776 lvalue.getType(), loc, lvalue.getBaseInfo(),
777 lvalue.isNontemporal());
778}
779
780/// Given an expression that represents a value lvalue, this
781/// method emits the address of the lvalue, then loads the result as an rvalue,
782/// returning the rvalue.
784 assert(!lv.getType()->isFunctionType());
785 assert(!(lv.getType()->isConstantMatrixType()) && "not implemented");
786
787 if (lv.isBitField())
788 return emitLoadOfBitfieldLValue(lv, loc);
789
790 if (lv.isSimple())
791 return RValue::get(emitLoadOfScalar(lv, loc));
792
793 if (lv.isVectorElt()) {
794 const mlir::Value load =
795 builder.createLoad(getLoc(loc), lv.getVectorAddress());
796 return RValue::get(cir::VecExtractOp::create(builder, getLoc(loc), load,
797 lv.getVectorIdx()));
798 }
799
800 if (lv.isExtVectorElt())
802
803 cgm.errorNYI(loc, "emitLoadOfLValue");
804 return RValue::get(nullptr);
805}
806
807int64_t CIRGenFunction::getAccessedFieldNo(unsigned int idx,
808 const mlir::ArrayAttr elts) {
809 auto elt = mlir::cast<mlir::IntegerAttr>(elts[idx]);
810 return elt.getInt();
811}
812
813// If this is a reference to a subset of the elements of a vector, create an
814// appropriate shufflevector.
816 mlir::Location loc = lv.getExtVectorPointer().getLoc();
817 mlir::Value vec = builder.createLoad(loc, lv.getExtVectorAddress());
818
819 // HLSL allows treating scalars as one-element vectors. Converting the scalar
820 // IR value to a vector here allows the rest of codegen to behave as normal.
821 if (getLangOpts().HLSL && !mlir::isa<cir::VectorType>(vec.getType())) {
822 cgm.errorNYI(loc, "emitLoadOfExtVectorElementLValue: HLSL");
823 return {};
824 }
825
826 const mlir::ArrayAttr elts = lv.getExtVectorElts();
827
828 // If the result of the expression is a non-vector type, we must be extracting
829 // a single element. Just codegen as an extractelement.
830 const auto *exprVecTy = lv.getType()->getAs<clang::VectorType>();
831 if (!exprVecTy) {
832 int64_t indexValue = getAccessedFieldNo(0, elts);
833 cir::ConstantOp index =
834 builder.getConstInt(loc, builder.getSInt64Ty(), indexValue);
835 return RValue::get(cir::VecExtractOp::create(builder, loc, vec, index));
836 }
837
838 // Always use shuffle vector to try to retain the original program structure
840 for (auto i : llvm::seq<unsigned>(0, exprVecTy->getNumElements()))
841 mask.push_back(getAccessedFieldNo(i, elts));
842
843 cir::VecShuffleOp resultVec = builder.createVecShuffle(loc, vec, mask);
844 if (lv.getType()->isExtVectorBoolType()) {
845 cgm.errorNYI(loc, "emitLoadOfExtVectorElementLValue: ExtVectorBoolType");
846 return {};
847 }
848
849 return RValue::get(resultVec);
850}
851
852LValue
854 assert((e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI) &&
855 "unexpected binary operator opcode");
856
857 Address baseAddr = Address::invalid();
858 if (e->getOpcode() == BO_PtrMemD)
859 baseAddr = emitLValue(e->getLHS()).getAddress();
860 else
861 baseAddr = emitPointerWithAlignment(e->getLHS());
862
863 const auto *memberPtrTy = e->getRHS()->getType()->castAs<MemberPointerType>();
864
865 mlir::Value memberPtr = emitScalarExpr(e->getRHS());
866
867 LValueBaseInfo baseInfo;
869 Address memberAddr = emitCXXMemberDataPointerAddress(e, baseAddr, memberPtr,
870 memberPtrTy, &baseInfo);
871
872 return makeAddrLValue(memberAddr, memberPtrTy->getPointeeType(), baseInfo);
873}
874
875/// Generates lvalue for partial ext_vector access.
877 mlir::Location loc) {
878 Address vectorAddress = lv.getExtVectorAddress();
879 QualType elementTy = lv.getType()->castAs<VectorType>()->getElementType();
880 mlir::Type vectorElementTy = cgm.getTypes().convertType(elementTy);
881 Address castToPointerElement =
882 vectorAddress.withElementType(builder, vectorElementTy);
883
884 mlir::ArrayAttr extVecElts = lv.getExtVectorElts();
885 unsigned idx = getAccessedFieldNo(0, extVecElts);
886 mlir::Value idxValue =
887 builder.getConstInt(loc, mlir::cast<cir::IntType>(ptrDiffTy), idx);
888
889 mlir::Value elementValue = builder.getArrayElement(
890 loc, loc, castToPointerElement.getPointer(), vectorElementTy, idxValue,
891 /*shouldDecay=*/false);
892
893 const CharUnits eltSize = getContext().getTypeSizeInChars(elementTy);
894 const CharUnits alignment =
895 castToPointerElement.getAlignment().alignmentAtOffset(idx * eltSize);
896 return Address(elementValue, vectorElementTy, alignment);
897}
898
899static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
901 return cgm.getAddrOfFunction(gd);
902}
903
905 mlir::Value thisValue) {
906 return cgf.emitLValueForLambdaField(fd, thisValue);
907}
908
909/// Given that we are currently emitting a lambda, emit an l-value for
910/// one of its members.
911///
913 mlir::Value thisValue) {
914 bool hasExplicitObjectParameter = false;
915 const auto *methD = dyn_cast_if_present<CXXMethodDecl>(curCodeDecl);
916 LValue lambdaLV;
917 if (methD) {
918 hasExplicitObjectParameter = methD->isExplicitObjectMemberFunction();
919 assert(methD->getParent()->isLambda());
920 assert(methD->getParent() == field->getParent());
921 }
922 if (hasExplicitObjectParameter) {
923 cgm.errorNYI(field->getSourceRange(), "ExplicitObjectMemberFunction");
924 } else {
925 QualType lambdaTagType =
927 lambdaLV = makeNaturalAlignAddrLValue(thisValue, lambdaTagType);
928 }
929 return emitLValueForField(lambdaLV, field);
930}
931
935
936static LValue emitFunctionDeclLValue(CIRGenFunction &cgf, const Expr *e,
937 GlobalDecl gd) {
938 const FunctionDecl *fd = cast<FunctionDecl>(gd.getDecl());
939 cir::FuncOp funcOp = emitFunctionDeclPointer(cgf.cgm, gd);
940 mlir::Location loc = cgf.getLoc(e->getSourceRange());
941 CharUnits align = cgf.getContext().getDeclAlign(fd);
942
944
945 mlir::Type fnTy = funcOp.getFunctionType();
946 mlir::Type ptrTy = cir::PointerType::get(fnTy);
947 mlir::Value addr = cir::GetGlobalOp::create(cgf.getBuilder(), loc, ptrTy,
948 funcOp.getSymName());
949
950 if (funcOp.getFunctionType() != cgf.convertType(fd->getType())) {
951 fnTy = cgf.convertType(fd->getType());
952 ptrTy = cir::PointerType::get(fnTy);
953
954 addr = cir::CastOp::create(cgf.getBuilder(), addr.getLoc(), ptrTy,
955 cir::CastKind::bitcast, addr);
956 }
957
958 return cgf.makeAddrLValue(Address(addr, fnTy, align), e->getType(),
960}
961
962/// Determine whether we can emit a reference to \p vd from the current
963/// context, despite not necessarily having seen an odr-use of the variable in
964/// this context.
965/// TODO(cir): This could be shared with classic codegen.
967 const DeclRefExpr *e,
968 const VarDecl *vd) {
969 // For a variable declared in an enclosing scope, do not emit a spurious
970 // reference even if we have a capture, as that will emit an unwarranted
971 // reference to our capture state, and will likely generate worse code than
972 // emitting a local copy.
974 return false;
975
976 // For a local declaration declared in this function, we can always reference
977 // it even if we don't have an odr-use.
978 if (vd->hasLocalStorage()) {
979 return vd->getDeclContext() ==
980 dyn_cast_or_null<DeclContext>(cgf.curCodeDecl);
981 }
982
983 // For a global declaration, we can emit a reference to it if we know
984 // for sure that we are able to emit a definition of it.
985 vd = vd->getDefinition(cgf.getContext());
986 if (!vd)
987 return false;
988
989 // Don't emit a spurious reference if it might be to a variable that only
990 // exists on a different device / target.
991 // FIXME: This is unnecessarily broad. Check whether this would actually be a
992 // cross-target reference.
993 if (cgf.getLangOpts().OpenMP || cgf.getLangOpts().CUDA ||
994 cgf.getLangOpts().OpenCL) {
995 return false;
996 }
997
998 // We can emit a spurious reference only if the linkage implies that we'll
999 // be emitting a non-interposable symbol that will be retained until link
1000 // time.
1001 switch (cgf.cgm.getCIRLinkageVarDefinition(vd)) {
1002 case cir::GlobalLinkageKind::ExternalLinkage:
1003 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
1004 case cir::GlobalLinkageKind::WeakODRLinkage:
1005 case cir::GlobalLinkageKind::InternalLinkage:
1006 case cir::GlobalLinkageKind::PrivateLinkage:
1007 return true;
1008 default:
1009 return false;
1010 }
1011}
1012
1014 const NamedDecl *nd = e->getDecl();
1015 QualType ty = e->getType();
1016
1017 assert(e->isNonOdrUse() != NOUR_Unevaluated &&
1018 "should not emit an unevaluated operand");
1019
1020 if (const auto *vd = dyn_cast<VarDecl>(nd)) {
1021 // Global Named registers access via intrinsics only
1022 if (vd->getStorageClass() == SC_Register && vd->hasAttr<AsmLabelAttr>() &&
1023 !vd->isLocalVarDecl()) {
1024 cgm.errorNYI(e->getSourceRange(),
1025 "emitDeclRefLValue: Global Named registers access");
1026 return LValue();
1027 }
1028
1029 if (e->isNonOdrUse() == NOUR_Constant &&
1030 (vd->getType()->isReferenceType() ||
1031 !canEmitSpuriousReferenceToVariable(*this, e, vd))) {
1032 vd->getAnyInitializer(vd);
1033 mlir::Attribute val = ConstantEmitter(*this).emitAbstract(
1034 e->getLocation(), *vd->evaluateValue(), vd->getType());
1035 assert(val && "failed to emit constant expression");
1036
1037 Address addr = Address::invalid();
1038 if (!vd->getType()->isReferenceType()) {
1039 // Spill the constant value to a global.
1040 addr = cgm.createUnnamedGlobalFrom(*vd, val,
1041 getContext().getDeclAlign(vd));
1042 mlir::Type varTy = getTypes().convertTypeForMem(vd->getType());
1043 auto ptrTy = mlir::cast<cir::PointerType>(addr.getPointer().getType());
1044 if (ptrTy.getPointee() != varTy) {
1045 addr = addr.withElementType(builder, varTy);
1046 }
1047 } else {
1048 // Should we be using the alignment of the constant pointer we emitted?
1049 CharUnits alignment = cgm.getNaturalTypeAlignment(
1050 e->getType(), /*baseInfo=*/nullptr, /*forPointeeType=*/true);
1051 // Classic codegen passes TBAA as null-ptr to the above function, so it
1052 // probably needs to deal with that.
1054 mlir::Value ptrVal = getBuilder().getConstant(
1055 getLoc(e->getSourceRange()), mlir::cast<mlir::TypedAttr>(val));
1056 addr = makeNaturalAddressForPointer(ptrVal, ty, alignment);
1057 }
1058 return makeAddrLValue(addr, ty, AlignmentSource::Decl);
1059 }
1060
1061 // Check for captured variables.
1063 vd = vd->getCanonicalDecl();
1064 if (FieldDecl *fd = lambdaCaptureFields.lookup(vd))
1065 return emitCapturedFieldLValue(*this, fd, cxxabiThisValue);
1068 }
1069 }
1070
1071 // FIXME: We should be able to assert this for FunctionDecls as well!
1072 // FIXME: We should be able to assert this for all DeclRefExprs, not just
1073 // those with a valid source location.
1074 assert((nd->isUsed(false) || !isa<VarDecl>(nd) || e->isNonOdrUse() ||
1075 !e->getLocation().isValid()) &&
1076 "Should not use decl without marking it used!");
1077
1078 if (nd->hasAttr<WeakRefAttr>())
1079 cgm.errorNYI(nd->getSourceRange(), "emitGlobal: WeakRefAttr");
1080
1081 if (const auto *vd = dyn_cast<VarDecl>(nd)) {
1082 // Checks for omitted feature handling
1089
1090 // Check if this is a global variable
1091 if (vd->hasLinkage() || vd->isStaticDataMember())
1092 return emitGlobalVarDeclLValue(*this, e, vd);
1093
1094 Address addr = Address::invalid();
1095
1096 // The variable should generally be present in the local decl map.
1097 auto iter = localDeclMap.find(vd);
1098 if (iter != localDeclMap.end()) {
1099 addr = iter->second;
1100
1101 } else if (vd->isStaticLocal()) {
1102 // Otherwise, it might be static local we haven't emitted yet for some
1103 // reason; most likely, because it's in an outer function.
1104 cir::GlobalOp var =
1105 cgm.getOrCreateStaticVarDecl(*vd, cgm.getCIRLinkageVarDefinition(vd));
1106 mlir::Value getGlobVal = builder.createGetGlobal(var);
1107 auto getGlob = getGlobVal.getDefiningOp<cir::GetGlobalOp>();
1108 getGlob.setStaticLocal(var.getStaticLocalGuard().has_value());
1109 getGlob.setTls(vd->getTLSKind() != VarDecl::TLS_None);
1110 addr = Address(getGlob, convertTypeForMem(vd->getType()),
1111 getContext().getDeclAlign(vd));
1112 } else {
1113 llvm_unreachable("DeclRefExpr for Decl not entered in localDeclMap?");
1114 }
1115
1116 // Drill into reference types.
1117 LValue lv =
1118 vd->getType()->isReferenceType()
1122
1123 // Statics are defined as globals, so they are not include in the function's
1124 // symbol table.
1125 assert((vd->isStaticLocal() || symbolTable.count(vd)) &&
1126 "non-static locals should be already mapped");
1127
1128 return lv;
1129 }
1130
1131 if (const auto *bd = dyn_cast<BindingDecl>(nd)) {
1133 FieldDecl *fd = lambdaCaptureFields.lookup(bd);
1134 return emitCapturedFieldLValue(*this, fd, cxxabiThisValue);
1135 }
1136 return emitLValue(bd->getBinding());
1137 }
1138
1139 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
1140 LValue lv = emitFunctionDeclLValue(*this, e, fd);
1141
1142 // Emit debuginfo for the function declaration if the target wants to.
1143 if (getContext().getTargetInfo().allowDebugInfoForExternalRef())
1145
1146 return lv;
1147 }
1148 if (isa<MSGuidDecl>(nd))
1149 cgm.errorNYI(e->getSourceRange(),
1150 "emitDeclRefLValue: unhandled MS Guid Decl");
1151
1152 if (const auto *tpo = dyn_cast<TemplateParamObjectDecl>(nd)) {
1153 CharUnits alignment = cgm.getNaturalTypeAlignment(tpo->getType());
1154 cir::GetGlobalOp atpo =
1155 builder.createGetGlobal(cgm.getAddrOfTemplateParamObject(tpo));
1157 "Do an address space conversion if necessary");
1158
1159 return makeAddrLValue(
1160 Address(atpo, convertTypeForMem(tpo->getType()), alignment), ty,
1162 }
1163
1164 llvm_unreachable("Unhandled DeclRefExpr");
1165}
1166
1168 QualType boolTy = getContext().BoolTy;
1169 SourceLocation loc = e->getExprLoc();
1170
1172 if (e->getType()->getAs<MemberPointerType>()) {
1173 cgm.errorNYI(e->getSourceRange(),
1174 "evaluateExprAsBool: member pointer type");
1175 return createDummyValue(getLoc(loc), boolTy);
1176 }
1177
1178 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1179 if (!e->getType()->isAnyComplexType())
1180 return emitScalarConversion(emitScalarExpr(e), e->getType(), boolTy, loc);
1181
1183 loc);
1184}
1185
1187 UnaryOperatorKind op = e->getOpcode();
1188
1189 // __extension__ doesn't affect lvalue-ness.
1190 if (op == UO_Extension)
1191 return emitLValue(e->getSubExpr());
1192
1193 switch (op) {
1194 case UO_Deref: {
1196 assert(!t.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
1197
1199 LValueBaseInfo baseInfo;
1200 Address addr = emitPointerWithAlignment(e->getSubExpr(), &baseInfo);
1201
1202 // Tag 'load' with deref attribute.
1203 // FIXME: This misses some derefence cases and has problematic interactions
1204 // with other operators.
1205 if (auto loadOp = addr.getDefiningOp<cir::LoadOp>())
1206 loadOp.setIsDerefAttr(mlir::UnitAttr::get(&getMLIRContext()));
1207
1208 LValue lv = makeAddrLValue(addr, t, baseInfo);
1211 return lv;
1212 }
1213 case UO_Real:
1214 case UO_Imag: {
1215 LValue lv = emitLValue(e->getSubExpr());
1216 assert(lv.isSimple() && "real/imag on non-ordinary l-value");
1217
1218 // __real is valid on scalars. This is a faster way of testing that.
1219 // __imag can only produce an rvalue on scalars.
1220 if (e->getOpcode() == UO_Real &&
1221 !mlir::isa<cir::ComplexType>(lv.getAddress().getElementType())) {
1222 assert(e->getSubExpr()->getType()->isArithmeticType());
1223 return lv;
1224 }
1225
1227 QualType elemTy = exprTy->castAs<clang::ComplexType>()->getElementType();
1228 mlir::Location loc = getLoc(e->getExprLoc());
1229 Address component =
1230 e->getOpcode() == UO_Real
1231 ? builder.createComplexRealPtr(loc, lv.getAddress())
1232 : builder.createComplexImagPtr(loc, lv.getAddress());
1234 LValue elemLV = makeAddrLValue(component, elemTy);
1235 elemLV.getQuals().addQualifiers(lv.getQuals());
1236 return elemLV;
1237 }
1238 case UO_PreInc:
1239 case UO_PreDec: {
1240 LValue lv = emitLValue(e->getSubExpr());
1241
1242 assert(e->isPrefix() && "Prefix operator in unexpected state!");
1243
1244 if (e->getType()->isAnyComplexType())
1246 else
1248
1249 return lv;
1250 }
1251 case UO_Extension:
1252 llvm_unreachable("UnaryOperator extension should be handled above!");
1253 case UO_Plus:
1254 case UO_Minus:
1255 case UO_Not:
1256 case UO_LNot:
1257 case UO_AddrOf:
1258 case UO_PostInc:
1259 case UO_PostDec:
1260 case UO_Coawait:
1261 llvm_unreachable("UnaryOperator of non-lvalue kind!");
1262 }
1263 llvm_unreachable("Unknown unary operator kind!");
1264}
1265
1266/// If the specified expr is a simple decay from an array to pointer,
1267/// return the array subexpression.
1268/// FIXME: this could be abstracted into a common AST helper.
1269static const Expr *getSimpleArrayDecayOperand(const Expr *e) {
1270 // If this isn't just an array->pointer decay, bail out.
1271 const auto *castExpr = dyn_cast<CastExpr>(e);
1272 if (!castExpr || castExpr->getCastKind() != CK_ArrayToPointerDecay)
1273 return nullptr;
1274
1275 // If this is a decay from variable width array, bail out.
1276 const Expr *subExpr = castExpr->getSubExpr();
1277 if (subExpr->getType()->isVariableArrayType())
1278 return nullptr;
1279
1280 return subExpr;
1281}
1282
1283static cir::IntAttr getConstantIndexOrNull(mlir::Value idx) {
1284 // TODO(cir): should we consider using MLIRs IndexType instead of IntegerAttr?
1285 if (auto constantOp = idx.getDefiningOp<cir::ConstantOp>())
1286 return constantOp.getValueAttr<cir::IntAttr>();
1287 return {};
1288}
1289
1290static CharUnits getArrayElementAlign(CharUnits arrayAlign, mlir::Value idx,
1291 CharUnits eltSize) {
1292 // If we have a constant index, we can use the exact offset of the
1293 // element we're accessing.
1294 if (const cir::IntAttr constantIdx = getConstantIndexOrNull(idx)) {
1295 const CharUnits offset = constantIdx.getValue().getZExtValue() * eltSize;
1296 return arrayAlign.alignmentAtOffset(offset);
1297 }
1298 // Otherwise, use the worst-case alignment for any element.
1299 return arrayAlign.alignmentOfArrayElement(eltSize);
1300}
1301
1303 const VariableArrayType *vla) {
1304 QualType eltType;
1305 do {
1306 eltType = vla->getElementType();
1307 } while ((vla = astContext.getAsVariableArrayType(eltType)));
1308 return eltType;
1309}
1310
1312 mlir::Location beginLoc,
1313 mlir::Location endLoc, mlir::Value ptr,
1314 mlir::Type eltTy, mlir::Value idx,
1315 bool shouldDecay) {
1316 CIRGenModule &cgm = cgf.getCIRGenModule();
1317 // TODO(cir): LLVM codegen emits in bound gep check here, is there anything
1318 // that would enhance tracking this later in CIR?
1320 return cgm.getBuilder().getArrayElement(beginLoc, endLoc, ptr, eltTy, idx,
1321 shouldDecay);
1322}
1323
1325 mlir::Location beginLoc,
1326 mlir::Location endLoc, Address addr,
1327 QualType eltType, mlir::Value idx,
1328 mlir::Location loc, bool shouldDecay) {
1329
1330 // Determine the element size of the statically-sized base. This is
1331 // the thing that the indices are expressed in terms of.
1332 if (const VariableArrayType *vla =
1333 cgf.getContext().getAsVariableArrayType(eltType)) {
1334 eltType = getFixedSizeElementType(cgf.getContext(), vla);
1335 }
1336
1337 // We can use that to compute the best alignment of the element.
1338 const CharUnits eltSize = cgf.getContext().getTypeSizeInChars(eltType);
1339 const CharUnits eltAlign =
1340 getArrayElementAlign(addr.getAlignment(), idx, eltSize);
1341
1343 const mlir::Value eltPtr =
1344 emitArraySubscriptPtr(cgf, beginLoc, endLoc, addr.getPointer(),
1345 addr.getElementType(), idx, shouldDecay);
1346 const mlir::Type elementType = cgf.convertTypeForMem(eltType);
1347 return Address(eltPtr, elementType, eltAlign);
1348}
1349
1350LValue
1352 if (e->getType()->getAs<ObjCObjectType>()) {
1353 cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjCObjectType");
1355 }
1356
1357 // The index must always be an integer, which is not an aggregate. Emit it
1358 // in lexical order (this complexity is, sadly, required by C++17).
1359 assert((e->getIdx() == e->getLHS() || e->getIdx() == e->getRHS()) &&
1360 "index was neither LHS nor RHS");
1361
1362 auto emitIdxAfterBase = [&](bool promote) -> mlir::Value {
1363 mlir::Value idx = emitScalarExpr(e->getIdx());
1364
1366
1367 // Extend or truncate the index type to pointer-sized integer.
1368 if (promote) {
1369 // Choose the type we extend or truncate to based on the signedness of the
1370 // index type.
1371 mlir::Type desiredIdxTy =
1373 ? ptrDiffTy
1374 : uIntPtrTy;
1375
1376 if (idx.getType() != desiredIdxTy) {
1377 cir::CastKind kind = mlir::isa<cir::BoolType>(idx.getType())
1378 ? cir::CastKind::bool_to_int
1379 : cir::CastKind::integral;
1380 idx = builder.createOrFold<cir::CastOp>(idx.getLoc(), desiredIdxTy,
1381 kind, idx);
1382 }
1383 }
1384
1385 return idx;
1386 };
1387
1388 // If the base is a vector type, then we are forming a vector element
1389 // with this subscript.
1390 if (e->getBase()->getType()->isSubscriptableVectorType() &&
1392 const mlir::Value idx = emitIdxAfterBase(/*promote=*/false);
1393 const LValue lv = emitLValue(e->getBase());
1394 return LValue::makeVectorElt(lv.getAddress(), idx, e->getBase()->getType(),
1395 lv.getBaseInfo());
1396 }
1397
1398 // The HLSL runtime handles subscript expressions on global resource arrays
1399 // and objects with HLSL buffer layouts.
1400 if (getLangOpts().HLSL) {
1401 cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: HLSL");
1402 return {};
1403 }
1404
1405 mlir::Value idx = emitIdxAfterBase(/*promote=*/true);
1406
1407 // Handle the extvector case we ignored above.
1409 const LValue lv = emitLValue(e->getBase());
1410 Address addr = emitExtVectorElementLValue(lv, cgm.getLoc(e->getExprLoc()));
1411
1412 QualType elementType = lv.getType()->castAs<VectorType>()->getElementType();
1413 addr = emitArraySubscriptPtr(*this, cgm.getLoc(e->getBeginLoc()),
1414 cgm.getLoc(e->getEndLoc()), addr, e->getType(),
1415 idx, cgm.getLoc(e->getExprLoc()),
1416 /*shouldDecay=*/false);
1417
1418 return makeAddrLValue(addr, elementType, lv.getBaseInfo());
1419 }
1420
1421 if (const VariableArrayType *vla =
1422 getContext().getAsVariableArrayType(e->getType())) {
1423 // The base must be a pointer, which is not an aggregate. Emit
1424 // it. It needs to be emitted first in case it's what captures
1425 // the VLA bounds.
1427
1428 // The element count here is the total number of non-VLA elements.
1429 mlir::Value numElements = getVLASize(vla).numElts;
1430 idx = builder.createIntCast(idx, numElements.getType());
1431
1432 // Effectively, the multiply by the VLA size is part of the GEP.
1433 // GEP indexes are signed, and scaling an index isn't permitted to
1434 // signed-overflow, so we use the same semantics for our explicit
1435 // multiply. We suppress this if overflow is not undefined behavior.
1436 OverflowBehavior overflowBehavior = getLangOpts().PointerOverflowDefined
1439 idx = builder.createMul(cgm.getLoc(e->getExprLoc()), idx, numElements,
1440 overflowBehavior);
1441
1442 addr = emitArraySubscriptPtr(*this, cgm.getLoc(e->getBeginLoc()),
1443 cgm.getLoc(e->getEndLoc()), addr, e->getType(),
1444 idx, cgm.getLoc(e->getExprLoc()),
1445 /*shouldDecay=*/false);
1446
1447 return makeAddrLValue(addr, vla->getElementType(), LValueBaseInfo());
1448 }
1449
1450 if (const Expr *array = getSimpleArrayDecayOperand(e->getBase())) {
1451 LValue arrayLV;
1452 if (const auto *ase = dyn_cast<ArraySubscriptExpr>(array))
1453 arrayLV = emitArraySubscriptExpr(ase);
1454 else
1455 arrayLV = emitLValue(array);
1456
1457 // Propagate the alignment from the array itself to the result.
1458 const Address addr = emitArraySubscriptPtr(
1459 *this, cgm.getLoc(array->getBeginLoc()), cgm.getLoc(array->getEndLoc()),
1460 arrayLV.getAddress(), e->getType(), idx, cgm.getLoc(e->getExprLoc()),
1461 /*shouldDecay=*/true);
1462
1463 const LValue lv = LValue::makeAddr(addr, e->getType(), LValueBaseInfo());
1464
1465 if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {
1466 cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjC with GC");
1467 }
1468
1469 return lv;
1470 }
1471
1472 // The base must be a pointer; emit it with an estimate of its alignment.
1473 assert(e->getBase()->getType()->isPointerType() &&
1474 "The base must be a pointer");
1475
1476 LValueBaseInfo eltBaseInfo;
1477 const Address ptrAddr = emitPointerWithAlignment(e->getBase(), &eltBaseInfo);
1478 // Propagate the alignment from the array itself to the result.
1479 const Address addxr = emitArraySubscriptPtr(
1480 *this, cgm.getLoc(e->getBeginLoc()), cgm.getLoc(e->getEndLoc()), ptrAddr,
1481 e->getType(), idx, cgm.getLoc(e->getExprLoc()),
1482 /*shouldDecay=*/false);
1483
1484 const LValue lv = LValue::makeAddr(addxr, e->getType(), eltBaseInfo);
1485
1486 if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {
1487 cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjC with GC");
1488 }
1489
1490 return lv;
1491}
1492
1494 // Emit the base vector as an l-value.
1495 LValue base;
1496
1497 // ExtVectorElementExpr's base can either be a vector or pointer to vector.
1498 if (e->isArrow()) {
1499 // If it is a pointer to a vector, emit the address and form an lvalue with
1500 // it.
1501 LValueBaseInfo baseInfo;
1502 Address ptr = emitPointerWithAlignment(e->getBase(), &baseInfo);
1503 const auto *clangPtrTy =
1505 base = makeAddrLValue(ptr, clangPtrTy->getPointeeType(), baseInfo);
1506 base.getQuals().removeObjCGCAttr();
1507 } else if (e->getBase()->isGLValue()) {
1508 // Otherwise, if the base is an lvalue ( as in the case of foo.x.x),
1509 // emit the base as an lvalue.
1510 assert(e->getBase()->getType()->isVectorType());
1511 base = emitLValue(e->getBase());
1512 } else {
1513 // Otherwise, the base is a normal rvalue (as in (V+V).x), emit it as such.
1514 assert(e->getBase()->getType()->isVectorType() &&
1515 "Result must be a vector");
1516 mlir::Value vec = emitScalarExpr(e->getBase());
1517
1518 // Store the vector to memory (because LValue wants an address).
1519 QualType baseTy = e->getBase()->getType();
1520 Address vecMem = createMemTemp(baseTy, vec.getLoc(), "tmp");
1521 if (!getLangOpts().HLSL && baseTy->isExtVectorBoolType()) {
1522 cgm.errorNYI(e->getSourceRange(),
1523 "emitExtVectorElementExpr: ExtVectorBoolType & !HLSL");
1524 return {};
1525 }
1526 builder.createStore(vec.getLoc(), vec, vecMem);
1527 base = makeAddrLValue(vecMem, baseTy, AlignmentSource::Decl);
1528 }
1529
1530 QualType type =
1532
1533 // Encode the element access list into a vector of unsigned indices.
1535 e->getEncodedElementAccess(indices);
1536
1537 if (base.isSimple()) {
1538 SmallVector<int64_t> attrElts(indices.begin(), indices.end());
1539 mlir::ArrayAttr elts = builder.getI64ArrayAttr(attrElts);
1540 return LValue::makeExtVectorElt(base.getAddress(), elts, type,
1541 base.getBaseInfo());
1542 }
1543
1544 if (base.isMatrixRow()) {
1545 cgm.errorNYI(e->getSourceRange(), "emitExtVectorElementExpr: isMatrixRow");
1546 return {};
1547 }
1548
1549 assert(base.isExtVectorElt() && "Can only subscript lvalue vec elts here!");
1550 mlir::ArrayAttr baseElts = base.getExtVectorElts();
1552 for (unsigned idx : indices)
1553 elts.push_back(getAccessedFieldNo(idx, baseElts));
1554 mlir::ArrayAttr cv = builder.getI64ArrayAttr(elts);
1555 return LValue::makeExtVectorElt(base.getAddress(), cv, type,
1556 base.getBaseInfo());
1557}
1558
1560 llvm::StringRef name) {
1561 cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e, name);
1562 assert(globalOp.getAlignment() && "expected alignment for string literal");
1563 unsigned align = *(globalOp.getAlignment());
1564 mlir::Value addr =
1565 builder.createGetGlobal(getLoc(e->getSourceRange()), globalOp);
1566 return makeAddrLValue(
1567 Address(addr, globalOp.getSymType(), CharUnits::fromQuantity(align)),
1569}
1570
1571/// Casts are never lvalues unless that cast is to a reference type. If the cast
1572/// is to a reference, we can have the usual lvalue result, otherwise if a cast
1573/// is needed by the code generator in an lvalue context, then it must mean that
1574/// we need the address of an aggregate in order to access one of its members.
1575/// This can happen for all the reasons that casts are permitted with aggregate
1576/// result, including noop aggregate casts, and cast from scalar to union.
1578 switch (e->getCastKind()) {
1579 case CK_ToVoid:
1580 case CK_BitCast:
1581 case CK_LValueToRValueBitCast:
1582 case CK_ArrayToPointerDecay:
1583 case CK_FunctionToPointerDecay:
1584 case CK_NullToMemberPointer:
1585 case CK_NullToPointer:
1586 case CK_IntegralToPointer:
1587 case CK_PointerToIntegral:
1588 case CK_PointerToBoolean:
1589 case CK_IntegralCast:
1590 case CK_BooleanToSignedIntegral:
1591 case CK_IntegralToBoolean:
1592 case CK_IntegralToFloating:
1593 case CK_FloatingToIntegral:
1594 case CK_FloatingToBoolean:
1595 case CK_FloatingCast:
1596 case CK_FloatingRealToComplex:
1597 case CK_FloatingComplexToReal:
1598 case CK_FloatingComplexToBoolean:
1599 case CK_FloatingComplexCast:
1600 case CK_FloatingComplexToIntegralComplex:
1601 case CK_IntegralRealToComplex:
1602 case CK_IntegralComplexToReal:
1603 case CK_IntegralComplexToBoolean:
1604 case CK_IntegralComplexCast:
1605 case CK_IntegralComplexToFloatingComplex:
1606 case CK_DerivedToBaseMemberPointer:
1607 case CK_BaseToDerivedMemberPointer:
1608 case CK_MemberPointerToBoolean:
1609 case CK_ReinterpretMemberPointer:
1610 case CK_AnyPointerToBlockPointerCast:
1611 case CK_ARCProduceObject:
1612 case CK_ARCConsumeObject:
1613 case CK_ARCReclaimReturnedObject:
1614 case CK_ARCExtendBlockObject:
1615 case CK_CopyAndAutoreleaseBlockObject:
1616 case CK_IntToOCLSampler:
1617 case CK_FloatingToFixedPoint:
1618 case CK_FixedPointToFloating:
1619 case CK_FixedPointCast:
1620 case CK_FixedPointToBoolean:
1621 case CK_FixedPointToIntegral:
1622 case CK_IntegralToFixedPoint:
1623 case CK_MatrixCast:
1624 case CK_HLSLVectorTruncation:
1625 case CK_HLSLMatrixTruncation:
1626 case CK_HLSLArrayRValue:
1627 case CK_HLSLElementwiseCast:
1628 case CK_HLSLAggregateSplatCast:
1629 llvm_unreachable("unexpected cast lvalue");
1630
1631 case CK_Dependent:
1632 llvm_unreachable("dependent cast kind in IR gen!");
1633
1634 case CK_BuiltinFnToFnPtr:
1635 llvm_unreachable("builtin functions are handled elsewhere");
1636
1637 case CK_Dynamic: {
1638 LValue lv = emitLValue(e->getSubExpr());
1639 Address v = lv.getAddress();
1640 const auto *dce = cast<CXXDynamicCastExpr>(e);
1642 }
1643
1644 // These are never l-values; just use the aggregate emission code.
1645 case CK_ToUnion:
1646 return emitAggExprToLValue(e);
1647
1648 case CK_ConstructorConversion:
1649 case CK_UserDefinedConversion:
1650 case CK_CPointerToObjCPointerCast:
1651 case CK_BlockPointerToObjCPointerCast:
1652 case CK_LValueToRValue:
1653 return emitLValue(e->getSubExpr());
1654
1655 case CK_NonAtomicToAtomic:
1656 case CK_AtomicToNonAtomic:
1657 case CK_ObjCObjectLValueCast:
1658 case CK_VectorSplat: {
1659 cgm.errorNYI(e->getSourceRange(),
1660 std::string("emitCastLValue for unhandled cast kind: ") +
1661 e->getCastKindName());
1662
1663 return {};
1664 }
1665
1666 case CK_AddressSpaceConversion: {
1667 LValue lv = emitLValue(e->getSubExpr());
1668 QualType destTy = getContext().getPointerType(e->getType());
1669
1670 mlir::Value v = performAddrSpaceCast(lv.getPointer(), convertType(destTy));
1671
1673 lv.getAddress().getAlignment()),
1674 e->getType(), lv.getBaseInfo());
1675 }
1676
1677 case CK_LValueBitCast: {
1678 // This must be a reinterpret_cast (or c-style equivalent).
1679 const auto *ce = cast<ExplicitCastExpr>(e);
1680
1681 cgm.emitExplicitCastExprType(ce, this);
1682 LValue LV = emitLValue(e->getSubExpr());
1684 builder, convertTypeForMem(ce->getTypeAsWritten()->getPointeeType()));
1685
1686 return makeAddrLValue(V, e->getType(), LV.getBaseInfo());
1687 }
1688
1689 case CK_NoOp: {
1690 // CK_NoOp can model a qualification conversion, which can remove an array
1691 // bound and change the IR type.
1692 LValue lv = emitLValue(e->getSubExpr());
1693 // Propagate the volatile qualifier to LValue, if exists in e.
1695 lv.getQuals() = e->getType().getQualifiers();
1696 if (lv.isSimple()) {
1697 Address v = lv.getAddress();
1698 if (v.isValid()) {
1699 mlir::Type ty = convertTypeForMem(e->getType());
1700 if (v.getElementType() != ty) {
1701 // We have only inspected/reproduced this with complete to incomplete
1702 // array types, so we do an NYI for other cases, so we can make sure
1703 // we're doing a conversion we want to be making.
1704 auto fromTy = dyn_cast<cir::ArrayType>(v.getElementType());
1705 auto toTy = dyn_cast<cir::ArrayType>(ty);
1706 if (!fromTy || !toTy ||
1707 fromTy.getElementType() != toTy.getElementType() ||
1708 toTy.getSize() != 0)
1709 cgm.errorNYI(e->getSourceRange(),
1710 "emitCastLValue NoOp not array-shrink case");
1711
1712 lv = makeAddrLValue(v.withElementType(builder, ty), e->getType(),
1713 lv.getBaseInfo());
1714 }
1715 }
1716 }
1717 return lv;
1718 }
1719
1720 case CK_UncheckedDerivedToBase:
1721 case CK_DerivedToBase: {
1722 auto *derivedClassDecl = e->getSubExpr()->getType()->castAsCXXRecordDecl();
1723
1724 LValue lv = emitLValue(e->getSubExpr());
1725 Address thisAddr = lv.getAddress();
1726
1727 // Perform the derived-to-base conversion
1728 Address baseAddr =
1729 getAddressOfBaseClass(thisAddr, derivedClassDecl, e->path(),
1730 /*NullCheckValue=*/false, e->getExprLoc());
1731
1732 // TODO: Support accesses to members of base classes in TBAA. For now, we
1733 // conservatively pretend that the complete object is of the base class
1734 // type.
1736 return makeAddrLValue(baseAddr, e->getType(), lv.getBaseInfo());
1737 }
1738
1739 case CK_BaseToDerived: {
1740 const auto *derivedClassDecl = e->getType()->castAsCXXRecordDecl();
1741 LValue lv = emitLValue(e->getSubExpr());
1742
1743 // Perform the base-to-derived conversion
1745 getLoc(e->getSourceRange()), lv.getAddress(), derivedClassDecl,
1746 e->path(), /*NullCheckValue=*/false);
1747 // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is
1748 // performed and the object is not of the derived type.
1750
1752 return makeAddrLValue(derived, e->getType(), lv.getBaseInfo());
1753 }
1754
1755 case CK_ZeroToOCLOpaqueType:
1756 llvm_unreachable("NULL to OpenCL opaque type lvalue cast is not valid");
1757 }
1758
1759 llvm_unreachable("Invalid cast kind");
1760}
1761
1763 const MemberExpr *me) {
1764 if (auto *vd = dyn_cast<VarDecl>(me->getMemberDecl())) {
1765 // Try to emit static variable member expressions as DREs.
1766 return DeclRefExpr::Create(
1768 /*RefersToEnclosingVariableOrCapture=*/false, me->getExprLoc(),
1769 me->getType(), me->getValueKind(), nullptr, nullptr, me->isNonOdrUse());
1770 }
1771 return nullptr;
1772}
1773
1775 if (DeclRefExpr *dre = tryToConvertMemberExprToDeclRefExpr(*this, e)) {
1777 return emitDeclRefLValue(dre);
1778 }
1779
1780 Expr *baseExpr = e->getBase();
1781 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
1782 LValue baseLV;
1783 if (e->isArrow()) {
1784 LValueBaseInfo baseInfo;
1786 Address addr = emitPointerWithAlignment(baseExpr, &baseInfo);
1787 QualType ptrTy = baseExpr->getType()->getPointeeType();
1789 baseLV = makeAddrLValue(addr, ptrTy, baseInfo);
1790 } else {
1792 baseLV = emitLValue(baseExpr);
1793 }
1794
1795 const NamedDecl *nd = e->getMemberDecl();
1796 if (auto *field = dyn_cast<FieldDecl>(nd)) {
1797 LValue lv = emitLValueForField(baseLV, field);
1799 if (getLangOpts().OpenMP) {
1800 // If the member was explicitly marked as nontemporal, mark it as
1801 // nontemporal. If the base lvalue is marked as nontemporal, mark access
1802 // to children as nontemporal too.
1803 cgm.errorNYI(e->getSourceRange(), "emitMemberExpr: OpenMP");
1804 }
1805 return lv;
1806 }
1807
1808 if (const auto *fd = dyn_cast<FunctionDecl>(nd))
1809 return emitFunctionDeclLValue(*this, e, fd);
1810
1811 llvm_unreachable("Unhandled member declaration!");
1812}
1813
1814/// Evaluate an expression into a given memory location.
1816 Qualifiers quals, bool isInit) {
1817 // FIXME: This function should take an LValue as an argument.
1818 switch (getEvaluationKind(e->getType())) {
1819 case cir::TEK_Complex: {
1820 LValue lv = makeAddrLValue(location, e->getType());
1821 emitComplexExprIntoLValue(e, lv, isInit);
1822 return;
1823 }
1824
1825 case cir::TEK_Aggregate: {
1826 emitAggExpr(e, AggValueSlot::forAddr(location, quals,
1830 return;
1831 }
1832
1833 case cir::TEK_Scalar: {
1835 LValue lv = makeAddrLValue(location, e->getType());
1836 emitStoreThroughLValue(rv, lv);
1837 return;
1838 }
1839 }
1840
1841 llvm_unreachable("bad evaluation kind");
1842}
1843
1845 const MaterializeTemporaryExpr *m,
1846 const Expr *inner) {
1847 // TODO(cir): cgf.getTargetHooks();
1848 switch (m->getStorageDuration()) {
1849 case SD_FullExpression:
1850 case SD_Automatic: {
1851 QualType ty = inner->getType();
1852
1854
1855 // The temporary memory should be created in the same scope as the extending
1856 // declaration of the temporary materialization expression.
1857 cir::AllocaOp extDeclAlloca;
1858 if (const ValueDecl *extDecl = m->getExtendingDecl()) {
1859 auto extDeclAddrIter = cgf.localDeclMap.find(extDecl);
1860 if (extDeclAddrIter != cgf.localDeclMap.end())
1861 extDeclAlloca = extDeclAddrIter->second.getUnderlyingAllocaOp();
1862 }
1863 mlir::OpBuilder::InsertPoint ip;
1864 if (extDeclAlloca) {
1865 ip = {extDeclAlloca->getBlock(), extDeclAlloca->getIterator()};
1866 } else if (cgf.isInConditionalBranch() &&
1868 // Place in the function entry block so the alloca dominates both
1869 // regions of any enclosing cir.cleanup.scope. The default path
1870 // would use curLexScope which may be a ternary branch.
1873 }
1874 return cgf.createMemTemp(ty, cgf.getLoc(m->getSourceRange()),
1875 cgf.getCounterRefTmpAsString(), /*alloca=*/nullptr,
1876 ip);
1877 }
1878 case SD_Thread:
1879 case SD_Static: {
1880 auto addr =
1881 mlir::cast<cir::GlobalOp>(cgf.cgm.getAddrOfGlobalTemporary(m, inner));
1882 auto getGlobal = cgf.cgm.getBuilder().createGetGlobal(addr);
1883 assert(addr.getAlignment().has_value() &&
1884 "This should always have an alignment");
1885 return Address(getGlobal,
1886 clang::CharUnits::fromQuantity(addr.getAlignment().value()));
1887 }
1888
1889 case SD_Dynamic:
1890 llvm_unreachable("temporary can't have dynamic storage duration");
1891 }
1892 llvm_unreachable("unknown storage duration");
1893}
1894
1896 const MaterializeTemporaryExpr *m,
1897 const Expr *e, Address referenceTemporary) {
1898 // Objective-C++ ARC:
1899 // If we are binding a reference to a temporary that has ownership, we
1900 // need to perform retain/release operations on the temporary.
1901 //
1902 // FIXME(ogcg): This should be looking at e, not m.
1903 if (m->getType().getObjCLifetime()) {
1904 cgf.cgm.errorNYI(e->getSourceRange(), "pushTemporaryCleanup: ObjCLifetime");
1905 return;
1906 }
1907
1909 if (dk == QualType::DK_none)
1910 return;
1911
1912 switch (m->getStorageDuration()) {
1913 case SD_Static:
1914 case SD_Thread: {
1915 CXXDestructorDecl *referenceTemporaryDtor = nullptr;
1916 if (const auto *classDecl =
1918 classDecl && !classDecl->hasTrivialDestructor())
1919 // Get the destructor for the reference temporary.
1920 referenceTemporaryDtor = classDecl->getDestructor();
1921
1922 if (!referenceTemporaryDtor)
1923 return;
1924
1925 // Classic codegen calls registerGlobalDtor here, passing either the
1926 // destructor or a generated array-destroy helper. CIR handles globals with
1927 // non-trivial destructors by attaching a dtor region to the cir.global op.
1928 CIRGenModule &cgm = cgf.cgm;
1929 auto globalOp =
1930 mlir::cast<cir::GlobalOp>(cgm.getAddrOfGlobalTemporary(m, e));
1931
1932 // The destruction of the reference temporary is done in the dtor
1933 // region of the global object it is associated with.
1934 const auto *extendingDecl = cast<VarDecl>(m->getExtendingDecl());
1935 cir::GlobalOp extendingGlobalOp = cgm.getOrCreateCIRGlobal(
1936 extendingDecl, /*ty=*/nullptr, NotForDefinition);
1937
1938 CIRGenBuilderTy &builder = cgm.getBuilder();
1939 mlir::OpBuilder::InsertionGuard guard(builder);
1940 assert(extendingGlobalOp.getDtorRegion().empty() &&
1941 "extending global already has a dtor region");
1942 mlir::Block *block =
1943 builder.createBlock(&extendingGlobalOp.getDtorRegion());
1944 builder.setInsertionPointToStart(block);
1945
1946 mlir::Location loc = cgm.getLoc(m->getSourceRange());
1947 mlir::Value tempAddr = builder.createGetGlobal(globalOp);
1948
1949 if (e->getType()->isArrayType()) {
1950 // emitDestroy will produce a cir.array.dtor here. LoweringPrepare's
1951 // getOrCreateDtorFunc recognizes the non-trivial dtor region and
1952 // hoists it into a __cxx_global_array_dtor helper.
1953 Address addr{tempAddr, cgf.convertTypeForMem(e->getType()),
1954 referenceTemporary.getAlignment()};
1956 } else {
1957 GlobalDecl gd(referenceTemporaryDtor, Dtor_Complete);
1958 cir::FuncOp dtorFn = cgm.getAddrAndTypeOfCXXStructor(gd).second;
1959 builder.createCallOp(loc, dtorFn, mlir::ValueRange{tempAddr});
1960 }
1961
1962 cir::YieldOp::create(builder, loc);
1963 break;
1964 }
1965
1966 case SD_FullExpression:
1967 cgf.pushDestroy(NormalAndEHCleanup, referenceTemporary, e->getType(),
1969 break;
1970
1971 case SD_Automatic:
1973 NormalAndEHCleanup, referenceTemporary, e->getType(),
1975 break;
1976
1977 case SD_Dynamic:
1978 llvm_unreachable("temporary cannot have dynamic storage duration");
1979 }
1980}
1981
1983 const MaterializeTemporaryExpr *m) {
1984 const Expr *e = m->getSubExpr();
1985
1986 assert((!m->getExtendingDecl() || !isa<VarDecl>(m->getExtendingDecl()) ||
1987 !cast<VarDecl>(m->getExtendingDecl())->isARCPseudoStrong()) &&
1988 "Reference should never be pseudo-strong!");
1989
1990 // FIXME: ideally this would use emitAnyExprToMem, however, we cannot do so
1991 // as that will cause the lifetime adjustment to be lost for ARC
1992 auto ownership = m->getType().getObjCLifetime();
1993 if (ownership != Qualifiers::OCL_None &&
1994 ownership != Qualifiers::OCL_ExplicitNone) {
1995 cgm.errorNYI(e->getSourceRange(),
1996 "emitMaterializeTemporaryExpr: ObjCLifetime");
1997 return {};
1998 }
1999
2002 e = e->skipRValueSubobjectAdjustments(commaLHSs, adjustments);
2003
2004 for (const Expr *ignored : commaLHSs)
2005 emitIgnoredExpr(ignored);
2006
2007 if (isa<OpaqueValueExpr>(e)) {
2008 cgm.errorNYI(e->getSourceRange(),
2009 "emitMaterializeTemporaryExpr: OpaqueValueExpr");
2010 return {};
2011 }
2012
2013 // Create and initialize the reference temporary.
2014 Address object = createReferenceTemporary(*this, m, e);
2015 cir::GlobalOp var = nullptr;
2016 if (auto getGlobalOp = object.getPointer().getDefiningOp<cir::GetGlobalOp>())
2017 var = mlir::dyn_cast_or_null<cir::GlobalOp>(
2018 cgm.getGlobalValue(getGlobalOp.getName()));
2019
2020 if (var) {
2021 if (!var.getInitialValue().has_value()) {
2022 var.setInitialValueAttr(cir::ZeroAttr::get(var.getSymType()));
2024 emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);
2025 }
2026 } else {
2028 emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);
2029 }
2030 pushTemporaryCleanup(*this, m, e, object);
2031
2032 // Perform derived-to-base casts and/or field accesses, to get from the
2033 // temporary object we created (and, potentially, for which we extended
2034 // the lifetime) to the subobject we're binding the reference to.
2035 for (SubobjectAdjustment &adjustment : llvm::reverse(adjustments)) {
2036 switch (adjustment.Kind) {
2038 object =
2039 getAddressOfBaseClass(object, adjustment.DerivedToBase.DerivedClass,
2040 adjustment.DerivedToBase.BasePath->path(),
2041 /*nullCheckValue=*/false, e->getExprLoc());
2042 break;
2045 lv = emitLValueForField(lv, adjustment.Field);
2046 assert(lv.isSimple() &&
2047 "materialized temporary field is not a simple lvalue");
2048 object = lv.getAddress();
2049 break;
2050 }
2052 mlir::Value ptr = emitScalarExpr(adjustment.Ptr.RHS);
2054 e, object, ptr, adjustment.Ptr.MPT, /*baseInfo=*/nullptr);
2055 break;
2056 }
2057 }
2058 }
2059
2060 return makeAddrLValue(object, m->getType(), AlignmentSource::Decl);
2061}
2062
2063LValue
2066
2067 auto it = opaqueLValues.find(e);
2068 if (it != opaqueLValues.end())
2069 return it->second;
2070
2071 assert(e->isUnique() && "LValue for a nonunique OVE hasn't been emitted");
2072 return emitLValue(e->getSourceExpr());
2073}
2074
2075RValue
2078
2079 auto it = opaqueRValues.find(e);
2080 if (it != opaqueRValues.end())
2081 return it->second;
2082
2083 assert(e->isUnique() && "RValue for a nonunique OVE hasn't been emitted");
2084 return emitAnyExpr(e->getSourceExpr());
2085}
2086
2088 if (e->isFileScope()) {
2089 cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope");
2090 return {};
2091 }
2092
2093 if (e->getType()->isVariablyModifiedType())
2095
2096 Address declPtr = createMemTemp(e->getType(), getLoc(e->getSourceRange()),
2097 ".compoundliteral");
2098 const Expr *initExpr = e->getInitializer();
2099 LValue result = makeAddrLValue(declPtr, e->getType(), AlignmentSource::Decl);
2100
2101 emitAnyExprToMem(initExpr, declPtr, e->getType().getQualifiers(),
2102 /*Init*/ true);
2103
2104 // Block-scope compound literals are destroyed at the end of the enclosing
2105 // scope in C.
2106 if (!getLangOpts().CPlusPlus && e->getType().isDestructedType()) {
2107 cgm.errorNYI(e->getSourceRange(),
2108 "emitCompoundLiteralLValue: non C++ DestructedType");
2109 return {};
2110 }
2111
2112 return result;
2113}
2114
2116 RValue rv = emitCallExpr(e);
2117
2118 if (!rv.isScalar())
2119 return makeAddrLValue(rv.getAggregateAddress(), e->getType(),
2121
2122 assert(e->getCallReturnType(getContext())->isReferenceType() &&
2123 "Can't have a scalar return unless the return type is a "
2124 "reference type!");
2125
2127}
2128
2129LValue
2138
2141 "binding l-value to type which needs a temporary");
2143 emitCXXConstructExpr(e, slot);
2145}
2146
2148 // Comma expressions just emit their LHS then their RHS as an l-value.
2149 if (e->getOpcode() == BO_Comma) {
2150 emitIgnoredExpr(e->getLHS());
2151 return emitLValue(e->getRHS());
2152 }
2153
2154 if (e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI)
2156
2157 assert(e->getOpcode() == BO_Assign && "unexpected binary l-value");
2158
2159 // Note that in all of these cases, __block variables need the RHS
2160 // evaluated first just in case the variable gets moved by the RHS.
2161
2163 case cir::TEK_Scalar: {
2165 if (e->getLHS()->getType().getObjCLifetime() !=
2167 cgm.errorNYI(e->getSourceRange(), "objc lifetimes");
2168 return {};
2169 }
2170
2171 RValue rv = emitAnyExpr(e->getRHS());
2172 LValue lv = emitLValue(e->getLHS());
2173
2174 SourceLocRAIIObject loc{*this, getLoc(e->getSourceRange())};
2175 if (lv.isBitField())
2177 else
2178 emitStoreThroughLValue(rv, lv);
2179
2180 if (getLangOpts().OpenMP) {
2181 cgm.errorNYI(e->getSourceRange(), "openmp");
2182 return {};
2183 }
2184
2185 return lv;
2186 }
2187
2188 case cir::TEK_Complex: {
2190 }
2191
2192 case cir::TEK_Aggregate:
2193 cgm.errorNYI(e->getSourceRange(), "aggregate lvalues");
2194 return {};
2195 }
2196 llvm_unreachable("bad evaluation kind");
2197}
2198
2199/// Emit code to compute the specified expression which
2200/// can have any type. The result is returned as an RValue struct.
2202 bool ignoreResult) {
2204 case cir::TEK_Scalar:
2205 return RValue::get(emitScalarExpr(e, ignoreResult));
2206 case cir::TEK_Complex:
2208 case cir::TEK_Aggregate: {
2209 if (!ignoreResult && aggSlot.isIgnored())
2210 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
2212 emitAggExpr(e, aggSlot);
2213 return aggSlot.asRValue();
2214 }
2215 }
2216 llvm_unreachable("bad evaluation kind");
2217}
2218
2219// Detect the unusual situation where an inline version is shadowed by a
2220// non-inline version. In that case we should pick the external one
2221// everywhere. That's GCC behavior too.
2223 for (const FunctionDecl *pd = fd; pd; pd = pd->getPreviousDecl())
2224 if (!pd->isInlineBuiltinDeclaration())
2225 return false;
2226 return true;
2227}
2228
2229CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {
2230 const auto *fd = cast<FunctionDecl>(gd.getDecl());
2231
2232 if (unsigned builtinID = fd->getBuiltinID()) {
2233 StringRef ident = cgm.getMangledName(gd);
2234 std::string fdInlineName = (ident + ".inline").str();
2235
2236 bool isPredefinedLibFunction =
2237 cgm.getASTContext().BuiltinInfo.isPredefinedLibFunction(builtinID);
2238 // TODO: Read no-builtin function attribute and set this accordingly.
2239 // Using false here matches OGCG's default behavior - builtins are called
2240 // as builtins unless explicitly disabled. The previous value of true was
2241 // overly conservative and caused functions to be marked as no_inline when
2242 // they shouldn't be.
2243 bool hasAttributeNoBuiltin = false;
2245
2246 // When directly calling an inline builtin, call it through it's mangled
2247 // name to make it clear it's not the actual builtin.
2248 if (auto fn = dyn_cast<cir::FuncOp>(curFn);
2249 (!fn || fn.getName() != fdInlineName) &&
2251 cir::FuncOp clone =
2252 mlir::cast_or_null<cir::FuncOp>(cgm.getGlobalValue(fdInlineName));
2253
2254 if (!clone) {
2255 // Create a forward declaration - the body will be generated in
2256 // generateCode when the function definition is processed
2257 cir::FuncOp calleeFunc = emitFunctionDeclPointer(cgm, gd);
2258 mlir::OpBuilder::InsertionGuard guard(builder);
2259 builder.setInsertionPointToStart(cgm.getModule().getBody());
2260
2261 clone = cir::FuncOp::create(builder, calleeFunc.getLoc(), fdInlineName,
2262 calleeFunc.getFunctionType());
2263 cgm.insertGlobalSymbol(clone);
2264 clone.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
2265 &cgm.getMLIRContext(), cir::GlobalLinkageKind::InternalLinkage));
2266 clone.setSymVisibility("private");
2267 clone.setInlineKind(cir::InlineKind::AlwaysInline);
2268 }
2269 return CIRGenCallee::forDirect(clone, gd);
2270 }
2271
2272 // Replaceable builtins provide their own implementation of a builtin. If we
2273 // are in an inline builtin implementation, avoid trivial infinite
2274 // recursion. Honor __attribute__((no_builtin("foo"))) or
2275 // __attribute__((no_builtin)) on the current function unless foo is
2276 // not a predefined library function which means we must generate the
2277 // builtin no matter what.
2278 else if (!isPredefinedLibFunction || !hasAttributeNoBuiltin)
2279 return CIRGenCallee::forBuiltin(builtinID, fd);
2280 }
2281
2282 cir::FuncOp callee = emitFunctionDeclPointer(cgm, gd);
2283
2284 if ((cgm.getLangOpts().CUDA || cgm.getLangOpts().HIP) &&
2285 !cgm.getLangOpts().CUDAIsDevice && fd->hasAttr<CUDAGlobalAttr>()) {
2286 mlir::Operation *handle = cgm.getCUDARuntime().getKernelHandle(callee, gd);
2287 callee =
2288 mlir::cast<cir::FuncOp>(*cgm.getCUDARuntime().getKernelStub(handle));
2289 }
2290
2291 return CIRGenCallee::forDirect(callee, gd);
2292}
2293
2294mlir::Value CIRGenFunction::getUndefConstant(mlir::Location loc,
2295 mlir::Type cirTy) {
2296 return builder.getConstant(loc, cir::UndefAttr::get(cirTy));
2297}
2298
2300 if (ty->isVoidType())
2301 return RValue::get(nullptr);
2302
2303 mlir::Location loc = builder.getUnknownLoc();
2304
2305 switch (getEvaluationKind(ty)) {
2306 case cir::TEK_Complex: {
2307 QualType elemTy = ty->castAs<ComplexType>()->getElementType();
2308 mlir::Type elemCirTy = convertType(elemTy);
2309 mlir::Value undefElem = getUndefConstant(loc, elemCirTy);
2310 mlir::Value v = builder.createComplexCreate(loc, undefElem, undefElem);
2311 return RValue::getComplex(v);
2312 }
2313
2314 // If this is a use of an undefined aggregate type, the aggregate must have
2315 // an identifiable address. Just because the contents of the value are
2316 // undefined doesn't mean that the address can't be taken and compared.
2317 case cir::TEK_Aggregate: {
2318 Address destPtr = createMemTempWithoutCast(ty, loc, "undef.agg.tmp");
2319 return RValue::getAggregate(destPtr);
2320 }
2321
2322 case cir::TEK_Scalar:
2323 return RValue::get(getUndefConstant(loc, convertType(ty)));
2324 }
2325 llvm_unreachable("bad evaluation kind");
2326}
2327
2329 const CIRGenCallee &origCallee,
2330 const clang::CallExpr *e,
2332 // Get the actual function type. The callee type will always be a pointer to
2333 // function type or a block pointer type.
2334 assert(calleeTy->isFunctionPointerType() &&
2335 "Callee must have function pointer type!");
2336
2337 calleeTy = getContext().getCanonicalType(calleeTy);
2338 auto pointeeTy = cast<PointerType>(calleeTy)->getPointeeType();
2339
2340 CIRGenCallee callee = origCallee;
2341
2342 if (getLangOpts().CPlusPlus)
2344
2345 const auto *fnType = cast<FunctionType>(pointeeTy);
2346
2348
2349 CallArgList args;
2351
2352 // C++23 static-member operators (`static operator()` /
2353 // `static operator[]`) produce a CXXOperatorCallExpr whose first argument
2354 // is the object expression even though the operator is static. Emit the
2355 // object for its side effects and drop it before walking the parameter
2356 // arguments.
2357 auto arguments = e->arguments();
2358 if (const auto *oce = dyn_cast<CXXOperatorCallExpr>(e)) {
2359 if (const auto *md =
2360 dyn_cast_if_present<CXXMethodDecl>(oce->getCalleeDecl());
2361 md && md->isStatic()) {
2362 emitIgnoredExpr(e->getArg(0));
2363 arguments = llvm::drop_begin(arguments, 1);
2364 }
2365 }
2366
2367 emitCallArgs(args, dyn_cast<FunctionProtoType>(fnType), arguments,
2368 e->getDirectCallee());
2369
2370 const CIRGenFunctionInfo &funcInfo =
2371 cgm.getTypes().arrangeFreeFunctionCall(args, fnType);
2372
2373 // C99 6.5.2.2p6:
2374 // If the expression that denotes the called function has a type that does
2375 // not include a prototype, [the default argument promotions are performed].
2376 // If the number of arguments does not equal the number of parameters, the
2377 // behavior is undefined. If the function is defined with a type that
2378 // includes a prototype, and either the prototype ends with an ellipsis (,
2379 // ...) or the types of the arguments after promotion are not compatible
2380 // with the types of the parameters, the behavior is undefined. If the
2381 // function is defined with a type that does not include a prototype, and
2382 // the types of the arguments after promotion are not compatible with those
2383 // of the parameters after promotion, the behavior is undefined [except in
2384 // some trivial cases].
2385 // That is, in the general case, we should assume that a call through an
2386 // unprototyped function type works like a *non-variadic* call. The way we
2387 // make this work is to cast to the exxact type fo the promoted arguments.
2388 if (isa<FunctionNoProtoType>(fnType)) {
2391 cir::FuncType calleeTy = getTypes().getFunctionType(funcInfo);
2392 // get non-variadic function type
2393 calleeTy = cir::FuncType::get(calleeTy.getInputs(),
2394 calleeTy.getReturnType(), false);
2395 auto calleePtrTy = cir::PointerType::get(calleeTy);
2396
2397 mlir::Operation *fn = callee.getFunctionPointer();
2398 mlir::Value addr;
2399 if (auto funcOp = mlir::dyn_cast<cir::FuncOp>(fn)) {
2400 addr = cir::GetGlobalOp::create(
2401 builder, getLoc(e->getSourceRange()),
2402 cir::PointerType::get(funcOp.getFunctionType()), funcOp.getSymName());
2403 } else {
2404 addr = fn->getResult(0);
2405 }
2406
2407 fn = builder.createBitcast(addr, calleePtrTy).getDefiningOp();
2408 callee.setFunctionPointer(fn);
2409 }
2410
2412 assert(!cir::MissingFeatures::hip());
2413
2414 cir::CIRCallOpInterface callOp;
2415 RValue callResult = emitCall(funcInfo, callee, returnValue, args, &callOp,
2416 e == mustTailCall, getLoc(e->getExprLoc()));
2417
2419
2420 return callResult;
2421}
2422
2424 e = e->IgnoreParens();
2425
2426 // Look through function-to-pointer decay.
2427 if (const auto *implicitCast = dyn_cast<ImplicitCastExpr>(e)) {
2428 if (implicitCast->getCastKind() == CK_FunctionToPointerDecay ||
2429 implicitCast->getCastKind() == CK_BuiltinFnToFnPtr) {
2430 return emitCallee(implicitCast->getSubExpr());
2431 }
2432 // Classic codegen has some handling here for ptr-auth (as a part of the
2433 // large ptr-auth-qualifier PR (#100830)). In the meantime, other cast kinds
2434 // can fall-through and be handled by the indirect call work below,
2435 // including L-to-R value conversions and atomic conversions.
2437
2438 } else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {
2439 // Resolve direct calls.
2440 if (const auto *funcDecl = dyn_cast<FunctionDecl>(declRef->getDecl()))
2441 return emitDirectCallee(funcDecl);
2442 } else if (auto me = dyn_cast<MemberExpr>(e)) {
2443 if (const auto *fd = dyn_cast<FunctionDecl>(me->getMemberDecl())) {
2444 emitIgnoredExpr(me->getBase());
2445 return emitDirectCallee(fd);
2446 }
2447 // Else fall through to the indirect reference handling below.
2448 } else if (auto *pde = dyn_cast<CXXPseudoDestructorExpr>(e)) {
2450 }
2451
2452 // Otherwise, we have an indirect reference.
2453 mlir::Value calleePtr;
2455 if (const auto *ptrType = e->getType()->getAs<clang::PointerType>()) {
2456 calleePtr = emitScalarExpr(e);
2457 functionType = ptrType->getPointeeType();
2458 } else {
2459 functionType = e->getType();
2460 calleePtr = emitLValue(e).getPointer();
2461 }
2462 assert(functionType->isFunctionType());
2463
2464 GlobalDecl gd;
2465 if (const auto *vd =
2466 dyn_cast_or_null<VarDecl>(e->getReferencedDeclOfCallee()))
2467 gd = GlobalDecl(vd);
2468
2469 CIRGenCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), gd);
2470 CIRGenCallee callee(calleeInfo, calleePtr.getDefiningOp());
2471 return callee;
2472}
2473
2477
2478 if (const auto *ce = dyn_cast<CXXMemberCallExpr>(e))
2480
2481 if (const auto *cudaKernelCallExpr = dyn_cast<CUDAKernelCallExpr>(e))
2483
2484 // A CXXOperatorCallExpr is created even for explicit-object methods or
2485 // static member operators (C++23 `static operator()` / `static
2486 // operator[]`), but those should be treated like ordinary static function
2487 // calls. Only route through the member-call path for ordinary instance
2488 // operators.
2489 if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(e)) {
2490 if (const auto *md =
2491 dyn_cast_if_present<CXXMethodDecl>(operatorCall->getCalleeDecl());
2492 md && md->isImplicitObjectMemberFunction())
2493 return emitCXXOperatorMemberCallExpr(operatorCall, md, returnValue);
2494 }
2495
2496 CIRGenCallee callee = emitCallee(e->getCallee());
2497
2498 if (callee.isBuiltin())
2499 return emitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(), e,
2500 returnValue);
2501
2502 if (callee.isPseudoDestructor())
2504
2505 return emitCall(e->getCallee()->getType(), callee, e, returnValue);
2506}
2507
2508/// Emit code to compute the specified expression, ignoring the result.
2510 if (e->isPRValue()) {
2511 emitAnyExpr(e, AggValueSlot::ignored(), /*ignoreResult=*/true);
2512 return;
2513 }
2514
2515 // Just emit it as an l-value and drop the result.
2516 emitLValue(e);
2517}
2518
2520 LValueBaseInfo *baseInfo) {
2522 assert(e->getType()->isArrayType() &&
2523 "Array to pointer decay must have array source type!");
2524
2525 // Expressions of array type can't be bitfields or vector elements.
2526 LValue lv = emitLValue(e);
2527 Address addr = lv.getAddress();
2528
2529 // If the array type was an incomplete type, we need to make sure
2530 // the decay ends up being the right type.
2531 auto lvalueAddrTy = mlir::cast<cir::PointerType>(addr.getPointer().getType());
2532
2533 if (e->getType()->isVariableArrayType())
2534 return addr;
2535
2536 [[maybe_unused]] auto pointeeTy =
2537 mlir::cast<cir::ArrayType>(lvalueAddrTy.getPointee());
2538
2539 [[maybe_unused]] mlir::Type arrayTy = convertType(e->getType());
2540 assert(mlir::isa<cir::ArrayType>(arrayTy) && "expected array");
2541 assert(pointeeTy == arrayTy);
2542
2543 // The result of this decay conversion points to an array element within the
2544 // base lvalue. However, since TBAA currently does not support representing
2545 // accesses to elements of member arrays, we conservatively represent accesses
2546 // to the pointee object as if it had no any base lvalue specified.
2547 // TODO: Support TBAA for member arrays.
2550
2551 mlir::Value ptr = builder.maybeBuildArrayDecay(
2552 cgm.getLoc(e->getSourceRange()), addr.getPointer(),
2553 convertTypeForMem(eltType));
2554 return Address(ptr, addr.getAlignment());
2555}
2556
2557/// Given the address of a temporary variable, produce an r-value of its type.
2561 switch (getEvaluationKind(type)) {
2562 case cir::TEK_Complex:
2563 return RValue::getComplex(emitLoadOfComplex(lvalue, loc));
2564 case cir::TEK_Aggregate:
2565 return lvalue.asAggregateRValue();
2566 case cir::TEK_Scalar:
2567 return RValue::get(emitLoadOfScalar(lvalue, loc));
2568 }
2569 llvm_unreachable("bad evaluation kind");
2570}
2571
2572/// Emit an `if` on a boolean condition, filling `then` and `else` into
2573/// appropriated regions.
2574mlir::LogicalResult CIRGenFunction::emitIfOnBoolExpr(const Expr *cond,
2575 const Stmt *thenS,
2576 const Stmt *elseS) {
2577 mlir::Location thenLoc = getLoc(thenS->getSourceRange());
2578 std::optional<mlir::Location> elseLoc;
2579 if (elseS)
2580 elseLoc = getLoc(elseS->getSourceRange());
2581
2582 mlir::LogicalResult resThen = mlir::success(), resElse = mlir::success();
2584 cond, /*thenBuilder=*/
2585 [&](mlir::OpBuilder &, mlir::Location) {
2586 LexicalScope lexScope{*this, thenLoc, builder.getInsertionBlock()};
2587 resThen = emitStmt(thenS, /*useCurrentScope=*/true);
2588 },
2589 thenLoc,
2590 /*elseBuilder=*/
2591 [&](mlir::OpBuilder &, mlir::Location) {
2592 assert(elseLoc && "Invalid location for elseS.");
2593 LexicalScope lexScope{*this, *elseLoc, builder.getInsertionBlock()};
2594 resElse = emitStmt(elseS, /*useCurrentScope=*/true);
2595 },
2596 elseLoc);
2597
2598 return mlir::LogicalResult::success(resThen.succeeded() &&
2599 resElse.succeeded());
2600}
2601
2602/// Emit an `if` on a boolean condition, filling `then` and `else` into
2603/// appropriated regions.
2605 const clang::Expr *cond, BuilderCallbackRef thenBuilder,
2606 mlir::Location thenLoc, BuilderCallbackRef elseBuilder,
2607 std::optional<mlir::Location> elseLoc) {
2608 // Attempt to be as accurate as possible with IfOp location, generate
2609 // one fused location that has either 2 or 4 total locations, depending
2610 // on else's availability.
2611 SmallVector<mlir::Location, 2> ifLocs{thenLoc};
2612 if (elseLoc)
2613 ifLocs.push_back(*elseLoc);
2614 mlir::Location loc = mlir::FusedLoc::get(&getMLIRContext(), ifLocs);
2615
2616 // Emit the code with the fully general case.
2617 mlir::Value condV = emitOpOnBoolExpr(loc, cond);
2618 cir::IfOp ifOp = cir::IfOp::create(builder, loc, condV, elseLoc.has_value(),
2619 /*thenBuilder=*/thenBuilder,
2620 /*elseBuilder=*/elseBuilder);
2621 terminateStructuredRegionBody(ifOp.getThenRegion(), thenLoc);
2622 assert((elseLoc.has_value() || ifOp.getElseRegion().empty()) &&
2623 "else region created with no else location");
2624 if (elseLoc.has_value())
2625 terminateStructuredRegionBody(ifOp.getElseRegion(), *elseLoc);
2626 return ifOp;
2627}
2628
2629/// TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
2630mlir::Value CIRGenFunction::emitOpOnBoolExpr(mlir::Location loc,
2631 const Expr *cond) {
2634 cond = cond->IgnoreParens();
2635
2636 // In LLVM the condition is reversed here for efficient codegen.
2637 // This should be done in CIR prior to LLVM lowering, if we do now
2638 // we can make CIR based diagnostics misleading.
2639 // cir.ternary(!x, t, f) -> cir.ternary(x, f, t)
2641
2642 if (const ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(cond)) {
2643 Expr *trueExpr = condOp->getTrueExpr();
2644 Expr *falseExpr = condOp->getFalseExpr();
2645 mlir::Value condV = emitOpOnBoolExpr(loc, condOp->getCond());
2646
2647 mlir::Value ternaryOpRes =
2648 cir::TernaryOp::create(
2649 builder, loc, condV, /*thenBuilder=*/
2650 [this, trueExpr](mlir::OpBuilder &b, mlir::Location loc) {
2651 mlir::Value lhs = emitScalarExpr(trueExpr);
2652 cir::YieldOp::create(b, loc, lhs);
2653 },
2654 /*elseBuilder=*/
2655 [this, falseExpr](mlir::OpBuilder &b, mlir::Location loc) {
2656 mlir::Value rhs = emitScalarExpr(falseExpr);
2657 cir::YieldOp::create(b, loc, rhs);
2658 })
2659 .getResult();
2660
2661 return emitScalarConversion(ternaryOpRes, condOp->getType(),
2662 getContext().BoolTy, condOp->getExprLoc());
2663 }
2664
2665 if (isa<CXXThrowExpr>(cond)) {
2666 cgm.errorNYI("NYI");
2667 return createDummyValue(loc, cond->getType());
2668 }
2669
2670 // If the branch has a condition wrapped by __builtin_unpredictable,
2671 // create metadata that specifies that the branch is unpredictable.
2672 // Don't bother if not optimizing because that metadata would not be used.
2674
2675 // Emit the code with the fully general case.
2676 return evaluateExprAsBool(cond);
2677}
2678
2679mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
2680 mlir::Location loc, CharUnits alignment,
2681 bool insertIntoFnEntryBlock,
2682 mlir::Value arraySize) {
2683 mlir::Block *entryBlock = insertIntoFnEntryBlock
2685 : curLexScope->getEntryBlock();
2686
2687 // If this is an alloca in the entry basic block of a cir.try and there's
2688 // a surrounding cir.scope, make sure the alloca ends up in the surrounding
2689 // scope instead. This is necessary in order to guarantee all SSA values are
2690 // reachable during cleanups.
2691 if (auto tryOp =
2692 llvm::dyn_cast_if_present<cir::TryOp>(entryBlock->getParentOp())) {
2693 if (auto scopeOp = llvm::dyn_cast<cir::ScopeOp>(tryOp->getParentOp()))
2694 entryBlock = &scopeOp.getScopeRegion().front();
2695 }
2696
2697 return emitAlloca(name, ty, loc, alignment,
2698 builder.getBestAllocaInsertPoint(entryBlock), arraySize);
2699}
2700
2701mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
2702 mlir::Location loc, CharUnits alignment,
2703 mlir::OpBuilder::InsertPoint ip,
2704 mlir::Value arraySize) {
2705 // CIR uses its own alloca address space rather than follow the target data
2706 // layout like original CodeGen. The data layout awareness should be done in
2707 // the lowering pass instead.
2708 cir::PointerType localVarPtrTy =
2710 mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);
2711
2712 mlir::Value addr;
2713 {
2714 mlir::OpBuilder::InsertionGuard guard(builder);
2715 builder.restoreInsertionPoint(ip);
2716 addr = builder.createAlloca(loc, /*addr type*/ localVarPtrTy, name,
2717 alignIntAttr, arraySize);
2719 }
2720 return addr;
2721}
2722
2723// Note: this function also emit constructor calls to support a MSVC extensions
2724// allowing explicit constructor function call.
2727 const Expr *callee = ce->getCallee()->IgnoreParens();
2728
2729 if (isa<BinaryOperator>(callee))
2731
2732 const auto *me = cast<MemberExpr>(callee);
2733 const auto *md = cast<CXXMethodDecl>(me->getMemberDecl());
2734
2735 if (md->isStatic()) {
2736 cgm.errorNYI(ce->getSourceRange(), "emitCXXMemberCallExpr: static method");
2737 return RValue::get(nullptr);
2738 }
2739
2740 bool hasQualifier = me->hasQualifier();
2741 NestedNameSpecifier qualifier = me->getQualifier();
2742 bool isArrow = me->isArrow();
2743 const Expr *base = me->getBase();
2744
2746 ce, md, returnValue, hasQualifier, qualifier, isArrow, base);
2747}
2748
2750 // Emit the expression as an lvalue.
2751 LValue lv = emitLValue(e);
2752 assert(lv.isSimple());
2753 mlir::Value value = lv.getPointer();
2754
2756
2757 return RValue::get(value);
2758}
2759
2761 LValueBaseInfo *pointeeBaseInfo) {
2762 if (refLVal.isVolatile())
2763 cgm.errorNYI(loc, "load of volatile reference");
2764
2765 cir::LoadOp load =
2766 cir::LoadOp::create(builder, loc, refLVal.getAddress().getElementType(),
2767 refLVal.getAddress().getPointer());
2768
2770
2771 QualType pointeeType = refLVal.getType()->getPointeeType();
2772 CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, pointeeBaseInfo);
2773 return Address(load, convertTypeForMem(pointeeType), align);
2774}
2775
2777 mlir::Location loc,
2778 QualType refTy,
2779 AlignmentSource source) {
2780 LValue refLVal = makeAddrLValue(refAddr, refTy, LValueBaseInfo(source));
2781 LValueBaseInfo pointeeBaseInfo;
2783 Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo);
2784 return makeAddrLValue(pointeeAddr, refLVal.getType()->getPointeeType(),
2785 pointeeBaseInfo);
2786}
2787
2788void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) {
2789 cir::TrapOp::create(builder, loc);
2790 if (createNewBlock)
2791 builder.createBlock(builder.getBlock()->getParent());
2792}
2793
2795 bool createNewBlock) {
2797 cir::UnreachableOp::create(builder, getLoc(loc));
2798 if (createNewBlock)
2799 builder.createBlock(builder.getBlock()->getParent());
2800}
2801
2802mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,
2803 clang::QualType qt) {
2804 mlir::Type t = convertType(qt);
2805 CharUnits alignment = getContext().getTypeAlignInChars(qt);
2806 return builder.createDummyValue(loc, t, alignment);
2807}
2808
2809//===----------------------------------------------------------------------===//
2810// CIR builder helpers
2811//===----------------------------------------------------------------------===//
2812
2814 mlir::Location loc,
2815 const Twine &name) {
2817 convertTypeForMem(ty), getContext().getTypeAlignInChars(ty), loc, name);
2818}
2819
2821 const Twine &name, Address *alloca,
2822 mlir::OpBuilder::InsertPoint ip) {
2823 // FIXME: Should we prefer the preferred type alignment here?
2824 return createMemTemp(ty, getContext().getTypeAlignInChars(ty), loc, name,
2825 alloca, ip);
2826}
2827
2829 mlir::Location loc, const Twine &name,
2830 Address *alloca,
2831 mlir::OpBuilder::InsertPoint ip) {
2832 Address result =
2833 createTempAlloca(convertTypeForMem(ty), /*destAddrSpace=*/{}, align, loc,
2834 name, /*arraySize=*/nullptr, alloca, ip);
2835 if (ty->isConstantMatrixType()) {
2837 cgm.errorNYI(loc, "temporary matrix value");
2838 }
2839 return result;
2840}
2841
2842/// This creates a alloca and inserts it into the entry block of the
2843/// current region.
2845 mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name,
2846 mlir::Value arraySize, mlir::OpBuilder::InsertPoint ip) {
2847 cir::AllocaOp alloca = ip.isSet()
2848 ? createTempAlloca(ty, loc, name, ip, arraySize)
2849 : createTempAlloca(ty, loc, name, arraySize);
2850 alloca.setAlignmentAttr(cgm.getSize(align));
2851 return Address(alloca, ty, align);
2852}
2853
2855 mlir::Location loc, const Twine &name,
2856 mlir::Value arraySize,
2857 Address *allocaAddr,
2858 mlir::OpBuilder::InsertPoint ip) {
2859 return createTempAlloca(ty, /*destAddrSpace=*/{}, align, loc, name, arraySize,
2860 allocaAddr, ip);
2861}
2862
2864 Address alloca, mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2865 mlir::Value arraySize) {
2866 if (!destAddrSpace)
2867 destAddrSpace = cir::toCIRAddressSpaceAttr(
2868 getMLIRContext(), cgm.getLangTempAllocaAddressSpace());
2869
2870 mlir::ptr::MemorySpaceAttrInterface srcAddrSpace = getCIRAllocaAddressSpace();
2871 // Alloca always returns a pointer in alloca address space, which may
2872 // be different from the type defined by the language. For example,
2873 // in C++ the auto variables are in the default address space. Therefore
2874 // cast alloca to the default address space when necessary.
2875 if (srcAddrSpace == destAddrSpace)
2876 return alloca;
2877
2878 mlir::OpBuilder::InsertionGuard guard(builder);
2879 if (cir::AllocaOp allocaOp = alloca.getUnderlyingAllocaOp()) {
2880 builder.setInsertionPointAfter(allocaOp);
2881 } else if (!arraySize) {
2882 mlir::Block *entryBlock = getCurFunctionEntryBlock();
2883 builder.restoreInsertionPoint(builder.getBestAllocaInsertPoint(entryBlock));
2884 }
2885
2886 mlir::Type destPtrTy =
2887 builder.getPointerTo(alloca.getElementType(), destAddrSpace);
2888 mlir::Value casted = performAddrSpaceCast(alloca.getPointer(), destPtrTy);
2889 return Address(casted, alloca.getElementType(), alloca.getAlignment(),
2890 /*isKnownNonNull=*/true);
2891}
2892
2893/// This creates a alloca and inserts it into the entry block. The alloca is
2894/// casted to the requested language address space if necessary.
2896 mlir::Type ty, mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2897 CharUnits align, mlir::Location loc, const Twine &name,
2898 mlir::Value arraySize, Address *allocaAddr,
2899 mlir::OpBuilder::InsertPoint ip) {
2900 Address alloca =
2901 createTempAllocaWithoutCast(ty, align, loc, name, arraySize, ip);
2902 if (allocaAddr)
2903 *allocaAddr = alloca;
2904 return maybeCastStackAddressSpace(alloca, destAddrSpace, arraySize);
2905}
2906
2907/// This creates an alloca and inserts it into the entry block if \p ArraySize
2908/// is nullptr, otherwise inserts it at the current insertion point of the
2909/// builder.
2910cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
2911 mlir::Location loc,
2912 const Twine &name,
2913 mlir::Value arraySize,
2914 bool insertIntoFnEntryBlock) {
2915 return mlir::cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(),
2916 insertIntoFnEntryBlock, arraySize)
2917 .getDefiningOp());
2918}
2919
2920/// This creates an alloca and inserts it into the provided insertion point
2921cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
2922 mlir::Location loc,
2923 const Twine &name,
2924 mlir::OpBuilder::InsertPoint ip,
2925 mlir::Value arraySize) {
2926 assert(ip.isSet() && "Insertion point is not set");
2927 return mlir::cast<cir::AllocaOp>(
2928 emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize)
2929 .getDefiningOp());
2930}
2931
2932/// CreateDefaultAlignTempAlloca - This creates an alloca with the
2933/// default alignment of the corresponding LLVM type, which is *not*
2934/// guaranteed to be related in any way to the expected alignment of
2935/// an AST type that might have been lowered to Ty.
2937 mlir::Location loc,
2938 const Twine &name) {
2939 CharUnits align =
2940 CharUnits::fromQuantity(cgm.getDataLayout().getABITypeAlign(ty));
2941 return createTempAlloca(ty, align, loc, name);
2942}
2943
2944/// Try to emit a reference to the given value without producing it as
2945/// an l-value. For many cases, this is just an optimization, but it avoids
2946/// us needing to emit global copies of variables if they're named without
2947/// triggering a formal use in a context where we can't emit a direct
2948/// reference to them, for instance if a block or lambda or a member of a
2949/// local class uses a const int variable or constexpr variable from an
2950/// enclosing function.
2951///
2952/// For named members of enums, this is the only way they are emitted.
2955 const ValueDecl *value = refExpr->getDecl();
2956
2957 // There is a lot more to do here, but for now only EnumConstantDecl is
2958 // supported.
2960
2961 // The value needs to be an enum constant or a constant variable.
2962 if (!isa<EnumConstantDecl>(value))
2963 return ConstantEmission();
2964
2965 Expr::EvalResult result;
2966 if (!refExpr->EvaluateAsRValue(result, getContext()))
2967 return ConstantEmission();
2968
2969 QualType resultType = refExpr->getType();
2970
2971 // As long as we're only handling EnumConstantDecl, there should be no
2972 // side-effects.
2973 assert(!result.HasSideEffects);
2974
2975 // Emit as a constant.
2976 // FIXME(cir): have emitAbstract build a TypedAttr instead (this requires
2977 // somewhat heavy refactoring...)
2978 mlir::Attribute c = ConstantEmitter(*this).emitAbstract(
2979 refExpr->getLocation(), result.Val, resultType);
2980 mlir::TypedAttr cstToEmit = mlir::dyn_cast_if_present<mlir::TypedAttr>(c);
2981 assert(cstToEmit && "expected a typed attribute");
2982
2984
2985 return ConstantEmission::forValue(cstToEmit);
2986}
2987
2991 return tryEmitAsConstant(dre);
2992 return ConstantEmission();
2993}
2994
2996 const CIRGenFunction::ConstantEmission &constant, Expr *e) {
2997 assert(constant && "not a constant");
2998 if (constant.isReference()) {
2999 cgm.errorNYI(e->getSourceRange(), "emitScalarConstant: reference");
3000 return {};
3001 }
3002 return builder.getConstant(getLoc(e->getSourceRange()), constant.getValue());
3003}
3004
3006 const StringLiteral *sl = e->getFunctionName();
3007 assert(sl != nullptr && "No StringLiteral name in PredefinedExpr");
3008 auto fn = cast<cir::FuncOp>(curFn);
3009 StringRef fnName = fn.getName();
3010 fnName.consume_front("\01");
3011 std::array<StringRef, 2> nameItems = {
3013 std::string gvName = llvm::join(nameItems, ".");
3014 if (isa_and_nonnull<BlockDecl>(curCodeDecl))
3015 cgm.errorNYI(e->getSourceRange(), "predefined lvalue in block");
3016
3017 return emitStringLiteralLValue(sl, gvName);
3018}
3019
3024
3025namespace {
3026// Handle the case where the condition is a constant evaluatable simple integer,
3027// which means we don't have to separately handle the true/false blocks.
3028std::optional<LValue> handleConditionalOperatorLValueSimpleCase(
3030 const Expr *condExpr = e->getCond();
3031 llvm::APSInt condExprVal;
3032 if (!cgf.constantFoldsToSimpleInteger(condExpr, condExprVal))
3033 return std::nullopt;
3034
3035 const Expr *live = e->getTrueExpr(), *dead = e->getFalseExpr();
3036 if (!condExprVal.getBoolValue())
3037 std::swap(live, dead);
3038
3039 if (cgf.containsLabel(dead))
3040 return std::nullopt;
3041
3042 // If the true case is live, we need to track its region.
3045 // If a throw expression we emit it and return an undefined lvalue
3046 // because it can't be used.
3047 if (auto *throwExpr = dyn_cast<CXXThrowExpr>(live->IgnoreParens())) {
3048 cgf.emitCXXThrowExpr(throwExpr);
3049 // Return an undefined lvalue - the throw terminates execution
3050 // so this value will never actually be used
3051 mlir::Type elemTy = cgf.convertType(dead->getType());
3052 mlir::Value undefPtr =
3053 cgf.getBuilder().getNullPtr(cgf.getBuilder().getPointerTo(elemTy),
3054 cgf.getLoc(throwExpr->getSourceRange()));
3055 return cgf.makeAddrLValue(Address(undefPtr, elemTy, CharUnits::One()),
3056 dead->getType());
3057 }
3058 return cgf.emitLValue(live);
3059}
3060
3061/// Emit the operand of a glvalue conditional operator. This is either a glvalue
3062/// or a (possibly-parenthesized) throw-expression. If this is a throw, no
3063/// LValue is returned and the current block has been terminated.
3064static std::optional<LValue> emitLValueOrThrowExpression(CIRGenFunction &cgf,
3065 const Expr *operand) {
3066 if (auto *throwExpr = dyn_cast<CXXThrowExpr>(operand->IgnoreParens())) {
3067 cgf.emitCXXThrowExpr(throwExpr);
3068 return std::nullopt;
3069 }
3070
3071 return cgf.emitLValue(operand);
3072}
3073} // namespace
3074
3075// Create and generate the 3 blocks for a conditional operator.
3076// Leaves the 'current block' in the continuation basic block.
3077template <typename FuncTy>
3080 const FuncTy &branchGenFunc) {
3081 ConditionalInfo info;
3082 ConditionalEvaluation eval(*this);
3083 mlir::Location loc = getLoc(e->getSourceRange());
3084 CIRGenBuilderTy &builder = getBuilder();
3085
3086 mlir::Value condV = emitOpOnBoolExpr(loc, e->getCond());
3087
3088 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc,
3089 const Expr *expr, std::optional<LValue> &resultLV) {
3090 CIRGenFunction::LexicalScope lexScope{*this, loc, b.getInsertionBlock()};
3091 curLexScope->setAsTernary();
3092
3093 mlir::Value resultPtr;
3094 {
3095 // Emit any cleanups that were needed on this branch so we can spill
3096 // and reload the return value.
3097 CIRGenFunction::RunCleanupsScope branchCleanups(*this);
3099 eval.beginEvaluation();
3100 resultLV = branchGenFunc(*this, expr);
3101 resultPtr = resultLV ? resultLV->getPointer() : mlir::Value();
3102 eval.endEvaluation();
3103 branchCleanups.forceCleanup({&resultPtr});
3104 }
3105
3106 // A branch that produced no result is a throw-expression; its region is
3107 // already terminated by cir.unreachable and needs no yield.
3108 if (resultPtr)
3109 cir::YieldOp::create(b, loc, resultPtr);
3110 };
3111
3112 cir::TernaryOp ternary = cir::TernaryOp::create(
3113 builder, loc, condV,
3114 /*trueBuilder=*/
3115 [&](mlir::OpBuilder &b, mlir::Location loc) {
3116 emitBranch(b, loc, e->getTrueExpr(), info.lhs);
3117 },
3118 /*falseBuilder=*/
3119 [&](mlir::OpBuilder &b, mlir::Location loc) {
3120 emitBranch(b, loc, e->getFalseExpr(), info.rhs);
3121 });
3122
3123 // Arms end with a yield or cir.unreachable (throw); this is a backstop
3124 // for error (NYI) paths that leave a region open.
3125 terminateStructuredRegionBody(ternary.getTrueRegion(), loc);
3126 terminateStructuredRegionBody(ternary.getFalseRegion(), loc);
3127
3128 info.result = ternary.getResult();
3129 return info;
3130}
3131
3134 if (!expr->isGLValue()) {
3135 // ?: here should be an aggregate.
3136 assert(hasAggregateEvaluationKind(expr->getType()) &&
3137 "Unexpected conditional operator!");
3138 return emitAggExprToLValue(expr);
3139 }
3140
3141 OpaqueValueMapping binding(*this, expr);
3142 if (std::optional<LValue> res =
3143 handleConditionalOperatorLValueSimpleCase(*this, expr))
3144 return *res;
3145
3146 ConditionalInfo info =
3147 emitConditionalBlocks(expr, [](CIRGenFunction &cgf, const Expr *e) {
3148 return emitLValueOrThrowExpression(cgf, e);
3149 });
3150
3151 if ((info.lhs && !info.lhs->isSimple()) ||
3152 (info.rhs && !info.rhs->isSimple())) {
3153 cgm.errorNYI(expr->getSourceRange(),
3154 "unsupported conditional operator with non-simple lvalue");
3155 return LValue();
3156 }
3157
3158 if (info.lhs && info.rhs) {
3159 Address lhsAddr = info.lhs->getAddress();
3160 Address rhsAddr = info.rhs->getAddress();
3161 Address result(info.result, lhsAddr.getElementType(),
3162 std::min(lhsAddr.getAlignment(), rhsAddr.getAlignment()));
3163 AlignmentSource alignSource =
3164 std::max(info.lhs->getBaseInfo().getAlignmentSource(),
3165 info.rhs->getBaseInfo().getAlignmentSource());
3167 return makeAddrLValue(result, expr->getType(), LValueBaseInfo(alignSource));
3168 }
3169
3170 assert((info.lhs || info.rhs) &&
3171 "both operands of glvalue conditional are throw-expressions?");
3172
3173 // One arm threw; the surviving arm's pointer is local to the ternary's
3174 // region, so address the result through the ternary's result value.
3175 const LValue &survivingLV = info.lhs ? *info.lhs : *info.rhs;
3176 Address survivingAddr = survivingLV.getAddress();
3177 Address result(info.result, survivingAddr.getElementType(),
3178 survivingAddr.getAlignment());
3180 return makeAddrLValue(result, expr->getType(), survivingLV.getBaseInfo());
3181}
3182
3183/// An LValue is a candidate for having its loads and stores be made atomic if
3184/// we are operating under /volatile:ms *and* the LValue itself is volatile and
3185/// performing such an operation can be performed without a libcall.
3187 if (!cgm.getLangOpts().MSVolatile)
3188 return false;
3189
3190 cgm.errorNYI("LValueSuitableForInlineAtomic LangOpts MSVolatile");
3191 return false;
3192}
3193
#define V(N, I)
Provides definitions for the various language-specific address spaces.
llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> BuilderCallbackRef
Definition CIRDialect.h:37
static Address createReferenceTemporary(CIRGenFunction &cgf, const MaterializeTemporaryExpr *m, const Expr *inner)
static bool isAAPCS(const TargetInfo &targetInfo)
Helper method to check if the underlying ABI is AAPCS.
static LValue emitFunctionDeclLValue(CIRGenFunction &cgf, const Expr *e, GlobalDecl gd)
static CharUnits getArrayElementAlign(CharUnits arrayAlign, mlir::Value idx, CharUnits eltSize)
static void pushTemporaryCleanup(CIRGenFunction &cgf, const MaterializeTemporaryExpr *m, const Expr *e, Address referenceTemporary)
static cir::IntAttr getConstantIndexOrNull(mlir::Value idx)
static const Expr * getSimpleArrayDecayOperand(const Expr *e)
If the specified expr is a simple decay from an array to pointer, return the array subexpression.
static QualType getFixedSizeElementType(const ASTContext &astContext, const VariableArrayType *vla)
static bool canEmitSpuriousReferenceToVariable(CIRGenFunction &cgf, const DeclRefExpr *e, const VarDecl *vd)
Determine whether we can emit a reference to vd from the current context, despite not necessarily hav...
static DeclRefExpr * tryToConvertMemberExprToDeclRefExpr(CIRGenFunction &cgf, const MemberExpr *me)
static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd)
static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e, const VarDecl *vd)
static mlir::Value emitArraySubscriptPtr(CIRGenFunction &cgf, mlir::Location beginLoc, mlir::Location endLoc, mlir::Value ptr, mlir::Type eltTy, mlir::Value idx, bool shouldDecay)
static LValue emitCapturedFieldLValue(CIRGenFunction &cgf, const FieldDecl *fd, mlir::Value thisValue)
static bool onlyHasInlineBuiltinDeclaration(const FunctionDecl *fd)
static Address emitAddrOfZeroSizeField(CIRGenFunction &cgf, Address base, const FieldDecl *field)
Get the address of a zero-sized field within a record.
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
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)
static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block)
cir::PointerType getPointerTo(mlir::Type ty)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
cir::GetGlobalOp createGetGlobal(mlir::Location loc, cir::GlobalOp global, bool threadLocal=false)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, llvm::StringRef name, mlir::IntegerAttr alignment, mlir::Value dynAllocSize)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={})
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const
llvm::ArrayRef< mlir::Type > getMembers() const
Definition CIRTypes.cpp:596
uint64_t getElementOffset(const mlir::DataLayout &dataLayout, unsigned idx) const
Definition CIRTypes.cpp:655
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType BoolTy
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const VariableArrayType * getAsVariableArrayType(QualType T) const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition Expr.h:4364
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Definition Expr.h:4542
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4548
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4554
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2732
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:2787
Expr * getLHS()
An array access can be written A[4] or 4[A] (both are equivalent).
Definition Expr.h:2761
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:2775
SourceLocation getEndLoc() const
Definition Expr.h:2778
QualType getElementType() const
Definition TypeBase.h:3848
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4049
Expr * getLHS() const
Definition Expr.h:4099
Expr * getRHS() const
Definition Expr.h:4101
Opcode getOpcode() const
Definition Expr.h:4094
mlir::Value getPointer() const
Definition Address.h:98
mlir::Type getElementType() const
Definition Address.h:125
static Address invalid()
Definition Address.h:76
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
clang::CharUnits getAlignment() const
Definition Address.h:138
mlir::Type getType() const
Definition Address.h:117
bool isValid() const
Definition Address.h:77
cir::AllocaOp getUnderlyingAllocaOp() const
Return the underlying alloca for this address, if any.
Definition Address.h:157
mlir::Operation * getDefiningOp() const
Get the operation which defines this address.
Definition Address.h:141
An aggregate value slot.
IsDestructed_t
This is set to true if the slot might be aliased and it's not undefined behavior to access it through...
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
void setExternallyDestructed(bool destructed=true)
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
cir::ConstantOp getUInt64(uint64_t c, mlir::Location loc)
Address createGetMember(mlir::Location loc, Address base, llvm::StringRef name, unsigned index)
Address createElementBitCast(mlir::Location loc, Address addr, mlir::Type destType)
Cast the element type of the given address to a different type, preserving information like the align...
mlir::Value getArrayElement(mlir::Location arrayLocBegin, mlir::Location arrayLocEnd, mlir::Value arrayPtr, mlir::Type eltTy, mlir::Value idx, bool shouldDecay)
Create a cir.ptr_stride operation to get access to an array element.
Abstract information about a function or function prototype.
Definition CIRGenCall.h:27
bool isPseudoDestructor() const
Definition CIRGenCall.h:123
void setFunctionPointer(mlir::Operation *functionPtr)
Definition CIRGenCall.h:185
const clang::FunctionDecl * getBuiltinDecl() const
Definition CIRGenCall.h:99
const CXXPseudoDestructorExpr * getPseudoDestructorExpr() const
Definition CIRGenCall.h:127
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:92
unsigned getBuiltinID() const
Definition CIRGenCall.h:103
static CIRGenCallee forBuiltin(unsigned builtinID, const clang::FunctionDecl *builtinDecl)
Definition CIRGenCall.h:108
mlir::Operation * getFunctionPointer() const
Definition CIRGenCall.h:147
static CIRGenCallee forPseudoDestructor(const clang::CXXPseudoDestructorExpr *expr)
Definition CIRGenCall.h:117
An object to manage conditionally-evaluated expressions.
static ConstantEmission forValue(mlir::TypedAttr c)
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
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.
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0)
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.
RValue convertTempToRValue(Address addr, clang::QualType type, clang::SourceLocation loc)
Given the address of a temporary variable, produce an r-value of its type.
Address emitCXXMemberDataPointerAddress(const Expr *e, Address base, mlir::Value memberPtr, const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo)
Address maybeCastStackAddressSpace(Address alloca, mlir::ptr::MemorySpaceAttrInterface destAddrSpace, mlir::Value arraySize)
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
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,...
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...
mlir::Block * getCurFunctionEntryBlock()
RValue emitCXXMemberCallExpr(const clang::CXXMemberCallExpr *e, ReturnValueSlot returnValue)
RValue emitCXXMemberPointerCallExpr(const CXXMemberCallExpr *ce, ReturnValueSlot returnValue)
LValue emitLValueForBitField(LValue base, const FieldDecl *field)
mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond, const clang::Stmt *thenS, const clang::Stmt *elseS)
Emit an if on a boolean condition to the specified blocks.
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
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...
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitMemberExpr(const MemberExpr *e)
LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr)
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
Address makeNaturalAddressForPointer(mlir::Value ptr, QualType t, CharUnits alignment, bool forPointeeType=false, LValueBaseInfo *baseInfo=nullptr)
Construct an address with the natural alignment of T.
LValue emitLValueForLambdaField(const FieldDecl *field)
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
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,...
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
void emitStoreThroughExtVectorComponentLValue(RValue src, LValue dst)
Address getAddressOfBaseClass(Address value, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue, SourceLocation loc)
LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc, QualType refTy, AlignmentSource source)
void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals, bool isInitializer)
Emits the code necessary to evaluate an arbitrary expression into the given memory location.
LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its LValue mapping if it exists, otherwise create one.
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
LValue emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e)
RValue emitCUDAKernelCallExpr(const CUDAKernelCallExpr *expr, ReturnValueSlot returnValue)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
Address emitExtVectorElementLValue(LValue lv, mlir::Location loc)
Generates lvalue for partial ext_vector access.
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, clang::QualType dstType, clang::SourceLocation loc)
Emit a conversion from the specified type to the specified destination type, both of which are CIR sc...
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, AggValueSlot slot=AggValueSlot::ignored())
AggValueSlot createAggTemp(QualType ty, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr)
Create a temporary memory object for the given aggregate type.
RValue emitLoadOfExtVectorElementLValue(LValue lv)
mlir::Value emitCXXTypeidExpr(const CXXTypeidExpr *e)
mlir::Type convertTypeForMem(QualType t)
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, mlir::Location loc, clang::CharUnits alignment, bool insertIntoFnEntryBlock, mlir::Value arraySize=nullptr)
mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv)
void emitUnreachable(clang::SourceLocation loc, bool createNewBlock)
Emit a reached-unreachable diagnostic if loc is valid and runtime checking is enabled.
mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt)
void emitCXXConstructExpr(const clang::CXXConstructExpr *e, AggValueSlot dest)
mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc)
Load a complex number from the specified l-value.
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)
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
Push the standard destructor for the given type as at least a normal cleanup.
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
Address returnValue
The temporary alloca to hold the return value.
static bool hasAggregateEvaluationKind(clang::QualType type)
LValue emitPointerToDataMemberBinaryExpr(const BinaryOperator *e)
LValue emitUnaryOpLValue(const clang::UnaryOperator *e)
RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc)
LValue emitComplexAssignmentLValue(const BinaryOperator *e)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
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...
LValue emitCallExprLValue(const clang::CallExpr *e)
void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType, Address ptr)
Emits all the code to cause the given temporary to be cleaned up.
LValue emitStringLiteralLValue(const StringLiteral *e, llvm::StringRef name=".str")
mlir::Value getUndefConstant(mlir::Location loc, mlir::Type cirTy)
Return a CIR constant for an undefined value of cirTy.
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty)
Given a value and its clang type, returns the value casted to its memory representation.
LValue emitLValueForField(LValue base, const clang::FieldDecl *field)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
Address emitLoadOfReference(LValue refLVal, mlir::Location loc, LValueBaseInfo *pointeeBaseInfo)
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
LValue emitBinaryOperatorLValue(const BinaryOperator *e)
Address getAddrOfBitFieldStorage(LValue base, const clang::FieldDecl *field, mlir::Type fieldType, unsigned index)
void emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
mlir::MLIRContext & getMLIRContext()
LValue emitCastLValue(const CastExpr *e)
Casts are never lvalues unless that cast is to a reference type.
LValue emitCXXTypeidLValue(const CXXTypeidExpr *e)
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
LValue emitDeclRefLValue(const clang::DeclRefExpr *e)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
llvm::DenseMap< const clang::ValueDecl *, clang::FieldDecl * > lambdaCaptureFields
ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr)
Try to emit a reference to the given value without producing it as an l-value.
void emitCXXThrowExpr(const CXXThrowExpr *e)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
int64_t getAccessedFieldNo(unsigned idx, mlir::ArrayAttr elts)
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.
llvm::DenseMap< const OpaqueValueExpr *, RValue > opaqueRValues
Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo=nullptr)
void emitAtomicStore(RValue rvalue, LValue dest, bool isInit)
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
llvm::DenseMap< const OpaqueValueExpr *, LValue > opaqueLValues
Keeps track of the current set of opaque value expressions.
CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
void terminateStructuredRegionBody(mlir::Region &r, mlir::Location loc)
Address createMemTempWithoutCast(QualType t, mlir::Location loc, const Twine &name="tmp")
LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e)
LValue emitExtVectorElementExpr(const ExtVectorElementExpr *e)
clang::ASTContext & getContext() const
RValue emitCXXMemberOrOperatorMemberCallExpr(const clang::CallExpr *ce, const clang::CXXMethodDecl *md, ReturnValueSlot returnValue, bool hasQualifier, clang::NestedNameSpecifier qualifier, bool isArrow, const clang::Expr *base)
mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e)
RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot returnValue)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, bool isMustTail, mlir::Location loc)
RValue emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *e, const CXXMethodDecl *md, ReturnValueSlot returnValue)
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...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its RValue mapping if it exists, otherwise create one.
Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, mlir::OpBuilder::InsertPoint ip={})
This creates a alloca and inserts it into the entry block of the current region.
mlir::Value emitFromMemory(mlir::Value value, clang::QualType ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
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...
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e, const FuncTy &branchGenFunc)
Address createDefaultAlignTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name)
CreateDefaultAlignTempAlloca - This creates an alloca with the default alignment of the corresponding...
LValue emitCXXConstructLValue(const CXXConstructExpr *e)
RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr)
LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e)
CIRGenCallee emitCallee(const clang::Expr *e)
Address emitAddrOfFieldStorage(Address base, const FieldDecl *field, llvm::StringRef fieldName, unsigned fieldIndex)
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.
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd)
mlir::IntegerAttr getSize(CharUnits size)
CIRGenBuilderTy & getBuilder()
std::pair< cir::FuncType, cir::FuncOp > getAddrAndTypeOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
cir::GlobalOp getOrCreateCIRGlobal(llvm::StringRef mangledName, mlir::Type ty, LangAS langAS, const VarDecl *d, ForDefinition_t isForDefinition)
If the specified mangled name is not in the module, create and return an mlir::GlobalOp value.
cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
Return the address of the given function.
mlir::Operation * getAddrOfGlobalTemporary(const MaterializeTemporaryExpr *mte, const Expr *init)
Returns a pointer to a global variable representing a temporary with static or thread storage duratio...
mlir::Value getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty={}, ForDefinition_t isForDefinition=NotForDefinition)
Return the mlir::Value for the address of the given global variable.
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
This class handles record and union layout info while lowering AST types to CIR types.
cir::RecordType getCIRType() const
Return the "complete object" LLVM type associated with this record.
const CIRGenBitFieldInfo & getBitFieldInfo(const clang::FieldDecl *fd) const
Return the BitFieldInfo that corresponds to the field FD.
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
mlir::Attribute emitAbstract(const Expr *e, QualType destType)
Emit the result of the given expression as an abstract constant, asserting that it succeeded.
AlignmentSource getAlignmentSource() const
void mergeForCast(const LValueBaseInfo &info)
bool isExtVectorElt() const
mlir::Value getVectorPointer() const
const clang::Qualifiers & getQuals() const
mlir::Value getExtVectorPointer() const
bool isMatrixRow() const
static LValue makeExtVectorElt(Address vecAddress, mlir::ArrayAttr elts, clang::QualType type, LValueBaseInfo baseInfo)
mlir::Value getVectorIdx() const
bool isVectorElt() const
Address getAddress() const
static LValue makeAddr(Address address, clang::QualType t, LValueBaseInfo baseInfo)
mlir::ArrayAttr getExtVectorElts() const
bool isMatrixElt() const
static LValue makeVectorElt(Address vecAddress, mlir::Value index, clang::QualType t, LValueBaseInfo baseInfo)
RValue asAggregateRValue() const
unsigned getVRQualifiers() const
clang::QualType getType() const
static LValue makeBitfield(Address addr, const CIRGenBitFieldInfo &info, clang::QualType type, LValueBaseInfo baseInfo)
Create a new object to represent a bit-field access.
mlir::Value getPointer() const
bool isVolatileQualified() const
bool isBitField() const
Address getVectorAddress() const
clang::CharUnits getAlignment() const
LValueBaseInfo getBaseInfo() const
bool isNontemporal() const
bool isVolatile() const
const CIRGenBitFieldInfo & getBitFieldInfo() const
Address getBitFieldAddress() const
Address getExtVectorAddress() const
bool isSimple() const
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
Address getAggregateAddress() const
Return the value of the address of the aggregate.
Definition CIRGenValue.h:69
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
static RValue getComplex(mlir::Value v)
Definition CIRGenValue.h:91
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:57
bool isScalar() const
Definition CIRGenValue.h:49
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:260
Represents binding an expression to a temporary.
Definition ExprCXX.h:1496
CXXTemporary * getTemporary()
Definition ExprCXX.h:1514
const Expr * getSubExpr() const
Definition ExprCXX.h:1518
Represents a call to a C++ constructor.
Definition ExprCXX.h:1551
Represents a C++ destructor within a class.
Definition DeclCXX.h:2902
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:182
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
Definition DeclCXX.h:1377
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
Definition ExprCXX.h:851
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2954
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3158
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3137
Expr * getCallee()
Definition Expr.h:3101
arg_range arguments()
Definition Expr.h:3206
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1609
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3687
CastKind getCastKind() const
Definition Expr.h:3731
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
Definition Expr.h:3774
bool changesVolatileQualification() const
Return.
Definition Expr.h:3821
static const char * getCastKindName(CastKind CK)
Definition Expr.cpp:1959
Expr * getSubExpr()
Definition Expr.h:3737
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
Definition CharUnits.h:207
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Definition CharUnits.h:214
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3355
CompoundLiteralExpr - [C99 6.5.2.5].
Definition Expr.h:3616
bool isFileScope() const
Definition Expr.h:3648
const Expr * getInitializer() const
Definition Expr.h:3644
ConditionalOperator - The ?
Definition Expr.h:4402
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1281
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
Definition Expr.h:1485
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition Expr.cpp:494
ValueDecl * getDecl()
Definition Expr.h:1349
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:1479
SourceLocation getLocation() const
Definition Expr.h:1357
SourceLocation getLocation() const
Definition DeclBase.h:447
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition DeclBase.cpp:579
DeclContext * getDeclContext()
Definition DeclBase.h:456
bool hasAttr() const
Definition DeclBase.h:585
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:435
const Expr * getBase() const
Definition Expr.h:6598
This represents one expression.
Definition Expr.h:112
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
Definition Expr.cpp:85
bool isGLValue() const
Definition Expr.h:287
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:447
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3097
bool isPRValue() const
Definition Expr.h:285
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Decl * getReferencedDeclOfCallee()
Definition Expr.cpp:1552
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:144
ExtVectorElementExpr - This represents access to specific elements of a vector, and may occur on the ...
Definition Expr.h:6627
bool isArrow() const
isArrow - Return true if the base expression is a pointer to vector, return false if the base express...
Definition Expr.cpp:4449
void getEncodedElementAccess(SmallVectorImpl< uint32_t > &Elts) const
getEncodedElementAccess - Encode the elements accessed into an llvm aggregate Constant of ConstantInt...
Definition Expr.cpp:4562
Represents a member of a struct/union/class.
Definition Decl.h:3294
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3397
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4889
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3379
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3530
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
Definition Decl.cpp:4867
Represents a function declaration or definition.
Definition Decl.h:2058
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5421
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
const Decl * getDecl() const
Definition GlobalDecl.h:106
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4919
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition ExprCXX.h:4944
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4936
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
Definition ExprCXX.h:4969
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3375
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3458
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:3599
Expr * getBase() const
Definition Expr.h:3452
bool isArrow() const
Definition Expr.h:3559
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3570
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3767
This represents a decl that may have a name.
Definition Decl.h:274
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
A C++ nested-name-specifier augmented with source location information.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1189
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1239
bool isUnique() const
Definition Expr.h:1247
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3408
[C99 6.4.2.2] - A predefined identifier such as func.
Definition Expr.h:2016
StringRef getIdentKindName() const
Definition Expr.h:2073
PredefinedIdentKind getIdentKind() const
Definition Expr.h:2051
StringLiteral * getFunctionName()
Definition Expr.h:2060
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8544
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition TypeBase.h:1454
QualType withCVRQualifiers(unsigned CVR) const
Definition TypeBase.h:1195
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1561
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
unsigned getCVRQualifiers() const
Definition TypeBase.h:489
GC getObjCGCAttr() const
Definition TypeBase.h:520
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition TypeBase.h:355
@ OCL_None
There is no lifetime qualification on this type.
Definition TypeBase.h:351
void addCVRQualifiers(unsigned mask)
Definition TypeBase.h:503
void addQualifiers(Qualifiers Q)
Add the qualifiers from the given set to this set.
Definition TypeBase.h:651
Represents a struct/union/class.
Definition Decl.h:4459
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
Stmt - This represents one statement.
Definition Stmt.h:85
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1810
bool isUnion() const
Definition Decl.h:4062
Exposes information about the current target.
Definition TargetInfo.h:227
virtual StringRef getABI() const
Get the ABI currently in use.
bool isVoidType() const
Definition TypeBase.h:9113
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2319
bool isPackedVectorBoolType(const ASTContext &ctx) const
Definition Type.cpp:455
const ArrayType * castAsArrayTypeUnsafe() const
A variant of castAs<> for array type which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9416
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isArrayType() const
Definition TypeBase.h:8840
bool isFunctionPointerType() const
Definition TypeBase.h:8808
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
bool isArithmeticType() const
Definition Type.cpp:2452
bool isConstantMatrixType() const
Definition TypeBase.h:8908
bool isPointerType() const
Definition TypeBase.h:8741
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9407
bool isReferenceType() const
Definition TypeBase.h:8765
bool isVariableArrayType() const
Definition TypeBase.h:8852
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isExtVectorBoolType() const
Definition TypeBase.h:8888
bool isConstantMatrixBoolType() const
Definition TypeBase.h:8894
bool isAnyComplexType() const
Definition TypeBase.h:8876
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
Definition TypeBase.h:9293
bool isAtomicType() const
Definition TypeBase.h:8933
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2877
bool isFunctionType() const
Definition TypeBase.h:8737
bool isVectorType() const
Definition TypeBase.h:8880
bool isSubscriptableVectorType() const
Definition TypeBase.h:8900
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9340
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2255
SourceLocation getExprLoc() const
Definition Expr.h:2379
Expr * getSubExpr() const
Definition Expr.h:2296
Opcode getOpcode() const
Definition Expr.h:2291
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
Definition Expr.h:2330
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
bool hasInit() const
Definition Decl.cpp:2379
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
Definition Decl.cpp:2347
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1190
@ TLS_None
Not a TLS variable.
Definition Decl.h:952
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4080
Represents a GCC generic vector type.
Definition TypeBase.h:4289
Defines the clang::TargetInfo interface.
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute interface.
OverflowBehavior
AlignmentSource
The source of the alignment of an l-value; an expression of confidence in the alignment actually matc...
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...
static AlignmentSource getFieldAlignmentSource(AlignmentSource source)
Given that the base address has the given alignment source, what's our confidence in the alignment of...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< FunctionType > functionType
const internal::VariadicDynCastAllOfMatcher< Stmt, CUDAKernelCallExpr > cudaKernelCallExpr
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus
@ SC_Register
Definition Specifiers.h:258
@ SD_Thread
Thread storage duration.
Definition Specifiers.h:343
@ SD_Static
Static storage duration.
Definition Specifiers.h:344
@ SD_FullExpression
Full-expression storage duration (for temporaries).
Definition Specifiers.h:341
@ SD_Automatic
Automatic storage duration (most local variables).
Definition Specifiers.h:342
@ SD_Dynamic
Dynamic storage duration.
Definition Specifiers.h:345
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
U cast(CodeGen::Address addr)
Definition Address.h:327
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
Definition Specifiers.h:178
@ NOUR_Constant
This name appears as a potential result of an lvalue-to-rvalue conversion that is a constant expressi...
Definition Specifiers.h:181
static bool weakRefReference()
static bool objCLifetime()
static bool emitLifetimeMarkers()
static bool opLoadEmitScalarRangeCheck()
static bool addressSpace()
static bool opAllocaNonGC()
static bool opAllocaOpenMPThreadPrivate()
static bool preservedAccessIndexRegion()
static bool mergeAllConstants()
static bool opLoadStoreTbaa()
static bool opCallChain()
static bool opAllocaImpreciseLifetime()
static bool opAllocaStaticLocal()
static bool opAllocaTLS()
static bool emitCheckedInBoundsGEP()
static bool attributeNoBuiltin()
static bool setObjCGCLValueClass()
static bool cirgenABIInfo()
static bool opLoadStoreObjC()
static bool opCallArgEvaluationOrder()
static bool pointerAuthentication()
static bool insertBuiltinUnpredictable()
static bool shouldReverseUnaryCondOnBoolExpr()
static bool tryEmitAsConstant()
static bool addressIsKnownNonNull()
static bool astVarDeclInterface()
static bool cgCapturedStmtInfo()
static bool opAllocaEscapeByReference()
static bool opCallFnInfoOpts()
static bool generateDebugInfo()
static bool incrementProfileCounter()
Record with information about how a bitfield should be accessed.
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:657
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:659
bool HasSideEffects
Whether the evaluated expression has side effects.
Definition Expr.h:616
An adjustment to be made to the temporary created when emitting a reference binding,...
Definition Expr.h:68