;
26using namespaceCodeGen;
43: CGF(CGF), AtomicSizeInBits(0), ValueSizeInBits(0),
50ValueTy = ATy->getValueType();
57 TypeInfoValueTI =
C.getTypeInfo(ValueTy);
58ValueSizeInBits = ValueTI.
Width;
59ValueAlignInBits = ValueTI.
Align;
61 TypeInfoAtomicTI =
C.getTypeInfo(AtomicTy);
62AtomicSizeInBits = AtomicTI.
Width;
63AtomicAlignInBits = AtomicTI.
Align;
65assert(ValueSizeInBits <= AtomicSizeInBits);
66assert(ValueAlignInBits <= AtomicAlignInBits);
68AtomicAlign =
C.toCharUnitsFromBits(AtomicAlignInBits);
69ValueAlign =
C.toCharUnitsFromBits(ValueAlignInBits);
76ValueSizeInBits =
C.getTypeSize(ValueTy);
78 autoOffset = OrigBFI.Offset %
C.toBits(lvalue.
getAlignment());
79AtomicSizeInBits =
C.toBits(
80 C.toCharUnitsFromBits(Offset + OrigBFI.Size +
C.getCharWidth() - 1)
84(
C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.
getAlignment()) *
86llvm::Value *StoragePtr = CGF.
Builder.CreateConstGEP1_64(
87CGF.
Int8Ty, BitFieldPtr, OffsetInChars.getQuantity());
89StoragePtr, CGF.
UnqualPtrTy,
"atomic_bitfield_base");
94llvm::Type *StorageTy = CGF.
Builder.getIntNTy(AtomicSizeInBits);
95LVal = LValue::MakeBitfield(
98AtomicTy =
C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned);
102 C.toCharUnitsFromBits(AtomicSizeInBits).getQuantity());
103AtomicTy =
C.getConstantArrayType(
C.CharTy, Size,
nullptr,
104ArraySizeModifier::Normal,
110ValueSizeInBits =
C.getTypeSize(ValueTy);
112AtomicSizeInBits =
C.getTypeSize(AtomicTy);
118ValueSizeInBits =
C.getTypeSize(ValueTy);
120lvalue.
getType(), cast<llvm::FixedVectorType>(
123AtomicSizeInBits =
C.getTypeSize(AtomicTy);
127UseLibcall = !
C.getTargetInfo().hasBuiltinAtomic(
131 QualTypegetAtomicType()
const{
returnAtomicTy; }
132 QualTypegetValueType()
const{
returnValueTy; }
133 CharUnitsgetAtomicAlignment()
const{
returnAtomicAlign; }
134 uint64_tgetAtomicSizeInBits()
const{
returnAtomicSizeInBits; }
135 uint64_tgetValueSizeInBits()
const{
returnValueSizeInBits; }
137 boolshouldUseLibcall()
const{
returnUseLibcall; }
138 const LValue&getAtomicLValue()
const{
returnLVal; }
139llvm::Value *getAtomicPointer()
const{
149 AddressgetAtomicAddress()
const{
159 return Address(getAtomicPointer(), ElTy, getAtomicAlignment());
162 AddressgetAtomicAddressAsAtomicIntPointer()
const{
163 returncastToAtomicIntPointer(getAtomicAddress());
172 boolhasPadding()
const{
173 return(ValueSizeInBits != AtomicSizeInBits);
176 boolemitMemSetZeroIfNecessary()
const;
178llvm::Value *getAtomicSizeValue()
const{
196llvm::Value *getScalarRValValueOrNull(
RValueRVal)
const;
199llvm::Value *convertRValueToInt(
RValueRVal,
boolCmpXchg =
false)
const;
203 boolCmpXchg =
false)
const;
206 voidemitCopyIntoMemory(
RValuervalue)
const;
209 LValueprojectValue()
const{
211 Addressaddr = getAtomicAddress();
215 returnLValue::MakeAddr(addr, getValueType(), CGF.
getContext(),
222 boolAsValue, llvm::AtomicOrdering AO,
233std::pair<RValue, llvm::Value *>
236llvm::AtomicOrdering::SequentiallyConsistent,
237llvm::AtomicOrdering Failure =
238llvm::AtomicOrdering::SequentiallyConsistent,
239 boolIsWeak =
false);
244 voidEmitAtomicUpdate(llvm::AtomicOrdering AO,
249 voidEmitAtomicUpdate(llvm::AtomicOrdering AO,
RValueUpdateRVal,
256 AddressCreateTempAlloca()
const;
258 boolrequiresMemSetZero(llvm::Type *
type)
const;
262 voidEmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
263llvm::AtomicOrdering AO,
boolIsVolatile);
265llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO,
boolIsVolatile,
266 boolCmpXchg =
false);
268llvm::Value *EmitAtomicCompareExchangeLibcall(
269llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,
271llvm::AtomicOrdering::SequentiallyConsistent,
272llvm::AtomicOrdering Failure =
273llvm::AtomicOrdering::SequentiallyConsistent);
275std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeOp(
276llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
278llvm::AtomicOrdering::SequentiallyConsistent,
279llvm::AtomicOrdering Failure =
280llvm::AtomicOrdering::SequentiallyConsistent,
281 boolIsWeak =
false);
284EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,
288 voidEmitAtomicUpdateOp(llvm::AtomicOrdering AO,
292 voidEmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,
RValueUpdateRVal,
295 voidEmitAtomicUpdateOp(llvm::AtomicOrdering AO,
RValueUpdateRal,
300AddressAtomicInfo::CreateTempAlloca()
const{
302(LVal.
isBitField() && ValueSizeInBits > AtomicSizeInBits) ? ValueTy
304getAtomicAlignment(),
309TempAlloca, getAtomicAddress().getType(),
310getAtomicAddress().getElementType());
322fnAttrB.addAttribute(llvm::Attribute::NoUnwind);
323fnAttrB.addAttribute(llvm::Attribute::WillReturn);
324llvm::AttributeList fnAttrs = llvm::AttributeList::get(
325CGF.
getLLVMContext(), llvm::AttributeList::FunctionIndex, fnAttrB);
327llvm::FunctionCallee fn =
335uint64_t expectedSize) {
342boolAtomicInfo::requiresMemSetZero(llvm::Type *
type)
const{
344 if(hasPadding())
return true;
347 switch(getEvaluationKind()) {
354AtomicSizeInBits / 2);
360llvm_unreachable(
"bad evaluation kind");
363boolAtomicInfo::emitMemSetZeroIfNecessary()
const{
380llvm::AtomicOrdering SuccessOrder,
381llvm::AtomicOrdering FailureOrder,
382llvm::SyncScope::ID
Scope) {
388Ptr,
Expected, Desired, SuccessOrder, FailureOrder,
Scope);
389Pair->setVolatile(
E->isVolatile());
390Pair->setWeak(IsWeak);
395llvm::Value *Old = CGF.
Builder.CreateExtractValue(Pair, 0);
396llvm::Value *Cmp = CGF.
Builder.CreateExtractValue(Pair, 1);
400llvm::BasicBlock *StoreExpectedBB =
405llvm::BasicBlock *ContinueBB =
410CGF.
Builder.CreateCondBr(Cmp, ContinueBB, StoreExpectedBB);
412CGF.
Builder.SetInsertPoint(StoreExpectedBB);
416CGF.
Builder.CreateBr(ContinueBB);
418CGF.
Builder.SetInsertPoint(ContinueBB);
429llvm::Value *FailureOrderVal,
431llvm::AtomicOrdering SuccessOrder,
432llvm::SyncScope::ID
Scope) {
433llvm::AtomicOrdering FailureOrder;
434 if(llvm::ConstantInt *FO = dyn_cast<llvm::ConstantInt>(FailureOrderVal)) {
435 autoFOS = FO->getSExtValue();
436 if(!llvm::isValidAtomicOrderingCABI(FOS))
437FailureOrder = llvm::AtomicOrdering::Monotonic;
439 switch((llvm::AtomicOrderingCABI)FOS) {
440 casellvm::AtomicOrderingCABI::relaxed:
443 casellvm::AtomicOrderingCABI::release:
444 casellvm::AtomicOrderingCABI::acq_rel:
445FailureOrder = llvm::AtomicOrdering::Monotonic;
447 casellvm::AtomicOrderingCABI::consume:
448 casellvm::AtomicOrderingCABI::acquire:
449FailureOrder = llvm::AtomicOrdering::Acquire;
451 casellvm::AtomicOrderingCABI::seq_cst:
452FailureOrder = llvm::AtomicOrdering::SequentiallyConsistent;
460FailureOrder,
Scope);
473llvm::SwitchInst *SI = CGF.
Builder.CreateSwitch(FailureOrderVal, MonotonicBB);
475SI->addCase(CGF.
Builder.getInt32((
int)llvm::AtomicOrderingCABI::consume),
477SI->addCase(CGF.
Builder.getInt32((
int)llvm::AtomicOrderingCABI::acquire),
479SI->addCase(CGF.
Builder.getInt32((
int)llvm::AtomicOrderingCABI::seq_cst),
483CGF.
Builder.SetInsertPoint(MonotonicBB);
485Size, SuccessOrder, llvm::AtomicOrdering::Monotonic,
Scope);
486CGF.
Builder.CreateBr(ContBB);
488CGF.
Builder.SetInsertPoint(AcquireBB);
490llvm::AtomicOrdering::Acquire,
Scope);
491CGF.
Builder.CreateBr(ContBB);
493CGF.
Builder.SetInsertPoint(SeqCstBB);
495llvm::AtomicOrdering::SequentiallyConsistent,
Scope);
496CGF.
Builder.CreateBr(ContBB);
498CGF.
Builder.SetInsertPoint(ContBB);
508llvm::CmpInst::Predicate Pred;
511llvm_unreachable(
"Unexpected min/max operation");
512 caseAtomicExpr::AO__atomic_max_fetch:
513 caseAtomicExpr::AO__scoped_atomic_max_fetch:
514Pred = IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT;
516 caseAtomicExpr::AO__atomic_min_fetch:
517 caseAtomicExpr::AO__scoped_atomic_min_fetch:
518Pred = IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT;
521llvm::Value *Cmp = Builder.CreateICmp(Pred, OldVal, RHS,
"tst");
522 returnBuilder.CreateSelect(Cmp, OldVal, RHS,
"newval");
527llvm::Value *IsWeak, llvm::Value *FailureOrder,
528uint64_t Size, llvm::AtomicOrdering Order,
529llvm::SyncScope::ID
Scope) {
530llvm::AtomicRMWInst::BinOp Op = llvm::AtomicRMWInst::Add;
531 boolPostOpMinMax =
false;
534 switch(
E->getOp()) {
535 caseAtomicExpr::AO__c11_atomic_init:
536 caseAtomicExpr::AO__opencl_atomic_init:
537llvm_unreachable(
"Already handled!");
539 caseAtomicExpr::AO__c11_atomic_compare_exchange_strong:
540 caseAtomicExpr::AO__hip_atomic_compare_exchange_strong:
541 caseAtomicExpr::AO__opencl_atomic_compare_exchange_strong:
543FailureOrder, Size, Order,
Scope);
545 caseAtomicExpr::AO__c11_atomic_compare_exchange_weak:
546 caseAtomicExpr::AO__opencl_atomic_compare_exchange_weak:
547 caseAtomicExpr::AO__hip_atomic_compare_exchange_weak:
549FailureOrder, Size, Order,
Scope);
551 caseAtomicExpr::AO__atomic_compare_exchange:
552 caseAtomicExpr::AO__atomic_compare_exchange_n:
553 caseAtomicExpr::AO__scoped_atomic_compare_exchange:
554 caseAtomicExpr::AO__scoped_atomic_compare_exchange_n: {
555 if(llvm::ConstantInt *IsWeakC = dyn_cast<llvm::ConstantInt>(IsWeak)) {
557Val1, Val2, FailureOrder, Size, Order,
Scope);
560llvm::BasicBlock *StrongBB =
563llvm::BasicBlock *ContBB =
566llvm::SwitchInst *SI = CGF.
Builder.CreateSwitch(IsWeak, WeakBB);
567SI->addCase(CGF.
Builder.getInt1(
false), StrongBB);
569CGF.
Builder.SetInsertPoint(StrongBB);
571FailureOrder, Size, Order,
Scope);
572CGF.
Builder.CreateBr(ContBB);
574CGF.
Builder.SetInsertPoint(WeakBB);
576FailureOrder, Size, Order,
Scope);
577CGF.
Builder.CreateBr(ContBB);
579CGF.
Builder.SetInsertPoint(ContBB);
583 caseAtomicExpr::AO__c11_atomic_load:
584 caseAtomicExpr::AO__opencl_atomic_load:
585 caseAtomicExpr::AO__hip_atomic_load:
586 caseAtomicExpr::AO__atomic_load_n:
587 caseAtomicExpr::AO__atomic_load:
588 caseAtomicExpr::AO__scoped_atomic_load_n:
589 caseAtomicExpr::AO__scoped_atomic_load: {
591Load->setAtomic(Order,
Scope);
592Load->setVolatile(
E->isVolatile());
597 caseAtomicExpr::AO__c11_atomic_store:
598 caseAtomicExpr::AO__opencl_atomic_store:
599 caseAtomicExpr::AO__hip_atomic_store:
600 caseAtomicExpr::AO__atomic_store:
601 caseAtomicExpr::AO__atomic_store_n:
602 caseAtomicExpr::AO__scoped_atomic_store:
603 caseAtomicExpr::AO__scoped_atomic_store_n: {
606Store->setAtomic(Order,
Scope);
607Store->setVolatile(
E->isVolatile());
611 caseAtomicExpr::AO__c11_atomic_exchange:
612 caseAtomicExpr::AO__hip_atomic_exchange:
613 caseAtomicExpr::AO__opencl_atomic_exchange:
614 caseAtomicExpr::AO__atomic_exchange_n:
615 caseAtomicExpr::AO__atomic_exchange:
616 caseAtomicExpr::AO__scoped_atomic_exchange_n:
617 caseAtomicExpr::AO__scoped_atomic_exchange:
618Op = llvm::AtomicRMWInst::Xchg;
621 caseAtomicExpr::AO__atomic_add_fetch:
622 caseAtomicExpr::AO__scoped_atomic_add_fetch:
623PostOp =
E->getValueType()->isFloatingType() ? llvm::Instruction::FAdd
624: llvm::Instruction::Add;
626 caseAtomicExpr::AO__c11_atomic_fetch_add:
627 caseAtomicExpr::AO__hip_atomic_fetch_add:
628 caseAtomicExpr::AO__opencl_atomic_fetch_add:
629 caseAtomicExpr::AO__atomic_fetch_add:
630 caseAtomicExpr::AO__scoped_atomic_fetch_add:
631Op =
E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FAdd
632: llvm::AtomicRMWInst::Add;
635 caseAtomicExpr::AO__atomic_sub_fetch:
636 caseAtomicExpr::AO__scoped_atomic_sub_fetch:
637PostOp =
E->getValueType()->isFloatingType() ? llvm::Instruction::FSub
638: llvm::Instruction::Sub;
640 caseAtomicExpr::AO__c11_atomic_fetch_sub:
641 caseAtomicExpr::AO__hip_atomic_fetch_sub:
642 caseAtomicExpr::AO__opencl_atomic_fetch_sub:
643 caseAtomicExpr::AO__atomic_fetch_sub:
644 caseAtomicExpr::AO__scoped_atomic_fetch_sub:
645Op =
E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FSub
646: llvm::AtomicRMWInst::Sub;
649 caseAtomicExpr::AO__atomic_min_fetch:
650 caseAtomicExpr::AO__scoped_atomic_min_fetch:
651PostOpMinMax =
true;
653 caseAtomicExpr::AO__c11_atomic_fetch_min:
654 caseAtomicExpr::AO__hip_atomic_fetch_min:
655 caseAtomicExpr::AO__opencl_atomic_fetch_min:
656 caseAtomicExpr::AO__atomic_fetch_min:
657 caseAtomicExpr::AO__scoped_atomic_fetch_min:
658Op =
E->getValueType()->isFloatingType()
659? llvm::AtomicRMWInst::FMin
660: (
E->getValueType()->isSignedIntegerType()
661? llvm::AtomicRMWInst::Min
662: llvm::AtomicRMWInst::UMin);
665 caseAtomicExpr::AO__atomic_max_fetch:
666 caseAtomicExpr::AO__scoped_atomic_max_fetch:
667PostOpMinMax =
true;
669 caseAtomicExpr::AO__c11_atomic_fetch_max:
670 caseAtomicExpr::AO__hip_atomic_fetch_max:
671 caseAtomicExpr::AO__opencl_atomic_fetch_max:
672 caseAtomicExpr::AO__atomic_fetch_max:
673 caseAtomicExpr::AO__scoped_atomic_fetch_max:
674Op =
E->getValueType()->isFloatingType()
675? llvm::AtomicRMWInst::FMax
676: (
E->getValueType()->isSignedIntegerType()
677? llvm::AtomicRMWInst::Max
678: llvm::AtomicRMWInst::UMax);
681 caseAtomicExpr::AO__atomic_and_fetch:
682 caseAtomicExpr::AO__scoped_atomic_and_fetch:
683PostOp = llvm::Instruction::And;
685 caseAtomicExpr::AO__c11_atomic_fetch_and:
686 caseAtomicExpr::AO__hip_atomic_fetch_and:
687 caseAtomicExpr::AO__opencl_atomic_fetch_and:
688 caseAtomicExpr::AO__atomic_fetch_and:
689 caseAtomicExpr::AO__scoped_atomic_fetch_and:
690Op = llvm::AtomicRMWInst::And;
693 caseAtomicExpr::AO__atomic_or_fetch:
694 caseAtomicExpr::AO__scoped_atomic_or_fetch:
695PostOp = llvm::Instruction::Or;
697 caseAtomicExpr::AO__c11_atomic_fetch_or:
698 caseAtomicExpr::AO__hip_atomic_fetch_or:
699 caseAtomicExpr::AO__opencl_atomic_fetch_or:
700 caseAtomicExpr::AO__atomic_fetch_or:
701 caseAtomicExpr::AO__scoped_atomic_fetch_or:
702Op = llvm::AtomicRMWInst::Or;
705 caseAtomicExpr::AO__atomic_xor_fetch:
706 caseAtomicExpr::AO__scoped_atomic_xor_fetch:
707PostOp = llvm::Instruction::Xor;
709 caseAtomicExpr::AO__c11_atomic_fetch_xor:
710 caseAtomicExpr::AO__hip_atomic_fetch_xor:
711 caseAtomicExpr::AO__opencl_atomic_fetch_xor:
712 caseAtomicExpr::AO__atomic_fetch_xor:
713 caseAtomicExpr::AO__scoped_atomic_fetch_xor:
714Op = llvm::AtomicRMWInst::Xor;
717 caseAtomicExpr::AO__atomic_nand_fetch:
718 caseAtomicExpr::AO__scoped_atomic_nand_fetch:
719PostOp = llvm::Instruction::And;
721 caseAtomicExpr::AO__c11_atomic_fetch_nand:
722 caseAtomicExpr::AO__atomic_fetch_nand:
723 caseAtomicExpr::AO__scoped_atomic_fetch_nand:
724Op = llvm::AtomicRMWInst::Nand;
727 caseAtomicExpr::AO__atomic_test_and_set: {
728llvm::AtomicRMWInst *RMWI =
731RMWI->setVolatile(
E->isVolatile());
732llvm::Value *Result = CGF.
Builder.CreateIsNotNull(RMWI,
"tobool");
737 caseAtomicExpr::AO__atomic_clear: {
738llvm::StoreInst *Store =
740Store->setAtomic(Order,
Scope);
741Store->setVolatile(
E->isVolatile());
747llvm::AtomicRMWInst *RMWI =
749RMWI->setVolatile(
E->isVolatile());
753llvm::Value *Result = RMWI;
756 E->getValueType()->isSignedIntegerType(),
759Result = CGF.
Builder.CreateBinOp((llvm::Instruction::BinaryOps)PostOp, RMWI,
761 if(
E->getOp() == AtomicExpr::AO__atomic_nand_fetch ||
762 E->getOp() == AtomicExpr::AO__scoped_atomic_nand_fetch)
763Result = CGF.
Builder.CreateNot(Result);
779llvm::Value *IsWeak, llvm::Value *FailureOrder,
780uint64_t Size, llvm::AtomicOrdering Order,
781llvm::Value *
Scope) {
782 autoScopeModel =
Expr->getScopeModel();
787llvm::SyncScope::ID SS;
794SyncScope::OpenCLDevice,
797SS = llvm::SyncScope::System;
798 EmitAtomicOp(CGF,
Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
804 if(
autoSC = dyn_cast<llvm::ConstantInt>(
Scope)) {
808 EmitAtomicOp(CGF,
Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
815 autoScopes = ScopeModel->getRuntimeValues();
816llvm::DenseMap<unsigned, llvm::BasicBlock *> BB;
817 for(
autoS : Scopes)
820llvm::BasicBlock *ContBB =
823 auto*SC = Builder.CreateIntCast(
Scope, Builder.getInt32Ty(),
false);
826 autoFallBack = ScopeModel->getFallBackValue();
827llvm::SwitchInst *SI = Builder.CreateSwitch(SC, BB[FallBack]);
828 for(
autoS : Scopes) {
831SI->addCase(Builder.getInt32(S), B);
833Builder.SetInsertPoint(B);
834 EmitAtomicOp(CGF,
Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
840Builder.CreateBr(ContBB);
843Builder.SetInsertPoint(ContBB);
850MemTy = AT->getValueType();
851llvm::Value *IsWeak =
nullptr, *OrderFail =
nullptr;
858 if(
E->getOp() == AtomicExpr::AO__c11_atomic_init ||
859 E->getOp() == AtomicExpr::AO__opencl_atomic_init) {
872 boolMisaligned = (Ptr.
getAlignment() % TInfo.Width) != 0;
873 boolOversized =
getContext().
toBits(TInfo.Width) > MaxInlineWidthInBits;
876<< (
int)TInfo.Width.getQuantity()
881<< (
int)TInfo.Width.getQuantity() << (
int)MaxInlineWidth.
getQuantity();
885llvm::Value *
Scope=
887 boolShouldCastToIntPtrTy =
true;
889 switch(
E->getOp()) {
890 caseAtomicExpr::AO__c11_atomic_init:
891 caseAtomicExpr::AO__opencl_atomic_init:
892llvm_unreachable(
"Already handled above with EmitAtomicInit!");
894 caseAtomicExpr::AO__atomic_load_n:
895 caseAtomicExpr::AO__scoped_atomic_load_n:
896 caseAtomicExpr::AO__c11_atomic_load:
897 caseAtomicExpr::AO__opencl_atomic_load:
898 caseAtomicExpr::AO__hip_atomic_load:
899 caseAtomicExpr::AO__atomic_test_and_set:
900 caseAtomicExpr::AO__atomic_clear:
903 caseAtomicExpr::AO__atomic_load:
904 caseAtomicExpr::AO__scoped_atomic_load:
908 caseAtomicExpr::AO__atomic_store:
909 caseAtomicExpr::AO__scoped_atomic_store:
913 caseAtomicExpr::AO__atomic_exchange:
914 caseAtomicExpr::AO__scoped_atomic_exchange:
919 caseAtomicExpr::AO__atomic_compare_exchange:
920 caseAtomicExpr::AO__atomic_compare_exchange_n:
921 caseAtomicExpr::AO__c11_atomic_compare_exchange_weak:
922 caseAtomicExpr::AO__c11_atomic_compare_exchange_strong:
923 caseAtomicExpr::AO__hip_atomic_compare_exchange_weak:
924 caseAtomicExpr::AO__hip_atomic_compare_exchange_strong:
925 caseAtomicExpr::AO__opencl_atomic_compare_exchange_weak:
926 caseAtomicExpr::AO__opencl_atomic_compare_exchange_strong:
927 caseAtomicExpr::AO__scoped_atomic_compare_exchange:
928 caseAtomicExpr::AO__scoped_atomic_compare_exchange_n:
930 if(
E->getOp() == AtomicExpr::AO__atomic_compare_exchange ||
931 E->getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)
936 if(
E->getOp() == AtomicExpr::AO__atomic_compare_exchange_n ||
937 E->getOp() == AtomicExpr::AO__atomic_compare_exchange ||
938 E->getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange_n ||
939 E->getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)
943 caseAtomicExpr::AO__c11_atomic_fetch_add:
944 caseAtomicExpr::AO__c11_atomic_fetch_sub:
945 caseAtomicExpr::AO__hip_atomic_fetch_add:
946 caseAtomicExpr::AO__hip_atomic_fetch_sub:
947 caseAtomicExpr::AO__opencl_atomic_fetch_add:
948 caseAtomicExpr::AO__opencl_atomic_fetch_sub:
965 caseAtomicExpr::AO__atomic_fetch_add:
966 caseAtomicExpr::AO__atomic_fetch_max:
967 caseAtomicExpr::AO__atomic_fetch_min:
968 caseAtomicExpr::AO__atomic_fetch_sub:
969 caseAtomicExpr::AO__atomic_add_fetch:
970 caseAtomicExpr::AO__atomic_max_fetch:
971 caseAtomicExpr::AO__atomic_min_fetch:
972 caseAtomicExpr::AO__atomic_sub_fetch:
973 caseAtomicExpr::AO__c11_atomic_fetch_max:
974 caseAtomicExpr::AO__c11_atomic_fetch_min:
975 caseAtomicExpr::AO__opencl_atomic_fetch_max:
976 caseAtomicExpr::AO__opencl_atomic_fetch_min:
977 caseAtomicExpr::AO__hip_atomic_fetch_max:
978 caseAtomicExpr::AO__hip_atomic_fetch_min:
979 caseAtomicExpr::AO__scoped_atomic_fetch_add:
980 caseAtomicExpr::AO__scoped_atomic_fetch_max:
981 caseAtomicExpr::AO__scoped_atomic_fetch_min:
982 caseAtomicExpr::AO__scoped_atomic_fetch_sub:
983 caseAtomicExpr::AO__scoped_atomic_add_fetch:
984 caseAtomicExpr::AO__scoped_atomic_max_fetch:
985 caseAtomicExpr::AO__scoped_atomic_min_fetch:
986 caseAtomicExpr::AO__scoped_atomic_sub_fetch:
990 caseAtomicExpr::AO__atomic_fetch_and:
991 caseAtomicExpr::AO__atomic_fetch_nand:
992 caseAtomicExpr::AO__atomic_fetch_or:
993 caseAtomicExpr::AO__atomic_fetch_xor:
994 caseAtomicExpr::AO__atomic_and_fetch:
995 caseAtomicExpr::AO__atomic_nand_fetch:
996 caseAtomicExpr::AO__atomic_or_fetch:
997 caseAtomicExpr::AO__atomic_xor_fetch:
998 caseAtomicExpr::AO__atomic_store_n:
999 caseAtomicExpr::AO__atomic_exchange_n:
1000 caseAtomicExpr::AO__c11_atomic_fetch_and:
1001 caseAtomicExpr::AO__c11_atomic_fetch_nand:
1002 caseAtomicExpr::AO__c11_atomic_fetch_or:
1003 caseAtomicExpr::AO__c11_atomic_fetch_xor:
1004 caseAtomicExpr::AO__c11_atomic_store:
1005 caseAtomicExpr::AO__c11_atomic_exchange:
1006 caseAtomicExpr::AO__hip_atomic_fetch_and:
1007 caseAtomicExpr::AO__hip_atomic_fetch_or:
1008 caseAtomicExpr::AO__hip_atomic_fetch_xor:
1009 caseAtomicExpr::AO__hip_atomic_store:
1010 caseAtomicExpr::AO__hip_atomic_exchange:
1011 caseAtomicExpr::AO__opencl_atomic_fetch_and:
1012 caseAtomicExpr::AO__opencl_atomic_fetch_or:
1013 caseAtomicExpr::AO__opencl_atomic_fetch_xor:
1014 caseAtomicExpr::AO__opencl_atomic_store:
1015 caseAtomicExpr::AO__opencl_atomic_exchange:
1016 caseAtomicExpr::AO__scoped_atomic_fetch_and:
1017 caseAtomicExpr::AO__scoped_atomic_fetch_nand:
1018 caseAtomicExpr::AO__scoped_atomic_fetch_or:
1019 caseAtomicExpr::AO__scoped_atomic_fetch_xor:
1020 caseAtomicExpr::AO__scoped_atomic_and_fetch:
1021 caseAtomicExpr::AO__scoped_atomic_nand_fetch:
1022 caseAtomicExpr::AO__scoped_atomic_or_fetch:
1023 caseAtomicExpr::AO__scoped_atomic_xor_fetch:
1024 caseAtomicExpr::AO__scoped_atomic_store_n:
1025 caseAtomicExpr::AO__scoped_atomic_exchange_n:
1036AtomicInfo Atomics(*
this, AtomicVal);
1038 if(ShouldCastToIntPtrTy) {
1039Ptr = Atomics.castToAtomicIntPointer(Ptr);
1041Val1 = Atomics.convertToAtomicIntPointer(Val1);
1043Val2 = Atomics.convertToAtomicIntPointer(Val2);
1046 if(ShouldCastToIntPtrTy)
1047Dest = Atomics.castToAtomicIntPointer(Dest);
1048}
else if(
E->isCmpXChg())
1051Dest = Atomics.CreateTempAlloca();
1052 if(ShouldCastToIntPtrTy)
1053Dest = Atomics.castToAtomicIntPointer(Dest);
1056 boolPowerOf2Size = (
Size& (
Size- 1)) == 0;
1057 boolUseLibcall = !PowerOf2Size || (
Size> 16);
1077 autoCastToGenericAddrSpace = [&](llvm::Value *
V,
QualTypePT) {
1078 if(!
E->isOpenCL())
1084 auto*DestType = llvm::PointerType::get(
getLLVMContext(), DestAS);
1095std::string LibCallName;
1097 boolHaveRetTy =
false;
1098 switch(
E->getOp()) {
1099 caseAtomicExpr::AO__c11_atomic_init:
1100 caseAtomicExpr::AO__opencl_atomic_init:
1101llvm_unreachable(
"Already handled!");
1108 caseAtomicExpr::AO__atomic_compare_exchange:
1109 caseAtomicExpr::AO__atomic_compare_exchange_n:
1110 caseAtomicExpr::AO__c11_atomic_compare_exchange_weak:
1111 caseAtomicExpr::AO__c11_atomic_compare_exchange_strong:
1112 caseAtomicExpr::AO__hip_atomic_compare_exchange_weak:
1113 caseAtomicExpr::AO__hip_atomic_compare_exchange_strong:
1114 caseAtomicExpr::AO__opencl_atomic_compare_exchange_weak:
1115 caseAtomicExpr::AO__opencl_atomic_compare_exchange_strong:
1116 caseAtomicExpr::AO__scoped_atomic_compare_exchange:
1117 caseAtomicExpr::AO__scoped_atomic_compare_exchange_n:
1118LibCallName =
"__atomic_compare_exchange";
1132 caseAtomicExpr::AO__atomic_exchange:
1133 caseAtomicExpr::AO__atomic_exchange_n:
1134 caseAtomicExpr::AO__c11_atomic_exchange:
1135 caseAtomicExpr::AO__hip_atomic_exchange:
1136 caseAtomicExpr::AO__opencl_atomic_exchange:
1137 caseAtomicExpr::AO__scoped_atomic_exchange:
1138 caseAtomicExpr::AO__scoped_atomic_exchange_n:
1139LibCallName =
"__atomic_exchange";
1145 caseAtomicExpr::AO__atomic_store:
1146 caseAtomicExpr::AO__atomic_store_n:
1147 caseAtomicExpr::AO__c11_atomic_store:
1148 caseAtomicExpr::AO__hip_atomic_store:
1149 caseAtomicExpr::AO__opencl_atomic_store:
1150 caseAtomicExpr::AO__scoped_atomic_store:
1151 caseAtomicExpr::AO__scoped_atomic_store_n:
1152LibCallName =
"__atomic_store";
1160 caseAtomicExpr::AO__atomic_load:
1161 caseAtomicExpr::AO__atomic_load_n:
1162 caseAtomicExpr::AO__c11_atomic_load:
1163 caseAtomicExpr::AO__hip_atomic_load:
1164 caseAtomicExpr::AO__opencl_atomic_load:
1165 caseAtomicExpr::AO__scoped_atomic_load:
1166 caseAtomicExpr::AO__scoped_atomic_load_n:
1167LibCallName =
"__atomic_load";
1169 caseAtomicExpr::AO__atomic_add_fetch:
1170 caseAtomicExpr::AO__scoped_atomic_add_fetch:
1171 caseAtomicExpr::AO__atomic_fetch_add:
1172 caseAtomicExpr::AO__c11_atomic_fetch_add:
1173 caseAtomicExpr::AO__hip_atomic_fetch_add:
1174 caseAtomicExpr::AO__opencl_atomic_fetch_add:
1175 caseAtomicExpr::AO__scoped_atomic_fetch_add:
1176 caseAtomicExpr::AO__atomic_and_fetch:
1177 caseAtomicExpr::AO__scoped_atomic_and_fetch:
1178 caseAtomicExpr::AO__atomic_fetch_and:
1179 caseAtomicExpr::AO__c11_atomic_fetch_and:
1180 caseAtomicExpr::AO__hip_atomic_fetch_and:
1181 caseAtomicExpr::AO__opencl_atomic_fetch_and:
1182 caseAtomicExpr::AO__scoped_atomic_fetch_and:
1183 caseAtomicExpr::AO__atomic_or_fetch:
1184 caseAtomicExpr::AO__scoped_atomic_or_fetch:
1185 caseAtomicExpr::AO__atomic_fetch_or:
1186 caseAtomicExpr::AO__c11_atomic_fetch_or:
1187 caseAtomicExpr::AO__hip_atomic_fetch_or:
1188 caseAtomicExpr::AO__opencl_atomic_fetch_or:
1189 caseAtomicExpr::AO__scoped_atomic_fetch_or:
1190 caseAtomicExpr::AO__atomic_sub_fetch:
1191 caseAtomicExpr::AO__scoped_atomic_sub_fetch:
1192 caseAtomicExpr::AO__atomic_fetch_sub:
1193 caseAtomicExpr::AO__c11_atomic_fetch_sub:
1194 caseAtomicExpr::AO__hip_atomic_fetch_sub:
1195 caseAtomicExpr::AO__opencl_atomic_fetch_sub:
1196 caseAtomicExpr::AO__scoped_atomic_fetch_sub:
1197 caseAtomicExpr::AO__atomic_xor_fetch:
1198 caseAtomicExpr::AO__scoped_atomic_xor_fetch:
1199 caseAtomicExpr::AO__atomic_fetch_xor:
1200 caseAtomicExpr::AO__c11_atomic_fetch_xor:
1201 caseAtomicExpr::AO__hip_atomic_fetch_xor:
1202 caseAtomicExpr::AO__opencl_atomic_fetch_xor:
1203 caseAtomicExpr::AO__scoped_atomic_fetch_xor:
1204 caseAtomicExpr::AO__atomic_nand_fetch:
1205 caseAtomicExpr::AO__atomic_fetch_nand:
1206 caseAtomicExpr::AO__c11_atomic_fetch_nand:
1207 caseAtomicExpr::AO__scoped_atomic_fetch_nand:
1208 caseAtomicExpr::AO__scoped_atomic_nand_fetch:
1209 caseAtomicExpr::AO__atomic_min_fetch:
1210 caseAtomicExpr::AO__atomic_fetch_min:
1211 caseAtomicExpr::AO__c11_atomic_fetch_min:
1212 caseAtomicExpr::AO__hip_atomic_fetch_min:
1213 caseAtomicExpr::AO__opencl_atomic_fetch_min:
1214 caseAtomicExpr::AO__scoped_atomic_fetch_min:
1215 caseAtomicExpr::AO__scoped_atomic_min_fetch:
1216 caseAtomicExpr::AO__atomic_max_fetch:
1217 caseAtomicExpr::AO__atomic_fetch_max:
1218 caseAtomicExpr::AO__c11_atomic_fetch_max:
1219 caseAtomicExpr::AO__hip_atomic_fetch_max:
1220 caseAtomicExpr::AO__opencl_atomic_fetch_max:
1221 caseAtomicExpr::AO__scoped_atomic_fetch_max:
1222 caseAtomicExpr::AO__scoped_atomic_max_fetch:
1223 caseAtomicExpr::AO__atomic_test_and_set:
1224 caseAtomicExpr::AO__atomic_clear:
1225llvm_unreachable(
"Integral atomic operations always become atomicrmw!");
1228 if(
E->isOpenCL()) {
1230std::string(
"__opencl") + StringRef(LibCallName).drop_front(1).str();
1243 if(
E->isOpenCL())
1248 if(
E->isCmpXChg())
1258 boolIsStore =
E->getOp() == AtomicExpr::AO__c11_atomic_store ||
1259 E->getOp() == AtomicExpr::AO__opencl_atomic_store ||
1260 E->getOp() == AtomicExpr::AO__hip_atomic_store ||
1261 E->getOp() == AtomicExpr::AO__atomic_store ||
1262 E->getOp() == AtomicExpr::AO__atomic_store_n ||
1263 E->getOp() == AtomicExpr::AO__scoped_atomic_store ||
1264 E->getOp() == AtomicExpr::AO__scoped_atomic_store_n ||
1265 E->getOp() == AtomicExpr::AO__atomic_clear;
1266 boolIsLoad =
E->getOp() == AtomicExpr::AO__c11_atomic_load ||
1267 E->getOp() == AtomicExpr::AO__opencl_atomic_load ||
1268 E->getOp() == AtomicExpr::AO__hip_atomic_load ||
1269 E->getOp() == AtomicExpr::AO__atomic_load ||
1270 E->getOp() == AtomicExpr::AO__atomic_load_n ||
1271 E->getOp() == AtomicExpr::AO__scoped_atomic_load ||
1272 E->getOp() == AtomicExpr::AO__scoped_atomic_load_n;
1274 if(isa<llvm::ConstantInt>(Order)) {
1275 autoord = cast<llvm::ConstantInt>(Order)->getZExtValue();
1278 if(llvm::isValidAtomicOrderingCABI(ord))
1279 switch((llvm::AtomicOrderingCABI)ord) {
1280 casellvm::AtomicOrderingCABI::relaxed:
1281 EmitAtomicOp(*
this,
E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1282llvm::AtomicOrdering::Monotonic,
Scope);
1284 casellvm::AtomicOrderingCABI::consume:
1285 casellvm::AtomicOrderingCABI::acquire:
1288 EmitAtomicOp(*
this,
E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1289llvm::AtomicOrdering::Acquire,
Scope);
1291 casellvm::AtomicOrderingCABI::release:
1294 EmitAtomicOp(*
this,
E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1295llvm::AtomicOrdering::Release,
Scope);
1297 casellvm::AtomicOrderingCABI::acq_rel:
1298 if(IsLoad || IsStore)
1300 EmitAtomicOp(*
this,
E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1301llvm::AtomicOrdering::AcquireRelease,
Scope);
1303 casellvm::AtomicOrderingCABI::seq_cst:
1304 EmitAtomicOp(*
this,
E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1305llvm::AtomicOrdering::SequentiallyConsistent,
Scope);
1318llvm::BasicBlock *MonotonicBB =
nullptr, *AcquireBB =
nullptr,
1319*ReleaseBB =
nullptr, *AcqRelBB =
nullptr,
1320*SeqCstBB =
nullptr;
1326 if(!IsLoad && !IsStore)
1335Order =
Builder.CreateIntCast(Order,
Builder.getInt32Ty(),
false);
1336llvm::SwitchInst *SI =
Builder.CreateSwitch(Order, MonotonicBB);
1339 Builder.SetInsertPoint(MonotonicBB);
1340 EmitAtomicOp(*
this,
E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1341llvm::AtomicOrdering::Monotonic,
Scope);
1344 Builder.SetInsertPoint(AcquireBB);
1345 EmitAtomicOp(*
this,
E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1346llvm::AtomicOrdering::Acquire,
Scope);
1348SI->addCase(
Builder.getInt32((
int)llvm::AtomicOrderingCABI::consume),
1350SI->addCase(
Builder.getInt32((
int)llvm::AtomicOrderingCABI::acquire),
1354 Builder.SetInsertPoint(ReleaseBB);
1355 EmitAtomicOp(*
this,
E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1356llvm::AtomicOrdering::Release,
Scope);
1358SI->addCase(
Builder.getInt32((
int)llvm::AtomicOrderingCABI::release),
1361 if(!IsLoad && !IsStore) {
1362 Builder.SetInsertPoint(AcqRelBB);
1363 EmitAtomicOp(*
this,
E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1364llvm::AtomicOrdering::AcquireRelease,
Scope);
1366SI->addCase(
Builder.getInt32((
int)llvm::AtomicOrderingCABI::acq_rel),
1369 Builder.SetInsertPoint(SeqCstBB);
1370 EmitAtomicOp(*
this,
E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1371llvm::AtomicOrdering::SequentiallyConsistent,
Scope);
1373SI->addCase(
Builder.getInt32((
int)llvm::AtomicOrderingCABI::seq_cst),
1377 Builder.SetInsertPoint(ContBB);
1381assert(Atomics.getValueSizeInBits() <= Atomics.getAtomicSizeInBits());
1387llvm::IntegerType *ty =
1388llvm::IntegerType::get(CGF.
getLLVMContext(), AtomicSizeInBits);
1392AddressAtomicInfo::convertToAtomicIntPointer(
AddressAddr)
const{
1395 if(SourceSizeInBits != AtomicSizeInBits) {
1396 AddressTmp = CreateTempAlloca();
1398std::min(AtomicSizeInBits, SourceSizeInBits) / 8);
1402 returncastToAtomicIntPointer(Addr);
1408 boolasValue)
const{
1444 if(ValTy->isFloatingPointTy())
1445 returnValTy->isX86_FP80Ty() || CmpXchg;
1446 return!ValTy->isIntegerTy() && !ValTy->isPointerTy();
1449RValueAtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val,
1452 boolCmpXchg)
const{
1454assert((Val->getType()->isIntegerTy() || Val->getType()->isPointerTy() ||
1455Val->getType()->isIEEELikeFPTy()) &&
1456 "Expected integer, pointer or floating point value when converting " 1463 auto*ValTy = AsValue
1465: getAtomicAddress().getElementType();
1467assert((!ValTy->isIntegerTy() || Val->getType() == ValTy) &&
1468 "Different integer types.");
1471 if(llvm::CastInst::isBitCastable(Val->getType(), ValTy))
1478 boolTempIsVolatile =
false;
1484Temp = CreateTempAlloca();
1488 AddressCastTemp = castToAtomicIntPointer(Temp);
1491 returnconvertAtomicTempToRValue(Temp, ResultSlot,
Loc, AsValue);
1494voidAtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
1495llvm::AtomicOrdering AO,
bool) {
1502 RValue::get(llvm::ConstantInt::get(CGF.
IntTy, (
int)llvm::toCABI(AO))),
1507llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,
1508 boolIsVolatile,
boolCmpXchg) {
1510 AddressAddr = getAtomicAddress();
1512Addr = castToAtomicIntPointer(Addr);
1514 Load->setAtomic(AO);
1518 Load->setVolatile(
true);
1528AtomicInfo AI(*
this, LV);
1531 boolAtomicIsInline = !AI.shouldUseLibcall();
1536 returnIsVolatile && AtomicIsInline;
1541llvm::AtomicOrdering AO;
1544AO = llvm::AtomicOrdering::SequentiallyConsistent;
1546AO = llvm::AtomicOrdering::Acquire;
1553 boolAsValue, llvm::AtomicOrdering AO,
1556 if(shouldUseLibcall()) {
1562TempAddr = CreateTempAlloca();
1564EmitAtomicLoadLibcall(TempAddr.
emitRawPointer(CGF), AO, IsVolatile);
1568 returnconvertAtomicTempToRValue(TempAddr, ResultSlot,
Loc, AsValue);
1572 auto*
Load= EmitAtomicLoadOp(AO, IsVolatile);
1580 returnConvertToValueOrAtomic(Load, ResultSlot,
Loc, AsValue);
1586llvm::AtomicOrdering AO,
boolIsVolatile,
1588AtomicInfo Atomics(*
this, src);
1589 returnAtomics.EmitAtomicLoad(resultSlot, loc,
true, AO,
1595voidAtomicInfo::emitCopyIntoMemory(
RValuervalue)
const{
1614emitMemSetZeroIfNecessary();
1617 LValueTempLVal = projectValue();
1630AddressAtomicInfo::materializeRValue(
RValuervalue)
const{
1638AtomicInfo Atomics(CGF, TempLV);
1639Atomics.emitCopyIntoMemory(rvalue);
1643llvm::Value *AtomicInfo::getScalarRValValueOrNull(
RValueRVal)
const{
1649llvm::Value *AtomicInfo::convertRValueToInt(
RValueRVal,
boolCmpXchg)
const{
1652 if(llvm::Value *
Value= getScalarRValValueOrNull(RVal)) {
1656llvm::IntegerType *InputIntTy = llvm::IntegerType::get(
1658LVal.
isSimple() ? getValueSizeInBits() : getAtomicSizeInBits());
1659 if(llvm::BitCastInst::isBitCastable(
Value->
getType(), InputIntTy))
1660 returnCGF.
Builder.CreateBitCast(
Value, InputIntTy);
1665 AddressAddr = materializeRValue(RVal);
1668Addr = castToAtomicIntPointer(Addr);
1672std::pair<llvm::Value *, llvm::Value *> AtomicInfo::EmitAtomicCompareExchangeOp(
1673llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
1674llvm::AtomicOrdering
Success, llvm::AtomicOrdering Failure,
boolIsWeak) {
1676 AddressAddr = getAtomicAddressAsAtomicIntPointer();
1681Inst->setWeak(IsWeak);
1684 auto*PreviousVal = CGF.
Builder.CreateExtractValue(Inst,
0);
1685 auto*SuccessFailureVal = CGF.
Builder.CreateExtractValue(Inst,
1);
1686 returnstd::make_pair(PreviousVal, SuccessFailureVal);
1690AtomicInfo::EmitAtomicCompareExchangeLibcall(llvm::Value *ExpectedAddr,
1691llvm::Value *DesiredAddr,
1692llvm::AtomicOrdering
Success,
1693llvm::AtomicOrdering Failure) {
1702llvm::ConstantInt::get(CGF.
IntTy, (
int)llvm::toCABI(
Success))),
1705llvm::ConstantInt::get(CGF.
IntTy, (
int)llvm::toCABI(Failure))),
1710 returnSuccessFailureRVal.getScalarVal();
1713std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
1715llvm::AtomicOrdering Failure,
boolIsWeak) {
1717 if(shouldUseLibcall()) {
1721llvm::Value *DesiredPtr = materializeRValue(Desired).emitRawPointer(CGF);
1722 auto*Res = EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr,
1724 returnstd::make_pair(
1732 auto*ExpectedVal = convertRValueToInt(
Expected,
true);
1733 auto*DesiredVal = convertRValueToInt(Desired,
true);
1734 autoRes = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal,
Success,
1736 returnstd::make_pair(
1745 constllvm::function_ref<
RValue(
RValue)> &UpdateOp,
1748 LValueAtomicLVal = Atomics.getAtomicLValue();
1755 AddressPtr = Atomics.materializeRValue(OldRVal);
1788 RValueNewRVal = UpdateOp(UpRVal);
1798voidAtomicInfo::EmitAtomicUpdateLibcall(
1799llvm::AtomicOrdering AO,
constllvm::function_ref<
RValue(
RValue)> &UpdateOp,
1801 autoFailure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
1803 AddressExpectedAddr = CreateTempAlloca();
1805EmitAtomicLoadLibcall(ExpectedAddr.
emitRawPointer(CGF), AO, IsVolatile);
1809 AddressDesiredAddr = CreateTempAlloca();
1811requiresMemSetZero(getAtomicAddress().getElementType())) {
1815 autoOldRVal = convertAtomicTempToRValue(ExpectedAddr,
1822EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure);
1823CGF.
Builder.CreateCondBr(Res, ExitBB, ContBB);
1827voidAtomicInfo::EmitAtomicUpdateOp(
1828llvm::AtomicOrdering AO,
constllvm::function_ref<
RValue(
RValue)> &UpdateOp,
1830 autoFailure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
1833 auto*OldVal = EmitAtomicLoadOp(Failure, IsVolatile,
true);
1837 auto*CurBB = CGF.
Builder.GetInsertBlock();
1839llvm::PHINode *PHI = CGF.
Builder.CreatePHI(OldVal->getType(),
1841PHI->addIncoming(OldVal, CurBB);
1842 AddressNewAtomicAddr = CreateTempAlloca();
1845? castToAtomicIntPointer(NewAtomicAddr)
1849requiresMemSetZero(getAtomicAddress().getElementType())) {
1858 autoRes = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure);
1859PHI->addIncoming(Res.
first, CGF.
Builder.GetInsertBlock());
1866 LValueAtomicLVal = Atomics.getAtomicLValue();
1890voidAtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,
1891 RValueUpdateRVal,
boolIsVolatile) {
1892 autoFailure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
1894 AddressExpectedAddr = CreateTempAlloca();
1896EmitAtomicLoadLibcall(ExpectedAddr.
emitRawPointer(CGF), AO, IsVolatile);
1900 AddressDesiredAddr = CreateTempAlloca();
1902requiresMemSetZero(getAtomicAddress().getElementType())) {
1910EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure);
1911CGF.
Builder.CreateCondBr(Res, ExitBB, ContBB);
1915voidAtomicInfo::EmitAtomicUpdateOp(llvm::AtomicOrdering AO,
RValueUpdateRVal,
1917 autoFailure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
1920 auto*OldVal = EmitAtomicLoadOp(Failure, IsVolatile,
true);
1924 auto*CurBB = CGF.
Builder.GetInsertBlock();
1926llvm::PHINode *PHI = CGF.
Builder.CreatePHI(OldVal->getType(),
1928PHI->addIncoming(OldVal, CurBB);
1929 AddressNewAtomicAddr = CreateTempAlloca();
1930 AddressNewAtomicIntAddr = castToAtomicIntPointer(NewAtomicAddr);
1932requiresMemSetZero(getAtomicAddress().getElementType())) {
1938 autoRes = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure);
1939PHI->addIncoming(Res.
first, CGF.
Builder.GetInsertBlock());
1944voidAtomicInfo::EmitAtomicUpdate(
1945llvm::AtomicOrdering AO,
constllvm::function_ref<
RValue(
RValue)> &UpdateOp,
1947 if(shouldUseLibcall()) {
1948EmitAtomicUpdateLibcall(AO, UpdateOp, IsVolatile);
1950EmitAtomicUpdateOp(AO, UpdateOp, IsVolatile);
1954voidAtomicInfo::EmitAtomicUpdate(llvm::AtomicOrdering AO,
RValueUpdateRVal,
1956 if(shouldUseLibcall()) {
1957EmitAtomicUpdateLibcall(AO, UpdateRVal, IsVolatile);
1959EmitAtomicUpdateOp(AO, UpdateRVal, IsVolatile);
1966llvm::AtomicOrdering AO;
1968AO = llvm::AtomicOrdering::SequentiallyConsistent;
1970AO = llvm::AtomicOrdering::Release;
1982llvm::AtomicOrdering AO,
boolIsVolatile,
1990AtomicInfo atomics(*
this, dest);
1991 LValueLVal = atomics.getAtomicLValue();
1996atomics.emitCopyIntoMemory(rvalue);
2001 if(atomics.shouldUseLibcall()) {
2003 AddresssrcAddr = atomics.materializeRValue(rvalue);
2020llvm::Value *ValToStore = atomics.convertRValueToInt(rvalue);
2023 AddressAddr = atomics.getAtomicAddress();
2024 if(llvm::Value *
Value= atomics.getScalarRValValueOrNull(rvalue))
2026Addr = atomics.castToAtomicIntPointer(Addr);
2032 if(AO == llvm::AtomicOrdering::Acquire)
2033AO = llvm::AtomicOrdering::Monotonic;
2034 else if(AO == llvm::AtomicOrdering::AcquireRelease)
2035AO = llvm::AtomicOrdering::Release;
2038store->setAtomic(AO);
2042store->setVolatile(
true);
2048atomics.EmitAtomicUpdate(AO, rvalue, IsVolatile);
2055llvm::AtomicOrdering
Success, llvm::AtomicOrdering Failure,
boolIsWeak,
2059assert(!
Expected.isAggregate() ||
2060 Expected.getAggregateAddress().getElementType() ==
2065AtomicInfo Atomics(*
this, Obj);
2067 returnAtomics.EmitAtomicCompareExchange(
Expected, Desired,
Success, Failure,
2071llvm::AtomicRMWInst *
2073llvm::Value *Val, llvm::AtomicOrdering Order,
2074llvm::SyncScope::ID SSID,
2076llvm::AtomicRMWInst *RMW =
2083 LValueLVal, llvm::AtomicOrdering AO,
2084 constllvm::function_ref<
RValue(
RValue)> &UpdateOp,
boolIsVolatile) {
2085AtomicInfo Atomics(*
this, LVal);
2086Atomics.EmitAtomicUpdate(AO, UpdateOp, IsVolatile);
2090AtomicInfo atomics(*
this, dest);
2092 switch(atomics.getEvaluationKind()) {
2108 boolZeroed =
false;
2110Zeroed = atomics.emitMemSetZeroIfNecessary();
2111dest = atomics.projectValue();
2125llvm_unreachable(
"bad evaluation kind");
Defines the clang::ASTContext interface.
static bool isFullSizeType(CodeGenModule &CGM, llvm::Type *type, uint64_t expectedSize)
Does a store of the given IR type modify the full expected width?
static llvm::Value * EmitPostAtomicMinMax(CGBuilderTy &Builder, AtomicExpr::AtomicOp Op, bool IsSigned, llvm::Value *OldVal, llvm::Value *RHS)
Duplicate the atomic min/max operation in conventional IR for the builtin variants that return the ne...
static void EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, RValue OldRVal, const llvm::function_ref< RValue(RValue)> &UpdateOp, Address DesiredAddr)
static Address EmitValToTemp(CodeGenFunction &CGF, Expr *E)
static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, Address Ptr, Address Val1, Address Val2, llvm::Value *IsWeak, llvm::Value *FailureOrder, uint64_t Size, llvm::AtomicOrdering Order, llvm::SyncScope::ID Scope)
static RValue emitAtomicLibcall(CodeGenFunction &CGF, StringRef fnName, QualType resultType, CallArgList &args)
static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak, Address Dest, Address Ptr, Address Val1, Address Val2, llvm::Value *FailureOrderVal, uint64_t Size, llvm::AtomicOrdering SuccessOrder, llvm::SyncScope::ID Scope)
Given an ordering required on success, emit all possible cmpxchg instructions to cope with the provid...
static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak, Address Dest, Address Ptr, Address Val1, Address Val2, uint64_t Size, llvm::AtomicOrdering SuccessOrder, llvm::AtomicOrdering FailureOrder, llvm::SyncScope::ID Scope)
static bool shouldCastToInt(llvm::Type *ValTy, bool CmpXchg)
Return true if.
CodeGenFunction::ComplexPairTy ComplexPairTy
static QualType getPointeeType(const MemRegion *R)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
TypeInfoChars getTypeInfoInChars(const Type *T) const
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
unsigned getTargetAddressSpace(LangAS AS) const
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
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.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
static AggValueSlot ignored()
ignored - Returns an aggregate value slot indicating that the aggregate value is being ignored.
Address getAddress() const
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
llvm::AtomicRMWInst * CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Ordering, llvm::SyncScope::ID SSID=llvm::SyncScope::System)
llvm::CallInst * CreateMemSet(Address Dest, llvm::Value *Value, llvm::Value *Size, bool IsVolatile=false)
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
llvm::AtomicCmpXchgInst * CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New, llvm::AtomicOrdering SuccessOrdering, llvm::AtomicOrdering FailureOrdering, llvm::SyncScope::ID SSID=llvm::SyncScope::System)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
CGFunctionInfo - Class to encapsulate the information about a function definition.
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
std::pair< RValue, llvm::Value * > EmitAtomicCompareExchange(LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc, llvm::AtomicOrdering Success=llvm::AtomicOrdering::SequentiallyConsistent, llvm::AtomicOrdering Failure=llvm::AtomicOrdering::SequentiallyConsistent, bool IsWeak=false, AggValueSlot Slot=AggValueSlot::ignored())
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
bool hasVolatileMember(QualType T)
hasVolatileMember - returns true if aggregate type has a volatile member.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO, const llvm::function_ref< RValue(RValue)> &UpdateOp, bool IsVolatile)
const LangOptions & getLangOpts() const
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
ComplexPairTy EmitComplexExpr(const Expr *E, bool IgnoreReal=false, bool IgnoreImag=false)
EmitComplexExpr - Emit the computation of the specified expression of complex type,...
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
RValue convertTempToRValue(Address addr, QualType type, SourceLocation Loc)
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
llvm::Type * ConvertTypeForMem(QualType T)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitAtomicInit(Expr *E, LValue lvalue)
const TargetInfo & getTarget() const
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
RValue EmitLoadOfExtVectorElementLValue(LValue V)
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
const TargetCodeGenInfo & getTargetHooks() const
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
llvm::Value * EmitToMemory(llvm::Value *Value, QualType Ty)
EmitToMemory - Change a scalar value from its value representation to its in-memory representation.
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
ASTContext & getContext() const
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::AtomicRMWInst * emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Order=llvm::AtomicOrdering::SequentiallyConsistent, llvm::SyncScope::ID SSID=llvm::SyncScope::System, const AtomicExpr *AE=nullptr)
Emit an atomicrmw instruction, and applying relevant metadata when applicable.
llvm::LLVMContext & getLLVMContext()
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
bool LValueIsSuitableForInlineAtomic(LValue Src)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
RValue EmitLoadOfBitfieldLValue(LValue LV, SourceLocation Loc)
This class organizes the cross-function state that is used while generating LLVM code.
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
void DecorateInstructionWithTBAA(llvm::Instruction *Inst, TBAAAccessInfo TBAAInfo)
DecorateInstructionWithTBAA - Decorate the instruction with a TBAA tag.
llvm::LLVMContext & getLLVMContext()
llvm::ConstantInt * getSize(CharUnits numChars)
Emit the given number of characters as a value of type size_t.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionCall(QualType resultType, const CallArgList &args)
LValue - This represents an lvalue references.
llvm::Value * getRawExtVectorPointer(CodeGenFunction &CGF) const
llvm::Constant * getExtVectorElts() const
void setAlignment(CharUnits A)
bool isVolatileQualified() const
llvm::Value * getRawBitFieldPointer(CodeGenFunction &CGF) const
CharUnits getAlignment() const
static LValue MakeExtVectorElt(Address Addr, llvm::Constant *Elts, QualType type, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo)
Address getAddress() const
llvm::Value * getRawVectorPointer(CodeGenFunction &CGF) const
bool isExtVectorElt() const
llvm::Value * getVectorIdx() const
LValueBaseInfo getBaseInfo() const
const CGBitFieldInfo & getBitFieldInfo() const
TBAAAccessInfo getTBAAInfo() const
Address getVectorAddress() const
static LValue MakeBitfield(Address Addr, const CGBitFieldInfo &Info, QualType type, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo)
Create a new object to represent a bit-field access.
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx, QualType type, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo)
Address getExtVectorAddress() const
Address getBitFieldAddress() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
bool isVolatileQualified() const
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, LangAS SrcAddr, LangAS DestAddr, llvm::Type *DestTy, bool IsNonNull=false) const
virtual llvm::SyncScope::ID getLLVMSyncScopeID(const LangOptions &LangOpts, SyncScope Scope, llvm::AtomicOrdering Ordering, llvm::LLVMContext &Ctx) const
Get the syncscope used in LLVM IR.
virtual void setTargetAtomicMetadata(CodeGenFunction &CGF, llvm::Instruction &AtomicInst, const AtomicExpr *Expr=nullptr) const
Allow the target to apply other metadata to an atomic instruction.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
LangAS getAddressSpace() const
Return the address space of this 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.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
SourceLocation getBeginLoc() const LLVM_READONLY
unsigned getMaxAtomicInlineWidth() const
Return the maximum width lock-free atomic operation which can be inlined given the supported features...
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
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>'.
Represents a GCC generic vector type.
TypeEvaluationKind
The kind of evaluation to perform on values of a particular type.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
bool Load(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
llvm::StringRef getAsString(SyncScope S)
@ Success
Template argument deduction was successful.
Structure with information about how a bitfield should be accessed.
CharUnits StorageOffset
The offset of the bitfield storage from the start of the struct.
unsigned Offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the L...
unsigned Size
The total size of the bit-field, in bits.
unsigned StorageSize
The storage size in bits which should be used when accessing this bitfield.
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * SizeTy
llvm::IntegerType * IntTy
int
llvm::PointerType * UnqualPtrTy
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4