clang 22.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 "mlir/IR/BuiltinAttributes.h"
19#include "mlir/IR/Value.h"
20#include "clang/AST/Attr.h"
21#include "clang/AST/CharUnits.h"
22#include "clang/AST/Decl.h"
23#include "clang/AST/Expr.h"
24#include "clang/AST/ExprCXX.h"
27#include <optional>
28
29using namespace clang;
30using namespace clang::CIRGen;
31using namespace cir;
32
33/// Get the address of a zero-sized field within a record. The resulting address
34/// doesn't necessarily have the right type.
36 const FieldDecl *field,
37 llvm::StringRef fieldName,
38 unsigned fieldIndex) {
39 if (field->isZeroSize(getContext())) {
41 "emitAddrOfFieldStorage: zero-sized field");
42 return Address::invalid();
43 }
44
45 mlir::Location loc = getLoc(field->getLocation());
46
47 mlir::Type fieldType = convertType(field->getType());
48 auto fieldPtr = cir::PointerType::get(fieldType);
49 // For most cases fieldName is the same as field->getName() but for lambdas,
50 // which do not currently carry the name, so it can be passed down from the
51 // CaptureStmt.
52 cir::GetMemberOp memberAddr = builder.createGetMember(
53 loc, fieldPtr, base.getPointer(), fieldName, fieldIndex);
54
55 // Retrieve layout information, compute alignment and return the final
56 // address.
57 const RecordDecl *rec = field->getParent();
59 unsigned idx = layout.getCIRFieldNo(field);
61 layout.getCIRType().getElementOffset(cgm.getDataLayout().layout, idx));
62 return Address(memberAddr, base.getAlignment().alignmentAtOffset(offset));
63}
64
65/// Given an expression of pointer type, try to
66/// derive a more accurate bound on the alignment of the pointer.
68 LValueBaseInfo *baseInfo) {
69 // We allow this with ObjC object pointers because of fragile ABIs.
70 assert(expr->getType()->isPointerType() ||
71 expr->getType()->isObjCObjectPointerType());
72 expr = expr->IgnoreParens();
73
74 // Casts:
75 if (auto const *ce = dyn_cast<CastExpr>(expr)) {
76 if (const auto *ece = dyn_cast<ExplicitCastExpr>(ce))
78
79 switch (ce->getCastKind()) {
80 // Non-converting casts (but not C's implicit conversion from void*).
81 case CK_BitCast:
82 case CK_NoOp:
83 case CK_AddressSpaceConversion: {
84 if (const auto *ptrTy =
85 ce->getSubExpr()->getType()->getAs<PointerType>()) {
86 if (ptrTy->getPointeeType()->isVoidType())
87 break;
88
89 LValueBaseInfo innerBaseInfo;
91 Address addr =
92 emitPointerWithAlignment(ce->getSubExpr(), &innerBaseInfo);
93 if (baseInfo)
94 *baseInfo = innerBaseInfo;
95
96 if (isa<ExplicitCastExpr>(ce)) {
97 LValueBaseInfo targetTypeBaseInfo;
98
99 const QualType pointeeType = expr->getType()->getPointeeType();
100 const CharUnits align =
101 cgm.getNaturalTypeAlignment(pointeeType, &targetTypeBaseInfo);
102
103 // If the source l-value is opaque, honor the alignment of the
104 // casted-to type.
105 if (innerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) {
106 if (baseInfo)
107 baseInfo->mergeForCast(targetTypeBaseInfo);
108 addr = Address(addr.getPointer(), addr.getElementType(), align);
109 }
110 }
111
113
114 const mlir::Type eltTy =
115 convertTypeForMem(expr->getType()->getPointeeType());
116 addr = getBuilder().createElementBitCast(getLoc(expr->getSourceRange()),
117 addr, eltTy);
119
120 return addr;
121 }
122 break;
123 }
124
125 // Array-to-pointer decay. TODO(cir): BaseInfo and TBAAInfo.
126 case CK_ArrayToPointerDecay:
127 return emitArrayToPointerDecay(ce->getSubExpr(), baseInfo);
128
129 case CK_UncheckedDerivedToBase:
130 case CK_DerivedToBase: {
133 Address addr = emitPointerWithAlignment(ce->getSubExpr(), baseInfo);
134 const CXXRecordDecl *derived =
135 ce->getSubExpr()->getType()->getPointeeCXXRecordDecl();
136 return getAddressOfBaseClass(addr, derived, ce->path(),
138 ce->getExprLoc());
139 }
140
141 case CK_AnyPointerToBlockPointerCast:
142 case CK_BaseToDerived:
143 case CK_BaseToDerivedMemberPointer:
144 case CK_BlockPointerToObjCPointerCast:
145 case CK_BuiltinFnToFnPtr:
146 case CK_CPointerToObjCPointerCast:
147 case CK_DerivedToBaseMemberPointer:
148 case CK_Dynamic:
149 case CK_FunctionToPointerDecay:
150 case CK_IntegralToPointer:
151 case CK_LValueToRValue:
152 case CK_LValueToRValueBitCast:
153 case CK_NullToMemberPointer:
154 case CK_NullToPointer:
155 case CK_ReinterpretMemberPointer:
156 // Common pointer conversions, nothing to do here.
157 // TODO: Is there any reason to treat base-to-derived conversions
158 // specially?
159 break;
160
161 case CK_ARCConsumeObject:
162 case CK_ARCExtendBlockObject:
163 case CK_ARCProduceObject:
164 case CK_ARCReclaimReturnedObject:
165 case CK_AtomicToNonAtomic:
166 case CK_BooleanToSignedIntegral:
167 case CK_ConstructorConversion:
168 case CK_CopyAndAutoreleaseBlockObject:
169 case CK_Dependent:
170 case CK_FixedPointCast:
171 case CK_FixedPointToBoolean:
172 case CK_FixedPointToFloating:
173 case CK_FixedPointToIntegral:
174 case CK_FloatingCast:
175 case CK_FloatingComplexCast:
176 case CK_FloatingComplexToBoolean:
177 case CK_FloatingComplexToIntegralComplex:
178 case CK_FloatingComplexToReal:
179 case CK_FloatingRealToComplex:
180 case CK_FloatingToBoolean:
181 case CK_FloatingToFixedPoint:
182 case CK_FloatingToIntegral:
183 case CK_HLSLAggregateSplatCast:
184 case CK_HLSLArrayRValue:
185 case CK_HLSLElementwiseCast:
186 case CK_HLSLVectorTruncation:
187 case CK_IntToOCLSampler:
188 case CK_IntegralCast:
189 case CK_IntegralComplexCast:
190 case CK_IntegralComplexToBoolean:
191 case CK_IntegralComplexToFloatingComplex:
192 case CK_IntegralComplexToReal:
193 case CK_IntegralRealToComplex:
194 case CK_IntegralToBoolean:
195 case CK_IntegralToFixedPoint:
196 case CK_IntegralToFloating:
197 case CK_LValueBitCast:
198 case CK_MatrixCast:
199 case CK_MemberPointerToBoolean:
200 case CK_NonAtomicToAtomic:
201 case CK_ObjCObjectLValueCast:
202 case CK_PointerToBoolean:
203 case CK_PointerToIntegral:
204 case CK_ToUnion:
205 case CK_ToVoid:
206 case CK_UserDefinedConversion:
207 case CK_VectorSplat:
208 case CK_ZeroToOCLOpaqueType:
209 llvm_unreachable("unexpected cast for emitPointerWithAlignment");
210 }
211 }
212
213 // Unary &
214 if (const UnaryOperator *uo = dyn_cast<UnaryOperator>(expr)) {
215 // TODO(cir): maybe we should use cir.unary for pointers here instead.
216 if (uo->getOpcode() == UO_AddrOf) {
217 LValue lv = emitLValue(uo->getSubExpr());
218 if (baseInfo)
219 *baseInfo = lv.getBaseInfo();
221 return lv.getAddress();
222 }
223 }
224
225 // std::addressof and variants.
226 if (auto const *call = dyn_cast<CallExpr>(expr)) {
227 switch (call->getBuiltinCallee()) {
228 default:
229 break;
230 case Builtin::BIaddressof:
231 case Builtin::BI__addressof:
232 case Builtin::BI__builtin_addressof: {
233 cgm.errorNYI(expr->getSourceRange(),
234 "emitPointerWithAlignment: builtin addressof");
235 return Address::invalid();
236 }
237 }
238 }
239
240 // Otherwise, use the alignment of the type.
242 emitScalarExpr(expr), expr->getType()->getPointeeType(), CharUnits(),
243 /*forPointeeType=*/true, baseInfo);
244}
245
247 bool isInit) {
248 if (!dst.isSimple()) {
249 if (dst.isVectorElt()) {
250 // Read/modify/write the vector, inserting the new element
251 const mlir::Location loc = dst.getVectorPointer().getLoc();
252 const mlir::Value vector =
253 builder.createLoad(loc, dst.getVectorAddress());
254 const mlir::Value newVector = builder.create<cir::VecInsertOp>(
255 loc, vector, src.getValue(), dst.getVectorIdx());
256 builder.createStore(loc, newVector, dst.getVectorAddress());
257 return;
258 }
259
260 assert(dst.isBitField() && "Unknown LValue type");
262 return;
263
264 cgm.errorNYI(dst.getPointer().getLoc(),
265 "emitStoreThroughLValue: non-simple lvalue");
266 return;
267 }
268
270
271 assert(src.isScalar() && "Can't emit an aggregate store with this method");
272 emitStoreOfScalar(src.getValue(), dst, isInit);
273}
274
276 const VarDecl *vd) {
277 QualType t = e->getType();
278
279 // If it's thread_local, emit a call to its wrapper function instead.
281 if (vd->getTLSKind() == VarDecl::TLS_Dynamic)
282 cgf.cgm.errorNYI(e->getSourceRange(),
283 "emitGlobalVarDeclLValue: thread_local variable");
284
285 // Check if the variable is marked as declare target with link clause in
286 // device codegen.
287 if (cgf.getLangOpts().OpenMP)
288 cgf.cgm.errorNYI(e->getSourceRange(), "emitGlobalVarDeclLValue: OpenMP");
289
290 // Traditional LLVM codegen handles thread local separately, CIR handles
291 // as part of getAddrOfGlobalVar.
292 mlir::Value v = cgf.cgm.getAddrOfGlobalVar(vd);
293
295 mlir::Type realVarTy = cgf.convertTypeForMem(vd->getType());
296 cir::PointerType realPtrTy = cgf.getBuilder().getPointerTo(realVarTy);
297 if (realPtrTy != v.getType())
298 v = cgf.getBuilder().createBitcast(v.getLoc(), v, realPtrTy);
299
300 CharUnits alignment = cgf.getContext().getDeclAlign(vd);
301 Address addr(v, realVarTy, alignment);
302 LValue lv;
303 if (vd->getType()->isReferenceType())
304 cgf.cgm.errorNYI(e->getSourceRange(),
305 "emitGlobalVarDeclLValue: reference type");
306 else
307 lv = cgf.makeAddrLValue(addr, t, AlignmentSource::Decl);
309 return lv;
310}
311
312void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
313 bool isVolatile, QualType ty,
314 bool isInit, bool isNontemporal) {
316
317 if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) {
318 // Boolean vectors use `iN` as storage type.
319 if (clangVecTy->isExtVectorBoolType())
320 cgm.errorNYI(addr.getPointer().getLoc(),
321 "emitStoreOfScalar ExtVectorBoolType");
322
323 // Handle vectors of size 3 like size 4 for better performance.
324 const mlir::Type elementType = addr.getElementType();
325 const auto vecTy = cast<cir::VectorType>(elementType);
326
327 // TODO(CIR): Use `ABIInfo::getOptimalVectorMemoryType` once it upstreamed
328 if (vecTy.getSize() == 3 && !getLangOpts().PreserveVec3Type)
329 cgm.errorNYI(addr.getPointer().getLoc(),
330 "emitStoreOfScalar Vec3 & PreserveVec3Type disabled");
331 }
332
333 value = emitToMemory(value, ty);
334
336
337 // Update the alloca with more info on initialization.
338 assert(addr.getPointer() && "expected pointer to exist");
339 auto srcAlloca = addr.getDefiningOp<cir::AllocaOp>();
340 if (currVarDecl && srcAlloca) {
341 const VarDecl *vd = currVarDecl;
342 assert(vd && "VarDecl expected");
343 if (vd->hasInit())
344 srcAlloca.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
345 }
346
347 assert(currSrcLoc && "must pass in source location");
348 builder.createStore(*currSrcLoc, value, addr /*, isVolatile*/);
349
350 if (isNontemporal) {
351 cgm.errorNYI(addr.getPointer().getLoc(), "emitStoreOfScalar nontemporal");
352 return;
353 }
354
356}
357
358// TODO: Replace this with a proper TargetInfo function call.
359/// Helper method to check if the underlying ABI is AAPCS
360static bool isAAPCS(const TargetInfo &targetInfo) {
361 return targetInfo.getABI().starts_with("aapcs");
362}
363
365 LValue dst) {
366
367 const CIRGenBitFieldInfo &info = dst.getBitFieldInfo();
368 mlir::Type resLTy = convertTypeForMem(dst.getType());
369 Address ptr = dst.getBitFieldAddress();
370
371 bool useVoaltile = cgm.getCodeGenOpts().AAPCSBitfieldWidth &&
372 dst.isVolatileQualified() &&
374
375 mlir::Value dstAddr = dst.getAddress().getPointer();
376
377 return builder.createSetBitfield(dstAddr.getLoc(), resLTy, ptr,
378 ptr.getElementType(), src.getValue(), info,
379 dst.isVolatileQualified(), useVoaltile);
380}
381
383 const CIRGenBitFieldInfo &info = lv.getBitFieldInfo();
384
385 // Get the output type.
386 mlir::Type resLTy = convertType(lv.getType());
387 Address ptr = lv.getBitFieldAddress();
388
389 bool useVoaltile = lv.isVolatileQualified() && info.volatileOffset != 0 &&
391
392 mlir::Value field =
393 builder.createGetBitfield(getLoc(loc), resLTy, ptr, ptr.getElementType(),
394 info, lv.isVolatile(), useVoaltile);
396 return RValue::get(field);
397}
398
400 const FieldDecl *field,
401 mlir::Type fieldType,
402 unsigned index) {
403 mlir::Location loc = getLoc(field->getLocation());
404 cir::PointerType fieldPtr = cir::PointerType::get(fieldType);
405 auto rec = cast<cir::RecordType>(base.getAddress().getElementType());
406 cir::GetMemberOp sea = getBuilder().createGetMember(
407 loc, fieldPtr, base.getPointer(), field->getName(),
408 rec.isUnion() ? field->getFieldIndex() : index);
410 rec.getElementOffset(cgm.getDataLayout().layout, index));
411 return Address(sea, base.getAlignment().alignmentAtOffset(offset));
412}
413
415 const FieldDecl *field) {
416 LValueBaseInfo baseInfo = base.getBaseInfo();
417 const CIRGenRecordLayout &layout =
419 const CIRGenBitFieldInfo &info = layout.getBitFieldInfo(field);
420
422
423 unsigned idx = layout.getCIRFieldNo(field);
424 Address addr = getAddrOfBitFieldStorage(base, field, info.storageType, idx);
425
426 mlir::Location loc = getLoc(field->getLocation());
427 if (addr.getElementType() != info.storageType)
428 addr = builder.createElementBitCast(loc, addr, info.storageType);
429
430 QualType fieldType =
432 // TODO(cir): Support TBAA for bit fields.
434 LValueBaseInfo fieldBaseInfo(baseInfo.getAlignmentSource());
435 return LValue::makeBitfield(addr, info, fieldType, fieldBaseInfo);
436}
437
439 LValueBaseInfo baseInfo = base.getBaseInfo();
440
441 if (field->isBitField())
442 return emitLValueForBitField(base, field);
443
444 QualType fieldType = field->getType();
445 const RecordDecl *rec = field->getParent();
446 AlignmentSource baseAlignSource = baseInfo.getAlignmentSource();
447 LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(baseAlignSource));
449
450 Address addr = base.getAddress();
451 if (auto *classDecl = dyn_cast<CXXRecordDecl>(rec)) {
452 if (cgm.getCodeGenOpts().StrictVTablePointers &&
453 classDecl->isDynamicClass()) {
454 cgm.errorNYI(field->getSourceRange(),
455 "emitLValueForField: strict vtable for dynamic class");
456 }
457 }
458
459 unsigned recordCVR = base.getVRQualifiers();
460
461 llvm::StringRef fieldName = field->getName();
462 unsigned fieldIndex;
464
465 if (rec->isUnion())
466 fieldIndex = field->getFieldIndex();
467 else {
468 const CIRGenRecordLayout &layout =
470 fieldIndex = layout.getCIRFieldNo(field);
471 }
472
473 addr = emitAddrOfFieldStorage(addr, field, fieldName, fieldIndex);
475
476 // If this is a reference field, load the reference right now.
477 if (fieldType->isReferenceType()) {
478 cgm.errorNYI(field->getSourceRange(), "emitLValueForField: reference type");
479 return LValue();
480 }
481
482 if (field->hasAttr<AnnotateAttr>()) {
483 cgm.errorNYI(field->getSourceRange(), "emitLValueForField: AnnotateAttr");
484 return LValue();
485 }
486
487 LValue lv = makeAddrLValue(addr, fieldType, fieldBaseInfo);
488 lv.getQuals().addCVRQualifiers(recordCVR);
489
490 // __weak attribute on a field is ignored.
492 cgm.errorNYI(field->getSourceRange(),
493 "emitLValueForField: __weak attribute");
494 return LValue();
495 }
496
497 return lv;
498}
499
501 LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName) {
502 QualType fieldType = field->getType();
503
504 if (!fieldType->isReferenceType())
505 return emitLValueForField(base, field);
506
507 const CIRGenRecordLayout &layout =
509 unsigned fieldIndex = layout.getCIRFieldNo(field);
510
511 Address v =
512 emitAddrOfFieldStorage(base.getAddress(), field, fieldName, fieldIndex);
513
514 // Make sure that the address is pointing to the right type.
515 mlir::Type memTy = convertTypeForMem(fieldType);
516 v = builder.createElementBitCast(getLoc(field->getSourceRange()), v, memTy);
517
518 // TODO: Generate TBAA information that describes this access as a structure
519 // member access and not just an access to an object of the field's type. This
520 // should be similar to what we do in EmitLValueForField().
521 LValueBaseInfo baseInfo = base.getBaseInfo();
522 AlignmentSource fieldAlignSource = baseInfo.getAlignmentSource();
523 LValueBaseInfo fieldBaseInfo(getFieldAlignmentSource(fieldAlignSource));
525 return makeAddrLValue(v, fieldType, fieldBaseInfo);
526}
527
528mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {
529 // Bool has a different representation in memory than in registers,
530 // but in ClangIR, it is simply represented as a cir.bool value.
531 // This function is here as a placeholder for possible future changes.
532 return value;
533}
534
535void CIRGenFunction::emitStoreOfScalar(mlir::Value value, LValue lvalue,
536 bool isInit) {
537 if (lvalue.getType()->isConstantMatrixType()) {
538 assert(0 && "NYI: emitStoreOfScalar constant matrix type");
539 return;
540 }
541
542 emitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),
543 lvalue.getType(), isInit, /*isNontemporal=*/false);
544}
545
547 SourceLocation loc) {
551
552 Address addr = lvalue.getAddress();
553 mlir::Type eltTy = addr.getElementType();
554
555 if (mlir::isa<cir::VoidType>(eltTy))
556 cgm.errorNYI(loc, "emitLoadOfScalar: void type");
557
558 mlir::Value loadOp = builder.createLoad(getLoc(loc), addr);
559
560 return loadOp;
561}
562
563/// Given an expression that represents a value lvalue, this
564/// method emits the address of the lvalue, then loads the result as an rvalue,
565/// returning the rvalue.
567 assert(!lv.getType()->isFunctionType());
568 assert(!(lv.getType()->isConstantMatrixType()) && "not implemented");
569
570 if (lv.isBitField())
571 return emitLoadOfBitfieldLValue(lv, loc);
572
573 if (lv.isSimple())
574 return RValue::get(emitLoadOfScalar(lv, loc));
575
576 if (lv.isVectorElt()) {
577 const mlir::Value load =
578 builder.createLoad(getLoc(loc), lv.getVectorAddress());
579 return RValue::get(builder.create<cir::VecExtractOp>(getLoc(loc), load,
580 lv.getVectorIdx()));
581 }
582
583 cgm.errorNYI(loc, "emitLoadOfLValue");
584 return RValue::get(nullptr);
585}
586
587static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
589 return cgm.getAddrOfFunction(gd);
590}
591
593 GlobalDecl gd) {
594 const FunctionDecl *fd = cast<FunctionDecl>(gd.getDecl());
595 cir::FuncOp funcOp = emitFunctionDeclPointer(cgf.cgm, gd);
596 mlir::Location loc = cgf.getLoc(e->getSourceRange());
597 CharUnits align = cgf.getContext().getDeclAlign(fd);
598
600
601 mlir::Type fnTy = funcOp.getFunctionType();
602 mlir::Type ptrTy = cir::PointerType::get(fnTy);
603 mlir::Value addr = cgf.getBuilder().create<cir::GetGlobalOp>(
604 loc, ptrTy, funcOp.getSymName());
605
606 if (funcOp.getFunctionType() != cgf.convertType(fd->getType())) {
607 fnTy = cgf.convertType(fd->getType());
608 ptrTy = cir::PointerType::get(fnTy);
609
610 addr = cir::CastOp::create(cgf.getBuilder(), addr.getLoc(), ptrTy,
611 cir::CastKind::bitcast, addr);
612 }
613
614 return cgf.makeAddrLValue(Address(addr, fnTy, align), e->getType(),
616}
617
619 const NamedDecl *nd = e->getDecl();
620 QualType ty = e->getType();
621
622 assert(e->isNonOdrUse() != NOUR_Unevaluated &&
623 "should not emit an unevaluated operand");
624
625 if (const auto *vd = dyn_cast<VarDecl>(nd)) {
626 // Checks for omitted feature handling
633
634 // Check if this is a global variable
635 if (vd->hasLinkage() || vd->isStaticDataMember())
636 return emitGlobalVarDeclLValue(*this, e, vd);
637
638 Address addr = Address::invalid();
639
640 // The variable should generally be present in the local decl map.
641 auto iter = localDeclMap.find(vd);
642 if (iter != localDeclMap.end()) {
643 addr = iter->second;
644 } else {
645 // Otherwise, it might be static local we haven't emitted yet for some
646 // reason; most likely, because it's in an outer function.
647 cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: static local");
648 }
649
650 // Drill into reference types.
651 LValue lv =
652 vd->getType()->isReferenceType()
654 vd->getType(), AlignmentSource::Decl)
656
657 // Statics are defined as globals, so they are not include in the function's
658 // symbol table.
659 assert((vd->isStaticLocal() || symbolTable.count(vd)) &&
660 "non-static locals should be already mapped");
661
662 return lv;
663 }
664
665 if (const auto *bd = dyn_cast<BindingDecl>(nd)) {
668 cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: lambda captures");
669 return LValue();
670 }
671 return emitLValue(bd->getBinding());
672 }
673
674 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
675 LValue lv = emitFunctionDeclLValue(*this, e, fd);
676
677 // Emit debuginfo for the function declaration if the target wants to.
678 if (getContext().getTargetInfo().allowDebugInfoForExternalRef())
680
681 return lv;
682 }
683
684 cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");
685 return LValue();
686}
687
689 QualType boolTy = getContext().BoolTy;
690 SourceLocation loc = e->getExprLoc();
691
693 if (e->getType()->getAs<MemberPointerType>()) {
695 "evaluateExprAsBool: member pointer type");
696 return createDummyValue(getLoc(loc), boolTy);
697 }
698
700 if (!e->getType()->isAnyComplexType())
701 return emitScalarConversion(emitScalarExpr(e), e->getType(), boolTy, loc);
702
703 cgm.errorNYI(e->getSourceRange(), "evaluateExprAsBool: complex type");
704 return createDummyValue(getLoc(loc), boolTy);
705}
706
709
710 // __extension__ doesn't affect lvalue-ness.
711 if (op == UO_Extension)
712 return emitLValue(e->getSubExpr());
713
714 switch (op) {
715 case UO_Deref: {
717 assert(!t.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
718
720 LValueBaseInfo baseInfo;
721 Address addr = emitPointerWithAlignment(e->getSubExpr(), &baseInfo);
722
723 // Tag 'load' with deref attribute.
724 // FIXME: This misses some derefence cases and has problematic interactions
725 // with other operators.
726 if (auto loadOp = addr.getDefiningOp<cir::LoadOp>())
727 loadOp.setIsDerefAttr(mlir::UnitAttr::get(&getMLIRContext()));
728
729 LValue lv = makeAddrLValue(addr, t, baseInfo);
732 return lv;
733 }
734 case UO_Real:
735 case UO_Imag: {
736 LValue lv = emitLValue(e->getSubExpr());
737 assert(lv.isSimple() && "real/imag on non-ordinary l-value");
738
739 // __real is valid on scalars. This is a faster way of testing that.
740 // __imag can only produce an rvalue on scalars.
741 if (e->getOpcode() == UO_Real &&
742 !mlir::isa<cir::ComplexType>(lv.getAddress().getElementType())) {
743 assert(e->getSubExpr()->getType()->isArithmeticType());
744 return lv;
745 }
746
748 QualType elemTy = exprTy->castAs<clang::ComplexType>()->getElementType();
749 mlir::Location loc = getLoc(e->getExprLoc());
750 Address component =
751 e->getOpcode() == UO_Real
752 ? builder.createComplexRealPtr(loc, lv.getAddress())
753 : builder.createComplexImagPtr(loc, lv.getAddress());
755 LValue elemLV = makeAddrLValue(component, elemTy);
756 elemLV.getQuals().addQualifiers(lv.getQuals());
757 return elemLV;
758 }
759 case UO_PreInc:
760 case UO_PreDec: {
761 cir::UnaryOpKind kind =
762 e->isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
763 LValue lv = emitLValue(e->getSubExpr());
764
765 assert(e->isPrefix() && "Prefix operator in unexpected state!");
766
767 if (e->getType()->isAnyComplexType()) {
768 cgm.errorNYI(e->getSourceRange(), "UnaryOp complex inc/dec");
769 lv = LValue();
770 } else {
771 emitScalarPrePostIncDec(e, lv, kind, /*isPre=*/true);
772 }
773
774 return lv;
775 }
776 case UO_Extension:
777 llvm_unreachable("UnaryOperator extension should be handled above!");
778 case UO_Plus:
779 case UO_Minus:
780 case UO_Not:
781 case UO_LNot:
782 case UO_AddrOf:
783 case UO_PostInc:
784 case UO_PostDec:
785 case UO_Coawait:
786 llvm_unreachable("UnaryOperator of non-lvalue kind!");
787 }
788 llvm_unreachable("Unknown unary operator kind!");
789}
790
791/// If the specified expr is a simple decay from an array to pointer,
792/// return the array subexpression.
793/// FIXME: this could be abstracted into a common AST helper.
794static const Expr *getSimpleArrayDecayOperand(const Expr *e) {
795 // If this isn't just an array->pointer decay, bail out.
796 const auto *castExpr = dyn_cast<CastExpr>(e);
797 if (!castExpr || castExpr->getCastKind() != CK_ArrayToPointerDecay)
798 return nullptr;
799
800 // If this is a decay from variable width array, bail out.
801 const Expr *subExpr = castExpr->getSubExpr();
802 if (subExpr->getType()->isVariableArrayType())
803 return nullptr;
804
805 return subExpr;
806}
807
808static cir::IntAttr getConstantIndexOrNull(mlir::Value idx) {
809 // TODO(cir): should we consider using MLIRs IndexType instead of IntegerAttr?
810 if (auto constantOp = idx.getDefiningOp<cir::ConstantOp>())
811 return constantOp.getValueAttr<cir::IntAttr>();
812 return {};
813}
814
815static CharUnits getArrayElementAlign(CharUnits arrayAlign, mlir::Value idx,
816 CharUnits eltSize) {
817 // If we have a constant index, we can use the exact offset of the
818 // element we're accessing.
819 if (const cir::IntAttr constantIdx = getConstantIndexOrNull(idx)) {
820 const CharUnits offset = constantIdx.getValue().getZExtValue() * eltSize;
821 return arrayAlign.alignmentAtOffset(offset);
822 }
823 // Otherwise, use the worst-case alignment for any element.
824 return arrayAlign.alignmentOfArrayElement(eltSize);
825}
826
828 const VariableArrayType *vla) {
829 QualType eltType;
830 do {
831 eltType = vla->getElementType();
832 } while ((vla = astContext.getAsVariableArrayType(eltType)));
833 return eltType;
834}
835
836static mlir::Value emitArraySubscriptPtr(CIRGenFunction &cgf,
837 mlir::Location beginLoc,
838 mlir::Location endLoc, mlir::Value ptr,
839 mlir::Type eltTy, mlir::Value idx,
840 bool shouldDecay) {
841 CIRGenModule &cgm = cgf.getCIRGenModule();
842 // TODO(cir): LLVM codegen emits in bound gep check here, is there anything
843 // that would enhance tracking this later in CIR?
845 return cgm.getBuilder().getArrayElement(beginLoc, endLoc, ptr, eltTy, idx,
846 shouldDecay);
847}
848
850 mlir::Location beginLoc,
851 mlir::Location endLoc, Address addr,
852 QualType eltType, mlir::Value idx,
853 mlir::Location loc, bool shouldDecay) {
854
855 // Determine the element size of the statically-sized base. This is
856 // the thing that the indices are expressed in terms of.
857 if (const VariableArrayType *vla =
858 cgf.getContext().getAsVariableArrayType(eltType)) {
859 eltType = getFixedSizeElementType(cgf.getContext(), vla);
860 }
861
862 // We can use that to compute the best alignment of the element.
863 const CharUnits eltSize = cgf.getContext().getTypeSizeInChars(eltType);
864 const CharUnits eltAlign =
865 getArrayElementAlign(addr.getAlignment(), idx, eltSize);
866
868 const mlir::Value eltPtr =
869 emitArraySubscriptPtr(cgf, beginLoc, endLoc, addr.getPointer(),
870 addr.getElementType(), idx, shouldDecay);
871 const mlir::Type elementType = cgf.convertTypeForMem(eltType);
872 return Address(eltPtr, elementType, eltAlign);
873}
874
875LValue
877 if (isa<ExtVectorElementExpr>(e->getBase())) {
879 "emitArraySubscriptExpr: ExtVectorElementExpr");
881 }
882
883 if (getContext().getAsVariableArrayType(e->getType())) {
885 "emitArraySubscriptExpr: VariableArrayType");
887 }
888
889 if (e->getType()->getAs<ObjCObjectType>()) {
890 cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjCObjectType");
892 }
893
894 // The index must always be an integer, which is not an aggregate. Emit it
895 // in lexical order (this complexity is, sadly, required by C++17).
896 assert((e->getIdx() == e->getLHS() || e->getIdx() == e->getRHS()) &&
897 "index was neither LHS nor RHS");
898
899 auto emitIdxAfterBase = [&](bool promote) -> mlir::Value {
900 const mlir::Value idx = emitScalarExpr(e->getIdx());
901
902 // Extend or truncate the index type to 32 or 64-bits.
903 auto ptrTy = mlir::dyn_cast<cir::PointerType>(idx.getType());
904 if (promote && ptrTy && ptrTy.isPtrTo<cir::IntType>())
906 "emitArraySubscriptExpr: index type cast");
907 return idx;
908 };
909
910 // If the base is a vector type, then we are forming a vector element
911 // with this subscript.
912 if (e->getBase()->getType()->isVectorType() &&
913 !isa<ExtVectorElementExpr>(e->getBase())) {
914 const mlir::Value idx = emitIdxAfterBase(/*promote=*/false);
915 const LValue lhs = emitLValue(e->getBase());
916 return LValue::makeVectorElt(lhs.getAddress(), idx, e->getBase()->getType(),
917 lhs.getBaseInfo());
918 }
919
920 const mlir::Value idx = emitIdxAfterBase(/*promote=*/true);
921 if (const Expr *array = getSimpleArrayDecayOperand(e->getBase())) {
922 LValue arrayLV;
923 if (const auto *ase = dyn_cast<ArraySubscriptExpr>(array))
924 arrayLV = emitArraySubscriptExpr(ase);
925 else
926 arrayLV = emitLValue(array);
927
928 // Propagate the alignment from the array itself to the result.
929 const Address addr = emitArraySubscriptPtr(
930 *this, cgm.getLoc(array->getBeginLoc()), cgm.getLoc(array->getEndLoc()),
931 arrayLV.getAddress(), e->getType(), idx, cgm.getLoc(e->getExprLoc()),
932 /*shouldDecay=*/true);
933
934 const LValue lv = LValue::makeAddr(addr, e->getType(), LValueBaseInfo());
935
936 if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {
937 cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjC with GC");
938 }
939
940 return lv;
941 }
942
943 // The base must be a pointer; emit it with an estimate of its alignment.
944 assert(e->getBase()->getType()->isPointerType() &&
945 "The base must be a pointer");
946
947 LValueBaseInfo eltBaseInfo;
948 const Address ptrAddr = emitPointerWithAlignment(e->getBase(), &eltBaseInfo);
949 // Propagate the alignment from the array itself to the result.
950 const Address addxr = emitArraySubscriptPtr(
951 *this, cgm.getLoc(e->getBeginLoc()), cgm.getLoc(e->getEndLoc()), ptrAddr,
952 e->getType(), idx, cgm.getLoc(e->getExprLoc()),
953 /*shouldDecay=*/false);
954
955 const LValue lv = LValue::makeAddr(addxr, e->getType(), eltBaseInfo);
956
957 if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {
958 cgm.errorNYI(e->getSourceRange(), "emitArraySubscriptExpr: ObjC with GC");
959 }
960
961 return lv;
962}
963
965 cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e);
966 assert(globalOp.getAlignment() && "expected alignment for string literal");
967 unsigned align = *(globalOp.getAlignment());
968 mlir::Value addr =
969 builder.createGetGlobal(getLoc(e->getSourceRange()), globalOp);
970 return makeAddrLValue(
971 Address(addr, globalOp.getSymType(), CharUnits::fromQuantity(align)),
973}
974
975/// Casts are never lvalues unless that cast is to a reference type. If the cast
976/// is to a reference, we can have the usual lvalue result, otherwise if a cast
977/// is needed by the code generator in an lvalue context, then it must mean that
978/// we need the address of an aggregate in order to access one of its members.
979/// This can happen for all the reasons that casts are permitted with aggregate
980/// result, including noop aggregate casts, and cast from scalar to union.
982 switch (e->getCastKind()) {
983 case CK_ToVoid:
984 case CK_BitCast:
985 case CK_LValueToRValueBitCast:
986 case CK_ArrayToPointerDecay:
987 case CK_FunctionToPointerDecay:
988 case CK_NullToMemberPointer:
989 case CK_NullToPointer:
990 case CK_IntegralToPointer:
991 case CK_PointerToIntegral:
992 case CK_PointerToBoolean:
993 case CK_IntegralCast:
994 case CK_BooleanToSignedIntegral:
995 case CK_IntegralToBoolean:
996 case CK_IntegralToFloating:
997 case CK_FloatingToIntegral:
998 case CK_FloatingToBoolean:
999 case CK_FloatingCast:
1000 case CK_FloatingRealToComplex:
1001 case CK_FloatingComplexToReal:
1002 case CK_FloatingComplexToBoolean:
1003 case CK_FloatingComplexCast:
1004 case CK_FloatingComplexToIntegralComplex:
1005 case CK_IntegralRealToComplex:
1006 case CK_IntegralComplexToReal:
1007 case CK_IntegralComplexToBoolean:
1008 case CK_IntegralComplexCast:
1009 case CK_IntegralComplexToFloatingComplex:
1010 case CK_DerivedToBaseMemberPointer:
1011 case CK_BaseToDerivedMemberPointer:
1012 case CK_MemberPointerToBoolean:
1013 case CK_ReinterpretMemberPointer:
1014 case CK_AnyPointerToBlockPointerCast:
1015 case CK_ARCProduceObject:
1016 case CK_ARCConsumeObject:
1017 case CK_ARCReclaimReturnedObject:
1018 case CK_ARCExtendBlockObject:
1019 case CK_CopyAndAutoreleaseBlockObject:
1020 case CK_IntToOCLSampler:
1021 case CK_FloatingToFixedPoint:
1022 case CK_FixedPointToFloating:
1023 case CK_FixedPointCast:
1024 case CK_FixedPointToBoolean:
1025 case CK_FixedPointToIntegral:
1026 case CK_IntegralToFixedPoint:
1027 case CK_MatrixCast:
1028 case CK_HLSLVectorTruncation:
1029 case CK_HLSLArrayRValue:
1030 case CK_HLSLElementwiseCast:
1031 case CK_HLSLAggregateSplatCast:
1032 llvm_unreachable("unexpected cast lvalue");
1033
1034 case CK_Dependent:
1035 llvm_unreachable("dependent cast kind in IR gen!");
1036
1037 case CK_BuiltinFnToFnPtr:
1038 llvm_unreachable("builtin functions are handled elsewhere");
1039
1040 // These are never l-values; just use the aggregate emission code.
1041 case CK_NonAtomicToAtomic:
1042 case CK_AtomicToNonAtomic:
1043 case CK_Dynamic:
1044 case CK_ToUnion:
1045 case CK_BaseToDerived:
1046 case CK_AddressSpaceConversion:
1047 case CK_ObjCObjectLValueCast:
1048 case CK_VectorSplat:
1049 case CK_ConstructorConversion:
1050 case CK_UserDefinedConversion:
1051 case CK_CPointerToObjCPointerCast:
1052 case CK_BlockPointerToObjCPointerCast:
1053 case CK_LValueToRValue: {
1055 std::string("emitCastLValue for unhandled cast kind: ") +
1056 e->getCastKindName());
1057
1058 return {};
1059 }
1060
1061 case CK_LValueBitCast: {
1062 // This must be a reinterpret_cast (or c-style equivalent).
1063 const auto *ce = cast<ExplicitCastExpr>(e);
1064
1065 cgm.emitExplicitCastExprType(ce, this);
1066 LValue LV = emitLValue(e->getSubExpr());
1068 builder, convertTypeForMem(ce->getTypeAsWritten()->getPointeeType()));
1069
1070 return makeAddrLValue(V, e->getType(), LV.getBaseInfo());
1071 }
1072
1073 case CK_NoOp: {
1074 // CK_NoOp can model a qualification conversion, which can remove an array
1075 // bound and change the IR type.
1076 LValue lv = emitLValue(e->getSubExpr());
1077 // Propagate the volatile qualifier to LValue, if exists in e.
1080 "emitCastLValue: NoOp changes volatile qual");
1081 if (lv.isSimple()) {
1082 Address v = lv.getAddress();
1083 if (v.isValid()) {
1084 mlir::Type ty = convertTypeForMem(e->getType());
1085 if (v.getElementType() != ty)
1087 "emitCastLValue: NoOp needs bitcast");
1088 }
1089 }
1090 return lv;
1091 }
1092
1093 case CK_UncheckedDerivedToBase:
1094 case CK_DerivedToBase: {
1095 auto *derivedClassDecl = e->getSubExpr()->getType()->castAsCXXRecordDecl();
1096
1097 LValue lv = emitLValue(e->getSubExpr());
1098 Address thisAddr = lv.getAddress();
1099
1100 // Perform the derived-to-base conversion
1101 Address baseAddr =
1102 getAddressOfBaseClass(thisAddr, derivedClassDecl, e->path(),
1103 /*NullCheckValue=*/false, e->getExprLoc());
1104
1105 // TODO: Support accesses to members of base classes in TBAA. For now, we
1106 // conservatively pretend that the complete object is of the base class
1107 // type.
1109 return makeAddrLValue(baseAddr, e->getType(), lv.getBaseInfo());
1110 }
1111
1112 case CK_ZeroToOCLOpaqueType:
1113 llvm_unreachable("NULL to OpenCL opaque type lvalue cast is not valid");
1114 }
1115
1116 llvm_unreachable("Invalid cast kind");
1117}
1118
1120 const MemberExpr *me) {
1121 if (auto *vd = dyn_cast<VarDecl>(me->getMemberDecl())) {
1122 // Try to emit static variable member expressions as DREs.
1123 return DeclRefExpr::Create(
1125 /*RefersToEnclosingVariableOrCapture=*/false, me->getExprLoc(),
1126 me->getType(), me->getValueKind(), nullptr, nullptr, me->isNonOdrUse());
1127 }
1128 return nullptr;
1129}
1130
1132 if (DeclRefExpr *dre = tryToConvertMemberExprToDeclRefExpr(*this, e)) {
1134 return emitDeclRefLValue(dre);
1135 }
1136
1137 Expr *baseExpr = e->getBase();
1138 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
1139 LValue baseLV;
1140 if (e->isArrow()) {
1141 LValueBaseInfo baseInfo;
1143 Address addr = emitPointerWithAlignment(baseExpr, &baseInfo);
1144 QualType ptrTy = baseExpr->getType()->getPointeeType();
1146 baseLV = makeAddrLValue(addr, ptrTy, baseInfo);
1147 } else {
1149 baseLV = emitLValue(baseExpr);
1150 }
1151
1152 const NamedDecl *nd = e->getMemberDecl();
1153 if (auto *field = dyn_cast<FieldDecl>(nd)) {
1154 LValue lv = emitLValueForField(baseLV, field);
1156 if (getLangOpts().OpenMP) {
1157 // If the member was explicitly marked as nontemporal, mark it as
1158 // nontemporal. If the base lvalue is marked as nontemporal, mark access
1159 // to children as nontemporal too.
1160 cgm.errorNYI(e->getSourceRange(), "emitMemberExpr: OpenMP");
1161 }
1162 return lv;
1163 }
1164
1165 if (isa<FunctionDecl>(nd)) {
1166 cgm.errorNYI(e->getSourceRange(), "emitMemberExpr: FunctionDecl");
1167 return LValue();
1168 }
1169
1170 llvm_unreachable("Unhandled member declaration!");
1171}
1172
1173/// Evaluate an expression into a given memory location.
1175 Qualifiers quals, bool isInit) {
1176 // FIXME: This function should take an LValue as an argument.
1177 switch (getEvaluationKind(e->getType())) {
1178 case cir::TEK_Complex: {
1179 LValue lv = makeAddrLValue(location, e->getType());
1180 emitComplexExprIntoLValue(e, lv, isInit);
1181 return;
1182 }
1183
1184 case cir::TEK_Aggregate: {
1185 emitAggExpr(e, AggValueSlot::forAddr(location, quals,
1189 return;
1190 }
1191
1192 case cir::TEK_Scalar: {
1194 LValue lv = makeAddrLValue(location, e->getType());
1195 emitStoreThroughLValue(rv, lv);
1196 return;
1197 }
1198 }
1199
1200 llvm_unreachable("bad evaluation kind");
1201}
1202
1204 const MaterializeTemporaryExpr *m,
1205 const Expr *inner) {
1206 // TODO(cir): cgf.getTargetHooks();
1207 switch (m->getStorageDuration()) {
1208 case SD_FullExpression:
1209 case SD_Automatic: {
1210 QualType ty = inner->getType();
1211
1213
1214 // The temporary memory should be created in the same scope as the extending
1215 // declaration of the temporary materialization expression.
1216 cir::AllocaOp extDeclAlloca;
1217 if (const ValueDecl *extDecl = m->getExtendingDecl()) {
1218 auto extDeclAddrIter = cgf.localDeclMap.find(extDecl);
1219 if (extDeclAddrIter != cgf.localDeclMap.end())
1220 extDeclAlloca = extDeclAddrIter->second.getDefiningOp<cir::AllocaOp>();
1221 }
1222 mlir::OpBuilder::InsertPoint ip;
1223 if (extDeclAlloca)
1224 ip = {extDeclAlloca->getBlock(), extDeclAlloca->getIterator()};
1225 return cgf.createMemTemp(ty, cgf.getLoc(m->getSourceRange()),
1226 cgf.getCounterRefTmpAsString(), /*alloca=*/nullptr,
1227 ip);
1228 }
1229 case SD_Thread:
1230 case SD_Static: {
1231 cgf.cgm.errorNYI(
1232 m->getSourceRange(),
1233 "createReferenceTemporary: static/thread storage duration");
1234 return Address::invalid();
1235 }
1236
1237 case SD_Dynamic:
1238 llvm_unreachable("temporary can't have dynamic storage duration");
1239 }
1240 llvm_unreachable("unknown storage duration");
1241}
1242
1244 const MaterializeTemporaryExpr *m,
1245 const Expr *e, Address referenceTemporary) {
1246 // Objective-C++ ARC:
1247 // If we are binding a reference to a temporary that has ownership, we
1248 // need to perform retain/release operations on the temporary.
1249 //
1250 // FIXME(ogcg): This should be looking at e, not m.
1251 if (m->getType().getObjCLifetime()) {
1252 cgf.cgm.errorNYI(e->getSourceRange(), "pushTemporaryCleanup: ObjCLifetime");
1253 return;
1254 }
1255
1257 if (dk == QualType::DK_none)
1258 return;
1259
1260 switch (m->getStorageDuration()) {
1261 case SD_Static:
1262 case SD_Thread: {
1263 CXXDestructorDecl *referenceTemporaryDtor = nullptr;
1264 if (const auto *classDecl =
1266 classDecl && !classDecl->hasTrivialDestructor())
1267 // Get the destructor for the reference temporary.
1268 referenceTemporaryDtor = classDecl->getDestructor();
1269
1270 if (!referenceTemporaryDtor)
1271 return;
1272
1273 cgf.cgm.errorNYI(e->getSourceRange(), "pushTemporaryCleanup: static/thread "
1274 "storage duration with destructors");
1275 break;
1276 }
1277
1278 case SD_FullExpression:
1279 cgf.pushDestroy(NormalAndEHCleanup, referenceTemporary, e->getType(),
1281 break;
1282
1283 case SD_Automatic:
1284 cgf.cgm.errorNYI(e->getSourceRange(),
1285 "pushTemporaryCleanup: automatic storage duration");
1286 break;
1287
1288 case SD_Dynamic:
1289 llvm_unreachable("temporary cannot have dynamic storage duration");
1290 }
1291}
1292
1294 const MaterializeTemporaryExpr *m) {
1295 const Expr *e = m->getSubExpr();
1296
1297 assert((!m->getExtendingDecl() || !isa<VarDecl>(m->getExtendingDecl()) ||
1298 !cast<VarDecl>(m->getExtendingDecl())->isARCPseudoStrong()) &&
1299 "Reference should never be pseudo-strong!");
1300
1301 // FIXME: ideally this would use emitAnyExprToMem, however, we cannot do so
1302 // as that will cause the lifetime adjustment to be lost for ARC
1303 auto ownership = m->getType().getObjCLifetime();
1304 if (ownership != Qualifiers::OCL_None &&
1305 ownership != Qualifiers::OCL_ExplicitNone) {
1307 "emitMaterializeTemporaryExpr: ObjCLifetime");
1308 return {};
1309 }
1310
1313 e = e->skipRValueSubobjectAdjustments(commaLHSs, adjustments);
1314
1315 for (const Expr *ignored : commaLHSs)
1316 emitIgnoredExpr(ignored);
1317
1318 if (isa<OpaqueValueExpr>(e)) {
1320 "emitMaterializeTemporaryExpr: OpaqueValueExpr");
1321 return {};
1322 }
1323
1324 // Create and initialize the reference temporary.
1325 Address object = createReferenceTemporary(*this, m, e);
1326
1327 if (auto var = object.getPointer().getDefiningOp<cir::GlobalOp>()) {
1328 // TODO(cir): add something akin to stripPointerCasts() to ptr above
1329 cgm.errorNYI(e->getSourceRange(), "emitMaterializeTemporaryExpr: GlobalOp");
1330 return {};
1331 } else {
1333 emitAnyExprToMem(e, object, Qualifiers(), /*isInitializer=*/true);
1334 }
1335 pushTemporaryCleanup(*this, m, e, object);
1336
1337 // Perform derived-to-base casts and/or field accesses, to get from the
1338 // temporary object we created (and, potentially, for which we extended
1339 // the lifetime) to the subobject we're binding the reference to.
1340 if (!adjustments.empty()) {
1342 "emitMaterializeTemporaryExpr: Adjustments");
1343 return {};
1344 }
1345
1346 return makeAddrLValue(object, m->getType(), AlignmentSource::Decl);
1347}
1348
1350 if (e->isFileScope()) {
1351 cgm.errorNYI(e->getSourceRange(), "emitCompoundLiteralLValue: FileScope");
1352 return {};
1353 }
1354
1355 if (e->getType()->isVariablyModifiedType()) {
1357 "emitCompoundLiteralLValue: VariablyModifiedType");
1358 return {};
1359 }
1360
1361 Address declPtr = createMemTemp(e->getType(), getLoc(e->getSourceRange()),
1362 ".compoundliteral");
1363 const Expr *initExpr = e->getInitializer();
1364 LValue result = makeAddrLValue(declPtr, e->getType(), AlignmentSource::Decl);
1365
1366 emitAnyExprToMem(initExpr, declPtr, e->getType().getQualifiers(),
1367 /*Init*/ true);
1368
1369 // Block-scope compound literals are destroyed at the end of the enclosing
1370 // scope in C.
1371 if (!getLangOpts().CPlusPlus && e->getType().isDestructedType()) {
1373 "emitCompoundLiteralLValue: non C++ DestructedType");
1374 return {};
1375 }
1376
1377 return result;
1378}
1379
1381 RValue rv = emitCallExpr(e);
1382
1383 if (!rv.isScalar()) {
1384 cgm.errorNYI(e->getSourceRange(), "emitCallExprLValue: non-scalar return");
1385 return {};
1386 }
1387
1388 assert(e->getCallReturnType(getContext())->isReferenceType() &&
1389 "Can't have a scalar return unless the return type is a "
1390 "reference type!");
1391
1393}
1394
1396 // Comma expressions just emit their LHS then their RHS as an l-value.
1397 if (e->getOpcode() == BO_Comma) {
1398 emitIgnoredExpr(e->getLHS());
1399 return emitLValue(e->getRHS());
1400 }
1401
1402 if (e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI) {
1403 cgm.errorNYI(e->getSourceRange(), "member pointers");
1404 return {};
1405 }
1406
1407 assert(e->getOpcode() == BO_Assign && "unexpected binary l-value");
1408
1409 // Note that in all of these cases, __block variables need the RHS
1410 // evaluated first just in case the variable gets moved by the RHS.
1411
1413 case cir::TEK_Scalar: {
1415 if (e->getLHS()->getType().getObjCLifetime() !=
1417 cgm.errorNYI(e->getSourceRange(), "objc lifetimes");
1418 return {};
1419 }
1420
1421 RValue rv = emitAnyExpr(e->getRHS());
1422 LValue lv = emitLValue(e->getLHS());
1423
1424 SourceLocRAIIObject loc{*this, getLoc(e->getSourceRange())};
1425 if (lv.isBitField())
1427 else
1428 emitStoreThroughLValue(rv, lv);
1429
1430 if (getLangOpts().OpenMP) {
1431 cgm.errorNYI(e->getSourceRange(), "openmp");
1432 return {};
1433 }
1434
1435 return lv;
1436 }
1437
1438 case cir::TEK_Complex: {
1440 }
1441
1442 case cir::TEK_Aggregate:
1443 cgm.errorNYI(e->getSourceRange(), "aggregate lvalues");
1444 return {};
1445 }
1446 llvm_unreachable("bad evaluation kind");
1447}
1448
1449/// Emit code to compute the specified expression which
1450/// can have any type. The result is returned as an RValue struct.
1453 case cir::TEK_Scalar:
1454 return RValue::get(emitScalarExpr(e));
1455 case cir::TEK_Complex:
1457 case cir::TEK_Aggregate: {
1458 if (aggSlot.isIgnored())
1459 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
1461 emitAggExpr(e, aggSlot);
1462 return aggSlot.asRValue();
1463 }
1464 }
1465 llvm_unreachable("bad evaluation kind");
1466}
1467
1468// Detect the unusual situation where an inline version is shadowed by a
1469// non-inline version. In that case we should pick the external one
1470// everywhere. That's GCC behavior too.
1472 for (const FunctionDecl *pd = fd; pd; pd = pd->getPreviousDecl())
1473 if (!pd->isInlineBuiltinDeclaration())
1474 return false;
1475 return true;
1476}
1477
1478CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {
1479 const auto *fd = cast<FunctionDecl>(gd.getDecl());
1480
1481 if (unsigned builtinID = fd->getBuiltinID()) {
1482 if (fd->getAttr<AsmLabelAttr>()) {
1483 cgm.errorNYI("AsmLabelAttr");
1484 }
1485
1486 StringRef ident = fd->getName();
1487 std::string fdInlineName = (ident + ".inline").str();
1488
1489 bool isPredefinedLibFunction =
1491 // Assume nobuiltins everywhere until we actually read the attributes.
1492 bool hasAttributeNoBuiltin = true;
1494
1495 // When directing calling an inline builtin, call it through it's mangled
1496 // name to make it clear it's not the actual builtin.
1497 auto fn = cast<cir::FuncOp>(curFn);
1498 if (fn.getName() != fdInlineName && onlyHasInlineBuiltinDeclaration(fd)) {
1499 cgm.errorNYI("Inline only builtin function calls");
1500 }
1501
1502 // Replaceable builtins provide their own implementation of a builtin. If we
1503 // are in an inline builtin implementation, avoid trivial infinite
1504 // recursion. Honor __attribute__((no_builtin("foo"))) or
1505 // __attribute__((no_builtin)) on the current function unless foo is
1506 // not a predefined library function which means we must generate the
1507 // builtin no matter what.
1508 else if (!isPredefinedLibFunction || !hasAttributeNoBuiltin)
1509 return CIRGenCallee::forBuiltin(builtinID, fd);
1510 }
1511
1512 cir::FuncOp callee = emitFunctionDeclPointer(cgm, gd);
1513
1514 assert(!cir::MissingFeatures::hip());
1515
1516 return CIRGenCallee::forDirect(callee, gd);
1517}
1518
1520 if (ty->isVoidType())
1521 return RValue::get(nullptr);
1522
1523 cgm.errorNYI("unsupported type for undef rvalue");
1524 return RValue::get(nullptr);
1525}
1526
1528 const CIRGenCallee &origCallee,
1529 const clang::CallExpr *e,
1530 ReturnValueSlot returnValue) {
1531 // Get the actual function type. The callee type will always be a pointer to
1532 // function type or a block pointer type.
1533 assert(calleeTy->isFunctionPointerType() &&
1534 "Callee must have function pointer type!");
1535
1536 calleeTy = getContext().getCanonicalType(calleeTy);
1537 auto pointeeTy = cast<PointerType>(calleeTy)->getPointeeType();
1538
1539 CIRGenCallee callee = origCallee;
1540
1541 if (getLangOpts().CPlusPlus)
1543
1544 const auto *fnType = cast<FunctionType>(pointeeTy);
1545
1547
1548 CallArgList args;
1550
1551 emitCallArgs(args, dyn_cast<FunctionProtoType>(fnType), e->arguments(),
1552 e->getDirectCallee());
1553
1554 const CIRGenFunctionInfo &funcInfo =
1555 cgm.getTypes().arrangeFreeFunctionCall(args, fnType);
1556
1557 // C99 6.5.2.2p6:
1558 // If the expression that denotes the called function has a type that does
1559 // not include a prototype, [the default argument promotions are performed].
1560 // If the number of arguments does not equal the number of parameters, the
1561 // behavior is undefined. If the function is defined with a type that
1562 // includes a prototype, and either the prototype ends with an ellipsis (,
1563 // ...) or the types of the arguments after promotion are not compatible
1564 // with the types of the parameters, the behavior is undefined. If the
1565 // function is defined with a type that does not include a prototype, and
1566 // the types of the arguments after promotion are not compatible with those
1567 // of the parameters after promotion, the behavior is undefined [except in
1568 // some trivial cases].
1569 // That is, in the general case, we should assume that a call through an
1570 // unprototyped function type works like a *non-variadic* call. The way we
1571 // make this work is to cast to the exxact type fo the promoted arguments.
1572 if (isa<FunctionNoProtoType>(fnType)) {
1575 cir::FuncType calleeTy = getTypes().getFunctionType(funcInfo);
1576 // get non-variadic function type
1577 calleeTy = cir::FuncType::get(calleeTy.getInputs(),
1578 calleeTy.getReturnType(), false);
1579 auto calleePtrTy = cir::PointerType::get(calleeTy);
1580
1581 mlir::Operation *fn = callee.getFunctionPointer();
1582 mlir::Value addr;
1583 if (auto funcOp = mlir::dyn_cast<cir::FuncOp>(fn)) {
1584 addr = builder.create<cir::GetGlobalOp>(
1585 getLoc(e->getSourceRange()),
1586 cir::PointerType::get(funcOp.getFunctionType()), funcOp.getSymName());
1587 } else {
1588 addr = fn->getResult(0);
1589 }
1590
1591 fn = builder.createBitcast(addr, calleePtrTy).getDefiningOp();
1592 callee.setFunctionPointer(fn);
1593 }
1594
1596 assert(!cir::MissingFeatures::hip());
1598
1599 cir::CIRCallOpInterface callOp;
1600 RValue callResult = emitCall(funcInfo, callee, returnValue, args, &callOp,
1601 getLoc(e->getExprLoc()));
1602
1604
1605 return callResult;
1606}
1607
1609 e = e->IgnoreParens();
1610
1611 // Look through function-to-pointer decay.
1612 if (const auto *implicitCast = dyn_cast<ImplicitCastExpr>(e)) {
1613 if (implicitCast->getCastKind() == CK_FunctionToPointerDecay ||
1614 implicitCast->getCastKind() == CK_BuiltinFnToFnPtr) {
1615 return emitCallee(implicitCast->getSubExpr());
1616 }
1617 // When performing an indirect call through a function pointer lvalue, the
1618 // function pointer lvalue is implicitly converted to an rvalue through an
1619 // lvalue-to-rvalue conversion.
1620 assert(implicitCast->getCastKind() == CK_LValueToRValue &&
1621 "unexpected implicit cast on function pointers");
1622 } else if (const auto *declRef = dyn_cast<DeclRefExpr>(e)) {
1623 // Resolve direct calls.
1624 const auto *funcDecl = cast<FunctionDecl>(declRef->getDecl());
1625 return emitDirectCallee(funcDecl);
1626 } else if (isa<MemberExpr>(e)) {
1628 "emitCallee: call to member function is NYI");
1629 return {};
1630 } else if (auto *pde = dyn_cast<CXXPseudoDestructorExpr>(e)) {
1632 }
1633
1634 // Otherwise, we have an indirect reference.
1635 mlir::Value calleePtr;
1637 if (const auto *ptrType = e->getType()->getAs<clang::PointerType>()) {
1638 calleePtr = emitScalarExpr(e);
1639 functionType = ptrType->getPointeeType();
1640 } else {
1641 functionType = e->getType();
1642 calleePtr = emitLValue(e).getPointer();
1643 }
1644 assert(functionType->isFunctionType());
1645
1646 GlobalDecl gd;
1647 if (const auto *vd =
1648 dyn_cast_or_null<VarDecl>(e->getReferencedDeclOfCallee()))
1649 gd = GlobalDecl(vd);
1650
1651 CIRGenCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), gd);
1652 CIRGenCallee callee(calleeInfo, calleePtr.getDefiningOp());
1653 return callee;
1654}
1655
1657 ReturnValueSlot returnValue) {
1659
1660 if (const auto *ce = dyn_cast<CXXMemberCallExpr>(e))
1661 return emitCXXMemberCallExpr(ce, returnValue);
1662
1663 if (isa<CUDAKernelCallExpr>(e)) {
1664 cgm.errorNYI(e->getSourceRange(), "call to CUDA kernel");
1665 return RValue::get(nullptr);
1666 }
1667
1668 if (const auto *operatorCall = dyn_cast<CXXOperatorCallExpr>(e)) {
1669 // If the callee decl is a CXXMethodDecl, we need to emit this as a C++
1670 // operator member call.
1671 if (const CXXMethodDecl *md =
1672 dyn_cast_or_null<CXXMethodDecl>(operatorCall->getCalleeDecl()))
1673 return emitCXXOperatorMemberCallExpr(operatorCall, md, returnValue);
1674 // A CXXOperatorCallExpr is created even for explicit object methods, but
1675 // these should be treated like static function calls. Fall through to do
1676 // that.
1677 }
1678
1679 CIRGenCallee callee = emitCallee(e->getCallee());
1680
1681 if (callee.isBuiltin())
1682 return emitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(), e,
1683 returnValue);
1684
1685 if (callee.isPseudoDestructor())
1687
1688 return emitCall(e->getCallee()->getType(), callee, e, returnValue);
1689}
1690
1691/// Emit code to compute the specified expression, ignoring the result.
1693 if (e->isPRValue()) {
1695 emitAnyExpr(e);
1696 return;
1697 }
1698
1699 // Just emit it as an l-value and drop the result.
1700 emitLValue(e);
1701}
1702
1704 LValueBaseInfo *baseInfo) {
1706 assert(e->getType()->isArrayType() &&
1707 "Array to pointer decay must have array source type!");
1708
1709 // Expressions of array type can't be bitfields or vector elements.
1710 LValue lv = emitLValue(e);
1711 Address addr = lv.getAddress();
1712
1713 // If the array type was an incomplete type, we need to make sure
1714 // the decay ends up being the right type.
1715 auto lvalueAddrTy = mlir::cast<cir::PointerType>(addr.getPointer().getType());
1716
1717 if (e->getType()->isVariableArrayType())
1718 return addr;
1719
1720 [[maybe_unused]] auto pointeeTy =
1721 mlir::cast<cir::ArrayType>(lvalueAddrTy.getPointee());
1722
1723 [[maybe_unused]] mlir::Type arrayTy = convertType(e->getType());
1724 assert(mlir::isa<cir::ArrayType>(arrayTy) && "expected array");
1725 assert(pointeeTy == arrayTy);
1726
1727 // The result of this decay conversion points to an array element within the
1728 // base lvalue. However, since TBAA currently does not support representing
1729 // accesses to elements of member arrays, we conservatively represent accesses
1730 // to the pointee object as if it had no any base lvalue specified.
1731 // TODO: Support TBAA for member arrays.
1734
1735 mlir::Value ptr = builder.maybeBuildArrayDecay(
1736 cgm.getLoc(e->getSourceRange()), addr.getPointer(),
1737 convertTypeForMem(eltType));
1738 return Address(ptr, addr.getAlignment());
1739}
1740
1741/// Given the address of a temporary variable, produce an r-value of its type.
1745 switch (getEvaluationKind(type)) {
1746 case cir::TEK_Complex:
1747 cgm.errorNYI(loc, "convertTempToRValue: complex type");
1748 return RValue::get(nullptr);
1749 case cir::TEK_Aggregate:
1750 cgm.errorNYI(loc, "convertTempToRValue: aggregate type");
1751 return RValue::get(nullptr);
1752 case cir::TEK_Scalar:
1753 return RValue::get(emitLoadOfScalar(lvalue, loc));
1754 }
1755 llvm_unreachable("bad evaluation kind");
1756}
1757
1758/// Emit an `if` on a boolean condition, filling `then` and `else` into
1759/// appropriated regions.
1760mlir::LogicalResult CIRGenFunction::emitIfOnBoolExpr(const Expr *cond,
1761 const Stmt *thenS,
1762 const Stmt *elseS) {
1763 mlir::Location thenLoc = getLoc(thenS->getSourceRange());
1764 std::optional<mlir::Location> elseLoc;
1765 if (elseS)
1766 elseLoc = getLoc(elseS->getSourceRange());
1767
1768 mlir::LogicalResult resThen = mlir::success(), resElse = mlir::success();
1770 cond, /*thenBuilder=*/
1771 [&](mlir::OpBuilder &, mlir::Location) {
1772 LexicalScope lexScope{*this, thenLoc, builder.getInsertionBlock()};
1773 resThen = emitStmt(thenS, /*useCurrentScope=*/true);
1774 },
1775 thenLoc,
1776 /*elseBuilder=*/
1777 [&](mlir::OpBuilder &, mlir::Location) {
1778 assert(elseLoc && "Invalid location for elseS.");
1779 LexicalScope lexScope{*this, *elseLoc, builder.getInsertionBlock()};
1780 resElse = emitStmt(elseS, /*useCurrentScope=*/true);
1781 },
1782 elseLoc);
1783
1784 return mlir::LogicalResult::success(resThen.succeeded() &&
1785 resElse.succeeded());
1786}
1787
1788/// Emit an `if` on a boolean condition, filling `then` and `else` into
1789/// appropriated regions.
1791 const clang::Expr *cond, BuilderCallbackRef thenBuilder,
1792 mlir::Location thenLoc, BuilderCallbackRef elseBuilder,
1793 std::optional<mlir::Location> elseLoc) {
1794 // Attempt to be as accurate as possible with IfOp location, generate
1795 // one fused location that has either 2 or 4 total locations, depending
1796 // on else's availability.
1797 SmallVector<mlir::Location, 2> ifLocs{thenLoc};
1798 if (elseLoc)
1799 ifLocs.push_back(*elseLoc);
1800 mlir::Location loc = mlir::FusedLoc::get(&getMLIRContext(), ifLocs);
1801
1802 // Emit the code with the fully general case.
1803 mlir::Value condV = emitOpOnBoolExpr(loc, cond);
1804 return builder.create<cir::IfOp>(loc, condV, elseLoc.has_value(),
1805 /*thenBuilder=*/thenBuilder,
1806 /*elseBuilder=*/elseBuilder);
1807}
1808
1809/// TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
1810mlir::Value CIRGenFunction::emitOpOnBoolExpr(mlir::Location loc,
1811 const Expr *cond) {
1814 cond = cond->IgnoreParens();
1815
1816 // In LLVM the condition is reversed here for efficient codegen.
1817 // This should be done in CIR prior to LLVM lowering, if we do now
1818 // we can make CIR based diagnostics misleading.
1819 // cir.ternary(!x, t, f) -> cir.ternary(x, f, t)
1821
1822 if (const ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(cond)) {
1823 Expr *trueExpr = condOp->getTrueExpr();
1824 Expr *falseExpr = condOp->getFalseExpr();
1825 mlir::Value condV = emitOpOnBoolExpr(loc, condOp->getCond());
1826
1827 mlir::Value ternaryOpRes =
1828 builder
1829 .create<cir::TernaryOp>(
1830 loc, condV, /*thenBuilder=*/
1831 [this, trueExpr](mlir::OpBuilder &b, mlir::Location loc) {
1832 mlir::Value lhs = emitScalarExpr(trueExpr);
1833 b.create<cir::YieldOp>(loc, lhs);
1834 },
1835 /*elseBuilder=*/
1836 [this, falseExpr](mlir::OpBuilder &b, mlir::Location loc) {
1837 mlir::Value rhs = emitScalarExpr(falseExpr);
1838 b.create<cir::YieldOp>(loc, rhs);
1839 })
1840 .getResult();
1841
1842 return emitScalarConversion(ternaryOpRes, condOp->getType(),
1843 getContext().BoolTy, condOp->getExprLoc());
1844 }
1845
1846 if (isa<CXXThrowExpr>(cond)) {
1847 cgm.errorNYI("NYI");
1848 return createDummyValue(loc, cond->getType());
1849 }
1850
1851 // If the branch has a condition wrapped by __builtin_unpredictable,
1852 // create metadata that specifies that the branch is unpredictable.
1853 // Don't bother if not optimizing because that metadata would not be used.
1855
1856 // Emit the code with the fully general case.
1857 return evaluateExprAsBool(cond);
1858}
1859
1860mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
1861 mlir::Location loc, CharUnits alignment,
1862 bool insertIntoFnEntryBlock,
1863 mlir::Value arraySize) {
1864 mlir::Block *entryBlock = insertIntoFnEntryBlock
1866 : curLexScope->getEntryBlock();
1867
1868 // If this is an alloca in the entry basic block of a cir.try and there's
1869 // a surrounding cir.scope, make sure the alloca ends up in the surrounding
1870 // scope instead. This is necessary in order to guarantee all SSA values are
1871 // reachable during cleanups.
1872 assert(!cir::MissingFeatures::tryOp());
1873
1874 return emitAlloca(name, ty, loc, alignment,
1875 builder.getBestAllocaInsertPoint(entryBlock), arraySize);
1876}
1877
1878mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
1879 mlir::Location loc, CharUnits alignment,
1880 mlir::OpBuilder::InsertPoint ip,
1881 mlir::Value arraySize) {
1882 // CIR uses its own alloca address space rather than follow the target data
1883 // layout like original CodeGen. The data layout awareness should be done in
1884 // the lowering pass instead.
1886 cir::PointerType localVarPtrTy = builder.getPointerTo(ty);
1887 mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);
1888
1889 mlir::Value addr;
1890 {
1891 mlir::OpBuilder::InsertionGuard guard(builder);
1892 builder.restoreInsertionPoint(ip);
1893 addr = builder.createAlloca(loc, /*addr type*/ localVarPtrTy,
1894 /*var type*/ ty, name, alignIntAttr);
1896 }
1897 return addr;
1898}
1899
1900// Note: this function also emit constructor calls to support a MSVC extensions
1901// allowing explicit constructor function call.
1903 ReturnValueSlot returnValue) {
1904 const Expr *callee = ce->getCallee()->IgnoreParens();
1905
1906 if (isa<BinaryOperator>(callee)) {
1908 "emitCXXMemberCallExpr: C++ binary operator");
1909 return RValue::get(nullptr);
1910 }
1911
1912 const auto *me = cast<MemberExpr>(callee);
1913 const auto *md = cast<CXXMethodDecl>(me->getMemberDecl());
1914
1915 if (md->isStatic()) {
1916 cgm.errorNYI(ce->getSourceRange(), "emitCXXMemberCallExpr: static method");
1917 return RValue::get(nullptr);
1918 }
1919
1920 bool hasQualifier = me->hasQualifier();
1921 NestedNameSpecifier qualifier = me->getQualifier();
1922 bool isArrow = me->isArrow();
1923 const Expr *base = me->getBase();
1924
1926 ce, md, returnValue, hasQualifier, qualifier, isArrow, base);
1927}
1928
1930 AggValueSlot dest) {
1931 assert(!dest.isIgnored() && "Must have a destination!");
1932 const CXXConstructorDecl *cd = e->getConstructor();
1933
1934 // If we require zero initialization before (or instead of) calling the
1935 // constructor, as can be the case with a non-user-provided default
1936 // constructor, emit the zero initialization now, unless destination is
1937 // already zeroed.
1938 if (e->requiresZeroInitialization() && !dest.isZeroed()) {
1940 "emitCXXConstructExpr: requires initialization");
1941 return;
1942 }
1943
1944 // If this is a call to a trivial default constructor:
1945 // In LLVM: do nothing.
1946 // In CIR: emit as a regular call, other later passes should lower the
1947 // ctor call into trivial initialization.
1948
1949 // Elide the constructor if we're constructing from a temporary
1950 if (getLangOpts().ElideConstructors && e->isElidable()) {
1952 "emitCXXConstructExpr: elidable constructor");
1953 return;
1954 }
1955
1956 if (const ArrayType *arrayType = getContext().getAsArrayType(e->getType())) {
1958 emitCXXAggrConstructorCall(cd, arrayType, dest.getAddress(), e, false);
1959 } else {
1960
1962 bool forVirtualBase = false;
1963 bool delegating = false;
1964
1965 switch (e->getConstructionKind()) {
1968 break;
1970 // We should be emitting a constructor; GlobalDecl will assert this
1972 delegating = true;
1973 break;
1975 forVirtualBase = true;
1976 [[fallthrough]];
1978 type = Ctor_Base;
1979 break;
1980 }
1981
1982 emitCXXConstructorCall(cd, type, forVirtualBase, delegating, dest, e);
1983 }
1984}
1985
1987 // Emit the expression as an lvalue.
1988 LValue lv = emitLValue(e);
1989 assert(lv.isSimple());
1990 mlir::Value value = lv.getPointer();
1991
1993
1994 return RValue::get(value);
1995}
1996
1998 LValueBaseInfo *pointeeBaseInfo) {
1999 if (refLVal.isVolatile())
2000 cgm.errorNYI(loc, "load of volatile reference");
2001
2002 cir::LoadOp load =
2003 builder.create<cir::LoadOp>(loc, refLVal.getAddress().getElementType(),
2004 refLVal.getAddress().getPointer());
2005
2007
2008 QualType pointeeType = refLVal.getType()->getPointeeType();
2009 CharUnits align = cgm.getNaturalTypeAlignment(pointeeType, pointeeBaseInfo);
2010 return Address(load, convertTypeForMem(pointeeType), align);
2011}
2012
2014 mlir::Location loc,
2015 QualType refTy,
2016 AlignmentSource source) {
2017 LValue refLVal = makeAddrLValue(refAddr, refTy, LValueBaseInfo(source));
2018 LValueBaseInfo pointeeBaseInfo;
2020 Address pointeeAddr = emitLoadOfReference(refLVal, loc, &pointeeBaseInfo);
2021 return makeAddrLValue(pointeeAddr, refLVal.getType()->getPointeeType(),
2022 pointeeBaseInfo);
2023}
2024
2025void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) {
2026 cir::TrapOp::create(builder, loc);
2027 if (createNewBlock)
2028 builder.createBlock(builder.getBlock()->getParent());
2029}
2030
2032 bool createNewBlock) {
2034 cir::UnreachableOp::create(builder, getLoc(loc));
2035 if (createNewBlock)
2036 builder.createBlock(builder.getBlock()->getParent());
2037}
2038
2039mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,
2040 clang::QualType qt) {
2041 mlir::Type t = convertType(qt);
2042 CharUnits alignment = getContext().getTypeAlignInChars(qt);
2043 return builder.createDummyValue(loc, t, alignment);
2044}
2045
2046//===----------------------------------------------------------------------===//
2047// CIR builder helpers
2048//===----------------------------------------------------------------------===//
2049
2051 const Twine &name, Address *alloca,
2052 mlir::OpBuilder::InsertPoint ip) {
2053 // FIXME: Should we prefer the preferred type alignment here?
2054 return createMemTemp(ty, getContext().getTypeAlignInChars(ty), loc, name,
2055 alloca, ip);
2056}
2057
2059 mlir::Location loc, const Twine &name,
2060 Address *alloca,
2061 mlir::OpBuilder::InsertPoint ip) {
2062 Address result = createTempAlloca(convertTypeForMem(ty), align, loc, name,
2063 /*ArraySize=*/nullptr, alloca, ip);
2064 if (ty->isConstantMatrixType()) {
2066 cgm.errorNYI(loc, "temporary matrix value");
2067 }
2068 return result;
2069}
2070
2071/// This creates a alloca and inserts it into the entry block of the
2072/// current region.
2074 mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name,
2075 mlir::Value arraySize, mlir::OpBuilder::InsertPoint ip) {
2076 cir::AllocaOp alloca = ip.isSet()
2077 ? createTempAlloca(ty, loc, name, ip, arraySize)
2078 : createTempAlloca(ty, loc, name, arraySize);
2079 alloca.setAlignmentAttr(cgm.getSize(align));
2080 return Address(alloca, ty, align);
2081}
2082
2083/// This creates a alloca and inserts it into the entry block. The alloca is
2084/// casted to default address space if necessary.
2086 mlir::Location loc, const Twine &name,
2087 mlir::Value arraySize,
2088 Address *allocaAddr,
2089 mlir::OpBuilder::InsertPoint ip) {
2090 Address alloca =
2091 createTempAllocaWithoutCast(ty, align, loc, name, arraySize, ip);
2092 if (allocaAddr)
2093 *allocaAddr = alloca;
2094 mlir::Value v = alloca.getPointer();
2095 // Alloca always returns a pointer in alloca address space, which may
2096 // be different from the type defined by the language. For example,
2097 // in C++ the auto variables are in the default address space. Therefore
2098 // cast alloca to the default address space when necessary.
2100 return Address(v, ty, align);
2101}
2102
2103/// This creates an alloca and inserts it into the entry block if \p ArraySize
2104/// is nullptr, otherwise inserts it at the current insertion point of the
2105/// builder.
2106cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
2107 mlir::Location loc,
2108 const Twine &name,
2109 mlir::Value arraySize,
2110 bool insertIntoFnEntryBlock) {
2111 return mlir::cast<cir::AllocaOp>(emitAlloca(name.str(), ty, loc, CharUnits(),
2112 insertIntoFnEntryBlock, arraySize)
2113 .getDefiningOp());
2114}
2115
2116/// This creates an alloca and inserts it into the provided insertion point
2117cir::AllocaOp CIRGenFunction::createTempAlloca(mlir::Type ty,
2118 mlir::Location loc,
2119 const Twine &name,
2120 mlir::OpBuilder::InsertPoint ip,
2121 mlir::Value arraySize) {
2122 assert(ip.isSet() && "Insertion point is not set");
2123 return mlir::cast<cir::AllocaOp>(
2124 emitAlloca(name.str(), ty, loc, CharUnits(), ip, arraySize)
2125 .getDefiningOp());
2126}
2127
2128/// Try to emit a reference to the given value without producing it as
2129/// an l-value. For many cases, this is just an optimization, but it avoids
2130/// us needing to emit global copies of variables if they're named without
2131/// triggering a formal use in a context where we can't emit a direct
2132/// reference to them, for instance if a block or lambda or a member of a
2133/// local class uses a const int variable or constexpr variable from an
2134/// enclosing function.
2135///
2136/// For named members of enums, this is the only way they are emitted.
2139 const ValueDecl *value = refExpr->getDecl();
2140
2141 // There is a lot more to do here, but for now only EnumConstantDecl is
2142 // supported.
2144
2145 // The value needs to be an enum constant or a constant variable.
2146 if (!isa<EnumConstantDecl>(value))
2147 return ConstantEmission();
2148
2149 Expr::EvalResult result;
2150 if (!refExpr->EvaluateAsRValue(result, getContext()))
2151 return ConstantEmission();
2152
2153 QualType resultType = refExpr->getType();
2154
2155 // As long as we're only handling EnumConstantDecl, there should be no
2156 // side-effects.
2157 assert(!result.HasSideEffects);
2158
2159 // Emit as a constant.
2160 // FIXME(cir): have emitAbstract build a TypedAttr instead (this requires
2161 // somewhat heavy refactoring...)
2162 mlir::Attribute c = ConstantEmitter(*this).emitAbstract(
2163 refExpr->getLocation(), result.Val, resultType);
2164 mlir::TypedAttr cstToEmit = mlir::dyn_cast_if_present<mlir::TypedAttr>(c);
2165 assert(cstToEmit && "expected a typed attribute");
2166
2168
2169 return ConstantEmission::forValue(cstToEmit);
2170}
2171
2175 return tryEmitAsConstant(dre);
2176 return ConstantEmission();
2177}
2178
2180 const CIRGenFunction::ConstantEmission &constant, Expr *e) {
2181 assert(constant && "not a constant");
2182 if (constant.isReference()) {
2183 cgm.errorNYI(e->getSourceRange(), "emitScalarConstant: reference");
2184 return {};
2185 }
2186 return builder.getConstant(getLoc(e->getSourceRange()), constant.getValue());
2187}
2188
2189/// An LValue is a candidate for having its loads and stores be made atomic if
2190/// we are operating under /volatile:ms *and* the LValue itself is volatile and
2191/// performing such an operation can be performed without a libcall.
2193 if (!cgm.getLangOpts().MSVolatile)
2194 return false;
2195
2196 cgm.errorNYI("LValueSuitableForInlineAtomic LangOpts MSVolatile");
2197 return false;
2198}
#define V(N, I)
Definition: ASTContext.h:3597
llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> BuilderCallbackRef
Definition: CIRDialect.h:38
static Address createReferenceTemporary(CIRGenFunction &cgf, const MaterializeTemporaryExpr *m, const Expr *inner)
static bool isAAPCS(const TargetInfo &targetInfo)
Helper method to check if the underlying ABI is AAPCS.
Definition: CIRGenExpr.cpp:360
static LValue emitFunctionDeclLValue(CIRGenFunction &cgf, const Expr *e, GlobalDecl gd)
Definition: CIRGenExpr.cpp:592
static CharUnits getArrayElementAlign(CharUnits arrayAlign, mlir::Value idx, CharUnits eltSize)
Definition: CIRGenExpr.cpp:815
static void pushTemporaryCleanup(CIRGenFunction &cgf, const MaterializeTemporaryExpr *m, const Expr *e, Address referenceTemporary)
static cir::IntAttr getConstantIndexOrNull(mlir::Value idx)
Definition: CIRGenExpr.cpp:808
static const Expr * getSimpleArrayDecayOperand(const Expr *e)
If the specified expr is a simple decay from an array to pointer, return the array subexpression.
Definition: CIRGenExpr.cpp:794
static QualType getFixedSizeElementType(const ASTContext &astContext, const VariableArrayType *vla)
Definition: CIRGenExpr.cpp:827
static DeclRefExpr * tryToConvertMemberExprToDeclRefExpr(CIRGenFunction &cgf, const MemberExpr *me)
static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd)
Definition: CIRGenExpr.cpp:587
static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e, const VarDecl *vd)
Definition: CIRGenExpr.cpp:275
static mlir::Value emitArraySubscriptPtr(CIRGenFunction &cgf, mlir::Location beginLoc, mlir::Location endLoc, mlir::Value ptr, mlir::Type eltTy, mlir::Value idx, bool shouldDecay)
Definition: CIRGenExpr.cpp:836
static bool onlyHasInlineBuiltinDeclaration(const FunctionDecl *fd)
Defines the clang::Expr interface and subclasses for C++ expressions.
__device__ __2f16 b
__device__ __2f16 float c
mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block)
cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy, mlir::Value base, llvm::StringRef name, unsigned index)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, mlir::IntegerAttr alignment)
mlir::Value createDummyValue(mlir::Location loc, mlir::Type type, clang::CharUnits alignment)
mlir::DataLayout layout
Definition: CIRDataLayout.h:28
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2851
Builtin::Context & BuiltinInfo
Definition: ASTContext.h:742
CanQualType BoolTy
Definition: ASTContext.h:1223
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
Definition: ASTContext.h:3059
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2723
SourceLocation getExprLoc() const LLVM_READONLY
Definition: Expr.h:2778
Expr * getLHS()
An array access can be written A[4] or 4[A] (both are equivalent).
Definition: Expr.h:2752
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.h:2766
SourceLocation getEndLoc() const
Definition: Expr.h:2769
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: TypeBase.h:3738
QualType getElementType() const
Definition: TypeBase.h:3750
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3974
Expr * getLHS() const
Definition: Expr.h:4024
Expr * getRHS() const
Definition: Expr.h:4026
Opcode getOpcode() const
Definition: Expr.h:4019
bool isPredefinedLibFunction(unsigned ID) const
Determines whether this builtin is a predefined libc/libm function, such as "malloc",...
Definition: Builtins.h:313
mlir::Value getPointer() const
Definition: Address.h:81
mlir::Type getElementType() const
Definition: Address.h:101
static Address invalid()
Definition: Address.h:66
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:109
bool isValid() const
Definition: Address.h:67
mlir::Operation * getDefiningOp() const
Get the operation which defines this address.
Definition: Address.h:112
An aggregate value slot.
Definition: CIRGenValue.h:302
IsZeroed_t isZeroed() const
Definition: CIRGenValue.h:382
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
Definition: CIRGenValue.h:359
Address getAddress() const
Definition: CIRGenValue.h:376
mlir::Value createComplexRealPtr(mlir::Location loc, mlir::Value value)
Create a cir.complex.real_ptr operation that derives a pointer to the real part of the complex value ...
mlir::Value createComplexImagPtr(mlir::Location loc, mlir::Value value)
Create a cir.complex.imag_ptr operation that derives a pointer to the imaginary part of the complex v...
mlir::Value maybeBuildArrayDecay(mlir::Location loc, mlir::Value arrayPtr, mlir::Type eltTy)
Returns a decayed pointer to the first element of the array pointed to by arrayPtr.
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 createGetBitfield(mlir::Location loc, mlir::Type resultType, Address addr, mlir::Type storageType, const CIRGenBitFieldInfo &info, bool isLvalueVolatile, bool useVolatile)
mlir::Value createSetBitfield(mlir::Location loc, mlir::Type resultType, Address dstAddr, mlir::Type storageType, mlir::Value src, const CIRGenBitFieldInfo &info, bool isLvalueVolatile, bool useVolatile)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
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.
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::MemOrderAttr order={})
Abstract information about a function or function prototype.
Definition: CIRGenCall.h:27
bool isPseudoDestructor() const
Definition: CIRGenCall.h:121
void setFunctionPointer(mlir::Operation *functionPtr)
Definition: CIRGenCall.h:183
const clang::FunctionDecl * getBuiltinDecl() const
Definition: CIRGenCall.h:97
const CXXPseudoDestructorExpr * getPseudoDestructorExpr() const
Definition: CIRGenCall.h:125
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition: CIRGenCall.h:90
unsigned getBuiltinID() const
Definition: CIRGenCall.h:101
static CIRGenCallee forBuiltin(unsigned builtinID, const clang::FunctionDecl *builtinDecl)
Definition: CIRGenCall.h:106
mlir::Operation * getFunctionPointer() const
Definition: CIRGenCall.h:145
static CIRGenCallee forPseudoDestructor(const clang::CXXPseudoDestructorExpr *expr)
Definition: CIRGenCall.h:115
static ConstantEmission forValue(mlir::TypedAttr c)
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0)
Definition: CIRGenCall.cpp:731
mlir::Type convertType(clang::QualType t)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
RValue convertTempToRValue(Address addr, clang::QualType type, clang::SourceLocation loc)
Given the address of a temporary variable, produce an r-value of its type.
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...
Definition: CIRGenExpr.cpp:67
RValue emitLoadOfLValue(LValue lv, SourceLocation loc)
Given an expression that represents a value lvalue, this method emits the address of the lvalue,...
Definition: CIRGenExpr.cpp:566
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)
LValue emitLValueForBitField(LValue base, const FieldDecl *field)
Definition: CIRGenExpr.cpp:414
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.
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 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.
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
Definition: CIRGenExpr.cpp:688
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, bool isInit=false, bool isNontemporal=false)
Definition: CIRGenExpr.cpp:312
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).
Address getAddressOfBaseClass(Address value, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue, SourceLocation loc)
LValue emitStringLiteralLValue(const StringLiteral *e)
Definition: CIRGenExpr.cpp:964
LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc, QualType refTy, AlignmentSource source)
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre)
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.
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored())
Emit code to compute the specified expression which can have any type.
LValue emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e)
Definition: CIRGenExpr.cpp:876
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...
AggValueSlot createAggTemp(QualType ty, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr)
Create a temporary memory object for the given aggregate type.
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)
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)
static Destroyer destroyCXXObject
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
void emitCXXConstructorCall(const clang::CXXConstructorDecl *d, clang::CXXCtorType type, bool forVirtualBase, bool delegating, AggValueSlot thisAVS, const clang::CXXConstructExpr *e)
LValue emitUnaryOpLValue(const clang::UnaryOperator *e)
Definition: CIRGenExpr.cpp:707
RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc)
Definition: CIRGenExpr.cpp:382
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
Definition: CIRGenCall.cpp:500
LValue emitComplexAssignmentLValue(const BinaryOperator *e)
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...
Definition: CIRGenExpr.cpp:500
LValue emitCallExprLValue(const clang::CallExpr *e)
mlir::Value emitScalarExpr(const clang::Expr *e)
Emit the computation of the specified expression of scalar type.
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty)
Given a value and its clang type, returns the value casted to its memory representation.
Definition: CIRGenExpr.cpp:528
LValue emitLValueForField(LValue base, const clang::FieldDecl *field)
Definition: CIRGenExpr.cpp:438
cir::FuncOp curFn
The function for which code is currently being generated.
void pushDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer)
Definition: CIRGenDecl.cpp:683
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)
Definition: CIRGenExpr.cpp:399
CIRGenModule & getCIRGenModule()
mlir::MLIRContext & getMLIRContext()
LValue emitCastLValue(const CastExpr *e)
Casts are never lvalues unless that cast is to a reference type.
Definition: CIRGenExpr.cpp:981
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
Definition: CIRGenExpr.cpp:546
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
LValue emitDeclRefLValue(const clang::DeclRefExpr *e)
Definition: CIRGenExpr.cpp:618
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr)
Try to emit a reference to the given value without producing it as an l-value.
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo=nullptr)
void emitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, const clang::ArrayType *arrayType, Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize=false)
Emit a loop to call a particular constructor for each of several members of an array.
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
Definition: CIRGenExpr.cpp:364
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *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 ...
Definition: CIRGenExpr.cpp:246
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={})
Definition: CIRGenStmt.cpp:110
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.
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...
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
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)
Get the address of a zero-sized field within a record.
Definition: CIRGenExpr.cpp:35
This class organizes the cross-function state that is used while generating CIR code.
Definition: CIRGenModule.h:56
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
Definition: CIRGenModule.h:102
cir::GlobalOp getGlobalForStringLiteral(const StringLiteral *s, llvm::StringRef name=".str")
Return a global symbol reference to a constant array for the given string literal.
mlir::IntegerAttr getSize(CharUnits size)
Definition: CIRGenModule.h:389
CIRGenBuilderTy & getBuilder()
Definition: CIRGenModule.h:101
clang::CharUnits getNaturalTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo)
FIXME: this could likely be a common helper and not necessarily related with codegen.
const clang::TargetInfo & getTarget() const
Definition: CIRGenModule.h:103
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.
void emitExplicitCastExprType(const ExplicitCastExpr *e, CIRGenFunction *cgf=nullptr)
Emit type info if type of an expression is a variably modified type.
const cir::CIRDataLayout getDataLayout() const
Definition: CIRGenModule.h:112
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::CodeGenOptions & getCodeGenOpts() const
Definition: CIRGenModule.h:104
const clang::LangOptions & getLangOpts() const
Definition: CIRGenModule.h:107
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
This class handles record and union layout info while lowering AST types to CIR types.
cir::RecordType getCIRType() const
Return the "complete object" LLVM type associated with this record.
const CIRGenBitFieldInfo & getBitFieldInfo(const clang::FieldDecl *fd) const
Return the BitFieldInfo that corresponds to the field FD.
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
const CIRGenFunctionInfo & arrangeFreeFunctionCall(const CallArgList &args, const FunctionType *fnType)
Definition: CIRGenCall.cpp:387
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
Definition: CIRGenCall.cpp:50
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
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
Definition: CIRGenValue.h:145
void mergeForCast(const LValueBaseInfo &info)
Definition: CIRGenValue.h:148
const clang::Qualifiers & getQuals() const
Definition: CIRGenValue.h:223
mlir::Value getVectorIdx() const
Definition: CIRGenValue.h:252
bool isVectorElt() const
Definition: CIRGenValue.h:191
Address getAddress() const
Definition: CIRGenValue.h:211
static LValue makeAddr(Address address, clang::QualType t, LValueBaseInfo baseInfo)
Definition: CIRGenValue.h:229
static LValue makeVectorElt(Address vecAddress, mlir::Value index, clang::QualType t, LValueBaseInfo baseInfo)
Definition: CIRGenValue.h:257
unsigned getVRQualifiers() const
Definition: CIRGenValue.h:198
clang::QualType getType() const
Definition: CIRGenValue.h:202
static LValue makeBitfield(Address addr, const CIRGenBitFieldInfo &info, clang::QualType type, LValueBaseInfo baseInfo)
Create a new object to represent a bit-field access.
Definition: CIRGenValue.h:289
mlir::Value getPointer() const
Definition: CIRGenValue.h:204
bool isVolatileQualified() const
Definition: CIRGenValue.h:196
bool isBitField() const
Definition: CIRGenValue.h:192
Address getVectorAddress() const
Definition: CIRGenValue.h:243
clang::CharUnits getAlignment() const
Definition: CIRGenValue.h:206
LValueBaseInfo getBaseInfo() const
Definition: CIRGenValue.h:226
bool isVolatile() const
Definition: CIRGenValue.h:194
const CIRGenBitFieldInfo & getBitFieldInfo() const
Definition: CIRGenValue.h:278
Address getBitFieldAddress() const
Definition: CIRGenValue.h:269
bool isSimple() const
Definition: CIRGenValue.h:190
This trivial value class is used to represent the result of an expression that is evaluated.
Definition: CIRGenValue.h:33
static RValue get(mlir::Value v)
Definition: CIRGenValue.h:82
static RValue getComplex(mlir::Value v)
Definition: CIRGenValue.h:90
mlir::Value getValue() const
Return the value of this scalar value.
Definition: CIRGenValue.h:56
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:252
Represents a call to a C++ constructor.
Definition: ExprCXX.h:1549
bool isElidable() const
Whether this construction is elidable.
Definition: ExprCXX.h:1618
bool requiresZeroInitialization() const
Whether this construction first requires zero-initialization before the initializer is called.
Definition: ExprCXX.h:1651
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition: ExprCXX.h:1612
CXXConstructionKind getConstructionKind() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...
Definition: ExprCXX.h:1660
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2604
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2869
Represents a call to a member function that may be written either with member call syntax (e....
Definition: ExprCXX.h:179
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2129
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:1366
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2879
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3062
Expr * getCallee()
Definition: Expr.h:3026
arg_range arguments()
Definition: Expr.h:3131
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition: Expr.cpp:1599
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3612
CastKind getCastKind() const
Definition: Expr.h:3656
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
Definition: Expr.h:3699
bool changesVolatileQualification() const
Return.
Definition: Expr.h:3746
static const char * getCastKindName(CastKind CK)
Definition: Expr.cpp:1946
Expr * getSubExpr()
Definition: Expr.h:3662
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
Definition: CharUnits.h:207
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Definition: CharUnits.h:214
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition: CharUnits.h:63
Complex values, per C99 6.2.5p11.
Definition: TypeBase.h:3293
CompoundLiteralExpr - [C99 6.5.2.5].
Definition: Expr.h:3541
bool isFileScope() const
Definition: Expr.h:3573
const Expr * getInitializer() const
Definition: Expr.h:3569
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:4327
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1272
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
Definition: Expr.h:1476
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:484
ValueDecl * getDecl()
Definition: Expr.h:1340
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition: Expr.h:1470
SourceLocation getLocation() const
Definition: Expr.h:1348
SourceLocation getLocation() const
Definition: DeclBase.h:439
bool hasAttr() const
Definition: DeclBase.h:577
This represents one expression.
Definition: Expr.h:112
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
Definition: Expr.cpp:80
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition: Expr.h:444
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3069
bool isPRValue() const
Definition: Expr.h:285
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Decl * getReferencedDeclOfCallee()
Definition: Expr.cpp:1542
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:273
QualType getType() const
Definition: Expr.h:144
Represents a member of a struct/union/class.
Definition: Decl.h:3153
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3256
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4763
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition: Decl.h:3238
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition: Decl.h:3389
bool isZeroSize(const ASTContext &Ctx) const
Determine if this field is a subobject of zero size, that is, either a zero-length bit-field or a fie...
Definition: Decl.cpp:4703
Represents a function declaration or definition.
Definition: Decl.h:1999
Represents a prototype with parameter type info, e.g.
Definition: TypeBase.h:5282
GlobalDecl - represents a global declaration.
Definition: GlobalDecl.h:57
CXXCtorType getCtorType() const
Definition: GlobalDecl.h:108
const Decl * getDecl() const
Definition: GlobalDecl.h:106
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition: ExprCXX.h:4914
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition: ExprCXX.h:4939
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition: ExprCXX.h:4931
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
Definition: ExprCXX.h:4964
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3300
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3383
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why? This is only meaningful if the named memb...
Definition: Expr.h:3524
Expr * getBase() const
Definition: Expr.h:3377
bool isArrow() const
Definition: Expr.h:3484
SourceLocation getExprLoc() const LLVM_READONLY
Definition: Expr.h:3495
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition: TypeBase.h:3669
This represents a decl that may have a name.
Definition: Decl.h:273
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:300
A C++ nested-name-specifier augmented with source location information.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
Represents a class type in Objective C.
Definition: TypeBase.h:7707
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: TypeBase.h:3346
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: TypeBase.h:1004
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: TypeBase.h:8383
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition: TypeBase.h:1438
QualType withCVRQualifiers(unsigned CVR) const
Definition: TypeBase.h:1179
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition: TypeBase.h:1545
The collection of all-type qualifiers we support.
Definition: TypeBase.h:331
GC getObjCGCAttr() const
Definition: TypeBase.h:519
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition: TypeBase.h:354
@ OCL_None
There is no lifetime qualification on this type.
Definition: TypeBase.h:350
void addCVRQualifiers(unsigned mask)
Definition: TypeBase.h:502
void addQualifiers(Qualifiers Q)
Add the qualifiers from the given set to this set.
Definition: TypeBase.h:650
Represents a struct/union/class.
Definition: Decl.h:4305
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Definition: Redeclarable.h:201
Encodes a location in the source.
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:334
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1801
bool isUnion() const
Definition: Decl.h:3915
Exposes information about the current target.
Definition: TargetInfo.h:226
virtual StringRef getABI() const
Get the ABI currently in use.
Definition: TargetInfo.h:1357
bool isVoidType() const
Definition: TypeBase.h:8936
const ArrayType * castAsArrayTypeUnsafe() const
A variant of castAs<> for array type which silently discards qualifiers from the outermost type.
Definition: TypeBase.h:9235
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:8679
bool isFunctionPointerType() const
Definition: TypeBase.h:8647
CXXRecordDecl * castAsCXXRecordDecl() const
Definition: Type.h:36
bool isArithmeticType() const
Definition: Type.cpp:2341
bool isConstantMatrixType() const
Definition: TypeBase.h:8741
bool isPointerType() const
Definition: TypeBase.h:8580
const T * castAs() const
Member-template castAs<specific type>.
Definition: TypeBase.h:9226
bool isReferenceType() const
Definition: TypeBase.h:8604
bool isVariableArrayType() const
Definition: TypeBase.h:8691
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
bool isAnyComplexType() const
Definition: TypeBase.h:8715
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
Definition: TypeBase.h:9109
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition: TypeBase.h:2818
bool isFunctionType() const
Definition: TypeBase.h:8576
bool isVectorType() const
Definition: TypeBase.h:8719
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2246
SourceLocation getExprLoc() const
Definition: Expr.h:2370
Expr * getSubExpr() const
Definition: Expr.h:2287
Opcode getOpcode() const
Definition: Expr.h:2282
static bool isIncrementOp(Opcode Op)
Definition: Expr.h:2328
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
Definition: Expr.h:2321
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:711
QualType getType() const
Definition: Decl.h:722
Represents a variable declaration or definition.
Definition: Decl.h:925
TLSKind getTLSKind() const
Definition: Decl.cpp:2168
bool hasInit() const
Definition: Decl.cpp:2398
@ TLS_Dynamic
TLS with a dynamic initializer.
Definition: Decl.h:951
Represents a C array with a specified size that is not an integer-constant-expression.
Definition: TypeBase.h:3982
Represents a GCC generic vector type.
Definition: TypeBase.h:4191
Definition: ABIArgInfo.h:22
AlignmentSource
The source of the alignment of an l-value; an expression of confidence in the alignment actually matc...
Definition: CIRGenValue.h:115
@ 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...
Definition: CIRGenValue.h:133
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
Matches all kinds of arrays.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
const AstTypeMatcher< FunctionType > functionType
Matches FunctionType nodes.
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
The JSON file list parser is used to communicate input to InstallAPI.
CXXCtorType
C++ constructor types.
Definition: ABI.h:24
@ Ctor_Base
Base object ctor.
Definition: ABI.h:26
@ Ctor_Complete
Complete object ctor.
Definition: ABI.h:25
@ CPlusPlus
Definition: LangStandard.h:55
@ SD_Thread
Thread storage duration.
Definition: Specifiers.h:342
@ SD_Static
Static storage duration.
Definition: Specifiers.h:343
@ SD_FullExpression
Full-expression storage duration (for temporaries).
Definition: Specifiers.h:340
@ SD_Automatic
Automatic storage duration (most local variables).
Definition: Specifiers.h:341
@ SD_Dynamic
Dynamic storage duration.
Definition: Specifiers.h:344
UnaryOperatorKind
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
Definition: Specifiers.h:177
static bool weakRefReference()
static bool objCLifetime()
static bool emitLifetimeMarkers()
static bool opLoadEmitScalarRangeCheck()
static bool addressSpace()
static bool opLoadStoreThreadLocal()
static bool opAllocaNonGC()
static bool opGlobalThreadLocal()
static bool opAllocaOpenMPThreadPrivate()
static bool opLoadBooleanRepresentation()
static bool preservedAccessIndexRegion()
static bool mergeAllConstants()
static bool opLoadStoreAtomic()
static bool cgFPOptionsRAII()
static bool opCallChain()
static bool sanitizers()
static bool opAllocaImpreciseLifetime()
static bool typeChecks()
static bool opAllocaStaticLocal()
static bool matrixType()
static bool aggValueSlot()
static bool opAllocaTLS()
static bool emitCheckedInBoundsGEP()
static bool attributeNoBuiltin()
static bool lambdaFieldToName()
static bool setObjCGCLValueClass()
static bool opLoadStoreObjC()
static bool opCallArgEvaluationOrder()
static bool objCBlocks()
static bool lambdaCaptures()
static bool insertBuiltinUnpredictable()
static bool opCallMustTail()
static bool shouldReverseUnaryCondOnBoolExpr()
static bool tryEmitAsConstant()
static bool addressIsKnownNonNull()
static bool astVarDeclInterface()
static bool opAllocaEscapeByReference()
static bool opCallFnInfoOpts()
static bool generateDebugInfo()
static bool setNonGC()
Record with information about how a bitfield should be accessed.
unsigned volatileStorageSize
The storage size in bits which should be used when accessing this bitfield.
unsigned volatileOffset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:645
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:647
bool HasSideEffects
Whether the evaluated expression has side effects.
Definition: Expr.h:612