@@ -5099,6 +5099,147 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
50995099 ReturnValueSlot(), Args);
51005100 }
51015101
5102+ case Builtin::BI__atomic_test_and_set: {
5103+ // Look at the argument type to determine whether this is a volatile
5104+ // operation. The parameter type is always volatile.
5105+ QualType PtrTy = E->getArg(0)->IgnoreImpCasts()->getType();
5106+ bool Volatile =
5107+ PtrTy->castAs<PointerType>()->getPointeeType().isVolatileQualified();
5108+
5109+ Address Ptr =
5110+ EmitPointerWithAlignment(E->getArg(0)).withElementType(Int8Ty);
5111+
5112+ Value *NewVal = Builder.getInt8(1);
5113+ Value *Order = EmitScalarExpr(E->getArg(1));
5114+ if (isa<llvm::ConstantInt>(Order)) {
5115+ int ord = cast<llvm::ConstantInt>(Order)->getZExtValue();
5116+ AtomicRMWInst *Result = nullptr;
5117+ switch (ord) {
5118+ case 0: // memory_order_relaxed
5119+ default: // invalid order
5120+ Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, Ptr, NewVal,
5121+ llvm::AtomicOrdering::Monotonic);
5122+ break;
5123+ case 1: // memory_order_consume
5124+ case 2: // memory_order_acquire
5125+ Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, Ptr, NewVal,
5126+ llvm::AtomicOrdering::Acquire);
5127+ break;
5128+ case 3: // memory_order_release
5129+ Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, Ptr, NewVal,
5130+ llvm::AtomicOrdering::Release);
5131+ break;
5132+ case 4: // memory_order_acq_rel
5133+
5134+ Result = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg, Ptr, NewVal,
5135+ llvm::AtomicOrdering::AcquireRelease);
5136+ break;
5137+ case 5: // memory_order_seq_cst
5138+ Result = Builder.CreateAtomicRMW(
5139+ llvm::AtomicRMWInst::Xchg, Ptr, NewVal,
5140+ llvm::AtomicOrdering::SequentiallyConsistent);
5141+ break;
5142+ }
5143+ Result->setVolatile(Volatile);
5144+ return RValue::get(Builder.CreateIsNotNull(Result, "tobool"));
5145+ }
5146+
5147+ llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn);
5148+
5149+ llvm::BasicBlock *BBs[5] = {
5150+ createBasicBlock("monotonic", CurFn),
5151+ createBasicBlock("acquire", CurFn),
5152+ createBasicBlock("release", CurFn),
5153+ createBasicBlock("acqrel", CurFn),
5154+ createBasicBlock("seqcst", CurFn)
5155+ };
5156+ llvm::AtomicOrdering Orders[5] = {
5157+ llvm::AtomicOrdering::Monotonic, llvm::AtomicOrdering::Acquire,
5158+ llvm::AtomicOrdering::Release, llvm::AtomicOrdering::AcquireRelease,
5159+ llvm::AtomicOrdering::SequentiallyConsistent};
5160+
5161+ Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false);
5162+ llvm::SwitchInst *SI = Builder.CreateSwitch(Order, BBs[0]);
5163+
5164+ Builder.SetInsertPoint(ContBB);
5165+ PHINode *Result = Builder.CreatePHI(Int8Ty, 5, "was_set");
5166+
5167+ for (unsigned i = 0; i < 5; ++i) {
5168+ Builder.SetInsertPoint(BBs[i]);
5169+ AtomicRMWInst *RMW = Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg,
5170+ Ptr, NewVal, Orders[i]);
5171+ RMW->setVolatile(Volatile);
5172+ Result->addIncoming(RMW, BBs[i]);
5173+ Builder.CreateBr(ContBB);
5174+ }
5175+
5176+ SI->addCase(Builder.getInt32(0), BBs[0]);
5177+ SI->addCase(Builder.getInt32(1), BBs[1]);
5178+ SI->addCase(Builder.getInt32(2), BBs[1]);
5179+ SI->addCase(Builder.getInt32(3), BBs[2]);
5180+ SI->addCase(Builder.getInt32(4), BBs[3]);
5181+ SI->addCase(Builder.getInt32(5), BBs[4]);
5182+
5183+ Builder.SetInsertPoint(ContBB);
5184+ return RValue::get(Builder.CreateIsNotNull(Result, "tobool"));
5185+ }
5186+
5187+ case Builtin::BI__atomic_clear: {
5188+ QualType PtrTy = E->getArg(0)->IgnoreImpCasts()->getType();
5189+ bool Volatile =
5190+ PtrTy->castAs<PointerType>()->getPointeeType().isVolatileQualified();
5191+
5192+ Address Ptr = EmitPointerWithAlignment(E->getArg(0));
5193+ Ptr = Ptr.withElementType(Int8Ty);
5194+ Value *NewVal = Builder.getInt8(0);
5195+ Value *Order = EmitScalarExpr(E->getArg(1));
5196+ if (isa<llvm::ConstantInt>(Order)) {
5197+ int ord = cast<llvm::ConstantInt>(Order)->getZExtValue();
5198+ StoreInst *Store = Builder.CreateStore(NewVal, Ptr, Volatile);
5199+ switch (ord) {
5200+ case 0: // memory_order_relaxed
5201+ default: // invalid order
5202+ Store->setOrdering(llvm::AtomicOrdering::Monotonic);
5203+ break;
5204+ case 3: // memory_order_release
5205+ Store->setOrdering(llvm::AtomicOrdering::Release);
5206+ break;
5207+ case 5: // memory_order_seq_cst
5208+ Store->setOrdering(llvm::AtomicOrdering::SequentiallyConsistent);
5209+ break;
5210+ }
5211+ return RValue::get(nullptr);
5212+ }
5213+
5214+ llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn);
5215+
5216+ llvm::BasicBlock *BBs[3] = {
5217+ createBasicBlock("monotonic", CurFn),
5218+ createBasicBlock("release", CurFn),
5219+ createBasicBlock("seqcst", CurFn)
5220+ };
5221+ llvm::AtomicOrdering Orders[3] = {
5222+ llvm::AtomicOrdering::Monotonic, llvm::AtomicOrdering::Release,
5223+ llvm::AtomicOrdering::SequentiallyConsistent};
5224+
5225+ Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false);
5226+ llvm::SwitchInst *SI = Builder.CreateSwitch(Order, BBs[0]);
5227+
5228+ for (unsigned i = 0; i < 3; ++i) {
5229+ Builder.SetInsertPoint(BBs[i]);
5230+ StoreInst *Store = Builder.CreateStore(NewVal, Ptr, Volatile);
5231+ Store->setOrdering(Orders[i]);
5232+ Builder.CreateBr(ContBB);
5233+ }
5234+
5235+ SI->addCase(Builder.getInt32(0), BBs[0]);
5236+ SI->addCase(Builder.getInt32(3), BBs[1]);
5237+ SI->addCase(Builder.getInt32(5), BBs[2]);
5238+
5239+ Builder.SetInsertPoint(ContBB);
5240+ return RValue::get(nullptr);
5241+ }
5242+
51025243 case Builtin::BI__atomic_thread_fence:
51035244 case Builtin::BI__atomic_signal_fence:
51045245 case Builtin::BI__c11_atomic_thread_fence:
0 commit comments