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