27 CharUnits atomicAlign;
34 AtomicInfo(CIRGenFunction &cgf, LValue &lvalue, mlir::Location loc)
35 : cgf(cgf), loc(loc) {
36 assert(!lvalue.isGlobalReg());
37 ASTContext &ctx = cgf.getContext();
38 if (lvalue.isSimple()) {
39 atomicTy = lvalue.getType();
40 if (
auto *ty = atomicTy->getAs<AtomicType>())
41 valueTy = ty->getValueType();
44 evaluationKind = cgf.getEvaluationKind(valueTy);
47 TypeInfo atomicTypeInfo = ctx.
getTypeInfo(atomicTy);
50 valueSizeInBits = valueTypeInfo.
Width;
51 atomicSizeInBits = atomicTypeInfo.
Width;
52 assert(valueSizeInBits <= atomicSizeInBits);
53 assert(valueAlignInBits <= atomicAlignInBits);
57 if (lvalue.getAlignment().isZero())
58 lvalue.setAlignment(atomicAlign);
60 this->lvalue = lvalue;
63 cgf.cgm.errorNYI(loc,
"AtomicInfo: non-simple lvalue");
69 QualType getValueType()
const {
return valueTy; }
70 CharUnits getAtomicAlignment()
const {
return atomicAlign; }
72 mlir::Value getAtomicPointer()
const {
73 if (lvalue.isSimple())
74 return lvalue.getPointer();
78 Address getAtomicAddress()
const {
80 if (lvalue.isSimple()) {
81 elemTy = lvalue.getAddress().getElementType();
84 cgf.cgm.errorNYI(loc,
"AtomicInfo::getAtomicAddress: non-simple lvalue");
86 return Address(getAtomicPointer(), elemTy, getAtomicAlignment());
95 bool hasPadding()
const {
return (valueSizeInBits != atomicSizeInBits); }
97 bool emitMemSetZeroIfNecessary()
const;
101 Address castToAtomicIntPointer(Address addr)
const;
106 Address convertToAtomicIntPointer(Address addr)
const;
109 void emitCopyIntoMemory(RValue rvalue)
const;
112 LValue projectValue()
const {
113 assert(lvalue.isSimple());
114 Address addr = getAtomicAddress();
116 cgf.cgm.errorNYI(loc,
"AtomicInfo::projectValue: padding");
120 return LValue::makeAddr(addr, getValueType(), lvalue.getBaseInfo());
124 Address createTempAlloca()
const;
127 bool requiresMemSetZero(mlir::Type ty)
const;
143 uint64_t expectedSize) {
150bool AtomicInfo::requiresMemSetZero(mlir::Type ty)
const {
156 switch (getEvaluationKind()) {
163 mlir::cast<cir::ComplexType>(ty).getElementType(),
164 atomicSizeInBits / 2);
169 llvm_unreachable(
"bad evaluation kind");
172Address AtomicInfo::convertToAtomicIntPointer(Address addr)
const {
175 if (sourceSizeInBits != atomicSizeInBits) {
178 "AtomicInfo::convertToAtomicIntPointer: convert through temp alloca");
181 return castToAtomicIntPointer(addr);
184Address AtomicInfo::createTempAlloca()
const {
186 (lvalue.isBitField() && valueSizeInBits > atomicSizeInBits) ? valueTy
188 getAtomicAlignment(), loc,
"atomic-temp");
191 if (lvalue.isBitField()) {
192 cgf.
cgm.
errorNYI(loc,
"AtomicInfo::createTempAlloca: bitfield lvalue");
198Address AtomicInfo::castToAtomicIntPointer(Address addr)
const {
201 if (intTy && intTy.getWidth() == atomicSizeInBits)
207bool AtomicInfo::emitMemSetZeroIfNecessary()
const {
208 assert(lvalue.isSimple());
209 Address addr = lvalue.getAddress();
214 "AtomicInfo::emitMemSetZeroIfNecessary: emit memset zero");
220void AtomicInfo::emitCopyIntoMemory(RValue rvalue)
const {
221 assert(lvalue.isSimple());
227 cgf.
cgm.
errorNYI(
"copying aggregate into atomic lvalue");
234 emitMemSetZeroIfNecessary();
237 LValue tempLValue = projectValue();
243 cgf.
cgm.
errorNYI(
"copying complex into atomic lvalue");
250 cir::MemOrder successOrder,
251 cir::MemOrder failureOrder) {
255 mlir::Value expected = builder.
createLoad(loc, val1);
256 mlir::Value desired = builder.
createLoad(loc, val2);
258 auto cmpxchg = cir::AtomicCmpXchgOp::create(
266 cmpxchg.setWeak(isWeak);
268 mlir::Value failed = builder.
createNot(cmpxchg.getSuccess());
269 cir::IfOp::create(builder, loc, failed,
false,
270 [&](mlir::OpBuilder &, mlir::Location) {
271 auto ptrTy = mlir::cast<cir::PointerType>(
290 Expr *failureOrderExpr, uint64_t size,
291 cir::MemOrder successOrder) {
294 uint64_t failureOrderInt = failureOrderEval.
Val.
getInt().getZExtValue();
296 cir::MemOrder failureOrder;
298 failureOrder = cir::MemOrder::Relaxed;
300 switch ((cir::MemOrder)failureOrderInt) {
301 case cir::MemOrder::Relaxed:
304 case cir::MemOrder::Release:
305 case cir::MemOrder::AcquireRelease:
306 failureOrder = cir::MemOrder::Relaxed;
308 case cir::MemOrder::Consume:
309 case cir::MemOrder::Acquire:
310 failureOrder = cir::MemOrder::Acquire;
312 case cir::MemOrder::SequentiallyConsistent:
313 failureOrder = cir::MemOrder::SequentiallyConsistent;
329 "emitAtomicCmpXchgFailureSet: non-constant failure order");
334 Expr *isWeakExpr,
Expr *failureOrderExpr, int64_t size,
335 cir::MemOrder order) {
336 std::unique_ptr<AtomicScopeModel> scopeModel =
expr->getScopeModel();
339 cgf.
cgm.
errorNYI(
expr->getSourceRange(),
"emitAtomicOp: atomic scope");
344 llvm::StringRef opName;
347 mlir::Location loc = cgf.
getLoc(
expr->getSourceRange());
348 auto orderAttr = cir::MemOrderAttr::get(builder.getContext(), order);
349 cir::AtomicFetchKindAttr fetchAttr;
350 bool fetchFirst =
true;
352 switch (
expr->getOp()) {
353 case AtomicExpr::AO__c11_atomic_init:
354 llvm_unreachable(
"already handled!");
356 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
358 val2, failureOrderExpr, size, order);
361 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
363 val2, failureOrderExpr, size, order);
366 case AtomicExpr::AO__atomic_compare_exchange:
367 case AtomicExpr::AO__atomic_compare_exchange_n: {
371 failureOrderExpr, size, order);
375 "emitAtomicOp: non-constant isWeak");
380 case AtomicExpr::AO__c11_atomic_load:
381 case AtomicExpr::AO__atomic_load_n:
382 case AtomicExpr::AO__atomic_load: {
388 load->setAttr(
"mem_order", orderAttr);
390 builder.
createStore(loc, load->getResult(0), dest);
394 case AtomicExpr::AO__c11_atomic_store:
395 case AtomicExpr::AO__atomic_store_n:
396 case AtomicExpr::AO__atomic_store: {
397 cir::LoadOp loadVal1 = builder.
createLoad(loc, val1);
402 mlir::IntegerAttr{}, orderAttr);
406 case AtomicExpr::AO__c11_atomic_exchange:
407 case AtomicExpr::AO__atomic_exchange_n:
408 case AtomicExpr::AO__atomic_exchange:
409 opName = cir::AtomicXchgOp::getOperationName();
412 case AtomicExpr::AO__atomic_add_fetch:
415 case AtomicExpr::AO__c11_atomic_fetch_add:
416 case AtomicExpr::AO__atomic_fetch_add:
417 opName = cir::AtomicFetchOp::getOperationName();
418 fetchAttr = cir::AtomicFetchKindAttr::get(builder.getContext(),
419 cir::AtomicFetchKind::Add);
422 case AtomicExpr::AO__atomic_sub_fetch:
425 case AtomicExpr::AO__c11_atomic_fetch_sub:
426 case AtomicExpr::AO__atomic_fetch_sub:
427 opName = cir::AtomicFetchOp::getOperationName();
428 fetchAttr = cir::AtomicFetchKindAttr::get(builder.getContext(),
429 cir::AtomicFetchKind::Sub);
432 case AtomicExpr::AO__atomic_min_fetch:
435 case AtomicExpr::AO__c11_atomic_fetch_min:
436 case AtomicExpr::AO__atomic_fetch_min:
437 opName = cir::AtomicFetchOp::getOperationName();
438 fetchAttr = cir::AtomicFetchKindAttr::get(builder.getContext(),
439 cir::AtomicFetchKind::Min);
442 case AtomicExpr::AO__atomic_max_fetch:
445 case AtomicExpr::AO__c11_atomic_fetch_max:
446 case AtomicExpr::AO__atomic_fetch_max:
447 opName = cir::AtomicFetchOp::getOperationName();
448 fetchAttr = cir::AtomicFetchKindAttr::get(builder.getContext(),
449 cir::AtomicFetchKind::Max);
452 case AtomicExpr::AO__atomic_and_fetch:
455 case AtomicExpr::AO__c11_atomic_fetch_and:
456 case AtomicExpr::AO__atomic_fetch_and:
457 opName = cir::AtomicFetchOp::getOperationName();
458 fetchAttr = cir::AtomicFetchKindAttr::get(builder.getContext(),
459 cir::AtomicFetchKind::And);
462 case AtomicExpr::AO__atomic_or_fetch:
465 case AtomicExpr::AO__c11_atomic_fetch_or:
466 case AtomicExpr::AO__atomic_fetch_or:
467 opName = cir::AtomicFetchOp::getOperationName();
468 fetchAttr = cir::AtomicFetchKindAttr::get(builder.getContext(),
469 cir::AtomicFetchKind::Or);
472 case AtomicExpr::AO__atomic_xor_fetch:
475 case AtomicExpr::AO__c11_atomic_fetch_xor:
476 case AtomicExpr::AO__atomic_fetch_xor:
477 opName = cir::AtomicFetchOp::getOperationName();
478 fetchAttr = cir::AtomicFetchKindAttr::get(builder.getContext(),
479 cir::AtomicFetchKind::Xor);
482 case AtomicExpr::AO__atomic_nand_fetch:
485 case AtomicExpr::AO__c11_atomic_fetch_nand:
486 case AtomicExpr::AO__atomic_fetch_nand:
487 opName = cir::AtomicFetchOp::getOperationName();
488 fetchAttr = cir::AtomicFetchKindAttr::get(builder.getContext(),
489 cir::AtomicFetchKind::Nand);
492 case AtomicExpr::AO__atomic_test_and_set: {
493 auto op = cir::AtomicTestAndSetOp::create(
501 case AtomicExpr::AO__atomic_clear: {
502 cir::AtomicClearOp::create(
509 case AtomicExpr::AO__opencl_atomic_init:
511 case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
512 case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
514 case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
515 case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
517 case AtomicExpr::AO__scoped_atomic_compare_exchange:
518 case AtomicExpr::AO__scoped_atomic_compare_exchange_n:
520 case AtomicExpr::AO__opencl_atomic_load:
521 case AtomicExpr::AO__hip_atomic_load:
522 case AtomicExpr::AO__scoped_atomic_load_n:
523 case AtomicExpr::AO__scoped_atomic_load:
525 case AtomicExpr::AO__opencl_atomic_store:
526 case AtomicExpr::AO__hip_atomic_store:
527 case AtomicExpr::AO__scoped_atomic_store:
528 case AtomicExpr::AO__scoped_atomic_store_n:
530 case AtomicExpr::AO__hip_atomic_exchange:
531 case AtomicExpr::AO__opencl_atomic_exchange:
532 case AtomicExpr::AO__scoped_atomic_exchange_n:
533 case AtomicExpr::AO__scoped_atomic_exchange:
535 case AtomicExpr::AO__scoped_atomic_add_fetch:
537 case AtomicExpr::AO__hip_atomic_fetch_add:
538 case AtomicExpr::AO__opencl_atomic_fetch_add:
539 case AtomicExpr::AO__scoped_atomic_fetch_add:
541 case AtomicExpr::AO__scoped_atomic_sub_fetch:
543 case AtomicExpr::AO__hip_atomic_fetch_sub:
544 case AtomicExpr::AO__opencl_atomic_fetch_sub:
545 case AtomicExpr::AO__scoped_atomic_fetch_sub:
547 case AtomicExpr::AO__scoped_atomic_min_fetch:
549 case AtomicExpr::AO__hip_atomic_fetch_min:
550 case AtomicExpr::AO__opencl_atomic_fetch_min:
551 case AtomicExpr::AO__scoped_atomic_fetch_min:
553 case AtomicExpr::AO__scoped_atomic_max_fetch:
555 case AtomicExpr::AO__hip_atomic_fetch_max:
556 case AtomicExpr::AO__opencl_atomic_fetch_max:
557 case AtomicExpr::AO__scoped_atomic_fetch_max:
559 case AtomicExpr::AO__scoped_atomic_and_fetch:
561 case AtomicExpr::AO__hip_atomic_fetch_and:
562 case AtomicExpr::AO__opencl_atomic_fetch_and:
563 case AtomicExpr::AO__scoped_atomic_fetch_and:
565 case AtomicExpr::AO__scoped_atomic_or_fetch:
567 case AtomicExpr::AO__hip_atomic_fetch_or:
568 case AtomicExpr::AO__opencl_atomic_fetch_or:
569 case AtomicExpr::AO__scoped_atomic_fetch_or:
571 case AtomicExpr::AO__scoped_atomic_xor_fetch:
573 case AtomicExpr::AO__hip_atomic_fetch_xor:
574 case AtomicExpr::AO__opencl_atomic_fetch_xor:
575 case AtomicExpr::AO__scoped_atomic_fetch_xor:
577 case AtomicExpr::AO__scoped_atomic_nand_fetch:
579 case AtomicExpr::AO__scoped_atomic_fetch_nand:
584 assert(!opName.empty() &&
"expected operation name to build");
585 mlir::Value loadVal1 = builder.
createLoad(loc, val1);
589 mlir::Operation *rmwOp = builder.create(loc, builder.getStringAttr(opName),
590 atomicOperands, atomicResTys);
593 rmwOp->setAttr(
"binop", fetchAttr);
594 rmwOp->setAttr(
"mem_order", orderAttr);
595 if (
expr->isVolatile())
596 rmwOp->setAttr(
"is_volatile", builder.getUnitAttr());
597 if (fetchFirst && opName == cir::AtomicFetchOp::getOperationName())
598 rmwOp->setAttr(
"fetch_first", builder.getUnitAttr());
600 mlir::Value result = rmwOp->getResult(0);
607 auto memOrder =
static_cast<cir::MemOrder
>(order);
609 return memOrder != cir::MemOrder::Consume &&
610 memOrder != cir::MemOrder::Acquire &&
611 memOrder != cir::MemOrder::AcquireRelease;
613 return memOrder != cir::MemOrder::Release &&
614 memOrder != cir::MemOrder::AcquireRelease;
622 memTy = ty->getValueType();
624 Expr *isWeakExpr =
nullptr;
625 Expr *orderFailExpr =
nullptr;
633 if (e->
getOp() == AtomicExpr::AO__c11_atomic_init) {
647 bool shouldCastToIntPtrTy =
true;
649 switch (e->
getOp()) {
654 case AtomicExpr::AO__c11_atomic_init:
655 llvm_unreachable(
"already handled above with emitAtomicInit");
657 case AtomicExpr::AO__atomic_load_n:
658 case AtomicExpr::AO__c11_atomic_load:
659 case AtomicExpr::AO__atomic_test_and_set:
660 case AtomicExpr::AO__atomic_clear:
663 case AtomicExpr::AO__atomic_load:
667 case AtomicExpr::AO__atomic_store:
671 case AtomicExpr::AO__atomic_exchange:
676 case AtomicExpr::AO__atomic_compare_exchange:
677 case AtomicExpr::AO__atomic_compare_exchange_n:
678 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
679 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
681 if (e->
getOp() == AtomicExpr::AO__atomic_compare_exchange ||
682 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)
687 if (e->
getOp() == AtomicExpr::AO__atomic_compare_exchange_n ||
688 e->
getOp() == AtomicExpr::AO__atomic_compare_exchange ||
689 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange_n ||
690 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)
694 case AtomicExpr::AO__c11_atomic_fetch_add:
695 case AtomicExpr::AO__c11_atomic_fetch_sub:
698 "atomic fetch-and-add and fetch-and-sub for pointers");
702 case AtomicExpr::AO__atomic_fetch_add:
703 case AtomicExpr::AO__atomic_fetch_max:
704 case AtomicExpr::AO__atomic_fetch_min:
705 case AtomicExpr::AO__atomic_fetch_sub:
706 case AtomicExpr::AO__atomic_add_fetch:
707 case AtomicExpr::AO__atomic_max_fetch:
708 case AtomicExpr::AO__atomic_min_fetch:
709 case AtomicExpr::AO__atomic_sub_fetch:
710 case AtomicExpr::AO__c11_atomic_fetch_max:
711 case AtomicExpr::AO__c11_atomic_fetch_min:
715 case AtomicExpr::AO__atomic_fetch_and:
716 case AtomicExpr::AO__atomic_fetch_nand:
717 case AtomicExpr::AO__atomic_fetch_or:
718 case AtomicExpr::AO__atomic_fetch_xor:
719 case AtomicExpr::AO__atomic_and_fetch:
720 case AtomicExpr::AO__atomic_nand_fetch:
721 case AtomicExpr::AO__atomic_or_fetch:
722 case AtomicExpr::AO__atomic_xor_fetch:
723 case AtomicExpr::AO__atomic_exchange_n:
724 case AtomicExpr::AO__atomic_store_n:
725 case AtomicExpr::AO__c11_atomic_fetch_and:
726 case AtomicExpr::AO__c11_atomic_fetch_nand:
727 case AtomicExpr::AO__c11_atomic_fetch_or:
728 case AtomicExpr::AO__c11_atomic_fetch_xor:
729 case AtomicExpr::AO__c11_atomic_exchange:
730 case AtomicExpr::AO__c11_atomic_store:
743 if (shouldCastToIntPtrTy) {
744 ptr = atomics.castToAtomicIntPointer(ptr);
746 val1 = atomics.convertToAtomicIntPointer(val1);
749 if (shouldCastToIntPtrTy)
750 dest = atomics.castToAtomicIntPointer(dest);
753 }
else if (e->
getOp() == AtomicExpr::AO__atomic_test_and_set) {
755 "test_and_set.bool");
757 dest = atomics.createTempAlloca();
758 if (shouldCastToIntPtrTy)
759 dest = atomics.castToAtomicIntPointer(dest);
762 bool powerOf2Size = (size & (size - 1)) == 0;
763 bool useLibCall = !powerOf2Size || (size > 16);
780 bool isStore = e->
getOp() == AtomicExpr::AO__c11_atomic_store ||
781 e->
getOp() == AtomicExpr::AO__opencl_atomic_store ||
782 e->
getOp() == AtomicExpr::AO__hip_atomic_store ||
783 e->
getOp() == AtomicExpr::AO__atomic_store ||
784 e->
getOp() == AtomicExpr::AO__atomic_store_n ||
785 e->
getOp() == AtomicExpr::AO__scoped_atomic_store ||
786 e->
getOp() == AtomicExpr::AO__scoped_atomic_store_n ||
787 e->
getOp() == AtomicExpr::AO__atomic_clear;
788 bool isLoad = e->
getOp() == AtomicExpr::AO__c11_atomic_load ||
789 e->
getOp() == AtomicExpr::AO__opencl_atomic_load ||
790 e->
getOp() == AtomicExpr::AO__hip_atomic_load ||
791 e->
getOp() == AtomicExpr::AO__atomic_load ||
792 e->
getOp() == AtomicExpr::AO__atomic_load_n ||
793 e->
getOp() == AtomicExpr::AO__scoped_atomic_load ||
794 e->
getOp() == AtomicExpr::AO__scoped_atomic_load_n;
800 uint64_t ord = orderConst.
Val.
getInt().getZExtValue();
802 emitAtomicOp(*
this, e, dest, ptr, val1, val2, isWeakExpr, orderFailExpr,
803 size,
static_cast<cir::MemOrder
>(ord));
821 switch (atomics.getEvaluationKind()) {
839 zeroed = atomics.emitMemSetZeroIfNecessary();
840 dest = atomics.projectValue();
855 llvm_unreachable(
"bad evaluation kind");
static void emitAtomicCmpXchg(CIRGenFunction &cgf, AtomicExpr *e, bool isWeak, Address dest, Address ptr, Address val1, Address val2, uint64_t size, cir::MemOrder successOrder, cir::MemOrder failureOrder)
static Address emitValToTemp(CIRGenFunction &cgf, Expr *e)
static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest, Address ptr, Address val1, Address val2, Expr *isWeakExpr, Expr *failureOrderExpr, int64_t size, cir::MemOrder order)
static bool isMemOrderValid(uint64_t order, bool isStore, bool isLoad)
static void emitAtomicCmpXchgFailureSet(CIRGenFunction &cgf, AtomicExpr *e, bool isWeak, Address dest, Address ptr, Address val1, Address val2, Expr *failureOrderExpr, uint64_t size, cir::MemOrder successOrder)
static bool isFullSizeType(CIRGenModule &cgm, mlir::Type ty, uint64_t expectedSize)
Does a store of the given IR type modify the full expected width?
mlir::Value createNot(mlir::Value value)
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
cir::BoolType getBoolTy()
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const
llvm::TypeSize getTypeStoreSize(mlir::Type ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
TypeInfo getTypeInfo(const Type *T) const
Get the size and alignment of the specified complete type in bits.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Expr * getOrderFail() const
Address withPointer(mlir::Value newPtr) const
Return address with different pointer, but same element type and alignment.
mlir::Value getPointer() const
mlir::Type getElementType() const
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
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
cir::IntType getUIntNTy(int n)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::MemOrderAttr order={})
RValue convertTempToRValue(Address addr, clang::QualType type, clang::SourceLocation loc)
Given the address of a temporary variable, produce an r-value of its type.
Address 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...
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, bool isInit=false, bool isNontemporal=false)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
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 emitAtomicExpr(AtomicExpr *e)
mlir::Type convertTypeForMem(QualType t)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
CIRGenBuilderTy & getBuilder()
mlir::MLIRContext & getMLIRContext()
void emitAtomicInit(Expr *init, LValue dest)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
clang::ASTContext & getContext() const
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)
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
const cir::CIRDataLayout getDataLayout() const
This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(mlir::Value v)
mlir::Value getValue() const
Return the value of this scalar value.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
A (possibly-)qualified type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isPointerType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isAtomicType() const
bool isFloatingType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isValidCIRAtomicOrderingCABI(Int value)
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
The JSON file list parser is used to communicate input to InstallAPI.
static bool atomicInfoGetAtomicPointer()
static bool aggValueSlotGC()
static bool atomicScope()
static bool atomicUseLibCall()
static bool atomicSyncScopeID()
static bool atomicInfoGetAtomicAddress()
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.