27 CharUnits atomicAlign;
30 bool useLibCall =
true;
35 AtomicInfo(CIRGenFunction &cgf, LValue &lvalue, mlir::Location loc)
36 : cgf(cgf), loc(loc) {
37 assert(!lvalue.isGlobalReg());
38 ASTContext &ctx = cgf.getContext();
39 if (lvalue.isSimple()) {
40 atomicTy = lvalue.getType();
41 if (
auto *ty = atomicTy->getAs<AtomicType>())
42 valueTy = ty->getValueType();
45 evaluationKind = cgf.getEvaluationKind(valueTy);
48 TypeInfo atomicTypeInfo = ctx.
getTypeInfo(atomicTy);
51 valueSizeInBits = valueTypeInfo.
Width;
52 atomicSizeInBits = atomicTypeInfo.
Width;
53 assert(valueSizeInBits <= atomicSizeInBits);
54 assert(valueAlignInBits <= atomicAlignInBits);
58 if (lvalue.getAlignment().isZero())
59 lvalue.setAlignment(atomicAlign);
61 this->lvalue = lvalue;
64 cgf.cgm.errorNYI(loc,
"AtomicInfo: non-simple lvalue");
67 atomicSizeInBits, ctx.
toBits(lvalue.getAlignment()));
70 QualType getValueType()
const {
return valueTy; }
71 QualType getAtomicType()
const {
return atomicTy; }
72 CharUnits getAtomicAlignment()
const {
return atomicAlign; }
74 mlir::Value getAtomicPointer()
const {
75 if (lvalue.isSimple())
76 return lvalue.getPointer();
80 bool shouldUseLibCall()
const {
return useLibCall; }
81 const LValue &getAtomicLValue()
const {
return lvalue; }
82 Address getAtomicAddress()
const {
84 if (lvalue.isSimple()) {
85 elemTy = lvalue.getAddress().getElementType();
88 cgf.cgm.errorNYI(loc,
"AtomicInfo::getAtomicAddress: non-simple lvalue");
90 return Address(getAtomicPointer(), elemTy, getAtomicAlignment());
99 bool hasPadding()
const {
return (valueSizeInBits != atomicSizeInBits); }
101 bool emitMemSetZeroIfNecessary()
const;
103 mlir::Value getScalarRValValueOrNull(RValue rvalue)
const;
107 Address castToAtomicIntPointer(Address addr)
const;
112 Address convertToAtomicIntPointer(Address addr)
const;
115 RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot,
116 SourceLocation loc,
bool asValue)
const;
119 mlir::Value convertRValueToInt(RValue rvalue, mlir::Location loc,
120 bool cmpxchg =
false)
const;
122 RValue convertToValueOrAtomic(mlir::Value intVal, AggValueSlot resultSlot,
123 SourceLocation loc,
bool asValue,
124 bool cmpxchg =
false)
const;
127 void emitCopyIntoMemory(RValue rvalue)
const;
130 LValue projectValue()
const {
131 assert(lvalue.isSimple());
132 Address addr = getAtomicAddress();
134 addr = cgf.getBuilder().createGetMember(loc, addr,
"value",
138 return LValue::makeAddr(addr, getValueType(), lvalue.getBaseInfo());
143 RValue emitAtomicLoad(AggValueSlot resultSlot, SourceLocation loc,
144 bool asValue, cir::MemOrder order,
bool isVolatile);
147 Address materializeRValue(RValue rvalue, mlir::Location loc)
const;
150 Address createTempAlloca()
const;
153 bool requiresMemSetZero(mlir::Type ty)
const;
156 mlir::Value emitAtomicLoadOp(cir::MemOrder order,
bool isVolatile,
157 bool cmpxchg =
false);
173 uint64_t expectedSize) {
180bool AtomicInfo::requiresMemSetZero(mlir::Type ty)
const {
186 switch (getEvaluationKind()) {
193 mlir::cast<cir::ComplexType>(ty).getElementType(),
194 atomicSizeInBits / 2);
199 llvm_unreachable(
"bad evaluation kind");
202Address AtomicInfo::convertToAtomicIntPointer(Address addr)
const {
205 if (sourceSizeInBits != atomicSizeInBits) {
208 "AtomicInfo::convertToAtomicIntPointer: convert through temp alloca");
211 return castToAtomicIntPointer(addr);
214RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
215 AggValueSlot resultSlot,
217 bool asValue)
const {
218 if (lvalue.isSimple()) {
225 "AtomicInfo::convertAtomicTempToRValue: hasPadding");
235 loc,
"AtomicInfo::convertAtomicTempToRValue: lvalue is not simple");
239RValue AtomicInfo::emitAtomicLoad(AggValueSlot resultSlot, SourceLocation loc,
240 bool asValue, cir::MemOrder order,
243 if (shouldUseLibCall()) {
245 cgf.
cgm.
errorNYI(loc,
"emitAtomicLoad: emit atomic lib call");
250 mlir::Value loadOp = emitAtomicLoadOp(order, isVolatile);
258 return convertToValueOrAtomic(loadOp, resultSlot, loc, asValue);
261Address AtomicInfo::createTempAlloca()
const {
264 QualType tmpTy = (lvalue.isBitField() && valueSizeInBits > atomicSizeInBits)
268 cgf.
createMemTemp(tmpTy, getAtomicAlignment(), loc,
"atomic-temp");
271 if (lvalue.isBitField()) {
272 cgf.
cgm.
errorNYI(loc,
"AtomicInfo::createTempAlloca: bitfield lvalue");
278mlir::Value AtomicInfo::getScalarRValValueOrNull(RValue rvalue)
const {
279 if (rvalue.
isScalar() && (!hasPadding() || !lvalue.isSimple()))
284Address AtomicInfo::castToAtomicIntPointer(Address addr)
const {
287 if (intTy && intTy.getWidth() == atomicSizeInBits)
293bool AtomicInfo::emitMemSetZeroIfNecessary()
const {
294 assert(lvalue.isSimple());
295 Address addr = lvalue.getAddress();
315 if (cir::isAnyFloatingPointType(valueTy))
320mlir::Value AtomicInfo::emitAtomicLoadOp(cir::MemOrder order,
bool isVolatile,
322 Address addr = getAtomicAddress();
324 addr = castToAtomicIntPointer(addr);
328 op.setMemOrder(order);
334mlir::Value AtomicInfo::convertRValueToInt(RValue rvalue, mlir::Location loc,
335 bool cmpxchg)
const {
338 if (mlir::Value value = getScalarRValValueOrNull(rvalue)) {
343 loc,
"AtomicInfo::convertRValueToInt: cast scalar rvalue to int");
349 Address addr = materializeRValue(rvalue, loc);
352 addr = castToAtomicIntPointer(addr);
357RValue AtomicInfo::convertToValueOrAtomic(mlir::Value intVal,
358 AggValueSlot resultSlot,
359 SourceLocation loc,
bool asValue,
360 bool cmpxchg)
const {
362 assert((mlir::isa<cir::IntType, cir::PointerType, cir::FPTypeInterface>(
363 intVal.getType())) &&
364 "Expected integer, pointer or floating point value when converting "
367 !lvalue.isBitField() || lvalue.getBitFieldInfo().size == valueSizeInBits;
369 ((isWholeValue && !hasPadding()) || !asValue)) {
371 : getAtomicAddress().getElementType();
373 assert((!mlir::isa<cir::IntType>(valTy) || intVal.getType() == valTy) &&
374 "Different integer types.");
378 cgf.
cgm.
errorNYI(
"convertToValueOrAtomic: convert through bitcast");
385 bool tempIsVolatile =
false;
391 temp = createTempAlloca();
395 Address castTemp = castToAtomicIntPointer(temp);
398 return convertAtomicTempToRValue(temp, resultSlot, loc, asValue);
403void AtomicInfo::emitCopyIntoMemory(RValue rvalue)
const {
404 assert(lvalue.isSimple());
410 cgf.
cgm.
errorNYI(
"copying aggregate into atomic lvalue");
417 emitMemSetZeroIfNecessary();
420 LValue tempLValue = projectValue();
433Address AtomicInfo::materializeRValue(RValue rvalue, mlir::Location loc)
const {
440 LValue tempLV = cgf.
makeAddrLValue(createTempAlloca(), getAtomicType());
441 AtomicInfo atomics(cgf, tempLV, loc);
443 atomics.emitCopyIntoMemory(rvalue);
444 return tempLV.getAddress();
448 mlir::ArrayAttr valuesAttr = builder.getArrayAttr({});
449 mlir::OpBuilder::InsertPoint insertPoint;
450 cir::CaseOp::create(builder, loc, valuesAttr, cir::CaseOpKind::Default,
452 builder.restoreInsertionPoint(insertPoint);
458 mlir::Type orderType,
461 for (cir::MemOrder order : orders)
462 orderAttrs.push_back(cir::IntAttr::get(orderType,
static_cast<int>(order)));
463 mlir::ArrayAttr ordersAttr = builder.getArrayAttr(orderAttrs);
465 mlir::OpBuilder::InsertPoint insertPoint;
466 cir::CaseOp::create(builder, loc, ordersAttr, cir::CaseOpKind::Anyof,
468 builder.restoreInsertionPoint(insertPoint);
474 cir::MemOrder successOrder,
475 cir::MemOrder failureOrder,
476 cir::SyncScopeKind scope) {
480 mlir::Value expected = builder.
createLoad(loc, val1);
481 mlir::Value desired = builder.
createLoad(loc, val2);
483 auto cmpxchg = cir::AtomicCmpXchgOp::create(
492 cmpxchg.setWeak(isWeak);
494 mlir::Value failed = builder.
createNot(cmpxchg.getSuccess());
495 cir::IfOp::create(builder, loc, failed,
false,
496 [&](mlir::OpBuilder &, mlir::Location) {
497 auto ptrTy = mlir::cast<cir::PointerType>(
516 Expr *failureOrderExpr, uint64_t size,
517 cir::MemOrder successOrder,
518 cir::SyncScopeKind scope) {
521 uint64_t failureOrderInt = failureOrderEval.
Val.
getInt().getZExtValue();
523 cir::MemOrder failureOrder;
525 failureOrder = cir::MemOrder::Relaxed;
527 switch ((cir::MemOrder)failureOrderInt) {
528 case cir::MemOrder::Relaxed:
531 case cir::MemOrder::Release:
532 case cir::MemOrder::AcquireRelease:
533 failureOrder = cir::MemOrder::Relaxed;
535 case cir::MemOrder::Consume:
536 case cir::MemOrder::Acquire:
537 failureOrder = cir::MemOrder::Acquire;
539 case cir::MemOrder::SequentiallyConsistent:
540 failureOrder = cir::MemOrder::SequentiallyConsistent;
550 failureOrder, scope);
558 mlir::Value failureOrderVal = cgf.
emitScalarExpr(failureOrderExpr);
560 cir::SwitchOp::create(
562 [&](mlir::OpBuilder &b, mlir::Location loc, mlir::OperationState &os) {
563 mlir::Block *switchBlock = cgf.getBuilder().getBlock();
575 emitDefaultCaseLabel(cgf.getBuilder(), atomicLoc);
576 emitAtomicCmpXchg(cgf, e, isWeak, dest, ptr, val1, val2, size,
577 successOrder, cir::MemOrder::Relaxed, scope);
578 cgf.getBuilder().createBreak(atomicLoc);
579 cgf.getBuilder().setInsertionPointToEnd(switchBlock);
583 emitMemOrderCaseLabel(cgf.getBuilder(), loc, failureOrderVal.getType(),
584 {cir::MemOrder::Consume, cir::MemOrder::Acquire});
586 successOrder, cir::MemOrder::Acquire, scope);
588 cgf.
getBuilder().setInsertionPointToEnd(switchBlock);
592 {cir::MemOrder::SequentiallyConsistent});
594 successOrder, cir::MemOrder::SequentiallyConsistent,
597 cgf.
getBuilder().setInsertionPointToEnd(switchBlock);
609 uint64_t size, cir::MemOrder successOrder, cir::SyncScopeKind scope) {
621 [&](mlir::OpBuilder &b, mlir::Location loc) {
622 emitAtomicCmpXchgFailureSet(cgf, e, true, dest, ptr, val1,
623 val2, failureOrderExpr, size, successOrder,
625 cgf.getBuilder().createYield(atomicLoc);
627 [&](mlir::OpBuilder &b, mlir::Location loc) {
628 emitAtomicCmpXchgFailureSet(cgf, e, false, dest, ptr, val1,
629 val2, failureOrderExpr, size, successOrder,
631 cgf.getBuilder().createYield(atomicLoc);
637 Expr *isWeakExpr,
Expr *failureOrderExpr, int64_t size,
638 cir::MemOrder order, cir::SyncScopeKind scope) {
640 llvm::StringRef opName;
643 mlir::Location loc = cgf.
getLoc(
expr->getSourceRange());
644 auto orderAttr = cir::MemOrderAttr::get(builder.getContext(), order);
645 auto scopeAttr = cir::SyncScopeKindAttr::get(builder.getContext(), scope);
646 cir::AtomicFetchKindAttr fetchAttr;
647 bool fetchFirst =
true;
649 auto handleFetchOp = [&](cir::AtomicFetchKind
kind) {
650 opName = cir::AtomicFetchOp::getOperationName();
651 fetchAttr = cir::AtomicFetchKindAttr::get(builder.getContext(),
kind);
654 switch (
expr->getOp()) {
655 case AtomicExpr::AO__c11_atomic_init:
656 llvm_unreachable(
"already handled!");
658 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
660 val2, failureOrderExpr, size, order, scope);
663 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
665 val2, failureOrderExpr, size, order, scope);
668 case AtomicExpr::AO__atomic_compare_exchange:
669 case AtomicExpr::AO__atomic_compare_exchange_n:
670 case AtomicExpr::AO__scoped_atomic_compare_exchange:
671 case AtomicExpr::AO__scoped_atomic_compare_exchange_n: {
675 failureOrderExpr, size, order, scope);
678 val1, val2, failureOrderExpr, size,
684 case AtomicExpr::AO__c11_atomic_load:
685 case AtomicExpr::AO__atomic_load_n:
686 case AtomicExpr::AO__atomic_load:
687 case AtomicExpr::AO__scoped_atomic_load_n:
688 case AtomicExpr::AO__scoped_atomic_load: {
692 load->setAttr(
"mem_order", orderAttr);
693 load->setAttr(
"sync_scope", scopeAttr);
695 builder.
createStore(loc, load->getResult(0), dest);
699 case AtomicExpr::AO__c11_atomic_store:
700 case AtomicExpr::AO__atomic_store_n:
701 case AtomicExpr::AO__atomic_store:
702 case AtomicExpr::AO__scoped_atomic_store:
703 case AtomicExpr::AO__scoped_atomic_store_n: {
704 cir::LoadOp loadVal1 = builder.
createLoad(loc, val1);
710 mlir::IntegerAttr{}, scopeAttr, orderAttr);
714 case AtomicExpr::AO__c11_atomic_exchange:
715 case AtomicExpr::AO__atomic_exchange_n:
716 case AtomicExpr::AO__atomic_exchange:
717 case AtomicExpr::AO__scoped_atomic_exchange_n:
718 case AtomicExpr::AO__scoped_atomic_exchange:
719 opName = cir::AtomicXchgOp::getOperationName();
722 case AtomicExpr::AO__atomic_add_fetch:
723 case AtomicExpr::AO__scoped_atomic_add_fetch:
726 case AtomicExpr::AO__c11_atomic_fetch_add:
727 case AtomicExpr::AO__atomic_fetch_add:
728 case AtomicExpr::AO__scoped_atomic_fetch_add:
729 handleFetchOp(cir::AtomicFetchKind::Add);
732 case AtomicExpr::AO__atomic_sub_fetch:
733 case AtomicExpr::AO__scoped_atomic_sub_fetch:
736 case AtomicExpr::AO__c11_atomic_fetch_sub:
737 case AtomicExpr::AO__atomic_fetch_sub:
738 case AtomicExpr::AO__scoped_atomic_fetch_sub:
739 handleFetchOp(cir::AtomicFetchKind::Sub);
742 case AtomicExpr::AO__atomic_min_fetch:
743 case AtomicExpr::AO__scoped_atomic_min_fetch:
746 case AtomicExpr::AO__c11_atomic_fetch_min:
747 case AtomicExpr::AO__atomic_fetch_min:
748 case AtomicExpr::AO__scoped_atomic_fetch_min:
749 handleFetchOp(cir::AtomicFetchKind::Min);
752 case AtomicExpr::AO__atomic_max_fetch:
753 case AtomicExpr::AO__scoped_atomic_max_fetch:
756 case AtomicExpr::AO__c11_atomic_fetch_max:
757 case AtomicExpr::AO__atomic_fetch_max:
758 case AtomicExpr::AO__scoped_atomic_fetch_max:
759 handleFetchOp(cir::AtomicFetchKind::Max);
762 case AtomicExpr::AO__atomic_and_fetch:
763 case AtomicExpr::AO__scoped_atomic_and_fetch:
766 case AtomicExpr::AO__c11_atomic_fetch_and:
767 case AtomicExpr::AO__atomic_fetch_and:
768 case AtomicExpr::AO__scoped_atomic_fetch_and:
769 handleFetchOp(cir::AtomicFetchKind::And);
772 case AtomicExpr::AO__atomic_or_fetch:
773 case AtomicExpr::AO__scoped_atomic_or_fetch:
776 case AtomicExpr::AO__c11_atomic_fetch_or:
777 case AtomicExpr::AO__atomic_fetch_or:
778 case AtomicExpr::AO__scoped_atomic_fetch_or:
779 handleFetchOp(cir::AtomicFetchKind::Or);
782 case AtomicExpr::AO__atomic_xor_fetch:
783 case AtomicExpr::AO__scoped_atomic_xor_fetch:
786 case AtomicExpr::AO__c11_atomic_fetch_xor:
787 case AtomicExpr::AO__atomic_fetch_xor:
788 case AtomicExpr::AO__scoped_atomic_fetch_xor:
789 handleFetchOp(cir::AtomicFetchKind::Xor);
792 case AtomicExpr::AO__atomic_nand_fetch:
793 case AtomicExpr::AO__scoped_atomic_nand_fetch:
796 case AtomicExpr::AO__c11_atomic_fetch_nand:
797 case AtomicExpr::AO__atomic_fetch_nand:
798 case AtomicExpr::AO__scoped_atomic_fetch_nand:
799 handleFetchOp(cir::AtomicFetchKind::Nand);
802 case AtomicExpr::AO__atomic_test_and_set: {
803 auto op = cir::AtomicTestAndSetOp::create(
811 case AtomicExpr::AO__atomic_clear: {
812 cir::AtomicClearOp::create(
819 case AtomicExpr::AO__atomic_fetch_uinc:
820 case AtomicExpr::AO__scoped_atomic_fetch_uinc:
821 handleFetchOp(cir::AtomicFetchKind::UIncWrap);
824 case AtomicExpr::AO__atomic_fetch_udec:
825 case AtomicExpr::AO__scoped_atomic_fetch_udec:
826 handleFetchOp(cir::AtomicFetchKind::UDecWrap);
829 case AtomicExpr::AO__opencl_atomic_init:
831 case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
832 case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
834 case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
835 case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
837 case AtomicExpr::AO__opencl_atomic_load:
838 case AtomicExpr::AO__hip_atomic_load:
840 case AtomicExpr::AO__opencl_atomic_store:
841 case AtomicExpr::AO__hip_atomic_store:
843 case AtomicExpr::AO__hip_atomic_exchange:
844 case AtomicExpr::AO__opencl_atomic_exchange:
846 case AtomicExpr::AO__hip_atomic_fetch_add:
847 case AtomicExpr::AO__opencl_atomic_fetch_add:
849 case AtomicExpr::AO__hip_atomic_fetch_sub:
850 case AtomicExpr::AO__opencl_atomic_fetch_sub:
852 case AtomicExpr::AO__hip_atomic_fetch_min:
853 case AtomicExpr::AO__opencl_atomic_fetch_min:
855 case AtomicExpr::AO__hip_atomic_fetch_max:
856 case AtomicExpr::AO__opencl_atomic_fetch_max:
858 case AtomicExpr::AO__hip_atomic_fetch_and:
859 case AtomicExpr::AO__opencl_atomic_fetch_and:
861 case AtomicExpr::AO__hip_atomic_fetch_or:
862 case AtomicExpr::AO__opencl_atomic_fetch_or:
864 case AtomicExpr::AO__hip_atomic_fetch_xor:
865 case AtomicExpr::AO__opencl_atomic_fetch_xor:
867 case AtomicExpr::AO__atomic_fetch_fmaximum:
868 case AtomicExpr::AO__atomic_fetch_fmaximum_num:
869 case AtomicExpr::AO__atomic_fetch_fminimum:
870 case AtomicExpr::AO__atomic_fetch_fminimum_num:
871 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
872 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
873 case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
874 case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
880 assert(!opName.empty() &&
"expected operation name to build");
881 mlir::Value loadVal1 = builder.
createLoad(loc, val1);
885 mlir::Operation *rmwOp = builder.create(loc, builder.getStringAttr(opName),
886 atomicOperands, atomicResTys);
889 rmwOp->setAttr(
"binop", fetchAttr);
890 rmwOp->setAttr(
"mem_order", orderAttr);
891 rmwOp->setAttr(
"sync_scope", scopeAttr);
892 if (
expr->isVolatile())
893 rmwOp->setAttr(
"is_volatile", builder.getUnitAttr());
894 if (fetchFirst && opName == cir::AtomicFetchOp::getOperationName())
895 rmwOp->setAttr(
"fetch_first", builder.getUnitAttr());
897 mlir::Value result = rmwOp->getResult(0);
908 return cir::SyncScopeKind::SingleThread;
910 return cir::SyncScopeKind::System;
912 return cir::SyncScopeKind::Device;
914 return cir::SyncScopeKind::Workgroup;
916 return cir::SyncScopeKind::Wavefront;
918 return cir::SyncScopeKind::Cluster;
921 return cir::SyncScopeKind::HIPSingleThread;
923 return cir::SyncScopeKind::HIPSystem;
925 return cir::SyncScopeKind::HIPAgent;
927 return cir::SyncScopeKind::HIPWorkgroup;
929 return cir::SyncScopeKind::HIPWavefront;
931 return cir::SyncScopeKind::HIPCluster;
934 return cir::SyncScopeKind::OpenCLWorkGroup;
936 return cir::SyncScopeKind::OpenCLDevice;
938 return cir::SyncScopeKind::OpenCLAllSVMDevices;
940 return cir::SyncScopeKind::OpenCLSubGroup;
943 llvm_unreachable(
"unhandled sync scope");
948 Expr *isWeakExpr,
Expr *failureOrderExpr, int64_t size,
950 const std::optional<Expr::EvalResult> &scopeConst,
951 mlir::Value scopeValue) {
952 std::unique_ptr<AtomicScopeModel> scopeModel =
expr->getScopeModel();
955 emitAtomicOp(cgf,
expr, dest, ptr, val1, val2, isWeakExpr, failureOrderExpr,
956 size, order, cir::SyncScopeKind::System);
960 if (scopeConst.has_value()) {
962 cgf,
expr->getScope()->getSourceRange(),
963 scopeModel->map(scopeConst->Val.getInt().getZExtValue()));
964 emitAtomicOp(cgf,
expr, dest, ptr, val1, val2, isWeakExpr, failureOrderExpr,
965 size, order, mappedScope);
972 mlir::Location loc = cgf.
getLoc(
expr->getSourceRange());
974 unsigned fallback = scopeModel->getFallBackValue();
976 cir::SwitchOp::create(
977 builder, loc, scopeValue,
978 [&](mlir::OpBuilder &, mlir::Location loc, mlir::OperationState &) {
979 mlir::Block *switchBlock = builder.getBlock();
983 cgf,
expr->getScope()->getSourceRange(), scopeModel->map(fallback));
986 failureOrderExpr, size, order, fallbackScope);
988 builder.setInsertionPointToEnd(switchBlock);
991 for (
unsigned scope : allScopes) {
992 if (scope == fallback)
996 cgf,
expr->getScope()->getSourceRange(), scopeModel->map(scope));
998 mlir::ArrayAttr casesAttr = builder.getArrayAttr(
999 {cir::IntAttr::get(scopeValue.getType(), scope)});
1000 mlir::OpBuilder::InsertPoint insertPoint;
1001 cir::CaseOp::create(builder, loc, casesAttr, cir::CaseOpKind::Equal,
1004 builder.restoreInsertionPoint(insertPoint);
1006 failureOrderExpr, size, order, cirScope);
1008 builder.setInsertionPointToEnd(switchBlock);
1015static std::optional<cir::MemOrder>
1025 if (oriOrder == cir::MemOrder::Consume ||
1026 oriOrder == cir::MemOrder::Acquire ||
1027 oriOrder == cir::MemOrder::AcquireRelease)
1028 return std::nullopt;
1029 }
else if (isLoad) {
1030 if (oriOrder == cir::MemOrder::Release ||
1031 oriOrder == cir::MemOrder::AcquireRelease)
1032 return std::nullopt;
1033 }
else if (isFence) {
1034 if (oriOrder == cir::MemOrder::Relaxed)
1035 return std::nullopt;
1039 if (oriOrder == cir::MemOrder::Consume)
1040 return cir::MemOrder::Acquire;
1045 CIRGenFunction &cgf, mlir::Value order,
bool isStore,
bool isLoad,
1046 bool isFence, llvm::function_ref<
void(cir::MemOrder)> emitAtomicOpFn) {
1054 cir::SwitchOp::create(
1055 builder, order.getLoc(), order,
1056 [&](mlir::OpBuilder &, mlir::Location loc, mlir::OperationState &) {
1057 mlir::Block *switchBlock = builder.getBlock();
1059 auto emitMemOrderCase = [&](llvm::ArrayRef<cir::MemOrder> caseOrders) {
1061 for (int i = 1, e = caseOrders.size(); i < e; i++)
1062 assert((getEffectiveAtomicMemOrder(caseOrders[i - 1], isStore,
1064 getEffectiveAtomicMemOrder(caseOrders[i], isStore, isLoad,
1066 "Effective memory order must be same!");
1068 if (caseOrders.empty()) {
1069 emitDefaultCaseLabel(builder, loc);
1073 emitAtomicOpFn(cir::MemOrder::Relaxed);
1074 } else if (std::optional<cir::MemOrder> actualOrder =
1075 getEffectiveAtomicMemOrder(caseOrders[0], isStore,
1078 if (!isFence && actualOrder == cir::MemOrder::Relaxed)
1083 emitMemOrderCaseLabel(builder, loc, order.getType(), caseOrders);
1084 emitAtomicOpFn(actualOrder.value());
1089 builder.createBreak(loc);
1090 builder.setInsertionPointToEnd(switchBlock);
1093 emitMemOrderCase( {});
1094 emitMemOrderCase({cir::MemOrder::Relaxed});
1095 emitMemOrderCase({cir::MemOrder::Consume, cir::MemOrder::Acquire});
1096 emitMemOrderCase({cir::MemOrder::Release});
1097 emitMemOrderCase({cir::MemOrder::AcquireRelease});
1098 emitMemOrderCase({cir::MemOrder::SequentiallyConsistent});
1105 const Expr *memOrder,
bool isStore,
bool isLoad,
bool isFence,
1106 llvm::function_ref<
void(cir::MemOrder)> emitAtomicOpFn) {
1110 uint64_t constOrder = eval.
Val.
getInt().getZExtValue();
1115 cir::MemOrder oriOrder =
static_cast<cir::MemOrder
>(constOrder);
1116 if (std::optional<cir::MemOrder> actualOrder =
1118 emitAtomicOpFn(actualOrder.value());
1135 mlir::NamedAttrList fnAttrs;
1145 Address val1, uint64_t atomicTySize,
1158 auto castToGenericAddrSpace = [&](mlir::Value v,
QualType pt) {
1163 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: openCL");
1171 llvm::StringRef calleeName;
1173 bool hasRetTy =
false;
1174 switch (e->
getOp()) {
1175 case AtomicExpr::AO__c11_atomic_init:
1176 case AtomicExpr::AO__opencl_atomic_init:
1177 llvm_unreachable(
"Already handled!");
1184 case AtomicExpr::AO__atomic_compare_exchange:
1185 case AtomicExpr::AO__atomic_compare_exchange_n:
1186 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
1187 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
1188 case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
1189 case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
1190 case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
1191 case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
1192 case AtomicExpr::AO__scoped_atomic_compare_exchange:
1193 case AtomicExpr::AO__scoped_atomic_compare_exchange_n:
1195 loc,
"emitLibCallForAtomicExpr: atomic compare-and-exchange NYI");
1200 case AtomicExpr::AO__atomic_exchange:
1201 case AtomicExpr::AO__atomic_exchange_n:
1202 case AtomicExpr::AO__c11_atomic_exchange:
1203 case AtomicExpr::AO__hip_atomic_exchange:
1204 case AtomicExpr::AO__opencl_atomic_exchange:
1205 case AtomicExpr::AO__scoped_atomic_exchange:
1206 case AtomicExpr::AO__scoped_atomic_exchange_n:
1207 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: atomic exchange NYI");
1211 case AtomicExpr::AO__atomic_store:
1212 case AtomicExpr::AO__atomic_store_n:
1213 case AtomicExpr::AO__c11_atomic_store:
1214 case AtomicExpr::AO__scoped_atomic_store:
1215 case AtomicExpr::AO__scoped_atomic_store_n: {
1216 calleeName =
"__atomic_store";
1225 case AtomicExpr::AO__hip_atomic_store:
1226 case AtomicExpr::AO__opencl_atomic_store:
1228 "emitLibCallForAtomicExpr: atomic store for hip/opencl");
1232 case AtomicExpr::AO__atomic_load:
1233 case AtomicExpr::AO__atomic_load_n:
1234 case AtomicExpr::AO__c11_atomic_load:
1235 case AtomicExpr::AO__scoped_atomic_load:
1236 case AtomicExpr::AO__scoped_atomic_load_n: {
1237 calleeName =
"__atomic_load";
1241 case AtomicExpr::AO__hip_atomic_load:
1242 case AtomicExpr::AO__opencl_atomic_load:
1244 "emitLibCallForAtomicExpr: atomic load for hip/opencl");
1247 case AtomicExpr::AO__atomic_fetch_fmaximum:
1248 case AtomicExpr::AO__atomic_fetch_fmaximum_num:
1249 case AtomicExpr::AO__atomic_fetch_fminimum:
1250 case AtomicExpr::AO__atomic_fetch_fminimum_num:
1251 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
1252 case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
1253 case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
1254 case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
1256 loc,
"emitLibCallForAtomicExpr: atomic fetch fmaximum/fminimum");
1259 case AtomicExpr::AO__atomic_add_fetch:
1260 case AtomicExpr::AO__scoped_atomic_add_fetch:
1261 case AtomicExpr::AO__atomic_fetch_add:
1262 case AtomicExpr::AO__c11_atomic_fetch_add:
1263 case AtomicExpr::AO__hip_atomic_fetch_add:
1264 case AtomicExpr::AO__opencl_atomic_fetch_add:
1265 case AtomicExpr::AO__scoped_atomic_fetch_add:
1266 case AtomicExpr::AO__atomic_and_fetch:
1267 case AtomicExpr::AO__scoped_atomic_and_fetch:
1268 case AtomicExpr::AO__atomic_fetch_and:
1269 case AtomicExpr::AO__c11_atomic_fetch_and:
1270 case AtomicExpr::AO__hip_atomic_fetch_and:
1271 case AtomicExpr::AO__opencl_atomic_fetch_and:
1272 case AtomicExpr::AO__scoped_atomic_fetch_and:
1273 case AtomicExpr::AO__atomic_or_fetch:
1274 case AtomicExpr::AO__scoped_atomic_or_fetch:
1275 case AtomicExpr::AO__atomic_fetch_or:
1276 case AtomicExpr::AO__c11_atomic_fetch_or:
1277 case AtomicExpr::AO__hip_atomic_fetch_or:
1278 case AtomicExpr::AO__opencl_atomic_fetch_or:
1279 case AtomicExpr::AO__scoped_atomic_fetch_or:
1280 case AtomicExpr::AO__atomic_sub_fetch:
1281 case AtomicExpr::AO__scoped_atomic_sub_fetch:
1282 case AtomicExpr::AO__atomic_fetch_sub:
1283 case AtomicExpr::AO__c11_atomic_fetch_sub:
1284 case AtomicExpr::AO__hip_atomic_fetch_sub:
1285 case AtomicExpr::AO__opencl_atomic_fetch_sub:
1286 case AtomicExpr::AO__scoped_atomic_fetch_sub:
1287 case AtomicExpr::AO__atomic_xor_fetch:
1288 case AtomicExpr::AO__scoped_atomic_xor_fetch:
1289 case AtomicExpr::AO__atomic_fetch_xor:
1290 case AtomicExpr::AO__c11_atomic_fetch_xor:
1291 case AtomicExpr::AO__hip_atomic_fetch_xor:
1292 case AtomicExpr::AO__opencl_atomic_fetch_xor:
1293 case AtomicExpr::AO__scoped_atomic_fetch_xor:
1294 case AtomicExpr::AO__atomic_nand_fetch:
1295 case AtomicExpr::AO__atomic_fetch_nand:
1296 case AtomicExpr::AO__c11_atomic_fetch_nand:
1297 case AtomicExpr::AO__scoped_atomic_fetch_nand:
1298 case AtomicExpr::AO__scoped_atomic_nand_fetch:
1299 case AtomicExpr::AO__atomic_min_fetch:
1300 case AtomicExpr::AO__atomic_fetch_min:
1301 case AtomicExpr::AO__c11_atomic_fetch_min:
1302 case AtomicExpr::AO__hip_atomic_fetch_min:
1303 case AtomicExpr::AO__opencl_atomic_fetch_min:
1304 case AtomicExpr::AO__scoped_atomic_fetch_min:
1305 case AtomicExpr::AO__scoped_atomic_min_fetch:
1306 case AtomicExpr::AO__atomic_max_fetch:
1307 case AtomicExpr::AO__atomic_fetch_max:
1308 case AtomicExpr::AO__c11_atomic_fetch_max:
1309 case AtomicExpr::AO__hip_atomic_fetch_max:
1310 case AtomicExpr::AO__opencl_atomic_fetch_max:
1311 case AtomicExpr::AO__scoped_atomic_fetch_max:
1312 case AtomicExpr::AO__scoped_atomic_max_fetch:
1313 case AtomicExpr::AO__scoped_atomic_fetch_uinc:
1314 case AtomicExpr::AO__scoped_atomic_fetch_udec:
1315 case AtomicExpr::AO__atomic_test_and_set:
1316 case AtomicExpr::AO__atomic_clear:
1317 case AtomicExpr::AO__atomic_fetch_uinc:
1318 case AtomicExpr::AO__atomic_fetch_udec:
1319 llvm_unreachable(
"Integral atomic operations always become atomicrmw!");
1324 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: openCL");
1341 cgf.
cgm.
errorNYI(loc,
"emitLibCallForAtomicExpr: openCL");
1363 memTy = ty->getValueType();
1365 Expr *isWeakExpr =
nullptr;
1366 Expr *orderFailExpr =
nullptr;
1374 if (e->
getOp() == AtomicExpr::AO__c11_atomic_init) {
1386 std::optional<Expr::EvalResult> scopeConst;
1389 scopeConst.emplace(std::move(eval));
1391 switch (e->
getOp()) {
1396 case AtomicExpr::AO__c11_atomic_init:
1397 llvm_unreachable(
"already handled above with emitAtomicInit");
1399 case AtomicExpr::AO__atomic_load_n:
1400 case AtomicExpr::AO__scoped_atomic_load_n:
1401 case AtomicExpr::AO__c11_atomic_load:
1402 case AtomicExpr::AO__atomic_test_and_set:
1403 case AtomicExpr::AO__atomic_clear:
1406 case AtomicExpr::AO__atomic_load:
1407 case AtomicExpr::AO__scoped_atomic_load:
1411 case AtomicExpr::AO__atomic_store:
1412 case AtomicExpr::AO__scoped_atomic_store:
1416 case AtomicExpr::AO__atomic_exchange:
1417 case AtomicExpr::AO__scoped_atomic_exchange:
1422 case AtomicExpr::AO__atomic_compare_exchange:
1423 case AtomicExpr::AO__atomic_compare_exchange_n:
1424 case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
1425 case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
1426 case AtomicExpr::AO__scoped_atomic_compare_exchange:
1427 case AtomicExpr::AO__scoped_atomic_compare_exchange_n:
1429 if (e->
getOp() == AtomicExpr::AO__atomic_compare_exchange ||
1430 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)
1435 if (e->
getOp() == AtomicExpr::AO__atomic_compare_exchange_n ||
1436 e->
getOp() == AtomicExpr::AO__atomic_compare_exchange ||
1437 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange_n ||
1438 e->
getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)
1442 case AtomicExpr::AO__c11_atomic_fetch_add:
1443 case AtomicExpr::AO__c11_atomic_fetch_sub:
1454 mlir::Value scale = builder.getConstInt(loc, val1Scalar.getType(),
1456 val1Scalar = builder.createMul(loc, val1Scalar, scale);
1462 case AtomicExpr::AO__atomic_fetch_add:
1463 case AtomicExpr::AO__atomic_fetch_sub:
1464 case AtomicExpr::AO__atomic_add_fetch:
1465 case AtomicExpr::AO__atomic_sub_fetch:
1475 case AtomicExpr::AO__atomic_fetch_max:
1476 case AtomicExpr::AO__atomic_fetch_min:
1477 case AtomicExpr::AO__atomic_max_fetch:
1478 case AtomicExpr::AO__atomic_min_fetch:
1479 case AtomicExpr::AO__c11_atomic_fetch_max:
1480 case AtomicExpr::AO__c11_atomic_fetch_min:
1481 case AtomicExpr::AO__scoped_atomic_fetch_add:
1482 case AtomicExpr::AO__scoped_atomic_fetch_max:
1483 case AtomicExpr::AO__scoped_atomic_fetch_min:
1484 case AtomicExpr::AO__scoped_atomic_fetch_sub:
1485 case AtomicExpr::AO__scoped_atomic_add_fetch:
1486 case AtomicExpr::AO__scoped_atomic_max_fetch:
1487 case AtomicExpr::AO__scoped_atomic_min_fetch:
1488 case AtomicExpr::AO__scoped_atomic_sub_fetch:
1491 case AtomicExpr::AO__atomic_fetch_and:
1492 case AtomicExpr::AO__atomic_fetch_nand:
1493 case AtomicExpr::AO__atomic_fetch_or:
1494 case AtomicExpr::AO__atomic_fetch_xor:
1495 case AtomicExpr::AO__atomic_and_fetch:
1496 case AtomicExpr::AO__atomic_nand_fetch:
1497 case AtomicExpr::AO__atomic_or_fetch:
1498 case AtomicExpr::AO__atomic_xor_fetch:
1499 case AtomicExpr::AO__atomic_exchange_n:
1500 case AtomicExpr::AO__atomic_store_n:
1501 case AtomicExpr::AO__c11_atomic_fetch_and:
1502 case AtomicExpr::AO__c11_atomic_fetch_nand:
1503 case AtomicExpr::AO__c11_atomic_fetch_or:
1504 case AtomicExpr::AO__c11_atomic_fetch_xor:
1505 case AtomicExpr::AO__c11_atomic_exchange:
1506 case AtomicExpr::AO__c11_atomic_store:
1507 case AtomicExpr::AO__scoped_atomic_fetch_and:
1508 case AtomicExpr::AO__scoped_atomic_fetch_nand:
1509 case AtomicExpr::AO__scoped_atomic_fetch_or:
1510 case AtomicExpr::AO__scoped_atomic_fetch_xor:
1511 case AtomicExpr::AO__scoped_atomic_and_fetch:
1512 case AtomicExpr::AO__scoped_atomic_nand_fetch:
1513 case AtomicExpr::AO__scoped_atomic_or_fetch:
1514 case AtomicExpr::AO__scoped_atomic_xor_fetch:
1515 case AtomicExpr::AO__scoped_atomic_store_n:
1516 case AtomicExpr::AO__scoped_atomic_exchange_n:
1517 case AtomicExpr::AO__atomic_fetch_uinc:
1518 case AtomicExpr::AO__atomic_fetch_udec:
1519 case AtomicExpr::AO__scoped_atomic_fetch_uinc:
1520 case AtomicExpr::AO__scoped_atomic_fetch_udec:
1527 bool shouldCastToIntPtrTy =
1536 if (shouldCastToIntPtrTy) {
1537 ptr = atomics.castToAtomicIntPointer(ptr);
1539 val1 = atomics.convertToAtomicIntPointer(val1);
1541 val2 = atomics.convertToAtomicIntPointer(val2);
1544 if (shouldCastToIntPtrTy)
1545 dest = atomics.castToAtomicIntPointer(dest);
1548 }
else if (e->
getOp() == AtomicExpr::AO__atomic_test_and_set) {
1550 "test_and_set.bool");
1552 dest = atomics.createTempAlloca();
1553 if (shouldCastToIntPtrTy)
1554 dest = atomics.castToAtomicIntPointer(dest);
1557 bool powerOf2Size = (size & (size - 1)) == 0;
1558 bool useLibCall = !powerOf2Size || (size > 16);
1572 bool isStore = e->
getOp() == AtomicExpr::AO__c11_atomic_store ||
1573 e->
getOp() == AtomicExpr::AO__opencl_atomic_store ||
1574 e->
getOp() == AtomicExpr::AO__hip_atomic_store ||
1575 e->
getOp() == AtomicExpr::AO__atomic_store ||
1576 e->
getOp() == AtomicExpr::AO__atomic_store_n ||
1577 e->
getOp() == AtomicExpr::AO__scoped_atomic_store ||
1578 e->
getOp() == AtomicExpr::AO__scoped_atomic_store_n ||
1579 e->
getOp() == AtomicExpr::AO__atomic_clear;
1580 bool isLoad = e->
getOp() == AtomicExpr::AO__c11_atomic_load ||
1581 e->
getOp() == AtomicExpr::AO__opencl_atomic_load ||
1582 e->
getOp() == AtomicExpr::AO__hip_atomic_load ||
1583 e->
getOp() == AtomicExpr::AO__atomic_load ||
1584 e->
getOp() == AtomicExpr::AO__atomic_load_n ||
1585 e->
getOp() == AtomicExpr::AO__scoped_atomic_load ||
1586 e->
getOp() == AtomicExpr::AO__scoped_atomic_load_n;
1588 auto emitAtomicOpCallBackFn = [&](cir::MemOrder memOrder) {
1589 emitAtomicOp(*
this, e, dest, ptr, val1, val2, isWeakExpr, orderFailExpr,
1590 size, memOrder, scopeConst, scope);
1593 emitAtomicOpCallBackFn);
1606 return emitAtomicLoad(lvalue, loc, cir::MemOrder::SequentiallyConsistent,
1613 cir::MemOrder order,
bool isVolatile,
1615 AtomicInfo info(*
this, lvalue,
getLoc(loc));
1616 return info.emitAtomicLoad(slot, loc,
true, order, isVolatile);
1621 auto order = cir::MemOrder::SequentiallyConsistent;
1634 cir::MemOrder order,
bool isVolatile,
1638 mlir::Location loc = dest.
getPointer().getLoc();
1643 AtomicInfo atomics(*
this, dest, loc);
1644 LValue lvalue = atomics.getAtomicLValue();
1649 atomics.emitCopyIntoMemory(rvalue);
1654 if (atomics.shouldUseLibCall()) {
1656 cgm.errorNYI(loc,
"emitAtomicStore: atomic store with library call");
1661 mlir::Value valueToStore = atomics.convertRValueToInt(rvalue, loc);
1664 Address addr = atomics.getAtomicAddress();
1665 if (mlir::Value value = atomics.getScalarRValValueOrNull(rvalue)) {
1667 addr = atomics.castToAtomicIntPointer(addr);
1672 cir::StoreOp store = builder.createStore(loc, valueToStore, addr);
1677 store.setMemOrder(order);
1682 store.setIsVolatile(
true);
1688 cgm.errorNYI(loc,
"emitAtomicStore: non-simple atomic lvalue");
1695 switch (atomics.getEvaluationKind()) {
1711 bool zeroed =
false;
1713 zeroed = atomics.emitMemSetZeroIfNecessary();
1714 dest = atomics.projectValue();
1729 llvm_unreachable(
"bad evaluation kind");
static bool shouldCastToInt(mlir::Type valueTy, bool cmpxchg)
Return true if.
static RValue emitLibCallForAtomicExpr(CIRGenFunction &cgf, AtomicExpr *e, Address atomicPtr, Address dest, Address val1, uint64_t atomicTySize, QualType resultTy)
static Address emitValToTemp(CIRGenFunction &cgf, Expr *e)
static void emitAtomicCmpXchgFailureSetCheckWeak(CIRGenFunction &cgf, AtomicExpr *e, Expr *isWeakExpr, Address dest, Address ptr, Address val1, Address val2, Expr *failureOrderExpr, uint64_t size, cir::MemOrder successOrder, cir::SyncScopeKind scope)
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, cir::SyncScopeKind scope)
static void emitMemOrderCaseLabel(CIRGenBuilderTy &builder, mlir::Location loc, mlir::Type orderType, llvm::ArrayRef< cir::MemOrder > orders)
static cir::SyncScopeKind convertSyncScopeToCIR(CIRGenFunction &cgf, SourceRange range, clang::SyncScope scope)
static void emitAtomicExprWithDynamicMemOrder(CIRGenFunction &cgf, mlir::Value order, bool isStore, bool isLoad, bool isFence, llvm::function_ref< void(cir::MemOrder)> emitAtomicOpFn)
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, cir::SyncScopeKind scope)
static void emitDefaultCaseLabel(CIRGenBuilderTy &builder, mlir::Location loc)
static bool isFullSizeType(CIRGenModule &cgm, mlir::Type ty, uint64_t expectedSize)
Does a store of the given IR type modify the full expected width?
static std::optional< cir::MemOrder > getEffectiveAtomicMemOrder(cir::MemOrder oriOrder, bool isStore, bool isLoad, bool isFence)
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, cir::SyncScopeKind scope)
static RValue emitAtomicLibCall(CIRGenFunction &cgf, llvm::StringRef funcName, QualType resultType, CallArgList &args)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::BreakOp createBreak(mlir::Location loc)
Create a break operation.
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
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.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
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,...
static std::unique_ptr< AtomicScopeModel > getScopeModel(AtomicOp Op)
Get atomic scope model for the atomic op code.
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
mlir::Value emitRawPointer() const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
Address getAddress() const
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
cir::MemSetOp createMemSet(mlir::Location loc, mlir::Value dst, mlir::Value val, mlir::Value len)
cir::IntType getUIntNTy(int n)
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
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.
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)
RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, AggValueSlot slot=AggValueSlot::ignored())
mlir::Type convertTypeForMem(QualType t)
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
void emitAtomicExprWithMemOrder(const Expr *memOrder, bool isStore, bool isLoad, bool isFence, llvm::function_ref< void(cir::MemOrder)> emitAtomicOp)
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty)
Given a value and its clang type, returns the value casted to its memory representation.
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)
void emitAtomicStore(RValue rvalue, LValue dest, bool isInit)
clang::ASTContext & getContext() const
mlir::Value emitFromMemory(mlir::Value value, clang::QualType ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
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.
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::NamedAttrList extraAttrs={}, bool isLocal=false, bool assumeConvergent=false)
const cir::CIRDataLayout getDataLayout() const
const CIRGenFunctionInfo & arrangeBuiltinFunctionCall(QualType resultType, const CallArgList &args)
A builtin function is a freestanding function using the default C conventions.
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
void add(RValue rvalue, clang::QualType type)
Address getAddress() const
clang::QualType getType() const
mlir::Value getPointer() const
bool isVolatileQualified() const
This trivial value class is used to represent the result of an expression that is evaluated.
Address getAggregateAddress() const
Return the value of the address of the aggregate.
static RValue get(mlir::Value v)
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
mlir::Value getValue() const
Return the value of this scalar value.
mlir::Value getComplexValue() const
Return the value of this complex value.
Contains the address where the return value of a function can be stored, and whether the address is v...
CharUnits - This is an opaque type for sizes expressed in character units.
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.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits, uint64_t AlignmentInBits) const
Returns true if the given target supports lock-free atomic operations at the specified width and alig...
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
const T * getAs() const
Member-template getAs<specific type>'.
bool isValidCIRAtomicOrderingCABI(Int value)
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
@ Address
A pointer to a ValueDecl.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
SyncScope
Defines sync scope values used internally by clang.
static bool atomicInfoGetAtomicPointer()
static bool aggValueSlotGC()
static bool opLoadStoreAtomic()
static bool opLoadStoreTbaa()
static bool opFuncExtraAttrs()
static bool atomicUseLibCall()
static bool atomicOpenMP()
static bool atomicMicrosoftVolatile()
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.