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"
34#include <optional>
35
36using namespace clang;
37using namespace clang::CIRGen;
38using namespace cir;
39
40/// Get the address of a zero-sized field within a record. Zero-sized fields
41/// (e.g. empty bases with [[no_unique_address]]) don't appear in the CIR
42/// record layout, so we compute their address using the ASTContext field
43/// offset and byte-level pointer arithmetic instead of cir.get_member.
45 const FieldDecl *field) {
46 CIRGenBuilderTy &builder = cgf.getBuilder();
48 cgf.getContext().getFieldOffset(field));
49 mlir::Type fieldType = cgf.convertType(field->getType());
50
51 if (offset.isZero()) {
52 return Address(builder.createPtrBitcast(base.getPointer(), fieldType),
53 base.getAlignment());
54 }
55
56 // Cast to byte pointer, stride by the field offset, then cast to the
57 // field pointer type (CIR pointers are typed, so we need explicit casts
58 // unlike OG's opaque-pointer GEP).
59 mlir::Location loc = cgf.getLoc(field->getLocation());
60 mlir::Value addr =
61 builder.createPtrBitcast(base.getPointer(), builder.getUInt8Ty());
62 addr = builder.createPtrStride(loc, addr,
63 builder.getUInt64(offset.getQuantity(), loc));
64 addr = builder.createPtrBitcast(addr, fieldType);
65 return Address(addr, base.getAlignment().alignmentAtOffset(offset));
66}
67
69 const FieldDecl *field,
70 llvm::StringRef fieldName,
71 unsigned fieldIndex) {
72 // Retrieve layout information for both type resolution and alignment.
73 const RecordDecl *rec = field->getParent();
74 const CIRGenRecordLayout &layout = cgm.getTypes().getCIRGenRecordLayout(rec);
75
76 bool addressedByFieldIndex =
78 ? layout.hasCIRField(field)
80 if (!addressedByFieldIndex)
81 return emitAddrOfZeroSizeField(*this, base, field);
82
83 mlir::Location loc = getLoc(field->getLocation());
84 unsigned idx = layout.getCIRFieldNo(field);
85
86 // For potentially-overlapping fields (e.g. [[no_unique_address]]), the
87 // record stores the base subobject type (without tail padding) rather than
88 // the complete object type. Use the record's member type for get_member,
89 // then bitcast to the complete type for downstream use.
90 //
91 // For unions, all fields map to index 0, so we use the field's declared type
92 // directly instead of looking up the member type from the layout.
93 mlir::Type fieldType = convertType(field->getType());
94 auto fieldPtr = cir::PointerType::get(fieldType);
95 bool needsBitcast = false;
96
97 if (!rec->isUnion() && field->isPotentiallyOverlapping()) {
98 mlir::Type memberType = layout.getCIRType().getMembers()[idx];
99 fieldPtr = cir::PointerType::get(memberType);
100 needsBitcast = true;
101 }
102
103 // For most cases fieldName is the same as field->getName() but for lambdas,
104 // which do not currently carry the name, so it can be passed down from the
105 // CaptureStmt.
106 mlir::Value addr = builder.createGetMember(loc, fieldPtr, base.getPointer(),
107 fieldName, fieldIndex);
108
109 // If the field is potentially overlapping, the record member uses the base
110 // subobject type. Cast to the complete object pointer type expected by
111 // callers (analogous to OG's opaque pointer behavior).
112 if (needsBitcast)
113 addr = builder.createPtrBitcast(addr, fieldType);
114
116 layout.getCIRType().getElementOffset(cgm.getDataLayout().layout, idx));
117 return Address(addr, base.getAlignment().alignmentAtOffset(offset));
118}
119
120/// Given an expression of pointer type, try to
121/// derive a more accurate bound on the alignment of the pointer.
123 LValueBaseInfo *baseInfo) {
124 // We allow this with ObjC object pointers because of fragile ABIs.
125 assert(expr->getType()->isPointerType() ||
126 expr->getType()->isObjCObjectPointerType());
127 expr = expr->IgnoreParens();
128
129 // Casts:
130 if (auto const *ce = dyn_cast<CastExpr>(expr)) {
131 if (const auto *ece = dyn_cast<ExplicitCastExpr>(ce))
132 cgm.emitExplicitCastExprType(ece);
133
134 switch (ce->getCastKind()) {
135 // Non-converting casts (but not C's implicit conversion from void*).
136 case CK_BitCast:
137 case CK_NoOp:
138 case CK_AddressSpaceConversion: {
139 if (const auto *ptrTy =
140 ce->getSubExpr()->getType()->getAs<PointerType>()) {
141 if (ptrTy->getPointeeType()->isVoidType())
142 break;
143
144 LValueBaseInfo innerBaseInfo;
146 Address addr =
147 emitPointerWithAlignment(ce->getSubExpr(), &innerBaseInfo);
148 if (baseInfo)
149 *baseInfo = innerBaseInfo;
150
151 if (isa<ExplicitCastExpr>(ce)) {
152 LValueBaseInfo targetTypeBaseInfo;
153
154 const QualType pointeeType = expr->getType()->getPointeeType();
155 const CharUnits align =
156 cgm.getNaturalTypeAlignment(pointeeType, &targetTypeBaseInfo);
157
158 // If the source l-value is opaque, honor the alignment of the
159 // casted-to type.
160 if (innerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) {
161 if (baseInfo)
162 baseInfo->mergeForCast(targetTypeBaseInfo);
163 addr = Address(addr.getPointer(), addr.getElementType(), align);
164 }
165 }
166
168
169 const mlir::Type eltTy =
170 convertTypeForMem(expr->getType()->getPointeeType());
171 addr = getBuilder().createElementBitCast(getLoc(expr->getSourceRange()),
172 addr, eltTy);
174
175 return addr;
176 }
177 break;
178 }
179
180 // Array-to-pointer decay. TODO(cir): BaseInfo and TBAAInfo.
181 case CK_ArrayToPointerDecay:
182 return emitArrayToPointerDecay(ce->getSubExpr(), baseInfo);
183
184 case CK_UncheckedDerivedToBase:
185 case CK_DerivedToBase: {
188 Address addr = emitPointerWithAlignment(ce->getSubExpr(), baseInfo);
189 const CXXRecordDecl *derived =
190 ce->getSubExpr()->getType()->getPointeeCXXRecordDecl();
191 return getAddressOfBaseClass(addr, derived, ce->path(),
193 ce->getExprLoc());
194 }
195
196 case CK_AnyPointerToBlockPointerCast:
197 case CK_BaseToDerived:
198 case CK_BaseToDerivedMemberPointer:
199 case CK_BlockPointerToObjCPointerCast:
200 case CK_BuiltinFnToFnPtr:
201 case CK_CPointerToObjCPointerCast:
202 case CK_DerivedToBaseMemberPointer:
203 case CK_Dynamic:
204 case CK_FunctionToPointerDecay:
205 case CK_IntegralToPointer:
206 case CK_LValueToRValue:
207 case CK_LValueToRValueBitCast:
208 case CK_NullToMemberPointer:
209 case CK_NullToPointer:
210 case CK_ReinterpretMemberPointer:
211 case CK_UserDefinedConversion:
212 // Common pointer conversions, nothing to do here.
213 // TODO: Is there any reason to treat base-to-derived conversions
214 // specially?
215 break;
216
217 case CK_ARCConsumeObject:
218 case CK_ARCExtendBlockObject:
219 case CK_ARCProduceObject:
220 case CK_ARCReclaimReturnedObject:
221 case CK_AtomicToNonAtomic:
222 case CK_BooleanToSignedIntegral:
223 case CK_ConstructorConversion:
224 case CK_CopyAndAutoreleaseBlockObject:
225 case CK_Dependent:
226 case CK_FixedPointCast:
227 case CK_FixedPointToBoolean:
228 case CK_FixedPointToFloating:
229 case CK_FixedPointToIntegral:
230 case CK_FloatingCast:
231 case CK_FloatingComplexCast:
232 case CK_FloatingComplexToBoolean:
233 case CK_FloatingComplexToIntegralComplex:
234 case CK_FloatingComplexToReal:
235 case CK_FloatingRealToComplex:
236 case CK_FloatingToBoolean:
237 case CK_FloatingToFixedPoint:
238 case CK_FloatingToIntegral:
239 case CK_HLSLAggregateSplatCast:
240 case CK_HLSLArrayRValue:
241 case CK_HLSLElementwiseCast:
242 case CK_HLSLVectorTruncation:
243 case CK_HLSLMatrixTruncation:
244 case CK_IntToOCLSampler:
245 case CK_IntegralCast:
246 case CK_IntegralComplexCast:
247 case CK_IntegralComplexToBoolean:
248 case CK_IntegralComplexToFloatingComplex:
249 case CK_IntegralComplexToReal:
250 case CK_IntegralRealToComplex:
251 case CK_IntegralToBoolean:
252 case CK_IntegralToFixedPoint:
253 case CK_IntegralToFloating:
254 case CK_LValueBitCast:
255 case CK_MatrixCast:
256 case CK_MemberPointerToBoolean:
257 case CK_NonAtomicToAtomic:
258 case CK_ObjCObjectLValueCast:
259 case CK_PointerToBoolean:
260 case CK_PointerToIntegral:
261 case CK_ToUnion:
262 case CK_ToVoid:
263 case CK_VectorSplat:
264 case CK_ZeroToOCLOpaqueType:
265 // Classic codegen has a default that does nothing. In CIR, we are issuing
266 // a diagnostic so we can examine casts that are reached here to be sure
267 // no action is needed. If nothing is needed, the cast can be moved to the
268 // group above that does nothing.
269 cgm.errorNYI(ce->getSourceRange(),
270 "unexpected cast for emitPointerWithAlignment: ",
271 ce->getCastKindName());
272 break;
273 }
274 }
275
276 // Unary &
277 if (const UnaryOperator *uo = dyn_cast<UnaryOperator>(expr)) {
278 // TODO(cir): maybe we should use a CIR unary op for pointers here instead.
279 if (uo->getOpcode() == UO_AddrOf) {
280 LValue lv = emitLValue(uo->getSubExpr());
281 if (baseInfo)
282 *baseInfo = lv.getBaseInfo();
284 return lv.getAddress();
285 }
286 }
287
288 // std::addressof and variants.
289 if (auto const *call = dyn_cast<CallExpr>(expr)) {
290 switch (call->getBuiltinCallee()) {
291 default:
292 break;
293 case Builtin::BIaddressof:
294 case Builtin::BI__addressof:
295 case Builtin::BI__builtin_addressof: {
296 LValue lv = emitLValue(call->getArg(0));
297 if (baseInfo)
298 *baseInfo = lv.getBaseInfo();
300 return lv.getAddress();
301 }
302 }
303 }
304
305 // Otherwise, use the alignment of the type.
307 emitScalarExpr(expr), expr->getType()->getPointeeType(), CharUnits(),
308 /*forPointeeType=*/true, baseInfo);
309}
310
312 LValue dst) {
313 auto getScalarSizeInBits = [&](mlir::Type ty) -> unsigned {
314 mlir::Type scalarTy = mlir::isa<cir::VectorType>(ty)
315 ? mlir::cast<cir::VectorType>(ty).getElementType()
316 : ty;
317 cir::CIRDataLayout dl = cgm.getDataLayout();
318 return dl.getTypeSizeInBits(scalarTy).getFixedValue();
319 };
320
321 mlir::Value srcVal = src.getValue();
322 Address dstAddr = dst.getExtVectorAddress();
323 if (getScalarSizeInBits(dstAddr.getElementType()) >
324 getScalarSizeInBits(srcVal.getType())) {
325 cgm.errorNYI(
326 dst.getPointer().getLoc(),
327 "emitStoreThroughExtVectorComponentLValue: dstTySize > srcTysize");
328 return;
329 }
330
331 if (getLangOpts().HLSL) {
332 cgm.errorNYI(dst.getPointer().getLoc(),
333 "emitStoreThroughExtVectorComponentLValue: HLSL");
334 return;
335 }
336
337 // This access turns into a read/modify/write of the vector. Load the input
338 // value now.
339 mlir::Location loc = dst.getExtVectorPointer().getLoc();
340
341 mlir::ArrayAttr elts = dst.getExtVectorElts();
342
343 mlir::Value vec = builder.createLoad(loc, dstAddr, dst.isVolatile());
344 if (const auto *vecTy = dst.getType()->getAs<clang::VectorType>()) {
345 unsigned numSrcElts = vecTy->getNumElements();
346 unsigned numDstElts = cast<cir::VectorType>(vec.getType()).getSize();
347 if (numDstElts == numSrcElts) {
348 // Use shuffle vector is the src and destination are the same number of
349 // elements and restore the vector mask since it is on the side it will be
350 // stored.
351 SmallVector<int64_t> mask(numDstElts);
352 for (unsigned i = 0; i != numDstElts; ++i)
353 mask[getAccessedFieldNo(i, elts)] = i;
354
355 vec = builder.createVecShuffle(loc, srcVal, mask);
356 } else if (numDstElts > numSrcElts) {
357 // Extended the source vector to the same length and then shuffle it
358 // into the destination.
359 // FIXME: since we're shuffling with undef, can we just use the indices
360 // into that? This could be simpler.
361 SmallVector<int64_t> extMask(numDstElts, -1);
362 std::iota(extMask.begin(), extMask.begin() + numSrcElts, 0);
363
364 mlir::Value extSrcVal = builder.createVecShuffle(loc, srcVal, extMask);
365
366 // build identity
367 SmallVector<int64_t> mask(numDstElts);
368 std::iota(mask.begin(), mask.begin() + numDstElts, 0);
369
370 // When the vector size is odd and .odd or .hi is used, the last element
371 // of the Elts constant array will be one past the size of the vector.
372 // Ignore the last element here, if it is greater than the mask size.
373 if ((unsigned)getAccessedFieldNo(numSrcElts - 1, elts) == mask.size())
374 numSrcElts--;
375
376 // modify when what gets shuffled in
377 for (unsigned i = 0; i != numSrcElts; ++i)
378 mask[getAccessedFieldNo(i, elts)] = i + numDstElts;
379
380 vec = builder.createVecShuffle(loc, vec, extSrcVal, mask);
381 } else {
382 // We should never shorten the vector
383 llvm_unreachable("unexpected shorten vector length");
384 }
385 } else {
386 // If the Src is a scalar (not a vector), and the target is a vector it
387 // must be updating one element.
388 unsigned inIdx = getAccessedFieldNo(0, elts);
389 cir::ConstantOp elt = builder.getSInt64(inIdx, loc);
390 vec = cir::VecInsertOp::create(builder, loc, vec, srcVal, elt);
391 }
392
393 builder.createStore(loc, vec, dst.getExtVectorAddress(),
394 dst.isVolatileQualified());
395}
396
398 bool isInit) {
399 if (!dst.isSimple()) {
400 if (dst.isVectorElt()) {
401 // Read/modify/write the vector, inserting the new element
402 const mlir::Location loc = dst.getVectorPointer().getLoc();
403 const mlir::Value vector =
404 builder.createLoad(loc, dst.getVectorAddress());
405 const mlir::Value newVector = cir::VecInsertOp::create(
406 builder, loc, vector, src.getValue(), dst.getVectorIdx());
407 builder.createStore(loc, newVector, dst.getVectorAddress());
408 return;
409 }
410
411 if (dst.isExtVectorElt())
413
414 if (dst.isMatrixElt()) {
415 cgm.errorNYI("emitStoreThroughLValue: !dst.isSimple() && isMatrixElt");
416 return;
417 }
418
419 if (dst.isMatrixRow()) {
420 cgm.errorNYI("emitStoreThroughLValue: !dst.isSimple() && isMatrixRow");
421 return;
422 }
423
424 assert(dst.isBitField() && "Unknown LValue type");
426 return;
427 }
428
431
432 assert(src.isScalar() && "Can't emit an aggregate store with this method");
433 emitStoreOfScalar(src.getValue(), dst, isInit);
434}
435
436static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e,
437 const VarDecl *vd) {
438 QualType t = e->getType();
439
440 // In classic codegen, thread-locals get a wrapper function here. Rather than
441 // doing that, we instead treat this as a normal 'global', and leave it to
442 // lowerng-prepare to correctly generate the wrapper/etc.
443
444 // Check if the variable is marked as declare target with link clause in
445 // device codegen.
446 if (cgf.getLangOpts().OpenMP)
447 cgf.cgm.errorNYI(e->getSourceRange(), "emitGlobalVarDeclLValue: OpenMP");
448
449 // Traditional LLVM codegen handles thread local separately, CIR handles
450 // as part of getAddrOfGlobalVar.
451 mlir::Value v = cgf.cgm.getAddrOfGlobalVar(vd);
452
453 mlir::Type realVarTy = cgf.convertTypeForMem(vd->getType());
454 cir::PointerType realPtrTy = cir::PointerType::get(
455 realVarTy, mlir::cast<cir::PointerType>(v.getType()).getAddrSpace());
456 if (realPtrTy != v.getType())
457 v = cgf.getBuilder().createBitcast(v.getLoc(), v, realPtrTy);
458
459 CharUnits alignment = cgf.getContext().getDeclAlign(vd);
460 Address addr(v, realVarTy, alignment);
461 LValue lv;
462 if (vd->getType()->isReferenceType())
463 lv = cgf.emitLoadOfReferenceLValue(addr, cgf.getLoc(e->getSourceRange()),
465 else
466 lv = cgf.makeAddrLValue(addr, t, AlignmentSource::Decl);
468 return lv;
469}
470
471void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
472 bool isVolatile, QualType ty,
473 LValueBaseInfo baseInfo, bool isInit,
474 bool isNontemporal) {
475
476 if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) {
477 // Handle vectors of size 3 like size 4 for better performance.
478 // TODO(CIR): Use `ABIInfo::getOptimalVectorMemoryType` once it upstreamed
480 if (clangVecTy->getNumElements() == 3 && !getLangOpts().PreserveVec3Type)
481 cgm.errorNYI(addr.getPointer().getLoc(),
482 "emitStoreOfScalar Vec3 & PreserveVec3Type disabled");
483 }
484
485 value = emitToMemory(value, ty);
486
488 LValue atomicLValue = LValue::makeAddr(addr, ty, baseInfo);
489 if (ty->isAtomicType() ||
490 (!isInit && isLValueSuitableForInlineAtomic(atomicLValue))) {
491 emitAtomicStore(RValue::get(value), atomicLValue, isInit);
492 return;
493 }
494
495 // Update the alloca with more info on initialization.
496 assert(addr.getPointer() && "expected pointer to exist");
497 cir::AllocaOp srcAlloca = addr.getUnderlyingAllocaOp();
498 if (currVarDecl && srcAlloca) {
499 const VarDecl *vd = currVarDecl;
500 assert(vd && "VarDecl expected");
501 if (vd->hasInit())
502 srcAlloca.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
503 }
504
505 assert(currSrcLoc && "must pass in source location");
506 builder.createStore(*currSrcLoc, value, addr, isVolatile, isNontemporal);
507
509}
510
512 LValue dst) {
513
514 const CIRGenBitFieldInfo &info = dst.getBitFieldInfo();
515 mlir::Type resLTy = convertTypeForMem(dst.getType());
516 Address ptr = dst.getBitFieldAddress();
517
518 bool useVoaltile =
519 cgm.getCodeGenOpts().AAPCSBitfieldWidth && dst.isVolatileQualified() &&
520 info.volatileStorageSize != 0 && CodeGenUtils::isAAPCS(cgm.getTarget());
521
522 assert(currSrcLoc && "must pass in source location");
523
524 return builder.createSetBitfield(*currSrcLoc, resLTy, ptr,
525 ptr.getElementType(), src.getValue(), info,
526 dst.isVolatileQualified(), useVoaltile);
527}
528
530 const CIRGenBitFieldInfo &info = lv.getBitFieldInfo();
531
532 // Get the output type.
533 mlir::Type resLTy = convertType(lv.getType());
534 Address ptr = lv.getBitFieldAddress();
535
536 bool useVoaltile = lv.isVolatileQualified() && info.volatileOffset != 0 &&
537 CodeGenUtils::isAAPCS(cgm.getTarget());
538
539 mlir::Value field =
540 builder.createGetBitfield(getLoc(loc), resLTy, ptr, ptr.getElementType(),
541 info, lv.isVolatile(), useVoaltile);
543 return RValue::get(field);
544}
545
547 const FieldDecl *field,
548 mlir::Type fieldType,
549 unsigned index) {
550 mlir::Location loc = getLoc(field->getLocation());
551 cir::PointerType fieldPtr = cir::PointerType::get(fieldType);
553 cir::GetMemberOp sea = getBuilder().createGetMember(
554 loc, fieldPtr, base.getPointer(), field->getName(),
555 mlir::isa<cir::UnionType>(rec) ? field->getFieldIndex() : index);
557 rec.getElementOffset(cgm.getDataLayout().layout, index));
558 return Address(sea, base.getAlignment().alignmentAtOffset(offset));
559}
560
562 const FieldDecl *field) {
563 LValueBaseInfo baseInfo = base.getBaseInfo();
564 const CIRGenRecordLayout &layout =
565 cgm.getTypes().getCIRGenRecordLayout(field->getParent());
566 const CIRGenBitFieldInfo &info = layout.getBitFieldInfo(field);
567
569
570 unsigned idx = layout.getCIRFieldNo(field);
571 Address addr = getAddrOfBitFieldStorage(base, field, info.storageType, idx);
572
573 mlir::Location loc = getLoc(field->getLocation());
574 if (addr.getElementType() != info.storageType)
575 addr = builder.createElementBitCast(loc, addr, info.storageType);
576
577 QualType fieldType =
579 // TODO(cir): Support TBAA for bit fields.
581 LValueBaseInfo fieldBaseInfo(baseInfo.getAlignmentSource());
582 return LValue::makeBitfield(addr, info, fieldType, fieldBaseInfo);
583}
584
586 LValueBaseInfo baseInfo = base.getBaseInfo();
587
588 if (field->isBitField())
589 return emitLValueForBitField(base, field);
590
591 QualType fieldType = field->getType();
592 const RecordDecl *rec = field->getParent();
593 AlignmentSource baseAlignSource = baseInfo.getAlignmentSource();
594 LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(baseAlignSource));
596
597 Address addr = base.getAddress();
598 if (auto *classDecl = dyn_cast<CXXRecordDecl>(rec)) {
599 if (cgm.getCodeGenOpts().StrictVTablePointers &&
600 classDecl->isDynamicClass()) {
601 cgm.errorNYI(field->getSourceRange(),
602 "emitLValueForField: strict vtable for dynamic class");
603 }
604 }
605
606 unsigned recordCVR = base.getVRQualifiers();
607
608 llvm::StringRef fieldName = field->getName();
609 unsigned fieldIndex;
610 if (cgm.lambdaFieldToName.count(field))
611 fieldName = cgm.lambdaFieldToName[field];
612
613 // Fields with no CIR field index (e.g. a [[no_unique_address]] field that
614 // is empty for both layout and the ABI) aren't in the record layout, so
615 // handle them separately: use the base address directly with the right
616 // type instead of get_member.
617 const CIRGenRecordLayout &layout =
618 cgm.getTypes().getCIRGenRecordLayout(field->getParent());
619 if (!rec->isUnion() && !layout.hasCIRField(field)) {
620 addr = emitAddrOfZeroSizeField(*this, addr, field);
621 LValue lv = makeAddrLValue(addr, fieldType, fieldBaseInfo);
622 lv.getQuals().addCVRQualifiers(recordCVR);
623 return lv;
624 }
625
626 if (rec->isUnion())
627 fieldIndex = field->getFieldIndex();
628 else
629 fieldIndex = layout.getCIRFieldNo(field);
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 const CIRGenRecordLayout &layout =
675 cgm.getTypes().getCIRGenRecordLayout(field->getParent());
676 if (!layout.hasCIRField(field)) {
677 v = emitAddrOfZeroSizeField(*this, v, field);
678 } else {
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 instead emits the
1927 // destruction into the dtor region of whatever destroys the variable that
1928 // extended the temporary: the cir.global's own region at namespace scope,
1929 // and the enclosing cir.local_init's for a function-local static, which the
1930 // verifier requires to be destroyed in-function under its guard.
1931 CIRGenModule &cgm = cgf.cgm;
1932 auto globalOp =
1933 mlir::cast<cir::GlobalOp>(cgm.getAddrOfGlobalTemporary(m, e));
1934
1935 mlir::Region *dtorRegion = cgf.curStaticVarDtorRegion;
1936 assert(dtorRegion && "temporary extended outside a static initializer");
1937
1938 CIRGenBuilderTy &builder = cgm.getBuilder();
1939 mlir::OpBuilder::InsertionGuard guard(builder);
1940 mlir::Location loc = cgm.getLoc(m->getSourceRange());
1941
1942 // Temporaries are destroyed in reverse order of construction, so each one
1943 // goes in front of those registered before it.
1944 if (dtorRegion->empty()) {
1945 builder.setInsertionPointToStart(builder.createBlock(dtorRegion));
1946 cir::YieldOp::create(builder, loc);
1947 }
1948 builder.setInsertionPointToStart(&dtorRegion->front());
1949
1950 mlir::Value tempAddr = builder.createGetGlobal(globalOp);
1951
1952 if (e->getType()->isArrayType()) {
1953 // emitDestroy will produce a cir.array.dtor here. LoweringPrepare's
1954 // getOrCreateDtorFunc recognizes the non-trivial dtor region and
1955 // hoists it into a __cxx_global_array_dtor helper.
1956 Address addr{tempAddr, cgf.convertTypeForMem(e->getType()),
1957 referenceTemporary.getAlignment()};
1959 } else {
1960 GlobalDecl gd(referenceTemporaryDtor, Dtor_Complete);
1961 cir::FuncOp dtorFn = cgm.getAddrAndTypeOfCXXStructor(gd).second;
1962 builder.createCallOp(loc, dtorFn, mlir::ValueRange{tempAddr});
1963 }
1964 break;
1965 }
1966
1967 case SD_FullExpression:
1968 cgf.pushDestroy(NormalAndEHCleanup, referenceTemporary, e->getType(),
1970 break;
1971
1972 case SD_Automatic:
1974 NormalAndEHCleanup, referenceTemporary, e->getType(),
1976 break;
1977
1978 case SD_Dynamic:
1979 llvm_unreachable("temporary cannot have dynamic storage duration");
1980 }
1981}
1982
1984 const MaterializeTemporaryExpr *m) {
1985 const Expr *e = m->getSubExpr();
1986
1987 assert((!m->getExtendingDecl() || !isa<VarDecl>(m->getExtendingDecl()) ||
1988 !cast<VarDecl>(m->getExtendingDecl())->isARCPseudoStrong()) &&
1989 "Reference should never be pseudo-strong!");
1990
1991 // FIXME: ideally this would use emitAnyExprToMem, however, we cannot do so
1992 // as that will cause the lifetime adjustment to be lost for ARC
1993 auto ownership = m->getType().getObjCLifetime();
1994 if (ownership != Qualifiers::OCL_None &&
1995 ownership != Qualifiers::OCL_ExplicitNone) {
1996 cgm.errorNYI(e->getSourceRange(),
1997 "emitMaterializeTemporaryExpr: ObjCLifetime");
1998 return {};
1999 }
2000
2003 e = e->skipRValueSubobjectAdjustments(commaLHSs, adjustments);
2004
2005 for (const Expr *ignored : commaLHSs)
2006 emitIgnoredExpr(ignored);
2007
2008 if (isa<OpaqueValueExpr>(e)) {
2009 cgm.errorNYI(e->getSourceRange(),
2010 "emitMaterializeTemporaryExpr: OpaqueValueExpr");
2011 return {};
2012 }
2013
2014 // Create and initialize the reference temporary.
2015 Address object = createReferenceTemporary(*this, m, e);
2016 cir::GlobalOp var = nullptr;
2017 if (auto getGlobalOp = object.getPointer().getDefiningOp<cir::GetGlobalOp>())
2018 var = mlir::dyn_cast_or_null<cir::GlobalOp>(
2019 cgm.getGlobalValue(getGlobalOp.getName()));
2020
2021 if (var) {
2022 if (!var.getInitialValue().has_value()) {
2023 var.setInitialValueAttr(builder.getZeroInitAttr(var.getSymType()));
2025 emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);
2026 }
2027 } else {
2029 emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);
2030 }
2031 pushTemporaryCleanup(*this, m, e, object);
2032
2033 // Perform derived-to-base casts and/or field accesses, to get from the
2034 // temporary object we created (and, potentially, for which we extended
2035 // the lifetime) to the subobject we're binding the reference to.
2036 for (SubobjectAdjustment &adjustment : llvm::reverse(adjustments)) {
2037 switch (adjustment.Kind) {
2039 object =
2040 getAddressOfBaseClass(object, adjustment.DerivedToBase.DerivedClass,
2041 adjustment.DerivedToBase.BasePath->path(),
2042 /*nullCheckValue=*/false, e->getExprLoc());
2043 break;
2046 lv = emitLValueForField(lv, adjustment.Field);
2047 assert(lv.isSimple() &&
2048 "materialized temporary field is not a simple lvalue");
2049 object = lv.getAddress();
2050 break;
2051 }
2053 mlir::Value ptr = emitScalarExpr(adjustment.Ptr.RHS);
2055 e, object, ptr, adjustment.Ptr.MPT, /*baseInfo=*/nullptr);
2056 break;
2057 }
2058 }
2059 }
2060
2061 return makeAddrLValue(object, m->getType(), AlignmentSource::Decl);
2062}
2063
2064LValue
2067
2068 auto it = opaqueLValues.find(e);
2069 if (it != opaqueLValues.end())
2070 return it->second;
2071
2072 assert(e->isUnique() && "LValue for a nonunique OVE hasn't been emitted");
2073 return emitLValue(e->getSourceExpr());
2074}
2075
2076RValue
2079
2080 auto it = opaqueRValues.find(e);
2081 if (it != opaqueRValues.end())
2082 return it->second;
2083
2084 assert(e->isUnique() && "RValue for a nonunique OVE hasn't been emitted");
2085 return emitAnyExpr(e->getSourceExpr());
2086}
2087
2089 if (e->isFileScope()) {
2090 cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope");
2091 return {};
2092 }
2093
2094 if (e->getType()->isVariablyModifiedType())
2096
2097 Address declPtr = createMemTemp(e->getType(), getLoc(e->getSourceRange()),
2098 ".compoundliteral");
2099 const Expr *initExpr = e->getInitializer();
2100 LValue result = makeAddrLValue(declPtr, e->getType(), AlignmentSource::Decl);
2101
2102 emitAnyExprToMem(initExpr, declPtr, e->getType().getQualifiers(),
2103 /*Init*/ true);
2104
2105 // Block-scope compound literals are destroyed at the end of the enclosing
2106 // scope in C.
2107 if (!getLangOpts().CPlusPlus && e->getType().isDestructedType()) {
2108 cgm.errorNYI(e->getSourceRange(),
2109 "emitCompoundLiteralLValue: non C++ DestructedType");
2110 return {};
2111 }
2112
2113 return result;
2114}
2115
2117 RValue rv = emitCallExpr(e);
2118
2119 if (!rv.isScalar())
2120 return makeAddrLValue(rv.getAggregateAddress(), e->getType(),
2122
2123 assert(e->getCallReturnType(getContext())->isReferenceType() &&
2124 "Can't have a scalar return unless the return type is a "
2125 "reference type!");
2126
2128}
2129
2130LValue
2139
2142 "binding l-value to type which needs a temporary");
2144 emitCXXConstructExpr(e, slot);
2146}
2147
2149 // Comma expressions just emit their LHS then their RHS as an l-value.
2150 if (e->getOpcode() == BO_Comma) {
2151 emitIgnoredExpr(e->getLHS());
2152 return emitLValue(e->getRHS());
2153 }
2154
2155 if (e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI)
2157
2158 assert(e->getOpcode() == BO_Assign && "unexpected binary l-value");
2159
2160 // Note that in all of these cases, __block variables need the RHS
2161 // evaluated first just in case the variable gets moved by the RHS.
2162
2164 case cir::TEK_Scalar: {
2166 if (e->getLHS()->getType().getObjCLifetime() !=
2168 cgm.errorNYI(e->getSourceRange(), "objc lifetimes");
2169 return {};
2170 }
2171
2172 RValue rv = emitAnyExpr(e->getRHS());
2173 LValue lv = emitLValue(e->getLHS());
2174
2175 SourceLocRAIIObject loc{*this, getLoc(e->getSourceRange())};
2176 if (lv.isBitField())
2178 else
2179 emitStoreThroughLValue(rv, lv);
2180
2181 if (getLangOpts().OpenMP) {
2182 cgm.errorNYI(e->getSourceRange(), "openmp");
2183 return {};
2184 }
2185
2186 return lv;
2187 }
2188
2189 case cir::TEK_Complex: {
2191 }
2192
2193 case cir::TEK_Aggregate:
2194 cgm.errorNYI(e->getSourceRange(), "aggregate lvalues");
2195 return {};
2196 }
2197 llvm_unreachable("bad evaluation kind");
2198}
2199
2200/// Emit code to compute the specified expression which
2201/// can have any type. The result is returned as an RValue struct.
2203 bool ignoreResult) {
2205 case cir::TEK_Scalar:
2206 return RValue::get(emitScalarExpr(e, ignoreResult));
2207 case cir::TEK_Complex:
2209 case cir::TEK_Aggregate: {
2210 if (!ignoreResult && aggSlot.isIgnored())
2211 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
2213 emitAggExpr(e, aggSlot);
2214 return aggSlot.asRValue();
2215 }
2216 }
2217 llvm_unreachable("bad evaluation kind");
2218}
2219
2220// Detect the unusual situation where an inline version is shadowed by a
2221// non-inline version. In that case we should pick the external one
2222// everywhere. That's GCC behavior too.
2224 for (const FunctionDecl *pd = fd; pd; pd = pd->getPreviousDecl())
2225 if (!pd->isInlineBuiltinDeclaration())
2226 return false;
2227 return true;
2228}
2229
2230CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {
2231 const auto *fd = cast<FunctionDecl>(gd.getDecl());
2232
2233 if (unsigned builtinID = fd->getBuiltinID()) {
2234 StringRef ident = cgm.getMangledName(gd);
2235 std::string fdInlineName = (ident + ".inline").str();
2236
2237 bool isPredefinedLibFunction =
2238 cgm.getASTContext().BuiltinInfo.isPredefinedLibFunction(builtinID);
2239 // TODO: Read no-builtin function attribute and set this accordingly.
2240 // Using false here matches OGCG's default behavior - builtins are called
2241 // as builtins unless explicitly disabled. The previous value of true was
2242 // overly conservative and caused functions to be marked as no_inline when
2243 // they shouldn't be.
2244 bool hasAttributeNoBuiltin = false;
2246
2247 // When directly calling an inline builtin, call it through it's mangled
2248 // name to make it clear it's not the actual builtin.
2249 if (auto fn = dyn_cast<cir::FuncOp>(curFn);
2250 (!fn || fn.getName() != fdInlineName) &&
2252 cir::FuncOp clone =
2253 mlir::cast_or_null<cir::FuncOp>(cgm.getGlobalValue(fdInlineName));
2254
2255 if (!clone) {
2256 // Create a forward declaration - the body will be generated in
2257 // generateCode when the function definition is processed
2258 cir::FuncOp calleeFunc = emitFunctionDeclPointer(cgm, gd);
2259 mlir::OpBuilder::InsertionGuard guard(builder);
2260 builder.setInsertionPointToStart(cgm.getModule().getBody());
2261
2262 clone = cir::FuncOp::create(builder, calleeFunc.getLoc(), fdInlineName,
2263 calleeFunc.getFunctionType());
2264 cgm.insertGlobalSymbol(clone);
2265 clone.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
2266 &cgm.getMLIRContext(), cir::GlobalLinkageKind::InternalLinkage));
2267 clone.setSymVisibility("private");
2268 clone.setInlineKind(cir::InlineKind::AlwaysInline);
2269 }
2270 return CIRGenCallee::forDirect(clone, gd);
2271 }
2272
2273 // Replaceable builtins provide their own implementation of a builtin. If we
2274 // are in an inline builtin implementation, avoid trivial infinite
2275 // recursion. Honor __attribute__((no_builtin("foo"))) or
2276 // __attribute__((no_builtin)) on the current function unless foo is
2277 // not a predefined library function which means we must generate the
2278 // builtin no matter what.
2279 else if (!isPredefinedLibFunction || !hasAttributeNoBuiltin)
2280 return CIRGenCallee::forBuiltin(builtinID, fd);
2281 }
2282
2283 cir::FuncOp callee = emitFunctionDeclPointer(cgm, gd);
2284
2285 if ((cgm.getLangOpts().CUDA || cgm.getLangOpts().HIP) &&
2286 !cgm.getLangOpts().CUDAIsDevice && fd->hasAttr<CUDAGlobalAttr>()) {
2287 mlir::Operation *handle = cgm.getCUDARuntime().getKernelHandle(callee, gd);
2288 callee =
2289 mlir::cast<cir::FuncOp>(*cgm.getCUDARuntime().getKernelStub(handle));
2290 }
2291
2292 return CIRGenCallee::forDirect(callee, gd);
2293}
2294
2295mlir::Value CIRGenFunction::getUndefConstant(mlir::Location loc,
2296 mlir::Type cirTy) {
2297 return builder.getConstant(loc, cir::UndefAttr::get(cirTy));
2298}
2299
2301 if (ty->isVoidType())
2302 return RValue::get(nullptr);
2303
2304 mlir::Location loc = builder.getUnknownLoc();
2305
2306 switch (getEvaluationKind(ty)) {
2307 case cir::TEK_Complex: {
2308 QualType elemTy = ty->castAs<ComplexType>()->getElementType();
2309 mlir::Type elemCirTy = convertType(elemTy);
2310 mlir::Value undefElem = getUndefConstant(loc, elemCirTy);
2311 mlir::Value v = builder.createComplexCreate(loc, undefElem, undefElem);
2312 return RValue::getComplex(v);
2313 }
2314
2315 // If this is a use of an undefined aggregate type, the aggregate must have
2316 // an identifiable address. Just because the contents of the value are
2317 // undefined doesn't mean that the address can't be taken and compared.
2318 case cir::TEK_Aggregate: {
2319 Address destPtr = createMemTempWithoutCast(ty, loc, "undef.agg.tmp");
2320 return RValue::getAggregate(destPtr);
2321 }
2322
2323 case cir::TEK_Scalar:
2324 return RValue::get(getUndefConstant(loc, convertType(ty)));
2325 }
2326 llvm_unreachable("bad evaluation kind");
2327}
2328
2330 const CIRGenCallee &origCallee,
2331 const clang::CallExpr *e,
2333 // Get the actual function type. The callee type will always be a pointer to
2334 // function type or a block pointer type.
2335 assert(calleeTy->isFunctionPointerType() &&
2336 "Callee must have function pointer type!");
2337
2338 calleeTy = getContext().getCanonicalType(calleeTy);
2339 auto pointeeTy = cast<PointerType>(calleeTy)->getPointeeType();
2340
2341 CIRGenCallee callee = origCallee;
2342
2343 if (getLangOpts().CPlusPlus)
2345
2346 const auto *fnType = cast<FunctionType>(pointeeTy);
2347
2349
2350 CallArgList args;
2352
2353 // C++23 static-member operators (`static operator()` /
2354 // `static operator[]`) produce a CXXOperatorCallExpr whose first argument
2355 // is the object expression even though the operator is static. Emit the
2356 // object for its side effects and drop it before walking the parameter
2357 // arguments.
2358 auto arguments = e->arguments();
2359 if (const auto *oce = dyn_cast<CXXOperatorCallExpr>(e)) {
2360 if (const auto *md =
2361 dyn_cast_if_present<CXXMethodDecl>(oce->getCalleeDecl());
2362 md && md->isStatic()) {
2363 emitIgnoredExpr(e->getArg(0));
2364 arguments = llvm::drop_begin(arguments, 1);
2365 }
2366 }
2367
2368 emitCallArgs(args, dyn_cast<FunctionProtoType>(fnType), arguments,
2369 e->getDirectCallee());
2370
2371 const CIRGenFunctionInfo &funcInfo =
2372 cgm.getTypes().arrangeFreeFunctionCall(args, fnType);
2373
2374 // C99 6.5.2.2p6:
2375 // If the expression that denotes the called function has a type that does
2376 // not include a prototype, [the default argument promotions are performed].
2377 // If the number of arguments does not equal the number of parameters, the
2378 // behavior is undefined. If the function is defined with a type that
2379 // includes a prototype, and either the prototype ends with an ellipsis (,
2380 // ...) or the types of the arguments after promotion are not compatible
2381 // with the types of the parameters, the behavior is undefined. If the
2382 // function is defined with a type that does not include a prototype, and
2383 // the types of the arguments after promotion are not compatible with those
2384 // of the parameters after promotion, the behavior is undefined [except in
2385 // some trivial cases].
2386 // That is, in the general case, we should assume that a call through an
2387 // unprototyped function type works like a *non-variadic* call. The way we
2388 // make this work is to cast to the exxact type fo the promoted arguments.
2389 if (isa<FunctionNoProtoType>(fnType)) {
2392 cir::FuncType calleeTy = getTypes().getFunctionType(funcInfo);
2393 // get non-variadic function type
2394 calleeTy = cir::FuncType::get(calleeTy.getInputs(),
2395 calleeTy.getReturnType(), false);
2396 auto calleePtrTy = cir::PointerType::get(calleeTy);
2397
2398 mlir::Operation *fn = callee.getFunctionPointer();
2399 mlir::Value addr;
2400 if (auto funcOp = mlir::dyn_cast<cir::FuncOp>(fn)) {
2401 addr = cir::GetGlobalOp::create(
2402 builder, getLoc(e->getSourceRange()),
2403 cir::PointerType::get(funcOp.getFunctionType()), funcOp.getSymName());
2404 } else {
2405 addr = fn->getResult(0);
2406 }
2407
2408 fn = builder.createBitcast(addr, calleePtrTy).getDefiningOp();
2409 callee.setFunctionPointer(fn);
2410 }
2411
2413 assert(!cir::MissingFeatures::hip());
2414
2415 cir::CIRCallOpInterface callOp;
2416 RValue callResult = emitCall(funcInfo, callee, returnValue, args, &callOp,
2417 e == mustTailCall, getLoc(e->getExprLoc()));
2418
2420
2421 return callResult;
2422}
2423
2425 e = e->IgnoreParens();
2426
2427 // Look through function-to-pointer decay.
2428 if (const auto *implicitCast = dyn_cast<ImplicitCastExpr>(e)) {
2429 if (implicitCast->getCastKind() == CK_FunctionToPointerDecay ||
2430 implicitCast->getCastKind() == CK_BuiltinFnToFnPtr) {
2431 return emitCallee(implicitCast->getSubExpr());
2432 }
2433 // Classic codegen has some handling here for ptr-auth (as a part of the
2434 // large ptr-auth-qualifier PR (#100830)). In the meantime, other cast kinds
2435 // can fall-through and be handled by the indirect call work below,
2436 // including L-to-R value conversions and atomic conversions.
2438
2439 } else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {
2440 // Resolve direct calls.
2441 if (const auto *funcDecl = dyn_cast<FunctionDecl>(declRef->getDecl()))
2442 return emitDirectCallee(funcDecl);
2443 } else if (auto me = dyn_cast<MemberExpr>(e)) {
2444 if (const auto *fd = dyn_cast<FunctionDecl>(me->getMemberDecl())) {
2445 emitIgnoredExpr(me->getBase());
2446 return emitDirectCallee(fd);
2447 }
2448 // Else fall through to the indirect reference handling below.
2449 } else if (auto *pde = dyn_cast<CXXPseudoDestructorExpr>(e)) {
2451 }
2452
2453 // Otherwise, we have an indirect reference.
2454 mlir::Value calleePtr;
2456 if (const auto *ptrType = e->getType()->getAs<clang::PointerType>()) {
2457 calleePtr = emitScalarExpr(e);
2458 functionType = ptrType->getPointeeType();
2459 } else {
2460 functionType = e->getType();
2461 calleePtr = emitLValue(e).getPointer();
2462 }
2463 assert(functionType->isFunctionType());
2464
2465 GlobalDecl gd;
2466 if (const auto *vd =
2467 dyn_cast_or_null<VarDecl>(e->getReferencedDeclOfCallee()))
2468 gd = GlobalDecl(vd);
2469
2470 CIRGenCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), gd);
2471 CIRGenCallee callee(calleeInfo, calleePtr.getDefiningOp());
2472 return callee;
2473}
2474
2478
2479 if (const auto *ce = dyn_cast<CXXMemberCallExpr>(e))
2481
2482 if (const auto *cudaKernelCallExpr = dyn_cast<CUDAKernelCallExpr>(e))
2484
2485 // A CXXOperatorCallExpr is created even for explicit-object methods or
2486 // static member operators (C++23 `static operator()` / `static
2487 // operator[]`), but those should be treated like ordinary static function
2488 // calls. Only route through the member-call path for ordinary instance
2489 // operators.
2490 if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(e)) {
2491 if (const auto *md =
2492 dyn_cast_if_present<CXXMethodDecl>(operatorCall->getCalleeDecl());
2493 md && md->isImplicitObjectMemberFunction())
2494 return emitCXXOperatorMemberCallExpr(operatorCall, md, returnValue);
2495 }
2496
2497 CIRGenCallee callee = emitCallee(e->getCallee());
2498
2499 if (callee.isBuiltin())
2500 return emitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(), e,
2501 returnValue);
2502
2503 if (callee.isPseudoDestructor())
2505
2506 return emitCall(e->getCallee()->getType(), callee, e, returnValue);
2507}
2508
2509/// Emit code to compute the specified expression, ignoring the result.
2511 if (e->isPRValue()) {
2512 emitAnyExpr(e, AggValueSlot::ignored(), /*ignoreResult=*/true);
2513 return;
2514 }
2515
2516 // Just emit it as an l-value and drop the result.
2517 emitLValue(e);
2518}
2519
2521 LValueBaseInfo *baseInfo) {
2523 assert(e->getType()->isArrayType() &&
2524 "Array to pointer decay must have array source type!");
2525
2526 // Expressions of array type can't be bitfields or vector elements.
2527 LValue lv = emitLValue(e);
2528 Address addr = lv.getAddress();
2529
2530 // If the array type was an incomplete type, we need to make sure
2531 // the decay ends up being the right type.
2532 auto lvalueAddrTy = mlir::cast<cir::PointerType>(addr.getPointer().getType());
2533
2534 if (e->getType()->isVariableArrayType())
2535 return addr;
2536
2537 [[maybe_unused]] auto pointeeTy =
2538 mlir::cast<cir::ArrayType>(lvalueAddrTy.getPointee());
2539
2540 [[maybe_unused]] mlir::Type arrayTy = convertType(e->getType());
2541 assert(mlir::isa<cir::ArrayType>(arrayTy) && "expected array");
2542 assert(pointeeTy == arrayTy);
2543
2544 // The result of this decay conversion points to an array element within the
2545 // base lvalue. However, since TBAA currently does not support representing
2546 // accesses to elements of member arrays, we conservatively represent accesses
2547 // to the pointee object as if it had no any base lvalue specified.
2548 // TODO: Support TBAA for member arrays.
2551
2552 mlir::Value ptr = builder.maybeBuildArrayDecay(
2553 cgm.getLoc(e->getSourceRange()), addr.getPointer(),
2554 convertTypeForMem(eltType));
2555 return Address(ptr, addr.getAlignment());
2556}
2557
2558/// Given the address of a temporary variable, produce an r-value of its type.
2562 switch (getEvaluationKind(type)) {
2563 case cir::TEK_Complex:
2564 return RValue::getComplex(emitLoadOfComplex(lvalue, loc));
2565 case cir::TEK_Aggregate:
2566 return lvalue.asAggregateRValue();
2567 case cir::TEK_Scalar:
2568 return RValue::get(emitLoadOfScalar(lvalue, loc));
2569 }
2570 llvm_unreachable("bad evaluation kind");
2571}
2572
2573/// Emit an `if` on a boolean condition, filling `then` and `else` into
2574/// appropriated regions.
2575mlir::LogicalResult CIRGenFunction::emitIfOnBoolExpr(const Expr *cond,
2576 const Stmt *thenS,
2577 const Stmt *elseS) {
2578 mlir::Location thenLoc = getLoc(thenS->getSourceRange());
2579 std::optional<mlir::Location> elseLoc;
2580 if (elseS)
2581 elseLoc = getLoc(elseS->getSourceRange());
2582
2583 mlir::LogicalResult resThen = mlir::success(), resElse = mlir::success();
2585 cond, /*thenBuilder=*/
2586 [&](mlir::OpBuilder &, mlir::Location) {
2587 LexicalScope lexScope{*this, thenLoc, builder.getInsertionBlock()};
2588 resThen = emitStmt(thenS, /*useCurrentScope=*/true);
2589 },
2590 thenLoc,
2591 /*elseBuilder=*/
2592 [&](mlir::OpBuilder &, mlir::Location) {
2593 assert(elseLoc && "Invalid location for elseS.");
2594 LexicalScope lexScope{*this, *elseLoc, builder.getInsertionBlock()};
2595 resElse = emitStmt(elseS, /*useCurrentScope=*/true);
2596 },
2597 elseLoc);
2598
2599 return mlir::LogicalResult::success(resThen.succeeded() &&
2600 resElse.succeeded());
2601}
2602
2603/// Emit an `if` on a boolean condition, filling `then` and `else` into
2604/// appropriated regions.
2606 const clang::Expr *cond, BuilderCallbackRef thenBuilder,
2607 mlir::Location thenLoc, BuilderCallbackRef elseBuilder,
2608 std::optional<mlir::Location> elseLoc) {
2609 // Attempt to be as accurate as possible with IfOp location, generate
2610 // one fused location that has either 2 or 4 total locations, depending
2611 // on else's availability.
2612 SmallVector<mlir::Location, 2> ifLocs{thenLoc};
2613 if (elseLoc)
2614 ifLocs.push_back(*elseLoc);
2615 mlir::Location loc = mlir::FusedLoc::get(&getMLIRContext(), ifLocs);
2616
2617 // Emit the code with the fully general case.
2618 mlir::Value condV = emitOpOnBoolExpr(loc, cond);
2619 cir::IfOp ifOp = cir::IfOp::create(builder, loc, condV, elseLoc.has_value(),
2620 /*thenBuilder=*/thenBuilder,
2621 /*elseBuilder=*/elseBuilder);
2622 terminateStructuredRegionBody(ifOp.getThenRegion(), thenLoc);
2623 assert((elseLoc.has_value() || ifOp.getElseRegion().empty()) &&
2624 "else region created with no else location");
2625 if (elseLoc.has_value())
2626 terminateStructuredRegionBody(ifOp.getElseRegion(), *elseLoc);
2627 return ifOp;
2628}
2629
2630/// TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
2631mlir::Value CIRGenFunction::emitOpOnBoolExpr(mlir::Location loc,
2632 const Expr *cond) {
2635 cond = cond->IgnoreParens();
2636
2637 // In LLVM the condition is reversed here for efficient codegen.
2638 // This should be done in CIR prior to LLVM lowering, if we do now
2639 // we can make CIR based diagnostics misleading.
2640 // cir.ternary(!x, t, f) -> cir.ternary(x, f, t)
2642
2643 if (const ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(cond)) {
2644 Expr *trueExpr = condOp->getTrueExpr();
2645 Expr *falseExpr = condOp->getFalseExpr();
2646 mlir::Value condV = emitOpOnBoolExpr(loc, condOp->getCond());
2647
2648 mlir::Value ternaryOpRes =
2649 cir::TernaryOp::create(
2650 builder, loc, condV, /*thenBuilder=*/
2651 [this, trueExpr](mlir::OpBuilder &b, mlir::Location loc) {
2652 mlir::Value lhs = emitScalarExpr(trueExpr);
2653 cir::YieldOp::create(b, loc, lhs);
2654 },
2655 /*elseBuilder=*/
2656 [this, falseExpr](mlir::OpBuilder &b, mlir::Location loc) {
2657 mlir::Value rhs = emitScalarExpr(falseExpr);
2658 cir::YieldOp::create(b, loc, rhs);
2659 })
2660 .getResult();
2661
2662 return emitScalarConversion(ternaryOpRes, condOp->getType(),
2663 getContext().BoolTy, condOp->getExprLoc());
2664 }
2665
2666 if (isa<CXXThrowExpr>(cond)) {
2667 cgm.errorNYI("NYI");
2668 return createDummyValue(loc, cond->getType());
2669 }
2670
2671 // If the branch has a condition wrapped by __builtin_unpredictable,
2672 // create metadata that specifies that the branch is unpredictable.
2673 // Don't bother if not optimizing because that metadata would not be used.
2675
2676 // Emit the code with the fully general case.
2677 return evaluateExprAsBool(cond);
2678}
2679
2680mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
2681 mlir::Location loc, CharUnits alignment,
2682 bool insertIntoFnEntryBlock,
2683 mlir::Value arraySize) {
2684 mlir::Block *entryBlock = insertIntoFnEntryBlock
2686 : curLexScope->getEntryBlock();
2687
2688 // If this is an alloca in the entry basic block of a cir.try and there's
2689 // a surrounding cir.scope, make sure the alloca ends up in the surrounding
2690 // scope instead. This is necessary in order to guarantee all SSA values are
2691 // reachable during cleanups.
2692 if (auto tryOp =
2693 llvm::dyn_cast_if_present<cir::TryOp>(entryBlock->getParentOp())) {
2694 if (auto scopeOp = llvm::dyn_cast<cir::ScopeOp>(tryOp->getParentOp()))
2695 entryBlock = &scopeOp.getScopeRegion().front();
2696 }
2697
2698 return emitAlloca(name, ty, loc, alignment,
2699 builder.getBestAllocaInsertPoint(entryBlock), arraySize);
2700}
2701
2702mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
2703 mlir::Location loc, CharUnits alignment,
2704 mlir::OpBuilder::InsertPoint ip,
2705 mlir::Value arraySize) {
2706 // CIR uses its own alloca address space rather than follow the target data
2707 // layout like original CodeGen. The data layout awareness should be done in
2708 // the lowering pass instead.
2709 cir::PointerType localVarPtrTy =
2711 mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);
2712
2713 mlir::Value addr;
2714 {
2715 mlir::OpBuilder::InsertionGuard guard(builder);
2716 builder.restoreInsertionPoint(ip);
2717 addr = builder.createAlloca(loc, /*addr type*/ localVarPtrTy, name,
2718 alignIntAttr, arraySize);
2720 }
2721 return addr;
2722}
2723
2724// Note: this function also emit constructor calls to support a MSVC extensions
2725// allowing explicit constructor function call.
2728 const Expr *callee = ce->getCallee()->IgnoreParens();
2729
2730 if (isa<BinaryOperator>(callee))
2732
2733 const auto *me = cast<MemberExpr>(callee);
2734 const auto *md = cast<CXXMethodDecl>(me->getMemberDecl());
2735
2736 if (md->isStatic()) {
2737 cgm.errorNYI(ce->getSourceRange(), "emitCXXMemberCallExpr: static method");
2738 return RValue::get(nullptr);
2739 }
2740
2741 bool hasQualifier = me->hasQualifier();
2742 NestedNameSpecifier qualifier = me->getQualifier();
2743 bool isArrow = me->isArrow();
2744 const Expr *base = me->getBase();
2745
2747 ce, md, returnValue, hasQualifier, qualifier, isArrow, base);
2748}
2749
2751 // Emit the expression as an lvalue.
2752 LValue lv = emitLValue(e);
2753 assert(lv.isSimple());
2754 mlir::Value value = lv.getPointer();
2755
2757
2758 return RValue::get(value);
2759}
2760
2762 LValueBaseInfo *pointeeBaseInfo) {
2763 if (refLVal.isVolatile())
2764 cgm.errorNYI(loc, "load of volatile reference");
2765
2766 cir::LoadOp load =
2767 cir::LoadOp::create(builder, loc, refLVal.getAddress().getElementType(),
2768 refLVal.getAddress().getPointer());
2769
2771
2772 QualType pointeeType = refLVal.getType()->getPointeeType();
2773 CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, pointeeBaseInfo);
2774 return Address(load, convertTypeForMem(pointeeType), align);
2775}
2776
2778 mlir::Location loc,
2779 QualType refTy,
2780 AlignmentSource source) {
2781 LValue refLVal = makeAddrLValue(refAddr, refTy, LValueBaseInfo(source));
2782 LValueBaseInfo pointeeBaseInfo;
2784 Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo);
2785 return makeAddrLValue(pointeeAddr, refLVal.getType()->getPointeeType(),
2786 pointeeBaseInfo);
2787}
2788
2789void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) {
2790 cir::TrapOp::create(builder, loc);
2791 if (createNewBlock)
2792 builder.createBlock(builder.getBlock()->getParent());
2793}
2794
2796 bool createNewBlock) {
2798 cir::UnreachableOp::create(builder, getLoc(loc));
2799 if (createNewBlock)
2800 builder.createBlock(builder.getBlock()->getParent());
2801}
2802
2803mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,
2804 clang::QualType qt) {
2805 mlir::Type t = convertType(qt);
2806 CharUnits alignment = getContext().getTypeAlignInChars(qt);
2807 return builder.createDummyValue(loc, t, alignment);
2808}
2809
2810//===----------------------------------------------------------------------===//
2811// CIR builder helpers
2812//===----------------------------------------------------------------------===//
2813
2815 mlir::Location loc,
2816 const Twine &name) {
2818 convertTypeForMem(ty), getContext().getTypeAlignInChars(ty), loc, name);
2819}
2820
2822 const Twine &name, Address *alloca,
2823 mlir::OpBuilder::InsertPoint ip) {
2824 // FIXME: Should we prefer the preferred type alignment here?
2825 return createMemTemp(ty, getContext().getTypeAlignInChars(ty), loc, name,
2826 alloca, ip);
2827}
2828
2830 mlir::Location loc, const Twine &name,
2831 Address *alloca,
2832 mlir::OpBuilder::InsertPoint ip) {
2833 Address result =
2834 createTempAlloca(convertTypeForMem(ty), /*destAddrSpace=*/{}, align, loc,
2835 name, /*arraySize=*/nullptr, alloca, ip);
2836 if (ty->isConstantMatrixType()) {
2838 cgm.errorNYI(loc, "temporary matrix value");
2839 }
2840 return result;
2841}
2842
2843/// This creates a alloca and inserts it into the entry block of the
2844/// current region.
2846 mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name,
2847 mlir::Value arraySize, mlir::OpBuilder::InsertPoint ip) {
2848 cir::AllocaOp alloca = ip.isSet()
2849 ? createTempAlloca(ty, loc, name, ip, arraySize)
2850 : createTempAlloca(ty, loc, name, arraySize);
2851 alloca.setAlignmentAttr(cgm.getSize(align));
2852 return Address(alloca, ty, align);
2853}
2854
2856 mlir::Location loc, const Twine &name,
2857 mlir::Value arraySize,
2858 Address *allocaAddr,
2859 mlir::OpBuilder::InsertPoint ip) {
2860 return createTempAlloca(ty, /*destAddrSpace=*/{}, align, loc, name, arraySize,
2861 allocaAddr, ip);
2862}
2863
2865 Address alloca, mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2866 mlir::Value arraySize) {
2867 if (!destAddrSpace)
2868 destAddrSpace = cir::toCIRAddressSpaceAttr(
2869 getMLIRContext(), cgm.getLangTempAllocaAddressSpace());
2870
2871 mlir::ptr::MemorySpaceAttrInterface srcAddrSpace = getCIRAllocaAddressSpace();
2872 // Alloca always returns a pointer in alloca address space, which may
2873 // be different from the type defined by the language. For example,
2874 // in C++ the auto variables are in the default address space. Therefore
2875 // cast alloca to the default address space when necessary.
2876 if (srcAddrSpace == destAddrSpace)
2877 return alloca;
2878
2879 mlir::OpBuilder::InsertionGuard guard(builder);
2880 if (cir::AllocaOp allocaOp = alloca.getUnderlyingAllocaOp()) {
2881 builder.setInsertionPointAfter(allocaOp);
2882 } else if (!arraySize) {
2883 mlir::Block *entryBlock = getCurFunctionEntryBlock();
2884 builder.restoreInsertionPoint(builder.getBestAllocaInsertPoint(entryBlock));
2885 }
2886
2887 mlir::Type destPtrTy =
2888 builder.getPointerTo(alloca.getElementType(), destAddrSpace);
2889 mlir::Value casted = performAddrSpaceCast(alloca.getPointer(), destPtrTy);
2890 return Address(casted, alloca.getElementType(), alloca.getAlignment(),
2891 /*isKnownNonNull=*/true);
2892}
2893
2894/// This creates a alloca and inserts it into the entry block. The alloca is
2895/// casted to the requested language address space if necessary.
2897 mlir::Type ty, mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2898 CharUnits align, mlir::Location loc, const Twine &name,
2899 mlir::Value arraySize, Address *allocaAddr,
2900 mlir::OpBuilder::InsertPoint ip) {
2901 Address alloca =
2902 createTempAllocaWithoutCast(ty, align, loc, name, arraySize, ip);
2903 if (allocaAddr)
2904 *allocaAddr = alloca;
2905 return maybeCastStackAddressSpace(alloca, destAddrSpace, arraySize);
2906}
2907
2908/// This creates an alloca and inserts it into the entry block if \p ArraySize
2909/// is nullptr, otherwise inserts it at the current insertion point of the
2910/// builder.
2911cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
2912 mlir::Location loc,
2913 const Twine &name,
2914 mlir::Value arraySize,
2915 bool insertIntoFnEntryBlock) {
2916 return mlir::cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(),
2917 insertIntoFnEntryBlock, arraySize)
2918 .getDefiningOp());
2919}
2920
2921/// This creates an alloca and inserts it into the provided insertion point
2922cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
2923 mlir::Location loc,
2924 const Twine &name,
2925 mlir::OpBuilder::InsertPoint ip,
2926 mlir::Value arraySize) {
2927 assert(ip.isSet() && "Insertion point is not set");
2928 return mlir::cast<cir::AllocaOp>(
2929 emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize)
2930 .getDefiningOp());
2931}
2932
2933/// CreateDefaultAlignTempAlloca - This creates an alloca with the
2934/// default alignment of the corresponding LLVM type, which is *not*
2935/// guaranteed to be related in any way to the expected alignment of
2936/// an AST type that might have been lowered to Ty.
2938 mlir::Location loc,
2939 const Twine &name) {
2940 CharUnits align =
2941 CharUnits::fromQuantity(cgm.getDataLayout().getABITypeAlign(ty));
2942 return createTempAlloca(ty, align, loc, name);
2943}
2944
2945/// Try to emit a reference to the given value without producing it as
2946/// an l-value. For many cases, this is just an optimization, but it avoids
2947/// us needing to emit global copies of variables if they're named without
2948/// triggering a formal use in a context where we can't emit a direct
2949/// reference to them, for instance if a block or lambda or a member of a
2950/// local class uses a const int variable or constexpr variable from an
2951/// enclosing function.
2952///
2953/// For named members of enums, this is the only way they are emitted.
2956 const ValueDecl *value = refExpr->getDecl();
2957
2958 // There is a lot more to do here, but for now only EnumConstantDecl is
2959 // supported.
2961
2962 // The value needs to be an enum constant or a constant variable.
2963 if (!isa<EnumConstantDecl>(value))
2964 return ConstantEmission();
2965
2966 Expr::EvalResult result;
2967 if (!refExpr->EvaluateAsRValue(result, getContext()))
2968 return ConstantEmission();
2969
2970 QualType resultType = refExpr->getType();
2971
2972 // As long as we're only handling EnumConstantDecl, there should be no
2973 // side-effects.
2974 assert(!result.HasSideEffects);
2975
2976 // Emit as a constant.
2977 // FIXME(cir): have emitAbstract build a TypedAttr instead (this requires
2978 // somewhat heavy refactoring...)
2979 mlir::Attribute c = ConstantEmitter(*this).emitAbstract(
2980 refExpr->getLocation(), result.Val, resultType);
2981 mlir::TypedAttr cstToEmit = mlir::dyn_cast_if_present<mlir::TypedAttr>(c);
2982 assert(cstToEmit && "expected a typed attribute");
2983
2985
2986 return ConstantEmission::forValue(cstToEmit);
2987}
2988
2992 return tryEmitAsConstant(dre);
2993 return ConstantEmission();
2994}
2995
2997 const CIRGenFunction::ConstantEmission &constant, Expr *e) {
2998 assert(constant && "not a constant");
2999 if (constant.isReference()) {
3000 cgm.errorNYI(e->getSourceRange(), "emitScalarConstant: reference");
3001 return {};
3002 }
3003 return builder.getConstant(getLoc(e->getSourceRange()), constant.getValue());
3004}
3005
3007 const StringLiteral *sl = e->getFunctionName();
3008 assert(sl != nullptr && "No StringLiteral name in PredefinedExpr");
3009 auto fn = cast<cir::FuncOp>(curFn);
3010 StringRef fnName = fn.getName();
3011 fnName.consume_front("\01");
3012 std::array<StringRef, 2> nameItems = {
3014 std::string gvName = llvm::join(nameItems, ".");
3015 if (isa_and_nonnull<BlockDecl>(curCodeDecl))
3016 cgm.errorNYI(e->getSourceRange(), "predefined lvalue in block");
3017
3018 return emitStringLiteralLValue(sl, gvName);
3019}
3020
3025
3026namespace {
3027// Handle the case where the condition is a constant evaluatable simple integer,
3028// which means we don't have to separately handle the true/false blocks.
3029std::optional<LValue> handleConditionalOperatorLValueSimpleCase(
3031 const Expr *condExpr = e->getCond();
3032 llvm::APSInt condExprVal;
3033 if (!cgf.constantFoldsToSimpleInteger(condExpr, condExprVal))
3034 return std::nullopt;
3035
3036 const Expr *live = e->getTrueExpr(), *dead = e->getFalseExpr();
3037 if (!condExprVal.getBoolValue())
3038 std::swap(live, dead);
3039
3040 if (cgf.containsLabel(dead))
3041 return std::nullopt;
3042
3043 // If the true case is live, we need to track its region.
3046 // If a throw expression we emit it and return an undefined lvalue
3047 // because it can't be used.
3048 if (auto *throwExpr = dyn_cast<CXXThrowExpr>(live->IgnoreParens())) {
3049 cgf.emitCXXThrowExpr(throwExpr);
3050 // Return an undefined lvalue - the throw terminates execution
3051 // so this value will never actually be used
3052 mlir::Type elemTy = cgf.convertType(dead->getType());
3053 mlir::Value undefPtr =
3054 cgf.getBuilder().getNullPtr(cgf.getBuilder().getPointerTo(elemTy),
3055 cgf.getLoc(throwExpr->getSourceRange()));
3056 return cgf.makeAddrLValue(Address(undefPtr, elemTy, CharUnits::One()),
3057 dead->getType());
3058 }
3059 return cgf.emitLValue(live);
3060}
3061
3062/// Emit the operand of a glvalue conditional operator. This is either a glvalue
3063/// or a (possibly-parenthesized) throw-expression. If this is a throw, no
3064/// LValue is returned and the current block has been terminated.
3065static std::optional<LValue> emitLValueOrThrowExpression(CIRGenFunction &cgf,
3066 const Expr *operand) {
3067 if (auto *throwExpr = dyn_cast<CXXThrowExpr>(operand->IgnoreParens())) {
3068 cgf.emitCXXThrowExpr(throwExpr);
3069 return std::nullopt;
3070 }
3071
3072 return cgf.emitLValue(operand);
3073}
3074} // namespace
3075
3076// Create and generate the 3 blocks for a conditional operator.
3077// Leaves the 'current block' in the continuation basic block.
3078template <typename FuncTy>
3081 const FuncTy &branchGenFunc) {
3082 ConditionalInfo info;
3083 ConditionalEvaluation eval(*this);
3084 mlir::Location loc = getLoc(e->getSourceRange());
3085 CIRGenBuilderTy &builder = getBuilder();
3086
3087 mlir::Value condV = emitOpOnBoolExpr(loc, e->getCond());
3088
3089 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc,
3090 const Expr *expr, std::optional<LValue> &resultLV) {
3091 CIRGenFunction::LexicalScope lexScope{*this, loc, b.getInsertionBlock()};
3092 curLexScope->setAsTernary();
3093
3094 mlir::Value resultPtr;
3095 {
3096 // Emit any cleanups that were needed on this branch so we can spill
3097 // and reload the return value.
3098 CIRGenFunction::RunCleanupsScope branchCleanups(*this);
3100 eval.beginEvaluation();
3101 resultLV = branchGenFunc(*this, expr);
3102 resultPtr = resultLV ? resultLV->getPointer() : mlir::Value();
3103 eval.endEvaluation();
3104 branchCleanups.forceCleanup({&resultPtr});
3105 }
3106
3107 // A branch that produced no result is a throw-expression; its region is
3108 // already terminated by cir.unreachable and needs no yield.
3109 if (resultPtr)
3110 cir::YieldOp::create(b, loc, resultPtr);
3111 };
3112
3113 cir::TernaryOp ternary = cir::TernaryOp::create(
3114 builder, loc, condV,
3115 /*trueBuilder=*/
3116 [&](mlir::OpBuilder &b, mlir::Location loc) {
3117 emitBranch(b, loc, e->getTrueExpr(), info.lhs);
3118 },
3119 /*falseBuilder=*/
3120 [&](mlir::OpBuilder &b, mlir::Location loc) {
3121 emitBranch(b, loc, e->getFalseExpr(), info.rhs);
3122 });
3123
3124 // Arms end with a yield or cir.unreachable (throw); this is a backstop
3125 // for error (NYI) paths that leave a region open.
3126 terminateStructuredRegionBody(ternary.getTrueRegion(), loc);
3127 terminateStructuredRegionBody(ternary.getFalseRegion(), loc);
3128
3129 info.result = ternary.getResult();
3130 return info;
3131}
3132
3135 if (!expr->isGLValue()) {
3136 // ?: here should be an aggregate.
3137 assert(hasAggregateEvaluationKind(expr->getType()) &&
3138 "Unexpected conditional operator!");
3139 return emitAggExprToLValue(expr);
3140 }
3141
3142 OpaqueValueMapping binding(*this, expr);
3143 if (std::optional<LValue> res =
3144 handleConditionalOperatorLValueSimpleCase(*this, expr))
3145 return *res;
3146
3147 ConditionalInfo info =
3148 emitConditionalBlocks(expr, [](CIRGenFunction &cgf, const Expr *e) {
3149 return emitLValueOrThrowExpression(cgf, e);
3150 });
3151
3152 if ((info.lhs && !info.lhs->isSimple()) ||
3153 (info.rhs && !info.rhs->isSimple())) {
3154 cgm.errorNYI(expr->getSourceRange(),
3155 "unsupported conditional operator with non-simple lvalue");
3156 return LValue();
3157 }
3158
3159 if (info.lhs && info.rhs) {
3160 Address lhsAddr = info.lhs->getAddress();
3161 Address rhsAddr = info.rhs->getAddress();
3162 Address result(info.result, lhsAddr.getElementType(),
3163 std::min(lhsAddr.getAlignment(), rhsAddr.getAlignment()));
3164 AlignmentSource alignSource =
3165 std::max(info.lhs->getBaseInfo().getAlignmentSource(),
3166 info.rhs->getBaseInfo().getAlignmentSource());
3168 return makeAddrLValue(result, expr->getType(), LValueBaseInfo(alignSource));
3169 }
3170
3171 assert((info.lhs || info.rhs) &&
3172 "both operands of glvalue conditional are throw-expressions?");
3173
3174 // One arm threw; the surviving arm's pointer is local to the ternary's
3175 // region, so address the result through the ternary's result value.
3176 const LValue &survivingLV = info.lhs ? *info.lhs : *info.rhs;
3177 Address survivingAddr = survivingLV.getAddress();
3178 Address result(info.result, survivingAddr.getElementType(),
3179 survivingAddr.getAlignment());
3181 return makeAddrLValue(result, expr->getType(), survivingLV.getBaseInfo());
3182}
3183
3184/// An LValue is a candidate for having its loads and stores be made atomic if
3185/// we are operating under /volatile:ms *and* the LValue itself is volatile and
3186/// performing such an operation can be performed without a libcall.
3188 if (!cgm.getLangOpts().MSVolatile)
3189 return false;
3190
3191 cgm.errorNYI("LValueSuitableForInlineAtomic LangOpts MSVolatile");
3192 return false;
3193}
3194
#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 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:609
uint64_t getElementOffset(const mlir::DataLayout &dataLayout, unsigned idx) const
Definition CIRTypes.cpp:667
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:4397
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Definition Expr.h:4575
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4581
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4587
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2765
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:2820
Expr * getLHS()
An array access can be written A[4] or 4[A] (both are equivalent).
Definition Expr.h:2794
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:2808
SourceLocation getEndLoc() const
Definition Expr.h:2811
QualType getElementType() const
Definition TypeBase.h:3848
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4082
Expr * getLHS() const
Definition Expr.h:4132
Expr * getRHS() const
Definition Expr.h:4134
Opcode getOpcode() const
Definition Expr.h:4127
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()
mlir::Region * curStaticVarDtorRegion
While the initializer of a variable with static storage duration is being emitted,...
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::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.
bool hasCIRField(const clang::FieldDecl *fd) const
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:1497
CXXTemporary * getTemporary()
Definition ExprCXX.h:1515
const Expr * getSubExpr() const
Definition ExprCXX.h:1519
Represents a call to a C++ constructor.
Definition ExprCXX.h:1552
Represents a C++ destructor within a class.
Definition DeclCXX.h:2906
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:183
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:1381
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
Definition ExprCXX.h:852
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2987
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3191
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3170
Expr * getCallee()
Definition Expr.h:3134
arg_range arguments()
Definition Expr.h:3239
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1631
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3720
CastKind getCastKind() const
Definition Expr.h:3764
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
Definition Expr.h:3807
bool changesVolatileQualification() const
Return.
Definition Expr.h:3854
static const char * getCastKindName(CastKind CK)
Definition Expr.cpp:1981
Expr * getSubExpr()
Definition Expr.h:3770
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:3649
bool isFileScope() const
Definition Expr.h:3681
const Expr * getInitializer() const
Definition Expr.h:3677
ConditionalOperator - The ?
Definition Expr.h:4435
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1290
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
Definition Expr.h:1494
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:1358
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:1488
SourceLocation getLocation() const
Definition Expr.h:1366
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:6631
This represents one expression.
Definition Expr.h:113
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:288
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:448
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3119
bool isPRValue() const
Definition Expr.h:286
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:1574
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:145
ExtVectorElementExpr - This represents access to specific elements of a vector, and may occur on the ...
Definition Expr.h:6660
bool isArrow() const
isArrow - Return true if the base expression is a pointer to vector, return false if the base express...
Definition Expr.cpp:4472
void getEncodedElementAccess(SmallVectorImpl< uint32_t > &Elts) const
getEncodedElementAccess - Encode the elements accessed into an llvm aggregate Constant of ConstantInt...
Definition Expr.cpp:4585
Represents a member of a struct/union/class.
Definition Decl.h:3295
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3398
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4890
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3380
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3531
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
Definition Decl.cpp:4868
Represents a function declaration or definition.
Definition Decl.h:2059
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:60
const Decl * getDecl() const
Definition GlobalDecl.h:115
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4973
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition ExprCXX.h:4998
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4990
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
Definition ExprCXX.h:5023
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3408
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3491
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:3632
Expr * getBase() const
Definition Expr.h:3485
bool isArrow() const
Definition Expr.h:3592
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3603
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:275
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
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:1198
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1248
bool isUnique() const
Definition Expr.h:1256
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:2049
StringRef getIdentKindName() const
Definition Expr.h:2106
PredefinedIdentKind getIdentKind() const
Definition Expr.h:2084
StringLiteral * getFunctionName()
Definition Expr.h:2093
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:8541
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:4460
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:1819
bool isUnion() const
Definition Decl.h:4063
bool isVoidType() const
Definition TypeBase.h:9110
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:9413
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:8837
bool isFunctionPointerType() const
Definition TypeBase.h:8805
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
bool isArithmeticType() const
Definition Type.cpp:2454
bool isConstantMatrixType() const
Definition TypeBase.h:8905
bool isPointerType() const
Definition TypeBase.h:8738
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9404
bool isReferenceType() const
Definition TypeBase.h:8762
bool isVariableArrayType() const
Definition TypeBase.h:8849
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:8885
bool isConstantMatrixBoolType() const
Definition TypeBase.h:8891
bool isAnyComplexType() const
Definition TypeBase.h:8873
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
Definition TypeBase.h:9290
bool isAtomicType() const
Definition TypeBase.h:8930
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:8734
bool isVectorType() const
Definition TypeBase.h:8877
bool isSubscriptableVectorType() const
Definition TypeBase.h:8897
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9337
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2288
SourceLocation getExprLoc() const
Definition Expr.h:2412
Expr * getSubExpr() const
Definition Expr.h:2329
Opcode getOpcode() const
Definition Expr.h:2324
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
Definition Expr.h:2363
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
bool hasInit() const
Definition Decl.cpp:2380
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
Definition Decl.cpp:2348
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1191
@ TLS_None
Not a TLS variable.
Definition Decl.h:953
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...
bool isAAPCS(const TargetInfo &TargetInfo)
Helper method to check if the underlying ABI is AAPCS.
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:341
@ SD_Static
Static storage duration.
Definition Specifiers.h:342
@ SD_FullExpression
Full-expression storage duration (for temporaries).
Definition Specifiers.h:339
@ SD_Automatic
Automatic storage duration (most local variables).
Definition Specifiers.h:340
@ SD_Dynamic
Dynamic storage duration.
Definition Specifiers.h:343
@ 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:666
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:668
bool HasSideEffects
Whether the evaluated expression has side effects.
Definition Expr.h:625
An adjustment to be made to the temporary created when emitting a reference binding,...
Definition Expr.h:69