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 rec.isUnion() ? 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 cgf.cgm.errorNYI(e->getSourceRange(), "pushTemporaryCleanup: static/thread "
1935 "storage duration with destructors");
1936 break;
1937 }
1938
1939 case SD_FullExpression:
1940 cgf.pushDestroy(NormalAndEHCleanup, referenceTemporary, e->getType(),
1942 break;
1943
1944 case SD_Automatic:
1946 NormalAndEHCleanup, referenceTemporary, e->getType(),
1948 break;
1949
1950 case SD_Dynamic:
1951 llvm_unreachable("temporary cannot have dynamic storage duration");
1952 }
1953}
1954
1956 const MaterializeTemporaryExpr *m) {
1957 const Expr *e = m->getSubExpr();
1958
1959 assert((!m->getExtendingDecl() || !isa<VarDecl>(m->getExtendingDecl()) ||
1960 !cast<VarDecl>(m->getExtendingDecl())->isARCPseudoStrong()) &&
1961 "Reference should never be pseudo-strong!");
1962
1963 // FIXME: ideally this would use emitAnyExprToMem, however, we cannot do so
1964 // as that will cause the lifetime adjustment to be lost for ARC
1965 auto ownership = m->getType().getObjCLifetime();
1966 if (ownership != Qualifiers::OCL_None &&
1967 ownership != Qualifiers::OCL_ExplicitNone) {
1968 cgm.errorNYI(e->getSourceRange(),
1969 "emitMaterializeTemporaryExpr: ObjCLifetime");
1970 return {};
1971 }
1972
1975 e = e->skipRValueSubobjectAdjustments(commaLHSs, adjustments);
1976
1977 for (const Expr *ignored : commaLHSs)
1978 emitIgnoredExpr(ignored);
1979
1980 if (isa<OpaqueValueExpr>(e)) {
1981 cgm.errorNYI(e->getSourceRange(),
1982 "emitMaterializeTemporaryExpr: OpaqueValueExpr");
1983 return {};
1984 }
1985
1986 // Create and initialize the reference temporary.
1987 Address object = createReferenceTemporary(*this, m, e);
1988
1989 if (auto var = object.getPointer().getDefiningOp<cir::GlobalOp>()) {
1990 // TODO(cir): add something akin to stripPointerCasts() to ptr above
1991 cgm.errorNYI(e->getSourceRange(), "emitMaterializeTemporaryExpr: GlobalOp");
1992 return {};
1993 } else {
1995 emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);
1996 }
1997 pushTemporaryCleanup(*this, m, e, object);
1998
1999 // Perform derived-to-base casts and/or field accesses, to get from the
2000 // temporary object we created (and, potentially, for which we extended
2001 // the lifetime) to the subobject we're binding the reference to.
2002 for (SubobjectAdjustment &adjustment : llvm::reverse(adjustments)) {
2003 switch (adjustment.Kind) {
2005 object =
2006 getAddressOfBaseClass(object, adjustment.DerivedToBase.DerivedClass,
2007 adjustment.DerivedToBase.BasePath->path(),
2008 /*nullCheckValue=*/false, e->getExprLoc());
2009 break;
2012 lv = emitLValueForField(lv, adjustment.Field);
2013 assert(lv.isSimple() &&
2014 "materialized temporary field is not a simple lvalue");
2015 object = lv.getAddress();
2016 break;
2017 }
2019 mlir::Value ptr = emitScalarExpr(adjustment.Ptr.RHS);
2021 e, object, ptr, adjustment.Ptr.MPT, /*baseInfo=*/nullptr);
2022 break;
2023 }
2024 }
2025 }
2026
2027 return makeAddrLValue(object, m->getType(), AlignmentSource::Decl);
2028}
2029
2030LValue
2033
2034 auto it = opaqueLValues.find(e);
2035 if (it != opaqueLValues.end())
2036 return it->second;
2037
2038 assert(e->isUnique() && "LValue for a nonunique OVE hasn't been emitted");
2039 return emitLValue(e->getSourceExpr());
2040}
2041
2042RValue
2045
2046 auto it = opaqueRValues.find(e);
2047 if (it != opaqueRValues.end())
2048 return it->second;
2049
2050 assert(e->isUnique() && "RValue for a nonunique OVE hasn't been emitted");
2051 return emitAnyExpr(e->getSourceExpr());
2052}
2053
2055 if (e->isFileScope()) {
2056 cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope");
2057 return {};
2058 }
2059
2060 if (e->getType()->isVariablyModifiedType())
2062
2063 Address declPtr = createMemTemp(e->getType(), getLoc(e->getSourceRange()),
2064 ".compoundliteral");
2065 const Expr *initExpr = e->getInitializer();
2066 LValue result = makeAddrLValue(declPtr, e->getType(), AlignmentSource::Decl);
2067
2068 emitAnyExprToMem(initExpr, declPtr, e->getType().getQualifiers(),
2069 /*Init*/ true);
2070
2071 // Block-scope compound literals are destroyed at the end of the enclosing
2072 // scope in C.
2073 if (!getLangOpts().CPlusPlus && e->getType().isDestructedType()) {
2074 cgm.errorNYI(e->getSourceRange(),
2075 "emitCompoundLiteralLValue: non C++ DestructedType");
2076 return {};
2077 }
2078
2079 return result;
2080}
2081
2083 RValue rv = emitCallExpr(e);
2084
2085 if (!rv.isScalar())
2086 return makeAddrLValue(rv.getAggregateAddress(), e->getType(),
2088
2089 assert(e->getCallReturnType(getContext())->isReferenceType() &&
2090 "Can't have a scalar return unless the return type is a "
2091 "reference type!");
2092
2094}
2095
2097 // Comma expressions just emit their LHS then their RHS as an l-value.
2098 if (e->getOpcode() == BO_Comma) {
2099 emitIgnoredExpr(e->getLHS());
2100 return emitLValue(e->getRHS());
2101 }
2102
2103 if (e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI)
2105
2106 assert(e->getOpcode() == BO_Assign && "unexpected binary l-value");
2107
2108 // Note that in all of these cases, __block variables need the RHS
2109 // evaluated first just in case the variable gets moved by the RHS.
2110
2112 case cir::TEK_Scalar: {
2114 if (e->getLHS()->getType().getObjCLifetime() !=
2116 cgm.errorNYI(e->getSourceRange(), "objc lifetimes");
2117 return {};
2118 }
2119
2120 RValue rv = emitAnyExpr(e->getRHS());
2121 LValue lv = emitLValue(e->getLHS());
2122
2123 SourceLocRAIIObject loc{*this, getLoc(e->getSourceRange())};
2124 if (lv.isBitField())
2126 else
2127 emitStoreThroughLValue(rv, lv);
2128
2129 if (getLangOpts().OpenMP) {
2130 cgm.errorNYI(e->getSourceRange(), "openmp");
2131 return {};
2132 }
2133
2134 return lv;
2135 }
2136
2137 case cir::TEK_Complex: {
2139 }
2140
2141 case cir::TEK_Aggregate:
2142 cgm.errorNYI(e->getSourceRange(), "aggregate lvalues");
2143 return {};
2144 }
2145 llvm_unreachable("bad evaluation kind");
2146}
2147
2148/// Emit code to compute the specified expression which
2149/// can have any type. The result is returned as an RValue struct.
2151 bool ignoreResult) {
2153 case cir::TEK_Scalar:
2154 return RValue::get(emitScalarExpr(e, ignoreResult));
2155 case cir::TEK_Complex:
2157 case cir::TEK_Aggregate: {
2158 if (!ignoreResult && aggSlot.isIgnored())
2159 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
2161 emitAggExpr(e, aggSlot);
2162 return aggSlot.asRValue();
2163 }
2164 }
2165 llvm_unreachable("bad evaluation kind");
2166}
2167
2168// Detect the unusual situation where an inline version is shadowed by a
2169// non-inline version. In that case we should pick the external one
2170// everywhere. That's GCC behavior too.
2172 for (const FunctionDecl *pd = fd; pd; pd = pd->getPreviousDecl())
2173 if (!pd->isInlineBuiltinDeclaration())
2174 return false;
2175 return true;
2176}
2177
2178CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {
2179 const auto *fd = cast<FunctionDecl>(gd.getDecl());
2180
2181 if (unsigned builtinID = fd->getBuiltinID()) {
2182 StringRef ident = cgm.getMangledName(gd);
2183 std::string fdInlineName = (ident + ".inline").str();
2184
2185 bool isPredefinedLibFunction =
2186 cgm.getASTContext().BuiltinInfo.isPredefinedLibFunction(builtinID);
2187 // TODO: Read no-builtin function attribute and set this accordingly.
2188 // Using false here matches OGCG's default behavior - builtins are called
2189 // as builtins unless explicitly disabled. The previous value of true was
2190 // overly conservative and caused functions to be marked as no_inline when
2191 // they shouldn't be.
2192 bool hasAttributeNoBuiltin = false;
2194
2195 // When directly calling an inline builtin, call it through it's mangled
2196 // name to make it clear it's not the actual builtin.
2197 if (auto fn = dyn_cast<cir::FuncOp>(curFn);
2198 (!fn || fn.getName() != fdInlineName) &&
2200 cir::FuncOp clone =
2201 mlir::cast_or_null<cir::FuncOp>(cgm.getGlobalValue(fdInlineName));
2202
2203 if (!clone) {
2204 // Create a forward declaration - the body will be generated in
2205 // generateCode when the function definition is processed
2206 cir::FuncOp calleeFunc = emitFunctionDeclPointer(cgm, gd);
2207 mlir::OpBuilder::InsertionGuard guard(builder);
2208 builder.setInsertionPointToStart(cgm.getModule().getBody());
2209
2210 clone = cir::FuncOp::create(builder, calleeFunc.getLoc(), fdInlineName,
2211 calleeFunc.getFunctionType());
2212 cgm.insertGlobalSymbol(clone);
2213 clone.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
2214 &cgm.getMLIRContext(), cir::GlobalLinkageKind::InternalLinkage));
2215 clone.setSymVisibility("private");
2216 clone.setInlineKind(cir::InlineKind::AlwaysInline);
2217 }
2218 return CIRGenCallee::forDirect(clone, gd);
2219 }
2220
2221 // Replaceable builtins provide their own implementation of a builtin. If we
2222 // are in an inline builtin implementation, avoid trivial infinite
2223 // recursion. Honor __attribute__((no_builtin("foo"))) or
2224 // __attribute__((no_builtin)) on the current function unless foo is
2225 // not a predefined library function which means we must generate the
2226 // builtin no matter what.
2227 else if (!isPredefinedLibFunction || !hasAttributeNoBuiltin)
2228 return CIRGenCallee::forBuiltin(builtinID, fd);
2229 }
2230
2231 cir::FuncOp callee = emitFunctionDeclPointer(cgm, gd);
2232
2233 if ((cgm.getLangOpts().CUDA || cgm.getLangOpts().HIP) &&
2234 !cgm.getLangOpts().CUDAIsDevice && fd->hasAttr<CUDAGlobalAttr>()) {
2235 mlir::Operation *handle = cgm.getCUDARuntime().getKernelHandle(callee, gd);
2236 callee =
2237 mlir::cast<cir::FuncOp>(*cgm.getCUDARuntime().getKernelStub(handle));
2238 }
2239
2240 return CIRGenCallee::forDirect(callee, gd);
2241}
2242
2243mlir::Value CIRGenFunction::getUndefConstant(mlir::Location loc,
2244 mlir::Type cirTy) {
2245 return builder.getConstant(loc, cir::UndefAttr::get(cirTy));
2246}
2247
2249 if (ty->isVoidType())
2250 return RValue::get(nullptr);
2251
2252 mlir::Location loc = builder.getUnknownLoc();
2253
2254 switch (getEvaluationKind(ty)) {
2255 case cir::TEK_Complex: {
2256 QualType elemTy = ty->castAs<ComplexType>()->getElementType();
2257 mlir::Type elemCirTy = convertType(elemTy);
2258 mlir::Value undefElem = getUndefConstant(loc, elemCirTy);
2259 mlir::Value v = builder.createComplexCreate(loc, undefElem, undefElem);
2260 return RValue::getComplex(v);
2261 }
2262
2263 // If this is a use of an undefined aggregate type, the aggregate must have
2264 // an identifiable address. Just because the contents of the value are
2265 // undefined doesn't mean that the address can't be taken and compared.
2266 case cir::TEK_Aggregate: {
2267 Address destPtr = createMemTempWithoutCast(ty, loc, "undef.agg.tmp");
2268 return RValue::getAggregate(destPtr);
2269 }
2270
2271 case cir::TEK_Scalar:
2272 return RValue::get(getUndefConstant(loc, convertType(ty)));
2273 }
2274 llvm_unreachable("bad evaluation kind");
2275}
2276
2278 const CIRGenCallee &origCallee,
2279 const clang::CallExpr *e,
2281 // Get the actual function type. The callee type will always be a pointer to
2282 // function type or a block pointer type.
2283 assert(calleeTy->isFunctionPointerType() &&
2284 "Callee must have function pointer type!");
2285
2286 calleeTy = getContext().getCanonicalType(calleeTy);
2287 auto pointeeTy = cast<PointerType>(calleeTy)->getPointeeType();
2288
2289 CIRGenCallee callee = origCallee;
2290
2291 if (getLangOpts().CPlusPlus)
2293
2294 const auto *fnType = cast<FunctionType>(pointeeTy);
2295
2297
2298 CallArgList args;
2300
2301 // C++23 static-member operators (`static operator()` /
2302 // `static operator[]`) produce a CXXOperatorCallExpr whose first argument
2303 // is the object expression even though the operator is static. Emit the
2304 // object for its side effects and drop it before walking the parameter
2305 // arguments.
2306 auto arguments = e->arguments();
2307 if (const auto *oce = dyn_cast<CXXOperatorCallExpr>(e)) {
2308 if (const auto *md =
2309 dyn_cast_if_present<CXXMethodDecl>(oce->getCalleeDecl());
2310 md && md->isStatic()) {
2311 emitIgnoredExpr(e->getArg(0));
2312 arguments = llvm::drop_begin(arguments, 1);
2313 }
2314 }
2315
2316 emitCallArgs(args, dyn_cast<FunctionProtoType>(fnType), arguments,
2317 e->getDirectCallee());
2318
2319 const CIRGenFunctionInfo &funcInfo =
2320 cgm.getTypes().arrangeFreeFunctionCall(args, fnType);
2321
2322 // C99 6.5.2.2p6:
2323 // If the expression that denotes the called function has a type that does
2324 // not include a prototype, [the default argument promotions are performed].
2325 // If the number of arguments does not equal the number of parameters, the
2326 // behavior is undefined. If the function is defined with a type that
2327 // includes a prototype, and either the prototype ends with an ellipsis (,
2328 // ...) or the types of the arguments after promotion are not compatible
2329 // with the types of the parameters, the behavior is undefined. If the
2330 // function is defined with a type that does not include a prototype, and
2331 // the types of the arguments after promotion are not compatible with those
2332 // of the parameters after promotion, the behavior is undefined [except in
2333 // some trivial cases].
2334 // That is, in the general case, we should assume that a call through an
2335 // unprototyped function type works like a *non-variadic* call. The way we
2336 // make this work is to cast to the exxact type fo the promoted arguments.
2337 if (isa<FunctionNoProtoType>(fnType)) {
2340 cir::FuncType calleeTy = getTypes().getFunctionType(funcInfo);
2341 // get non-variadic function type
2342 calleeTy = cir::FuncType::get(calleeTy.getInputs(),
2343 calleeTy.getReturnType(), false);
2344 auto calleePtrTy = cir::PointerType::get(calleeTy);
2345
2346 mlir::Operation *fn = callee.getFunctionPointer();
2347 mlir::Value addr;
2348 if (auto funcOp = mlir::dyn_cast<cir::FuncOp>(fn)) {
2349 addr = cir::GetGlobalOp::create(
2350 builder, getLoc(e->getSourceRange()),
2351 cir::PointerType::get(funcOp.getFunctionType()), funcOp.getSymName());
2352 } else {
2353 addr = fn->getResult(0);
2354 }
2355
2356 fn = builder.createBitcast(addr, calleePtrTy).getDefiningOp();
2357 callee.setFunctionPointer(fn);
2358 }
2359
2361 assert(!cir::MissingFeatures::hip());
2363
2364 cir::CIRCallOpInterface callOp;
2365 RValue callResult = emitCall(funcInfo, callee, returnValue, args, &callOp,
2366 getLoc(e->getExprLoc()));
2367
2369
2370 return callResult;
2371}
2372
2374 e = e->IgnoreParens();
2375
2376 // Look through function-to-pointer decay.
2377 if (const auto *implicitCast = dyn_cast<ImplicitCastExpr>(e)) {
2378 if (implicitCast->getCastKind() == CK_FunctionToPointerDecay ||
2379 implicitCast->getCastKind() == CK_BuiltinFnToFnPtr) {
2380 return emitCallee(implicitCast->getSubExpr());
2381 }
2382 // Classic codegen has some handling here for ptr-auth (as a part of the
2383 // large ptr-auth-qualifier PR (#100830)). In the meantime, other cast kinds
2384 // can fall-through and be handled by the indirect call work below,
2385 // including L-to-R value conversions and atomic conversions.
2387
2388 } else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {
2389 // Resolve direct calls.
2390 if (const auto *funcDecl = dyn_cast<FunctionDecl>(declRef->getDecl()))
2391 return emitDirectCallee(funcDecl);
2392 } else if (auto me = dyn_cast<MemberExpr>(e)) {
2393 if (const auto *fd = dyn_cast<FunctionDecl>(me->getMemberDecl())) {
2394 emitIgnoredExpr(me->getBase());
2395 return emitDirectCallee(fd);
2396 }
2397 // Else fall through to the indirect reference handling below.
2398 } else if (auto *pde = dyn_cast<CXXPseudoDestructorExpr>(e)) {
2400 }
2401
2402 // Otherwise, we have an indirect reference.
2403 mlir::Value calleePtr;
2405 if (const auto *ptrType = e->getType()->getAs<clang::PointerType>()) {
2406 calleePtr = emitScalarExpr(e);
2407 functionType = ptrType->getPointeeType();
2408 } else {
2409 functionType = e->getType();
2410 calleePtr = emitLValue(e).getPointer();
2411 }
2412 assert(functionType->isFunctionType());
2413
2414 GlobalDecl gd;
2415 if (const auto *vd =
2416 dyn_cast_or_null<VarDecl>(e->getReferencedDeclOfCallee()))
2417 gd = GlobalDecl(vd);
2418
2419 CIRGenCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), gd);
2420 CIRGenCallee callee(calleeInfo, calleePtr.getDefiningOp());
2421 return callee;
2422}
2423
2427
2428 if (const auto *ce = dyn_cast<CXXMemberCallExpr>(e))
2430
2431 if (const auto *cudaKernelCallExpr = dyn_cast<CUDAKernelCallExpr>(e))
2433
2434 // A CXXOperatorCallExpr is created even for explicit-object methods or
2435 // static member operators (C++23 `static operator()` / `static
2436 // operator[]`), but those should be treated like ordinary static function
2437 // calls. Only route through the member-call path for ordinary instance
2438 // operators.
2439 if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(e)) {
2440 if (const auto *md =
2441 dyn_cast_if_present<CXXMethodDecl>(operatorCall->getCalleeDecl());
2442 md && md->isImplicitObjectMemberFunction())
2443 return emitCXXOperatorMemberCallExpr(operatorCall, md, returnValue);
2444 }
2445
2446 CIRGenCallee callee = emitCallee(e->getCallee());
2447
2448 if (callee.isBuiltin())
2449 return emitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(), e,
2450 returnValue);
2451
2452 if (callee.isPseudoDestructor())
2454
2455 return emitCall(e->getCallee()->getType(), callee, e, returnValue);
2456}
2457
2458/// Emit code to compute the specified expression, ignoring the result.
2460 if (e->isPRValue()) {
2461 emitAnyExpr(e, AggValueSlot::ignored(), /*ignoreResult=*/true);
2462 return;
2463 }
2464
2465 // Just emit it as an l-value and drop the result.
2466 emitLValue(e);
2467}
2468
2470 LValueBaseInfo *baseInfo) {
2472 assert(e->getType()->isArrayType() &&
2473 "Array to pointer decay must have array source type!");
2474
2475 // Expressions of array type can't be bitfields or vector elements.
2476 LValue lv = emitLValue(e);
2477 Address addr = lv.getAddress();
2478
2479 // If the array type was an incomplete type, we need to make sure
2480 // the decay ends up being the right type.
2481 auto lvalueAddrTy = mlir::cast<cir::PointerType>(addr.getPointer().getType());
2482
2483 if (e->getType()->isVariableArrayType())
2484 return addr;
2485
2486 [[maybe_unused]] auto pointeeTy =
2487 mlir::cast<cir::ArrayType>(lvalueAddrTy.getPointee());
2488
2489 [[maybe_unused]] mlir::Type arrayTy = convertType(e->getType());
2490 assert(mlir::isa<cir::ArrayType>(arrayTy) && "expected array");
2491 assert(pointeeTy == arrayTy);
2492
2493 // The result of this decay conversion points to an array element within the
2494 // base lvalue. However, since TBAA currently does not support representing
2495 // accesses to elements of member arrays, we conservatively represent accesses
2496 // to the pointee object as if it had no any base lvalue specified.
2497 // TODO: Support TBAA for member arrays.
2500
2501 mlir::Value ptr = builder.maybeBuildArrayDecay(
2502 cgm.getLoc(e->getSourceRange()), addr.getPointer(),
2503 convertTypeForMem(eltType));
2504 return Address(ptr, addr.getAlignment());
2505}
2506
2507/// Given the address of a temporary variable, produce an r-value of its type.
2511 switch (getEvaluationKind(type)) {
2512 case cir::TEK_Complex:
2513 return RValue::getComplex(emitLoadOfComplex(lvalue, loc));
2514 case cir::TEK_Aggregate:
2515 return lvalue.asAggregateRValue();
2516 case cir::TEK_Scalar:
2517 return RValue::get(emitLoadOfScalar(lvalue, loc));
2518 }
2519 llvm_unreachable("bad evaluation kind");
2520}
2521
2522/// Emit an `if` on a boolean condition, filling `then` and `else` into
2523/// appropriated regions.
2524mlir::LogicalResult CIRGenFunction::emitIfOnBoolExpr(const Expr *cond,
2525 const Stmt *thenS,
2526 const Stmt *elseS) {
2527 mlir::Location thenLoc = getLoc(thenS->getSourceRange());
2528 std::optional<mlir::Location> elseLoc;
2529 if (elseS)
2530 elseLoc = getLoc(elseS->getSourceRange());
2531
2532 mlir::LogicalResult resThen = mlir::success(), resElse = mlir::success();
2534 cond, /*thenBuilder=*/
2535 [&](mlir::OpBuilder &, mlir::Location) {
2536 LexicalScope lexScope{*this, thenLoc, builder.getInsertionBlock()};
2537 resThen = emitStmt(thenS, /*useCurrentScope=*/true);
2538 },
2539 thenLoc,
2540 /*elseBuilder=*/
2541 [&](mlir::OpBuilder &, mlir::Location) {
2542 assert(elseLoc && "Invalid location for elseS.");
2543 LexicalScope lexScope{*this, *elseLoc, builder.getInsertionBlock()};
2544 resElse = emitStmt(elseS, /*useCurrentScope=*/true);
2545 },
2546 elseLoc);
2547
2548 return mlir::LogicalResult::success(resThen.succeeded() &&
2549 resElse.succeeded());
2550}
2551
2552/// Emit an `if` on a boolean condition, filling `then` and `else` into
2553/// appropriated regions.
2555 const clang::Expr *cond, BuilderCallbackRef thenBuilder,
2556 mlir::Location thenLoc, BuilderCallbackRef elseBuilder,
2557 std::optional<mlir::Location> elseLoc) {
2558 // Attempt to be as accurate as possible with IfOp location, generate
2559 // one fused location that has either 2 or 4 total locations, depending
2560 // on else's availability.
2561 SmallVector<mlir::Location, 2> ifLocs{thenLoc};
2562 if (elseLoc)
2563 ifLocs.push_back(*elseLoc);
2564 mlir::Location loc = mlir::FusedLoc::get(&getMLIRContext(), ifLocs);
2565
2566 // Emit the code with the fully general case.
2567 mlir::Value condV = emitOpOnBoolExpr(loc, cond);
2568 cir::IfOp ifOp = cir::IfOp::create(builder, loc, condV, elseLoc.has_value(),
2569 /*thenBuilder=*/thenBuilder,
2570 /*elseBuilder=*/elseBuilder);
2571 terminateStructuredRegionBody(ifOp.getThenRegion(), thenLoc);
2572 assert((elseLoc.has_value() || ifOp.getElseRegion().empty()) &&
2573 "else region created with no else location");
2574 if (elseLoc.has_value())
2575 terminateStructuredRegionBody(ifOp.getElseRegion(), *elseLoc);
2576 return ifOp;
2577}
2578
2579/// TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
2580mlir::Value CIRGenFunction::emitOpOnBoolExpr(mlir::Location loc,
2581 const Expr *cond) {
2584 cond = cond->IgnoreParens();
2585
2586 // In LLVM the condition is reversed here for efficient codegen.
2587 // This should be done in CIR prior to LLVM lowering, if we do now
2588 // we can make CIR based diagnostics misleading.
2589 // cir.ternary(!x, t, f) -> cir.ternary(x, f, t)
2591
2592 if (const ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(cond)) {
2593 Expr *trueExpr = condOp->getTrueExpr();
2594 Expr *falseExpr = condOp->getFalseExpr();
2595 mlir::Value condV = emitOpOnBoolExpr(loc, condOp->getCond());
2596
2597 mlir::Value ternaryOpRes =
2598 cir::TernaryOp::create(
2599 builder, loc, condV, /*thenBuilder=*/
2600 [this, trueExpr](mlir::OpBuilder &b, mlir::Location loc) {
2601 mlir::Value lhs = emitScalarExpr(trueExpr);
2602 cir::YieldOp::create(b, loc, lhs);
2603 },
2604 /*elseBuilder=*/
2605 [this, falseExpr](mlir::OpBuilder &b, mlir::Location loc) {
2606 mlir::Value rhs = emitScalarExpr(falseExpr);
2607 cir::YieldOp::create(b, loc, rhs);
2608 })
2609 .getResult();
2610
2611 return emitScalarConversion(ternaryOpRes, condOp->getType(),
2612 getContext().BoolTy, condOp->getExprLoc());
2613 }
2614
2615 if (isa<CXXThrowExpr>(cond)) {
2616 cgm.errorNYI("NYI");
2617 return createDummyValue(loc, cond->getType());
2618 }
2619
2620 // If the branch has a condition wrapped by __builtin_unpredictable,
2621 // create metadata that specifies that the branch is unpredictable.
2622 // Don't bother if not optimizing because that metadata would not be used.
2624
2625 // Emit the code with the fully general case.
2626 return evaluateExprAsBool(cond);
2627}
2628
2629mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
2630 mlir::Location loc, CharUnits alignment,
2631 bool insertIntoFnEntryBlock,
2632 mlir::Value arraySize) {
2633 mlir::Block *entryBlock = insertIntoFnEntryBlock
2635 : curLexScope->getEntryBlock();
2636
2637 // If this is an alloca in the entry basic block of a cir.try and there's
2638 // a surrounding cir.scope, make sure the alloca ends up in the surrounding
2639 // scope instead. This is necessary in order to guarantee all SSA values are
2640 // reachable during cleanups.
2641 if (auto tryOp =
2642 llvm::dyn_cast_if_present<cir::TryOp>(entryBlock->getParentOp())) {
2643 if (auto scopeOp = llvm::dyn_cast<cir::ScopeOp>(tryOp->getParentOp()))
2644 entryBlock = &scopeOp.getScopeRegion().front();
2645 }
2646
2647 return emitAlloca(name, ty, loc, alignment,
2648 builder.getBestAllocaInsertPoint(entryBlock), arraySize);
2649}
2650
2651mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
2652 mlir::Location loc, CharUnits alignment,
2653 mlir::OpBuilder::InsertPoint ip,
2654 mlir::Value arraySize) {
2655 // CIR uses its own alloca address space rather than follow the target data
2656 // layout like original CodeGen. The data layout awareness should be done in
2657 // the lowering pass instead.
2658 cir::PointerType localVarPtrTy =
2660 mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);
2661
2662 mlir::Value addr;
2663 {
2664 mlir::OpBuilder::InsertionGuard guard(builder);
2665 builder.restoreInsertionPoint(ip);
2666 addr = builder.createAlloca(loc, /*addr type*/ localVarPtrTy,
2667 /*var type*/ ty, name, alignIntAttr, arraySize);
2669 }
2670 return addr;
2671}
2672
2673// Note: this function also emit constructor calls to support a MSVC extensions
2674// allowing explicit constructor function call.
2677 const Expr *callee = ce->getCallee()->IgnoreParens();
2678
2679 if (isa<BinaryOperator>(callee))
2681
2682 const auto *me = cast<MemberExpr>(callee);
2683 const auto *md = cast<CXXMethodDecl>(me->getMemberDecl());
2684
2685 if (md->isStatic()) {
2686 cgm.errorNYI(ce->getSourceRange(), "emitCXXMemberCallExpr: static method");
2687 return RValue::get(nullptr);
2688 }
2689
2690 bool hasQualifier = me->hasQualifier();
2691 NestedNameSpecifier qualifier = me->getQualifier();
2692 bool isArrow = me->isArrow();
2693 const Expr *base = me->getBase();
2694
2696 ce, md, returnValue, hasQualifier, qualifier, isArrow, base);
2697}
2698
2700 // Emit the expression as an lvalue.
2701 LValue lv = emitLValue(e);
2702 assert(lv.isSimple());
2703 mlir::Value value = lv.getPointer();
2704
2706
2707 return RValue::get(value);
2708}
2709
2711 LValueBaseInfo *pointeeBaseInfo) {
2712 if (refLVal.isVolatile())
2713 cgm.errorNYI(loc, "load of volatile reference");
2714
2715 cir::LoadOp load =
2716 cir::LoadOp::create(builder, loc, refLVal.getAddress().getElementType(),
2717 refLVal.getAddress().getPointer());
2718
2720
2721 QualType pointeeType = refLVal.getType()->getPointeeType();
2722 CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, pointeeBaseInfo);
2723 return Address(load, convertTypeForMem(pointeeType), align);
2724}
2725
2727 mlir::Location loc,
2728 QualType refTy,
2729 AlignmentSource source) {
2730 LValue refLVal = makeAddrLValue(refAddr, refTy, LValueBaseInfo(source));
2731 LValueBaseInfo pointeeBaseInfo;
2733 Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo);
2734 return makeAddrLValue(pointeeAddr, refLVal.getType()->getPointeeType(),
2735 pointeeBaseInfo);
2736}
2737
2738void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) {
2739 cir::TrapOp::create(builder, loc);
2740 if (createNewBlock)
2741 builder.createBlock(builder.getBlock()->getParent());
2742}
2743
2745 bool createNewBlock) {
2747 cir::UnreachableOp::create(builder, getLoc(loc));
2748 if (createNewBlock)
2749 builder.createBlock(builder.getBlock()->getParent());
2750}
2751
2752mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,
2753 clang::QualType qt) {
2754 mlir::Type t = convertType(qt);
2755 CharUnits alignment = getContext().getTypeAlignInChars(qt);
2756 return builder.createDummyValue(loc, t, alignment);
2757}
2758
2759//===----------------------------------------------------------------------===//
2760// CIR builder helpers
2761//===----------------------------------------------------------------------===//
2762
2764 mlir::Location loc,
2765 const Twine &name) {
2767 convertTypeForMem(ty), getContext().getTypeAlignInChars(ty), loc, name);
2768}
2769
2771 const Twine &name, Address *alloca,
2772 mlir::OpBuilder::InsertPoint ip) {
2773 // FIXME: Should we prefer the preferred type alignment here?
2774 return createMemTemp(ty, getContext().getTypeAlignInChars(ty), loc, name,
2775 alloca, ip);
2776}
2777
2779 mlir::Location loc, const Twine &name,
2780 Address *alloca,
2781 mlir::OpBuilder::InsertPoint ip) {
2782 Address result =
2783 createTempAlloca(convertTypeForMem(ty), /*destAddrSpace=*/{}, align, loc,
2784 name, /*arraySize=*/nullptr, alloca, ip);
2785 if (ty->isConstantMatrixType()) {
2787 cgm.errorNYI(loc, "temporary matrix value");
2788 }
2789 return result;
2790}
2791
2792/// This creates a alloca and inserts it into the entry block of the
2793/// current region.
2795 mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name,
2796 mlir::Value arraySize, mlir::OpBuilder::InsertPoint ip) {
2797 cir::AllocaOp alloca = ip.isSet()
2798 ? createTempAlloca(ty, loc, name, ip, arraySize)
2799 : createTempAlloca(ty, loc, name, arraySize);
2800 alloca.setAlignmentAttr(cgm.getSize(align));
2801 return Address(alloca, ty, align);
2802}
2803
2805 mlir::Location loc, const Twine &name,
2806 mlir::Value arraySize,
2807 Address *allocaAddr,
2808 mlir::OpBuilder::InsertPoint ip) {
2809 return createTempAlloca(ty, /*destAddrSpace=*/{}, align, loc, name, arraySize,
2810 allocaAddr, ip);
2811}
2812
2814 Address alloca, mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2815 mlir::Value arraySize) {
2816 if (!destAddrSpace)
2817 destAddrSpace = cir::toCIRAddressSpaceAttr(
2818 getMLIRContext(), cgm.getLangTempAllocaAddressSpace());
2819
2820 mlir::ptr::MemorySpaceAttrInterface srcAddrSpace = getCIRAllocaAddressSpace();
2821 // Alloca always returns a pointer in alloca address space, which may
2822 // be different from the type defined by the language. For example,
2823 // in C++ the auto variables are in the default address space. Therefore
2824 // cast alloca to the default address space when necessary.
2825 if (srcAddrSpace == destAddrSpace)
2826 return alloca;
2827
2828 mlir::OpBuilder::InsertionGuard guard(builder);
2829 if (cir::AllocaOp allocaOp = alloca.getUnderlyingAllocaOp()) {
2830 builder.setInsertionPointAfter(allocaOp);
2831 } else if (!arraySize) {
2832 mlir::Block *entryBlock = getCurFunctionEntryBlock();
2833 builder.restoreInsertionPoint(builder.getBestAllocaInsertPoint(entryBlock));
2834 }
2835
2836 mlir::Type destPtrTy =
2837 builder.getPointerTo(alloca.getElementType(), destAddrSpace);
2838 mlir::Value casted = performAddrSpaceCast(alloca.getPointer(), destPtrTy);
2839 return Address(casted, alloca.getElementType(), alloca.getAlignment(),
2840 /*isKnownNonNull=*/true);
2841}
2842
2843/// This creates a alloca and inserts it into the entry block. The alloca is
2844/// casted to the requested language address space if necessary.
2846 mlir::Type ty, mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2847 CharUnits align, mlir::Location loc, const Twine &name,
2848 mlir::Value arraySize, Address *allocaAddr,
2849 mlir::OpBuilder::InsertPoint ip) {
2850 Address alloca =
2851 createTempAllocaWithoutCast(ty, align, loc, name, arraySize, ip);
2852 if (allocaAddr)
2853 *allocaAddr = alloca;
2854 return maybeCastStackAddressSpace(alloca, destAddrSpace, arraySize);
2855}
2856
2857/// This creates an alloca and inserts it into the entry block if \p ArraySize
2858/// is nullptr, otherwise inserts it at the current insertion point of the
2859/// builder.
2860cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
2861 mlir::Location loc,
2862 const Twine &name,
2863 mlir::Value arraySize,
2864 bool insertIntoFnEntryBlock) {
2865 return mlir::cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(),
2866 insertIntoFnEntryBlock, arraySize)
2867 .getDefiningOp());
2868}
2869
2870/// This creates an alloca and inserts it into the provided insertion point
2871cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
2872 mlir::Location loc,
2873 const Twine &name,
2874 mlir::OpBuilder::InsertPoint ip,
2875 mlir::Value arraySize) {
2876 assert(ip.isSet() && "Insertion point is not set");
2877 return mlir::cast<cir::AllocaOp>(
2878 emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize)
2879 .getDefiningOp());
2880}
2881
2882/// CreateDefaultAlignTempAlloca - This creates an alloca with the
2883/// default alignment of the corresponding LLVM type, which is *not*
2884/// guaranteed to be related in any way to the expected alignment of
2885/// an AST type that might have been lowered to Ty.
2887 mlir::Location loc,
2888 const Twine &name) {
2889 CharUnits align =
2890 CharUnits::fromQuantity(cgm.getDataLayout().getABITypeAlign(ty));
2891 return createTempAlloca(ty, align, loc, name);
2892}
2893
2894/// Try to emit a reference to the given value without producing it as
2895/// an l-value. For many cases, this is just an optimization, but it avoids
2896/// us needing to emit global copies of variables if they're named without
2897/// triggering a formal use in a context where we can't emit a direct
2898/// reference to them, for instance if a block or lambda or a member of a
2899/// local class uses a const int variable or constexpr variable from an
2900/// enclosing function.
2901///
2902/// For named members of enums, this is the only way they are emitted.
2905 const ValueDecl *value = refExpr->getDecl();
2906
2907 // There is a lot more to do here, but for now only EnumConstantDecl is
2908 // supported.
2910
2911 // The value needs to be an enum constant or a constant variable.
2912 if (!isa<EnumConstantDecl>(value))
2913 return ConstantEmission();
2914
2915 Expr::EvalResult result;
2916 if (!refExpr->EvaluateAsRValue(result, getContext()))
2917 return ConstantEmission();
2918
2919 QualType resultType = refExpr->getType();
2920
2921 // As long as we're only handling EnumConstantDecl, there should be no
2922 // side-effects.
2923 assert(!result.HasSideEffects);
2924
2925 // Emit as a constant.
2926 // FIXME(cir): have emitAbstract build a TypedAttr instead (this requires
2927 // somewhat heavy refactoring...)
2928 mlir::Attribute c = ConstantEmitter(*this).emitAbstract(
2929 refExpr->getLocation(), result.Val, resultType);
2930 mlir::TypedAttr cstToEmit = mlir::dyn_cast_if_present<mlir::TypedAttr>(c);
2931 assert(cstToEmit && "expected a typed attribute");
2932
2934
2935 return ConstantEmission::forValue(cstToEmit);
2936}
2937
2941 return tryEmitAsConstant(dre);
2942 return ConstantEmission();
2943}
2944
2946 const CIRGenFunction::ConstantEmission &constant, Expr *e) {
2947 assert(constant && "not a constant");
2948 if (constant.isReference()) {
2949 cgm.errorNYI(e->getSourceRange(), "emitScalarConstant: reference");
2950 return {};
2951 }
2952 return builder.getConstant(getLoc(e->getSourceRange()), constant.getValue());
2953}
2954
2956 const StringLiteral *sl = e->getFunctionName();
2957 assert(sl != nullptr && "No StringLiteral name in PredefinedExpr");
2958 auto fn = cast<cir::FuncOp>(curFn);
2959 StringRef fnName = fn.getName();
2960 fnName.consume_front("\01");
2961 std::array<StringRef, 2> nameItems = {
2963 std::string gvName = llvm::join(nameItems, ".");
2964 if (isa_and_nonnull<BlockDecl>(curCodeDecl))
2965 cgm.errorNYI(e->getSourceRange(), "predefined lvalue in block");
2966
2967 return emitStringLiteralLValue(sl, gvName);
2968}
2969
2974
2975namespace {
2976// Handle the case where the condition is a constant evaluatable simple integer,
2977// which means we don't have to separately handle the true/false blocks.
2978std::optional<LValue> handleConditionalOperatorLValueSimpleCase(
2980 const Expr *condExpr = e->getCond();
2981 llvm::APSInt condExprVal;
2982 if (!cgf.constantFoldsToSimpleInteger(condExpr, condExprVal))
2983 return std::nullopt;
2984
2985 const Expr *live = e->getTrueExpr(), *dead = e->getFalseExpr();
2986 if (!condExprVal.getBoolValue())
2987 std::swap(live, dead);
2988
2989 if (cgf.containsLabel(dead))
2990 return std::nullopt;
2991
2992 // If the true case is live, we need to track its region.
2995 // If a throw expression we emit it and return an undefined lvalue
2996 // because it can't be used.
2997 if (auto *throwExpr = dyn_cast<CXXThrowExpr>(live->IgnoreParens())) {
2998 cgf.emitCXXThrowExpr(throwExpr);
2999 // Return an undefined lvalue - the throw terminates execution
3000 // so this value will never actually be used
3001 mlir::Type elemTy = cgf.convertType(dead->getType());
3002 mlir::Value undefPtr =
3003 cgf.getBuilder().getNullPtr(cgf.getBuilder().getPointerTo(elemTy),
3004 cgf.getLoc(throwExpr->getSourceRange()));
3005 return cgf.makeAddrLValue(Address(undefPtr, elemTy, CharUnits::One()),
3006 dead->getType());
3007 }
3008 return cgf.emitLValue(live);
3009}
3010
3011/// Emit the operand of a glvalue conditional operator. This is either a glvalue
3012/// or a (possibly-parenthesized) throw-expression. If this is a throw, no
3013/// LValue is returned and the current block has been terminated.
3014static std::optional<LValue> emitLValueOrThrowExpression(CIRGenFunction &cgf,
3015 const Expr *operand) {
3016 if (auto *throwExpr = dyn_cast<CXXThrowExpr>(operand->IgnoreParens())) {
3017 cgf.emitCXXThrowExpr(throwExpr);
3018 return std::nullopt;
3019 }
3020
3021 return cgf.emitLValue(operand);
3022}
3023} // namespace
3024
3025// Create and generate the 3 blocks for a conditional operator.
3026// Leaves the 'current block' in the continuation basic block.
3027template <typename FuncTy>
3030 const FuncTy &branchGenFunc) {
3031 ConditionalInfo info;
3032 ConditionalEvaluation eval(*this);
3033 mlir::Location loc = getLoc(e->getSourceRange());
3034 CIRGenBuilderTy &builder = getBuilder();
3035
3036 mlir::Value condV = emitOpOnBoolExpr(loc, e->getCond());
3038 mlir::Type yieldTy{};
3039
3040 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc,
3041 const Expr *expr, std::optional<LValue> &resultLV) {
3042 CIRGenFunction::LexicalScope lexScope{*this, loc, b.getInsertionBlock()};
3043 curLexScope->setAsTernary();
3044
3045 mlir::Value resultPtr;
3046 {
3047 // Emit any cleanups that were needed on this branch so we can spill
3048 // and reload the return value.
3049 CIRGenFunction::RunCleanupsScope branchCleanups(*this);
3051 eval.beginEvaluation();
3052 resultLV = branchGenFunc(*this, expr);
3053 resultPtr = resultLV ? resultLV->getPointer() : mlir::Value();
3054 eval.endEvaluation();
3055 branchCleanups.forceCleanup({&resultPtr});
3056 }
3057
3058 if (resultPtr) {
3059 yieldTy = resultPtr.getType();
3060 cir::YieldOp::create(b, loc, resultPtr);
3061 } else {
3062 // If LHS or RHS is a void expression we need
3063 // to patch arms as to properly match yield types.
3064 // If the current block's terminator is an UnreachableOp (from a throw),
3065 // we don't need a yield
3066 if (builder.getInsertionBlock()->mightHaveTerminator()) {
3067 mlir::Operation *terminator =
3068 builder.getInsertionBlock()->getTerminator();
3069 if (isa_and_nonnull<cir::UnreachableOp>(terminator))
3070 insertPoints.push_back(b.saveInsertionPoint());
3071 }
3072 }
3073 };
3074
3075 info.result = cir::TernaryOp::create(
3076 builder, loc, condV,
3077 /*trueBuilder=*/
3078 [&](mlir::OpBuilder &b, mlir::Location loc) {
3079 emitBranch(b, loc, e->getTrueExpr(), info.lhs);
3080 },
3081 /*falseBuilder=*/
3082 [&](mlir::OpBuilder &b, mlir::Location loc) {
3083 emitBranch(b, loc, e->getFalseExpr(), info.rhs);
3084 })
3085 .getResult();
3086
3087 // If both arms are void, so be it.
3088 if (!yieldTy)
3089 yieldTy = voidTy;
3090
3091 // Insert required yields.
3092 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
3093 mlir::OpBuilder::InsertionGuard guard(builder);
3094 builder.restoreInsertionPoint(toInsert);
3095
3096 // Block does not return: build empty yield.
3097 if (!yieldTy) {
3098 cir::YieldOp::create(builder, loc);
3099 } else { // Block returns: set null yield value.
3100 mlir::Value op0 = builder.getNullValue(yieldTy, loc);
3101 cir::YieldOp::create(builder, loc, op0);
3102 }
3103 }
3104
3105 return info;
3106}
3107
3110 if (!expr->isGLValue()) {
3111 // ?: here should be an aggregate.
3112 assert(hasAggregateEvaluationKind(expr->getType()) &&
3113 "Unexpected conditional operator!");
3114 return emitAggExprToLValue(expr);
3115 }
3116
3117 OpaqueValueMapping binding(*this, expr);
3118 if (std::optional<LValue> res =
3119 handleConditionalOperatorLValueSimpleCase(*this, expr))
3120 return *res;
3121
3122 ConditionalInfo info =
3123 emitConditionalBlocks(expr, [](CIRGenFunction &cgf, const Expr *e) {
3124 return emitLValueOrThrowExpression(cgf, e);
3125 });
3126
3127 if ((info.lhs && !info.lhs->isSimple()) ||
3128 (info.rhs && !info.rhs->isSimple())) {
3129 cgm.errorNYI(expr->getSourceRange(),
3130 "unsupported conditional operator with non-simple lvalue");
3131 return LValue();
3132 }
3133
3134 if (info.lhs && info.rhs) {
3135 Address lhsAddr = info.lhs->getAddress();
3136 Address rhsAddr = info.rhs->getAddress();
3137 Address result(info.result, lhsAddr.getElementType(),
3138 std::min(lhsAddr.getAlignment(), rhsAddr.getAlignment()));
3139 AlignmentSource alignSource =
3140 std::max(info.lhs->getBaseInfo().getAlignmentSource(),
3141 info.rhs->getBaseInfo().getAlignmentSource());
3143 return makeAddrLValue(result, expr->getType(), LValueBaseInfo(alignSource));
3144 }
3145
3146 assert((info.lhs || info.rhs) &&
3147 "both operands of glvalue conditional are throw-expressions?");
3148 return info.lhs ? *info.lhs : *info.rhs;
3149}
3150
3151/// An LValue is a candidate for having its loads and stores be made atomic if
3152/// we are operating under /volatile:ms *and* the LValue itself is volatile and
3153/// performing such an operation can be performed without a libcall.
3155 if (!cgm.getLangOpts().MSVolatile)
3156 return false;
3157
3158 cgm.errorNYI("LValueSuitableForInlineAtomic LangOpts MSVolatile");
3159 return false;
3160}
3161
#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
__device__ __2f16 b
__device__ __2f16 float c
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::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy, mlir::Value base, llvm::StringRef name, unsigned index)
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 createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, mlir::IntegerAttr alignment, mlir::Value dynAllocSize)
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:228
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:3796
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)
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 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 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)
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)
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)
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...
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()
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.
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 a C++ destructor within a class.
Definition DeclCXX.h:2882
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:1372
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:1608
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:1956
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:3337
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:493
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:84
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:3093
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:1551
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:282
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:4443
void getEncodedElementAccess(SmallVectorImpl< uint32_t > &Elts) const
getEncodedElementAccess - Encode the elements accessed into an llvm aggregate Constant of ConstantInt...
Definition Expr.cpp:4556
Represents a member of a struct/union/class.
Definition Decl.h:3178
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3281
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4800
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3263
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3414
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
Definition Decl.cpp:4778
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:5369
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:3715
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:3390
[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:8485
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:4343
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:3946
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:9048
bool isBooleanType() const
Definition TypeBase.h:9185
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2289
bool isPackedVectorBoolType(const ASTContext &ctx) const
Definition Type.cpp:455
const ArrayType * castAsArrayTypeUnsafe() const
A variant of castAs<> for array type which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9351
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:8781
bool isFunctionPointerType() const
Definition TypeBase.h:8749
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
bool isArithmeticType() const
Definition Type.cpp:2422
bool isConstantMatrixType() const
Definition TypeBase.h:8849
bool isPointerType() const
Definition TypeBase.h:8682
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9342
bool isReferenceType() const
Definition TypeBase.h:8706
bool isVariableArrayType() const
Definition TypeBase.h:8793
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isExtVectorBoolType() const
Definition TypeBase.h:8829
bool isAnyComplexType() const
Definition TypeBase.h:8817
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
Definition TypeBase.h:9228
bool isAtomicType() const
Definition TypeBase.h:8874
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2862
bool isFunctionType() const
Definition TypeBase.h:8678
bool isVectorType() const
Definition TypeBase.h:8821
bool isSubscriptableVectorType() const
Definition TypeBase.h:8841
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9275
bool hasBooleanRepresentation() const
Determine whether this type has a boolean representation – i.e., it is a boolean type,...
Definition Type.cpp:2444
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:4028
Represents a GCC generic vector type.
Definition TypeBase.h:4237
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
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