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