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