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