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