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 break;
2069
2070 case SD_Dynamic:
2071 llvm_unreachable("temporary cannot have dynamic storage duration");
2072 }
2073}
2074
2076 const MaterializeTemporaryExpr *m) {
2077 const Expr *e = m->getSubExpr();
2078
2079 assert((!m->getExtendingDecl() || !isa<VarDecl>(m->getExtendingDecl()) ||
2080 !cast<VarDecl>(m->getExtendingDecl())->isARCPseudoStrong()) &&
2081 "Reference should never be pseudo-strong!");
2082
2083 // FIXME: ideally this would use emitAnyExprToMem, however, we cannot do so
2084 // as that will cause the lifetime adjustment to be lost for ARC
2085 auto ownership = m->getType().getObjCLifetime();
2086 if (ownership != Qualifiers::OCL_None &&
2087 ownership != Qualifiers::OCL_ExplicitNone) {
2088 cgm.errorNYI(e->getSourceRange(),
2089 "emitMaterializeTemporaryExpr: ObjCLifetime");
2090 return {};
2091 }
2092
2095 e = e->skipRValueSubobjectAdjustments(commaLHSs, adjustments);
2096
2097 for (const Expr *ignored : commaLHSs)
2098 emitIgnoredExpr(ignored);
2099
2100 if (isa<OpaqueValueExpr>(e)) {
2101 cgm.errorNYI(e->getSourceRange(),
2102 "emitMaterializeTemporaryExpr: OpaqueValueExpr");
2103 return {};
2104 }
2105
2106 // Create and initialize the reference temporary.
2107 Address object = createReferenceTemporary(*this, m, e);
2108 cir::GlobalOp var = nullptr;
2109 if (auto getGlobalOp = object.getPointer().getDefiningOp<cir::GetGlobalOp>())
2110 var = mlir::dyn_cast_or_null<cir::GlobalOp>(
2111 cgm.getGlobalValue(getGlobalOp.getName()));
2112
2113 if (var) {
2114 if (!var.getInitialValue().has_value()) {
2115 var.setInitialValueAttr(builder.getZeroInitAttr(var.getSymType()));
2117 emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);
2118 }
2119 } else {
2121 emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);
2122 }
2123 pushTemporaryCleanup(*this, m, e, object);
2124
2125 // Perform derived-to-base casts and/or field accesses, to get from the
2126 // temporary object we created (and, potentially, for which we extended
2127 // the lifetime) to the subobject we're binding the reference to.
2128 for (SubobjectAdjustment &adjustment : llvm::reverse(adjustments)) {
2129 switch (adjustment.Kind) {
2131 object =
2132 getAddressOfBaseClass(object, adjustment.DerivedToBase.DerivedClass,
2133 adjustment.DerivedToBase.BasePath->path(),
2134 /*nullCheckValue=*/false, e->getExprLoc());
2135 break;
2138 lv = emitLValueForField(lv, adjustment.Field);
2139 assert(lv.isSimple() &&
2140 "materialized temporary field is not a simple lvalue");
2141 object = lv.getAddress();
2142 break;
2143 }
2145 mlir::Value ptr = emitScalarExpr(adjustment.Ptr.RHS);
2147 e, object, ptr, adjustment.Ptr.MPT, /*baseInfo=*/nullptr);
2148 break;
2149 }
2150 }
2151 }
2152
2153 return makeAddrLValue(object, m->getType(), AlignmentSource::Decl);
2154}
2155
2156LValue
2159
2160 auto it = opaqueLValues.find(e);
2161 if (it != opaqueLValues.end())
2162 return it->second;
2163
2164 assert(e->isUnique() && "LValue for a nonunique OVE hasn't been emitted");
2165 return emitLValue(e->getSourceExpr());
2166}
2167
2168RValue
2171
2172 auto it = opaqueRValues.find(e);
2173 if (it != opaqueRValues.end())
2174 return it->second;
2175
2176 assert(e->isUnique() && "RValue for a nonunique OVE hasn't been emitted");
2177 return emitAnyExpr(e->getSourceExpr());
2178}
2179
2181 if (e->isFileScope()) {
2182 cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope");
2183 return {};
2184 }
2185
2186 if (e->getType()->isVariablyModifiedType())
2188
2189 Address declPtr = createMemTemp(e->getType(), getLoc(e->getSourceRange()),
2190 ".compoundliteral");
2191 const Expr *initExpr = e->getInitializer();
2192 LValue result = makeAddrLValue(declPtr, e->getType(), AlignmentSource::Decl);
2193
2194 emitAnyExprToMem(initExpr, declPtr, e->getType().getQualifiers(),
2195 /*Init*/ true);
2196
2197 // Block-scope compound literals are destroyed at the end of the enclosing
2198 // scope in C.
2199 if (!getLangOpts().CPlusPlus && e->getType().isDestructedType()) {
2200 cgm.errorNYI(e->getSourceRange(),
2201 "emitCompoundLiteralLValue: non C++ DestructedType");
2202 return {};
2203 }
2204
2205 return result;
2206}
2207
2209 RValue rv = emitCallExpr(e);
2210
2211 if (!rv.isScalar())
2212 return makeAddrLValue(rv.getAggregateAddress(), e->getType(),
2214
2215 assert(e->getCallReturnType(getContext())->isReferenceType() &&
2216 "Can't have a scalar return unless the return type is a "
2217 "reference type!");
2218
2220}
2221
2222LValue
2231
2234 "binding l-value to type which needs a temporary");
2236 emitCXXConstructExpr(e, slot);
2238}
2239
2241 // Comma expressions just emit their LHS then their RHS as an l-value.
2242 if (e->getOpcode() == BO_Comma) {
2243 emitIgnoredExpr(e->getLHS());
2244 return emitLValue(e->getRHS());
2245 }
2246
2247 if (e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI)
2249
2250 assert(e->getOpcode() == BO_Assign && "unexpected binary l-value");
2251
2252 // Note that in all of these cases, __block variables need the RHS
2253 // evaluated first just in case the variable gets moved by the RHS.
2254
2256 case cir::TEK_Scalar: {
2258 if (e->getLHS()->getType().getObjCLifetime() !=
2260 cgm.errorNYI(e->getSourceRange(), "objc lifetimes");
2261 return {};
2262 }
2263
2264 RValue rv = emitAnyExpr(e->getRHS());
2265 LValue lv = emitLValue(e->getLHS());
2266
2267 SourceLocRAIIObject loc{*this, e->getSourceRange()};
2268 if (lv.isBitField())
2270 else
2271 emitStoreThroughLValue(rv, lv);
2272
2273 if (getLangOpts().OpenMP) {
2274 cgm.errorNYI(e->getSourceRange(), "openmp");
2275 return {};
2276 }
2277
2278 return lv;
2279 }
2280
2281 case cir::TEK_Complex: {
2283 }
2284
2285 case cir::TEK_Aggregate:
2286 cgm.errorNYI(e->getSourceRange(), "aggregate lvalues");
2287 return {};
2288 }
2289 llvm_unreachable("bad evaluation kind");
2290}
2291
2292/// Emit code to compute the specified expression which
2293/// can have any type. The result is returned as an RValue struct.
2295 bool ignoreResult) {
2297 case cir::TEK_Scalar:
2298 return RValue::get(emitScalarExpr(e, ignoreResult));
2299 case cir::TEK_Complex:
2301 case cir::TEK_Aggregate: {
2302 if (!ignoreResult && aggSlot.isIgnored())
2303 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
2305 emitAggExpr(e, aggSlot);
2306 return aggSlot.asRValue();
2307 }
2308 }
2309 llvm_unreachable("bad evaluation kind");
2310}
2311
2312CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {
2313 const auto *fd = cast<FunctionDecl>(gd.getDecl());
2314
2315 if (unsigned builtinID = fd->getBuiltinID()) {
2316 StringRef ident = cgm.getMangledName(gd);
2317 std::string fdInlineName = (ident + ".inline").str();
2318
2319 bool isPredefinedLibFunction =
2321 // TODO: Read no-builtin function attribute and set this accordingly.
2322 // Using false here matches OGCG's default behavior - builtins are called
2323 // as builtins unless explicitly disabled. The previous value of true was
2324 // overly conservative and caused functions to be marked as no_inline when
2325 // they shouldn't be.
2326 bool hasAttributeNoBuiltin = false;
2328
2329 // When directly calling an inline builtin, call it through it's mangled
2330 // name to make it clear it's not the actual builtin.
2331 if (auto fn = dyn_cast<cir::FuncOp>(curFn);
2332 (!fn || fn.getName() != fdInlineName) &&
2334 cir::FuncOp clone =
2335 mlir::cast_or_null<cir::FuncOp>(cgm.getGlobalValue(fdInlineName));
2336
2337 if (!clone) {
2338 // Create a forward declaration - the body will be generated in
2339 // generateCode when the function definition is processed
2340 cir::FuncOp calleeFunc = emitFunctionDeclPointer(cgm, gd);
2341 mlir::OpBuilder::InsertionGuard guard(builder);
2342 builder.setInsertionPointToStart(cgm.getModule().getBody());
2343
2344 clone = cir::FuncOp::create(builder, calleeFunc.getLoc(), fdInlineName,
2345 calleeFunc.getFunctionType());
2346 cgm.insertGlobalSymbol(clone);
2347 clone.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
2348 &cgm.getMLIRContext(), cir::GlobalLinkageKind::InternalLinkage));
2349 clone.setSymVisibility("private");
2350 clone.setInlineKind(cir::InlineKind::AlwaysInline);
2351 }
2352 return CIRGenCallee::forDirect(clone, gd);
2353 }
2354
2355 // Replaceable builtins provide their own implementation of a builtin. If we
2356 // are in an inline builtin implementation, avoid trivial infinite
2357 // recursion. Honor __attribute__((no_builtin("foo"))) or
2358 // __attribute__((no_builtin)) on the current function unless foo is
2359 // not a predefined library function which means we must generate the
2360 // builtin no matter what.
2361 else if (!isPredefinedLibFunction || !hasAttributeNoBuiltin)
2362 return CIRGenCallee::forBuiltin(builtinID, fd);
2363 }
2364
2365 cir::FuncOp callee = emitFunctionDeclPointer(cgm, gd);
2366
2367 if ((cgm.getLangOpts().CUDA || cgm.getLangOpts().HIP) &&
2368 !cgm.getLangOpts().CUDAIsDevice && fd->hasAttr<CUDAGlobalAttr>()) {
2369 mlir::Operation *handle = cgm.getCUDARuntime().getKernelHandle(callee, gd);
2370 callee =
2371 mlir::cast<cir::FuncOp>(*cgm.getCUDARuntime().getKernelStub(handle));
2372 }
2373
2374 return CIRGenCallee::forDirect(callee, gd);
2375}
2376
2377mlir::Value CIRGenFunction::getUndefConstant(mlir::Location loc,
2378 mlir::Type cirTy) {
2379 return builder.getConstant(loc, cir::UndefAttr::get(cirTy));
2380}
2381
2383 if (ty->isVoidType())
2384 return RValue::get(nullptr);
2385
2386 mlir::Location loc = builder.getUnknownLoc();
2387
2388 switch (getEvaluationKind(ty)) {
2389 case cir::TEK_Complex: {
2390 QualType elemTy = ty->castAs<ComplexType>()->getElementType();
2391 mlir::Type elemCirTy = convertType(elemTy);
2392 mlir::Value undefElem = getUndefConstant(loc, elemCirTy);
2393 mlir::Value v = builder.createComplexCreate(loc, undefElem, undefElem);
2394 return RValue::getComplex(v);
2395 }
2396
2397 // If this is a use of an undefined aggregate type, the aggregate must have
2398 // an identifiable address. Just because the contents of the value are
2399 // undefined doesn't mean that the address can't be taken and compared.
2400 case cir::TEK_Aggregate: {
2401 Address destPtr = createMemTempWithoutCast(ty, loc, "undef.agg.tmp");
2402 return RValue::getAggregate(destPtr);
2403 }
2404
2405 case cir::TEK_Scalar:
2406 return RValue::get(getUndefConstant(loc, convertType(ty)));
2407 }
2408 llvm_unreachable("bad evaluation kind");
2409}
2410
2412 const CIRGenCallee &origCallee,
2413 const clang::CallExpr *e,
2415 // Get the actual function type. The callee type will always be a pointer to
2416 // function type or a block pointer type.
2417 assert(calleeTy->isFunctionPointerType() &&
2418 "Callee must have function pointer type!");
2419
2420 calleeTy = getContext().getCanonicalType(calleeTy);
2421 auto pointeeTy = cast<PointerType>(calleeTy)->getPointeeType();
2422
2423 CIRGenCallee callee = origCallee;
2424
2425 if (getLangOpts().CPlusPlus)
2427
2428 const auto *fnType = cast<FunctionType>(pointeeTy);
2429
2431
2432 CallArgList args;
2434
2435 // C++23 static-member operators (`static operator()` /
2436 // `static operator[]`) produce a CXXOperatorCallExpr whose first argument
2437 // is the object expression even though the operator is static. Emit the
2438 // object for its side effects and drop it before walking the parameter
2439 // arguments.
2440 auto arguments = e->arguments();
2441 if (const auto *oce = dyn_cast<CXXOperatorCallExpr>(e)) {
2442 if (const auto *md =
2443 dyn_cast_if_present<CXXMethodDecl>(oce->getCalleeDecl());
2444 md && md->isStatic()) {
2445 emitIgnoredExpr(e->getArg(0));
2446 arguments = llvm::drop_begin(arguments, 1);
2447 }
2448 }
2449
2450 emitCallArgs(args, dyn_cast<FunctionProtoType>(fnType), arguments,
2451 e->getDirectCallee());
2452
2453 const CIRGenFunctionInfo &funcInfo =
2454 cgm.getTypes().arrangeFreeFunctionCall(args, fnType);
2455
2456 // C99 6.5.2.2p6:
2457 // If the expression that denotes the called function has a type that does
2458 // not include a prototype, [the default argument promotions are performed].
2459 // If the number of arguments does not equal the number of parameters, the
2460 // behavior is undefined. If the function is defined with a type that
2461 // includes a prototype, and either the prototype ends with an ellipsis (,
2462 // ...) or the types of the arguments after promotion are not compatible
2463 // with the types of the parameters, the behavior is undefined. If the
2464 // function is defined with a type that does not include a prototype, and
2465 // the types of the arguments after promotion are not compatible with those
2466 // of the parameters after promotion, the behavior is undefined [except in
2467 // some trivial cases].
2468 // That is, in the general case, we should assume that a call through an
2469 // unprototyped function type works like a *non-variadic* call. The way we
2470 // make this work is to cast to the exxact type fo the promoted arguments.
2471 if (isa<FunctionNoProtoType>(fnType)) {
2474 cir::FuncType calleeTy = getTypes().getFunctionType(funcInfo);
2475 // get non-variadic function type
2476 calleeTy = cir::FuncType::get(calleeTy.getInputs(),
2477 calleeTy.getReturnType(), false);
2478 auto calleePtrTy = cir::PointerType::get(calleeTy);
2479
2480 mlir::Operation *fn = callee.getFunctionPointer();
2481 mlir::Value addr;
2482 if (auto funcOp = mlir::dyn_cast<cir::FuncOp>(fn)) {
2483 addr = cir::GetGlobalOp::create(
2484 builder, getLoc(e->getSourceRange()),
2485 cir::PointerType::get(funcOp.getFunctionType()), funcOp.getSymName());
2486 } else {
2487 addr = fn->getResult(0);
2488 }
2489
2490 fn = builder.createBitcast(addr, calleePtrTy).getDefiningOp();
2491 callee.setFunctionPointer(fn);
2492 }
2493
2495
2496 // HIP function pointer contains kernel handle when it is used in triple
2497 // chevron. The kernel stub needs to be loaded from kernel handle and used
2498 // as callee.
2499 const clang::Decl *targetDecl =
2500 origCallee.getAbstractInfo().getCalleeDecl().getDecl();
2501 if (getLangOpts().HIP && !getLangOpts().CUDAIsDevice &&
2503 (!targetDecl || !isa<FunctionDecl>(targetDecl))) {
2504 mlir::Value handleAddr = callee.getFunctionPointer()->getResult(0);
2505 mlir::Location loc = getLoc(e->getSourceRange());
2506 auto handlePtrTy = mlir::cast<cir::PointerType>(handleAddr.getType());
2507 mlir::Value handleAddrAddr =
2508 builder.createBitcast(handleAddr, cir::PointerType::get(handlePtrTy));
2509 cir::LoadOp stub = builder.createLoad(
2510 loc, Address(handleAddrAddr, handlePtrTy, getPointerAlign()));
2511 callee.setFunctionPointer(stub.getOperation());
2512 }
2513
2514 cir::CIRCallOpInterface callOp;
2515 RValue callResult = emitCall(funcInfo, callee, returnValue, args, &callOp,
2516 e == mustTailCall, e->getSourceRange());
2517
2519
2520 return callResult;
2521}
2522
2524 e = e->IgnoreParens();
2525
2526 // Look through function-to-pointer decay.
2527 if (const auto *implicitCast = dyn_cast<ImplicitCastExpr>(e)) {
2528 if (implicitCast->getCastKind() == CK_FunctionToPointerDecay ||
2529 implicitCast->getCastKind() == CK_BuiltinFnToFnPtr) {
2530 return emitCallee(implicitCast->getSubExpr());
2531 }
2532 // Classic codegen has some handling here for ptr-auth (as a part of the
2533 // large ptr-auth-qualifier PR (#100830)). In the meantime, other cast kinds
2534 // can fall-through and be handled by the indirect call work below,
2535 // including L-to-R value conversions and atomic conversions.
2537
2538 } else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {
2539 // Resolve direct calls.
2540 if (const auto *funcDecl = dyn_cast<FunctionDecl>(declRef->getDecl()))
2541 return emitDirectCallee(funcDecl);
2542 } else if (auto me = dyn_cast<MemberExpr>(e)) {
2543 if (const auto *fd = dyn_cast<FunctionDecl>(me->getMemberDecl())) {
2544 emitIgnoredExpr(me->getBase());
2545 return emitDirectCallee(fd);
2546 }
2547 // Else fall through to the indirect reference handling below.
2548 } else if (auto *pde = dyn_cast<CXXPseudoDestructorExpr>(e)) {
2550 }
2551
2552 // Otherwise, we have an indirect reference.
2553 mlir::Value calleePtr;
2555 if (const auto *ptrType = e->getType()->getAs<clang::PointerType>()) {
2556 calleePtr = emitScalarExpr(e);
2557 functionType = ptrType->getPointeeType();
2558 } else {
2559 functionType = e->getType();
2560 calleePtr = emitLValue(e).getPointer();
2561 }
2562 assert(functionType->isFunctionType());
2563
2564 GlobalDecl gd;
2565 if (const auto *vd =
2566 dyn_cast_or_null<VarDecl>(e->getReferencedDeclOfCallee()))
2567 gd = GlobalDecl(vd);
2568
2569 CIRGenCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), gd);
2570 CIRGenCallee callee(calleeInfo, calleePtr.getDefiningOp());
2571 return callee;
2572}
2573
2577
2578 if (const auto *ce = dyn_cast<CXXMemberCallExpr>(e))
2580
2581 if (const auto *cudaKernelCallExpr = dyn_cast<CUDAKernelCallExpr>(e))
2583
2584 // A CXXOperatorCallExpr is created even for explicit-object methods or
2585 // static member operators (C++23 `static operator()` / `static
2586 // operator[]`), but those should be treated like ordinary static function
2587 // calls. Only route through the member-call path for ordinary instance
2588 // operators.
2589 if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(e)) {
2590 if (const auto *md =
2591 dyn_cast_if_present<CXXMethodDecl>(operatorCall->getCalleeDecl());
2592 md && md->isImplicitObjectMemberFunction())
2593 return emitCXXOperatorMemberCallExpr(operatorCall, md, returnValue);
2594 }
2595
2596 CIRGenCallee callee = emitCallee(e->getCallee());
2597
2598 if (callee.isBuiltin())
2599 return emitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(), e,
2600 returnValue);
2601
2602 if (callee.isPseudoDestructor())
2604
2605 return emitCall(e->getCallee()->getType(), callee, e, returnValue);
2606}
2607
2608/// Emit code to compute the specified expression, ignoring the result.
2610 if (e->isPRValue()) {
2611 emitAnyExpr(e, AggValueSlot::ignored(), /*ignoreResult=*/true);
2612 return;
2613 }
2614
2615 // Just emit it as an l-value and drop the result.
2616 emitLValue(e);
2617}
2618
2620 LValueBaseInfo *baseInfo) {
2622 assert(e->getType()->isArrayType() &&
2623 "Array to pointer decay must have array source type!");
2624
2625 // Expressions of array type can't be bitfields or vector elements.
2626 LValue lv = emitLValue(e);
2627 Address addr = lv.getAddress();
2628
2629 if (e->getType()->isVariableArrayType())
2630 return addr;
2631
2632 // If the array type was an incomplete type, we need to make sure
2633 // the decay ends up being the right type.
2634 mlir::Type arrayTy = convertType(e->getType());
2635 assert(mlir::isa<cir::ArrayType>(arrayTy) && "expected array");
2636 addr = addr.withElementType(builder, arrayTy);
2637
2638 // The result of this decay conversion points to an array element within the
2639 // base lvalue. However, since TBAA currently does not support representing
2640 // accesses to elements of member arrays, we conservatively represent accesses
2641 // to the pointee object as if it had no any base lvalue specified.
2642 // TODO: Support TBAA for member arrays.
2645
2646 mlir::Value ptr = builder.maybeBuildArrayDecay(
2647 cgm.getLoc(e->getSourceRange()), addr.getPointer(),
2648 convertTypeForMem(eltType));
2649 return Address(ptr, addr.getAlignment());
2650}
2651
2652/// Given the address of a temporary variable, produce an r-value of its type.
2656 switch (getEvaluationKind(type)) {
2657 case cir::TEK_Complex:
2658 return RValue::getComplex(emitLoadOfComplex(lvalue, loc));
2659 case cir::TEK_Aggregate:
2660 return lvalue.asAggregateRValue();
2661 case cir::TEK_Scalar:
2662 return RValue::get(emitLoadOfScalar(lvalue, loc));
2663 }
2664 llvm_unreachable("bad evaluation kind");
2665}
2666
2667/// Emit an `if` on a boolean condition, filling `then` and `else` into
2668/// appropriated regions.
2669mlir::LogicalResult CIRGenFunction::emitIfOnBoolExpr(const Expr *cond,
2670 const Stmt *thenS,
2671 const Stmt *elseS) {
2672 mlir::Location thenLoc = getLoc(thenS->getSourceRange());
2673 std::optional<mlir::Location> elseLoc;
2674 if (elseS)
2675 elseLoc = getLoc(elseS->getSourceRange());
2676
2677 mlir::LogicalResult resThen = mlir::success(), resElse = mlir::success();
2679 cond, /*thenBuilder=*/
2680 [&](mlir::OpBuilder &, mlir::Location) {
2681 LexicalScope lexScope{*this, thenLoc, builder.getInsertionBlock()};
2682 resThen = emitStmt(thenS, /*useCurrentScope=*/true);
2683 },
2684 thenLoc,
2685 /*elseBuilder=*/
2686 [&](mlir::OpBuilder &, mlir::Location) {
2687 assert(elseLoc && "Invalid location for elseS.");
2688 LexicalScope lexScope{*this, *elseLoc, builder.getInsertionBlock()};
2689 resElse = emitStmt(elseS, /*useCurrentScope=*/true);
2690 },
2691 elseLoc);
2692
2693 return mlir::LogicalResult::success(resThen.succeeded() &&
2694 resElse.succeeded());
2695}
2696
2697/// Emit an `if` on a boolean condition, filling `then` and `else` into
2698/// appropriated regions.
2700 const clang::Expr *cond, BuilderCallbackRef thenBuilder,
2701 mlir::Location thenLoc, BuilderCallbackRef elseBuilder,
2702 std::optional<mlir::Location> elseLoc) {
2703 // Attempt to be as accurate as possible with IfOp location, generate
2704 // one fused location that has either 2 or 4 total locations, depending
2705 // on else's availability.
2706 SmallVector<mlir::Location, 2> ifLocs{thenLoc};
2707 if (elseLoc)
2708 ifLocs.push_back(*elseLoc);
2709 mlir::Location loc = mlir::FusedLoc::get(&getMLIRContext(), ifLocs);
2710
2711 // Emit the code with the fully general case.
2712 mlir::Value condV = emitOpOnBoolExpr(loc, cond);
2713 return emitIfOnBoolValue(condV, loc, thenBuilder, thenLoc, elseBuilder,
2714 elseLoc);
2715}
2716
2718 mlir::Value condV, mlir::Location loc, BuilderCallbackRef thenBuilder,
2719 mlir::Location thenLoc, BuilderCallbackRef elseBuilder,
2720 std::optional<mlir::Location> elseLoc) {
2721 cir::IfOp ifOp = cir::IfOp::create(builder, loc, condV, elseLoc.has_value(),
2722 /*thenBuilder=*/thenBuilder,
2723 /*elseBuilder=*/elseBuilder);
2724 terminateStructuredRegionBody(ifOp.getThenRegion(), thenLoc);
2725 assert((elseLoc.has_value() || ifOp.getElseRegion().empty()) &&
2726 "else region created with no else location");
2727 if (elseLoc.has_value())
2728 terminateStructuredRegionBody(ifOp.getElseRegion(), *elseLoc);
2729 return ifOp;
2730}
2731
2732/// TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
2733mlir::Value CIRGenFunction::emitOpOnBoolExpr(mlir::Location loc,
2734 const Expr *cond) {
2737 cond = cond->IgnoreParens();
2738
2739 // In LLVM the condition is reversed here for efficient codegen.
2740 // This should be done in CIR prior to LLVM lowering, if we do now
2741 // we can make CIR based diagnostics misleading.
2742 // cir.ternary(!x, t, f) -> cir.ternary(x, f, t)
2744
2745 if (const ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(cond)) {
2746 Expr *trueExpr = condOp->getTrueExpr();
2747 Expr *falseExpr = condOp->getFalseExpr();
2748 mlir::Value condV = emitOpOnBoolExpr(loc, condOp->getCond());
2749
2750 mlir::Value ternaryOpRes =
2751 cir::TernaryOp::create(
2752 builder, loc, condV, /*thenBuilder=*/
2753 [this, trueExpr](mlir::OpBuilder &b, mlir::Location loc) {
2754 mlir::Value lhs = emitScalarExpr(trueExpr);
2755 cir::YieldOp::create(b, loc, lhs);
2756 },
2757 /*elseBuilder=*/
2758 [this, falseExpr](mlir::OpBuilder &b, mlir::Location loc) {
2759 mlir::Value rhs = emitScalarExpr(falseExpr);
2760 cir::YieldOp::create(b, loc, rhs);
2761 })
2762 .getResult();
2763
2764 return emitScalarConversion(ternaryOpRes, condOp->getType(),
2765 getContext().BoolTy, condOp->getExprLoc());
2766 }
2767
2768 if (isa<CXXThrowExpr>(cond)) {
2769 cgm.errorNYI("NYI");
2770 return createDummyValue(loc, cond->getType());
2771 }
2772
2773 // If the branch has a condition wrapped by __builtin_unpredictable,
2774 // create metadata that specifies that the branch is unpredictable.
2775 // Don't bother if not optimizing because that metadata would not be used.
2777
2778 // Emit the code with the fully general case.
2779 return evaluateExprAsBool(cond);
2780}
2781
2782mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
2783 mlir::Location loc, CharUnits alignment,
2784 bool insertIntoFnEntryBlock,
2785 mlir::Value arraySize) {
2786 mlir::Block *entryBlock = insertIntoFnEntryBlock
2788 : curLexScope->getEntryBlock();
2789
2790 // If this is an alloca in the entry basic block of a cir.try and there's
2791 // a surrounding cir.scope, make sure the alloca ends up in the surrounding
2792 // scope instead. This is necessary in order to guarantee all SSA values are
2793 // reachable during cleanups.
2794 if (auto tryOp =
2795 llvm::dyn_cast_if_present<cir::TryOp>(entryBlock->getParentOp())) {
2796 if (auto scopeOp = llvm::dyn_cast<cir::ScopeOp>(tryOp->getParentOp()))
2797 entryBlock = &scopeOp.getScopeRegion().front();
2798 }
2799
2800 return emitAlloca(name, ty, loc, alignment,
2801 builder.getBestAllocaInsertPoint(entryBlock), arraySize);
2802}
2803
2804mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
2805 mlir::Location loc, CharUnits alignment,
2806 mlir::OpBuilder::InsertPoint ip,
2807 mlir::Value arraySize) {
2808 // CIR uses its own alloca address space rather than follow the target data
2809 // layout like original CodeGen. The data layout awareness should be done in
2810 // the lowering pass instead.
2811 cir::PointerType localVarPtrTy =
2813 mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);
2814
2815 mlir::Value addr;
2816 {
2817 mlir::OpBuilder::InsertionGuard guard(builder);
2818 builder.restoreInsertionPoint(ip);
2819 addr = builder.createAlloca(loc, /*addr type*/ localVarPtrTy, name,
2820 alignIntAttr, arraySize);
2822 }
2823 return addr;
2824}
2825
2826// Note: this function also emit constructor calls to support a MSVC extensions
2827// allowing explicit constructor function call.
2830 const Expr *callee = ce->getCallee()->IgnoreParens();
2831
2832 if (isa<BinaryOperator>(callee))
2834
2835 const auto *me = cast<MemberExpr>(callee);
2836 const auto *md = cast<CXXMethodDecl>(me->getMemberDecl());
2837
2838 if (md->isStatic()) {
2839 cgm.errorNYI(ce->getSourceRange(), "emitCXXMemberCallExpr: static method");
2840 return RValue::get(nullptr);
2841 }
2842
2843 bool hasQualifier = me->hasQualifier();
2844 NestedNameSpecifier qualifier = me->getQualifier();
2845 bool isArrow = me->isArrow();
2846 const Expr *base = me->getBase();
2847
2849 ce, md, returnValue, hasQualifier, qualifier, isArrow, base);
2850}
2851
2853 // Emit the expression as an lvalue.
2854 LValue lv = emitLValue(e);
2855 assert(lv.isSimple());
2856 mlir::Value value = lv.getPointer();
2857
2859
2860 return RValue::get(value);
2861}
2862
2864 LValueBaseInfo *pointeeBaseInfo) {
2865 if (refLVal.isVolatile())
2866 cgm.errorNYI(loc, "load of volatile reference");
2867
2868 cir::LoadOp load =
2869 cir::LoadOp::create(builder, loc, refLVal.getAddress().getElementType(),
2870 refLVal.getAddress().getPointer());
2871
2873
2875 CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, pointeeBaseInfo);
2876 return Address(load, convertTypeForMem(pointeeType), align);
2877}
2878
2880 mlir::Location loc,
2881 QualType refTy,
2882 AlignmentSource source) {
2883 LValue refLVal = makeAddrLValue(refAddr, refTy, LValueBaseInfo(source));
2884 LValueBaseInfo pointeeBaseInfo;
2886 Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo);
2887 return makeAddrLValue(pointeeAddr, refLVal.getType()->getPointeeType(),
2888 pointeeBaseInfo);
2889}
2890
2891void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) {
2892 cir::TrapOp::create(builder, loc);
2893 if (createNewBlock)
2894 builder.createBlock(builder.getBlock()->getParent());
2895}
2896
2898 bool createNewBlock) {
2900 cir::UnreachableOp::create(builder, getLoc(loc));
2901 if (createNewBlock)
2902 builder.createBlock(builder.getBlock()->getParent());
2903}
2904
2905mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,
2906 clang::QualType qt) {
2907 mlir::Type t = convertType(qt);
2908 CharUnits alignment = getContext().getTypeAlignInChars(qt);
2909 return builder.createDummyValue(loc, t, alignment);
2910}
2911
2912//===----------------------------------------------------------------------===//
2913// CIR builder helpers
2914//===----------------------------------------------------------------------===//
2915
2917 mlir::Location loc,
2918 const Twine &name) {
2920 convertTypeForMem(ty), getContext().getTypeAlignInChars(ty), loc, name);
2921}
2922
2924 const Twine &name, Address *alloca,
2925 mlir::OpBuilder::InsertPoint ip) {
2926 // FIXME: Should we prefer the preferred type alignment here?
2927 return createMemTemp(ty, getContext().getTypeAlignInChars(ty), loc, name,
2928 alloca, ip);
2929}
2930
2932 mlir::Location loc, const Twine &name,
2933 Address *alloca,
2934 mlir::OpBuilder::InsertPoint ip) {
2935 Address result =
2936 createTempAlloca(convertTypeForMem(ty), /*destAddrSpace=*/{}, align, loc,
2937 name, /*arraySize=*/nullptr, alloca, ip);
2938 if (ty->isConstantMatrixType()) {
2940 cgm.errorNYI(loc, "createMemTemp constant matrix type");
2941 return Address::invalid();
2942 }
2943
2944 return result;
2945}
2946
2947/// This creates a alloca and inserts it into the entry block of the
2948/// current region.
2950 mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name,
2951 mlir::Value arraySize, mlir::OpBuilder::InsertPoint ip) {
2952 cir::AllocaOp alloca = ip.isSet()
2953 ? createTempAlloca(ty, loc, name, ip, arraySize)
2954 : createTempAlloca(ty, loc, name, arraySize);
2955 alloca.setAlignmentAttr(cgm.getSize(align));
2956 return Address(alloca, ty, align);
2957}
2958
2960 mlir::Location loc, const Twine &name,
2961 mlir::Value arraySize,
2962 Address *allocaAddr,
2963 mlir::OpBuilder::InsertPoint ip) {
2964 return createTempAlloca(ty, /*destAddrSpace=*/{}, align, loc, name, arraySize,
2965 allocaAddr, ip);
2966}
2967
2969 Address alloca, mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2970 mlir::Value arraySize) {
2971 if (!destAddrSpace)
2972 destAddrSpace = cir::toCIRAddressSpaceAttr(
2973 getMLIRContext(), cgm.getLangTempAllocaAddressSpace());
2974
2975 // Resolve the default address space through getTargetAddressSpace, as
2976 // classic CodeGen does and as CIRGenTypes::getPointerAddressSpace does for
2977 // default pointer types. This is only non-zero for targets where the default
2978 // address space is not 0 (e.g. generic for SYCL device code).
2979 if (!cir::normalizeDefaultAddressSpace(destAddrSpace))
2980 if (unsigned targetAS = getContext().getTargetAddressSpace(LangAS::Default))
2981 destAddrSpace =
2982 cir::TargetAddressSpaceAttr::get(&getMLIRContext(), targetAS);
2983
2984 mlir::ptr::MemorySpaceAttrInterface srcAddrSpace = getCIRAllocaAddressSpace();
2985 // Alloca always returns a pointer in alloca address space, which may
2986 // be different from the type defined by the language. For example,
2987 // in C++ the auto variables are in the default address space. Therefore
2988 // cast alloca to the default address space when necessary.
2989 if (srcAddrSpace == destAddrSpace)
2990 return alloca;
2991
2992 mlir::OpBuilder::InsertionGuard guard(builder);
2993 if (cir::AllocaOp allocaOp = alloca.getUnderlyingAllocaOp()) {
2994 builder.setInsertionPointAfter(allocaOp);
2995 } else if (!arraySize) {
2996 mlir::Block *entryBlock = getCurFunctionEntryBlock();
2997 builder.restoreInsertionPoint(builder.getBestAllocaInsertPoint(entryBlock));
2998 }
2999
3000 mlir::Type destPtrTy =
3001 builder.getPointerTo(alloca.getElementType(), destAddrSpace);
3002 mlir::Value casted = performAddrSpaceCast(alloca.getPointer(), destPtrTy);
3003 return Address(casted, alloca.getElementType(), alloca.getAlignment(),
3004 /*isKnownNonNull=*/true);
3005}
3006
3007/// This creates a alloca and inserts it into the entry block. The alloca is
3008/// casted to the requested language address space if necessary.
3010 mlir::Type ty, mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
3011 CharUnits align, mlir::Location loc, const Twine &name,
3012 mlir::Value arraySize, Address *allocaAddr,
3013 mlir::OpBuilder::InsertPoint ip) {
3014 Address alloca =
3015 createTempAllocaWithoutCast(ty, align, loc, name, arraySize, ip);
3016 if (allocaAddr)
3017 *allocaAddr = alloca;
3018 return maybeCastStackAddressSpace(alloca, destAddrSpace, arraySize);
3019}
3020
3021/// This creates an alloca and inserts it into the entry block if \p ArraySize
3022/// is nullptr, otherwise inserts it at the current insertion point of the
3023/// builder.
3024cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
3025 mlir::Location loc,
3026 const Twine &name,
3027 mlir::Value arraySize,
3028 bool insertIntoFnEntryBlock) {
3029 return mlir::cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(),
3030 insertIntoFnEntryBlock, arraySize)
3031 .getDefiningOp());
3032}
3033
3034/// This creates an alloca and inserts it into the provided insertion point
3035cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
3036 mlir::Location loc,
3037 const Twine &name,
3038 mlir::OpBuilder::InsertPoint ip,
3039 mlir::Value arraySize) {
3040 assert(ip.isSet() && "Insertion point is not set");
3041 return mlir::cast<cir::AllocaOp>(
3042 emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize)
3043 .getDefiningOp());
3044}
3045
3046/// CreateDefaultAlignTempAlloca - This creates an alloca with the
3047/// default alignment of the corresponding LLVM type, which is *not*
3048/// guaranteed to be related in any way to the expected alignment of
3049/// an AST type that might have been lowered to Ty.
3051 mlir::Location loc,
3052 const Twine &name) {
3053 CharUnits align =
3054 CharUnits::fromQuantity(cgm.getDataLayout().getABITypeAlign(ty));
3055 return createTempAlloca(ty, align, loc, name);
3056}
3057
3058/// Try to emit a reference to the given value without producing it as
3059/// an l-value. For many cases, this is just an optimization, but it avoids
3060/// us needing to emit global copies of variables if they're named without
3061/// triggering a formal use in a context where we can't emit a direct
3062/// reference to them, for instance if a block or lambda or a member of a
3063/// local class uses a const int variable or constexpr variable from an
3064/// enclosing function.
3065///
3066/// For named members of enums, this is the only way they are emitted.
3069 const ValueDecl *value = refExpr->getDecl();
3070
3071 // There is a lot more to do here, but for now only EnumConstantDecl is
3072 // supported.
3074
3075 // The value needs to be an enum constant or a constant variable.
3076 if (!isa<EnumConstantDecl>(value))
3077 return ConstantEmission();
3078
3079 Expr::EvalResult result;
3080 if (!refExpr->EvaluateAsRValue(result, getContext()))
3081 return ConstantEmission();
3082
3083 QualType resultType = refExpr->getType();
3084
3085 // As long as we're only handling EnumConstantDecl, there should be no
3086 // side-effects.
3087 assert(!result.HasSideEffects);
3088
3089 // Emit as a constant.
3090 // FIXME(cir): have emitAbstract build a TypedAttr instead (this requires
3091 // somewhat heavy refactoring...)
3092 mlir::Attribute c = ConstantEmitter(*this).emitAbstract(
3093 refExpr->getLocation(), result.Val, resultType);
3094 mlir::TypedAttr cstToEmit = mlir::dyn_cast_if_present<mlir::TypedAttr>(c);
3095 assert(cstToEmit && "expected a typed attribute");
3096
3098
3099 return ConstantEmission::forValue(cstToEmit);
3100}
3101
3105 return tryEmitAsConstant(dre);
3106 return ConstantEmission();
3107}
3108
3110 const CIRGenFunction::ConstantEmission &constant, Expr *e) {
3111 assert(constant && "not a constant");
3112 if (constant.isReference()) {
3113 cgm.errorNYI(e->getSourceRange(), "emitScalarConstant: reference");
3114 return {};
3115 }
3116 return builder.getConstant(getLoc(e->getSourceRange()), constant.getValue());
3117}
3118
3120 const StringLiteral *sl = e->getFunctionName();
3121 assert(sl != nullptr && "No StringLiteral name in PredefinedExpr");
3122 auto fn = cast<cir::FuncOp>(curFn);
3123 StringRef fnName = fn.getName();
3124 fnName.consume_front("\01");
3125 std::array<StringRef, 2> nameItems = {
3127 std::string gvName = llvm::join(nameItems, ".");
3128 if (isa_and_nonnull<BlockDecl>(curCodeDecl))
3129 cgm.errorNYI(e->getSourceRange(), "predefined lvalue in block");
3130
3131 return emitStringLiteralLValue(sl, gvName);
3132}
3133
3138
3139namespace {
3140// Handle the case where the condition is a constant evaluatable simple integer,
3141// which means we don't have to separately handle the true/false blocks.
3142std::optional<LValue> handleConditionalOperatorLValueSimpleCase(
3144 const Expr *condExpr = e->getCond();
3145 llvm::APSInt condExprVal;
3146 if (!cgf.constantFoldsToSimpleInteger(condExpr, condExprVal))
3147 return std::nullopt;
3148
3149 const Expr *live = e->getTrueExpr(), *dead = e->getFalseExpr();
3150 if (!condExprVal.getBoolValue())
3151 std::swap(live, dead);
3152
3153 if (cgf.containsLabel(dead))
3154 return std::nullopt;
3155
3156 // If the true case is live, we need to track its region.
3159 // If a throw expression we emit it and return an undefined lvalue
3160 // because it can't be used.
3161 if (auto *throwExpr = dyn_cast<CXXThrowExpr>(live->IgnoreParens())) {
3162 cgf.emitCXXThrowExpr(throwExpr);
3163 // Return an undefined lvalue - the throw terminates execution
3164 // so this value will never actually be used
3165 mlir::Type elemTy = cgf.convertType(dead->getType());
3166 mlir::Value undefPtr =
3167 cgf.getBuilder().getNullPtr(cgf.getBuilder().getPointerTo(elemTy),
3168 cgf.getLoc(throwExpr->getSourceRange()));
3169 return cgf.makeAddrLValue(Address(undefPtr, elemTy, CharUnits::One()),
3170 dead->getType());
3171 }
3172 return cgf.emitLValue(live);
3173}
3174
3175/// Emit the operand of a glvalue conditional operator. This is either a glvalue
3176/// or a (possibly-parenthesized) throw-expression. If this is a throw, no
3177/// LValue is returned and the current block has been terminated.
3178static std::optional<LValue> emitLValueOrThrowExpression(CIRGenFunction &cgf,
3179 const Expr *operand) {
3180 if (auto *throwExpr = dyn_cast<CXXThrowExpr>(operand->IgnoreParens())) {
3181 cgf.emitCXXThrowExpr(throwExpr);
3182 return std::nullopt;
3183 }
3184
3185 return cgf.emitLValue(operand);
3186}
3187} // namespace
3188
3189// Create and generate the 3 blocks for a conditional operator.
3190// Leaves the 'current block' in the continuation basic block.
3191template <typename FuncTy>
3194 const FuncTy &branchGenFunc) {
3195 ConditionalInfo info;
3196 mlir::Location loc = getLoc(e->getSourceRange());
3197 CIRGenBuilderTy &builder = getBuilder();
3198
3199 mlir::Value condV = emitOpOnBoolExpr(loc, e->getCond());
3200
3201 ConditionalEvaluation eval(*this, loc);
3202
3203 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc,
3204 const Expr *expr, std::optional<LValue> &resultLV) {
3205 CIRGenFunction::LexicalScope lexScope{*this, loc, b.getInsertionBlock()};
3206 curLexScope->setAsTernary();
3207
3208 mlir::Value resultPtr;
3209 {
3210 // Emit any cleanups that were needed on this branch so we can spill
3211 // and reload the return value.
3212 CIRGenFunction::RunCleanupsScope branchCleanups(*this);
3214 eval.beginEvaluation();
3215 resultLV = branchGenFunc(*this, expr);
3216 resultPtr = resultLV ? resultLV->getPointer() : mlir::Value();
3217 eval.endEvaluation();
3218 branchCleanups.forceCleanup({&resultPtr});
3219 }
3220
3221 // A branch that produced no result is a throw-expression; its region is
3222 // already terminated by cir.unreachable and needs no yield.
3223 if (resultPtr)
3224 cir::YieldOp::create(b, loc, resultPtr);
3225 };
3226
3227 cir::TernaryOp ternary = cir::TernaryOp::create(
3228 builder, loc, condV,
3229 /*trueBuilder=*/
3230 [&](mlir::OpBuilder &b, mlir::Location loc) {
3231 emitBranch(b, loc, e->getTrueExpr(), info.lhs);
3232 },
3233 /*falseBuilder=*/
3234 [&](mlir::OpBuilder &b, mlir::Location loc) {
3235 emitBranch(b, loc, e->getFalseExpr(), info.rhs);
3236 });
3237
3238 // Arms end with a yield or cir.unreachable (throw); this is a backstop
3239 // for error (NYI) paths that leave a region open.
3240 terminateStructuredRegionBody(ternary.getTrueRegion(), loc);
3241 terminateStructuredRegionBody(ternary.getFalseRegion(), loc);
3242
3243 info.result = ternary.getResult();
3244 return info;
3245}
3246
3249 if (!expr->isGLValue()) {
3250 // ?: here should be an aggregate.
3251 assert(hasAggregateEvaluationKind(expr->getType()) &&
3252 "Unexpected conditional operator!");
3253 return emitAggExprToLValue(expr);
3254 }
3255
3256 OpaqueValueMapping binding(*this, expr);
3257 if (std::optional<LValue> res =
3258 handleConditionalOperatorLValueSimpleCase(*this, expr))
3259 return *res;
3260
3261 ConditionalInfo info =
3262 emitConditionalBlocks(expr, [](CIRGenFunction &cgf, const Expr *e) {
3263 return emitLValueOrThrowExpression(cgf, e);
3264 });
3265
3266 if ((info.lhs && !info.lhs->isSimple()) ||
3267 (info.rhs && !info.rhs->isSimple())) {
3268 cgm.errorNYI(expr->getSourceRange(),
3269 "unsupported conditional operator with non-simple lvalue");
3270 return LValue();
3271 }
3272
3273 if (info.lhs && info.rhs) {
3274 Address lhsAddr = info.lhs->getAddress();
3275 Address rhsAddr = info.rhs->getAddress();
3276 Address result(info.result, lhsAddr.getElementType(),
3277 std::min(lhsAddr.getAlignment(), rhsAddr.getAlignment()));
3278 AlignmentSource alignSource =
3279 std::max(info.lhs->getBaseInfo().getAlignmentSource(),
3280 info.rhs->getBaseInfo().getAlignmentSource());
3282 return makeAddrLValue(result, expr->getType(), LValueBaseInfo(alignSource));
3283 }
3284
3285 assert((info.lhs || info.rhs) &&
3286 "both operands of glvalue conditional are throw-expressions?");
3287
3288 // One arm threw; the surviving arm's pointer is local to the ternary's
3289 // region, so address the result through the ternary's result value.
3290 const LValue &survivingLV = info.lhs ? *info.lhs : *info.rhs;
3291 Address survivingAddr = survivingLV.getAddress();
3292 Address result(info.result, survivingAddr.getElementType(),
3293 survivingAddr.getAlignment());
3295 return makeAddrLValue(result, expr->getType(), survivingLV.getBaseInfo());
3296}
3297
3298/// An LValue is a candidate for having its loads and stores be made atomic if
3299/// we are operating under /volatile:ms *and* the LValue itself is volatile and
3300/// performing such an operation can be performed without a libcall.
3302 if (!cgm.getLangOpts().MSVolatile)
3303 return false;
3304
3305 cgm.errorNYI("LValueSuitableForInlineAtomic LangOpts MSVolatile");
3306 return false;
3307}
3308
#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:609
uint64_t getElementOffset(const mlir::DataLayout &dataLayout, unsigned idx) const
Definition CIRTypes.cpp:667
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
Builtin::Context & BuiltinInfo
Definition ASTContext.h: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)
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.
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={})
void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its RValue mapping if it exists, otherwise create one.
Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, mlir::OpBuilder::InsertPoint ip={})
This creates a alloca and inserts it into the entry block of the current region.
mlir::Value emitFromMemory(mlir::Value value, clang::QualType ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e, const FuncTy &branchGenFunc)
Address createDefaultAlignTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name)
CreateDefaultAlignTempAlloca - This creates an alloca with the default alignment of the corresponding...
LValue emitCXXConstructLValue(const CXXConstructExpr *e)
RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr)
LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e)
CIRGenCallee emitCallee(const clang::Expr *e)
Address emitAddrOfFieldStorage(Address base, const FieldDecl *field, llvm::StringRef fieldName, unsigned fieldIndex)
This class organizes the cross-function state that is used while generating CIR code.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd)
clang::ASTContext & getASTContext() const
void insertGlobalSymbol(mlir::Operation *op)
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