clang API Documentation
00001 //===--- CGAtomic.cpp - Emit LLVM IR for atomic operations ----------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains the code for emitting atomic operations. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "CodeGenFunction.h" 00015 #include "CGCall.h" 00016 #include "CodeGenModule.h" 00017 #include "clang/AST/ASTContext.h" 00018 #include "clang/CodeGen/CGFunctionInfo.h" 00019 #include "llvm/ADT/StringExtras.h" 00020 #include "llvm/IR/DataLayout.h" 00021 #include "llvm/IR/Intrinsics.h" 00022 #include "llvm/IR/Operator.h" 00023 00024 using namespace clang; 00025 using namespace CodeGen; 00026 00027 namespace { 00028 class AtomicInfo { 00029 CodeGenFunction &CGF; 00030 QualType AtomicTy; 00031 QualType ValueTy; 00032 uint64_t AtomicSizeInBits; 00033 uint64_t ValueSizeInBits; 00034 CharUnits AtomicAlign; 00035 CharUnits ValueAlign; 00036 CharUnits LValueAlign; 00037 TypeEvaluationKind EvaluationKind; 00038 bool UseLibcall; 00039 public: 00040 AtomicInfo(CodeGenFunction &CGF, LValue &lvalue) : CGF(CGF) { 00041 assert(lvalue.isSimple()); 00042 00043 AtomicTy = lvalue.getType(); 00044 ValueTy = AtomicTy->castAs<AtomicType>()->getValueType(); 00045 EvaluationKind = CGF.getEvaluationKind(ValueTy); 00046 00047 ASTContext &C = CGF.getContext(); 00048 00049 uint64_t ValueAlignInBits; 00050 uint64_t AtomicAlignInBits; 00051 TypeInfo ValueTI = C.getTypeInfo(ValueTy); 00052 ValueSizeInBits = ValueTI.Width; 00053 ValueAlignInBits = ValueTI.Align; 00054 00055 TypeInfo AtomicTI = C.getTypeInfo(AtomicTy); 00056 AtomicSizeInBits = AtomicTI.Width; 00057 AtomicAlignInBits = AtomicTI.Align; 00058 00059 assert(ValueSizeInBits <= AtomicSizeInBits); 00060 assert(ValueAlignInBits <= AtomicAlignInBits); 00061 00062 AtomicAlign = C.toCharUnitsFromBits(AtomicAlignInBits); 00063 ValueAlign = C.toCharUnitsFromBits(ValueAlignInBits); 00064 if (lvalue.getAlignment().isZero()) 00065 lvalue.setAlignment(AtomicAlign); 00066 00067 UseLibcall = 00068 (AtomicSizeInBits > uint64_t(C.toBits(lvalue.getAlignment())) || 00069 AtomicSizeInBits > C.getTargetInfo().getMaxAtomicInlineWidth()); 00070 } 00071 00072 QualType getAtomicType() const { return AtomicTy; } 00073 QualType getValueType() const { return ValueTy; } 00074 CharUnits getAtomicAlignment() const { return AtomicAlign; } 00075 CharUnits getValueAlignment() const { return ValueAlign; } 00076 uint64_t getAtomicSizeInBits() const { return AtomicSizeInBits; } 00077 uint64_t getValueSizeInBits() const { return AtomicSizeInBits; } 00078 TypeEvaluationKind getEvaluationKind() const { return EvaluationKind; } 00079 bool shouldUseLibcall() const { return UseLibcall; } 00080 00081 /// Is the atomic size larger than the underlying value type? 00082 /// 00083 /// Note that the absence of padding does not mean that atomic 00084 /// objects are completely interchangeable with non-atomic 00085 /// objects: we might have promoted the alignment of a type 00086 /// without making it bigger. 00087 bool hasPadding() const { 00088 return (ValueSizeInBits != AtomicSizeInBits); 00089 } 00090 00091 bool emitMemSetZeroIfNecessary(LValue dest) const; 00092 00093 llvm::Value *getAtomicSizeValue() const { 00094 CharUnits size = CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits); 00095 return CGF.CGM.getSize(size); 00096 } 00097 00098 /// Cast the given pointer to an integer pointer suitable for 00099 /// atomic operations. 00100 llvm::Value *emitCastToAtomicIntPointer(llvm::Value *addr) const; 00101 00102 /// Turn an atomic-layout object into an r-value. 00103 RValue convertTempToRValue(llvm::Value *addr, 00104 AggValueSlot resultSlot, 00105 SourceLocation loc) const; 00106 00107 /// Copy an atomic r-value into atomic-layout memory. 00108 void emitCopyIntoMemory(RValue rvalue, LValue lvalue) const; 00109 00110 /// Project an l-value down to the value field. 00111 LValue projectValue(LValue lvalue) const { 00112 llvm::Value *addr = lvalue.getAddress(); 00113 if (hasPadding()) 00114 addr = CGF.Builder.CreateStructGEP(addr, 0); 00115 00116 return LValue::MakeAddr(addr, getValueType(), lvalue.getAlignment(), 00117 CGF.getContext(), lvalue.getTBAAInfo()); 00118 } 00119 00120 /// Materialize an atomic r-value in atomic-layout memory. 00121 llvm::Value *materializeRValue(RValue rvalue) const; 00122 00123 private: 00124 bool requiresMemSetZero(llvm::Type *type) const; 00125 }; 00126 } 00127 00128 static RValue emitAtomicLibcall(CodeGenFunction &CGF, 00129 StringRef fnName, 00130 QualType resultType, 00131 CallArgList &args) { 00132 const CGFunctionInfo &fnInfo = 00133 CGF.CGM.getTypes().arrangeFreeFunctionCall(resultType, args, 00134 FunctionType::ExtInfo(), RequiredArgs::All); 00135 llvm::FunctionType *fnTy = CGF.CGM.getTypes().GetFunctionType(fnInfo); 00136 llvm::Constant *fn = CGF.CGM.CreateRuntimeFunction(fnTy, fnName); 00137 return CGF.EmitCall(fnInfo, fn, ReturnValueSlot(), args); 00138 } 00139 00140 /// Does a store of the given IR type modify the full expected width? 00141 static bool isFullSizeType(CodeGenModule &CGM, llvm::Type *type, 00142 uint64_t expectedSize) { 00143 return (CGM.getDataLayout().getTypeStoreSize(type) * 8 == expectedSize); 00144 } 00145 00146 /// Does the atomic type require memsetting to zero before initialization? 00147 /// 00148 /// The IR type is provided as a way of making certain queries faster. 00149 bool AtomicInfo::requiresMemSetZero(llvm::Type *type) const { 00150 // If the atomic type has size padding, we definitely need a memset. 00151 if (hasPadding()) return true; 00152 00153 // Otherwise, do some simple heuristics to try to avoid it: 00154 switch (getEvaluationKind()) { 00155 // For scalars and complexes, check whether the store size of the 00156 // type uses the full size. 00157 case TEK_Scalar: 00158 return !isFullSizeType(CGF.CGM, type, AtomicSizeInBits); 00159 case TEK_Complex: 00160 return !isFullSizeType(CGF.CGM, type->getStructElementType(0), 00161 AtomicSizeInBits / 2); 00162 00163 // Padding in structs has an undefined bit pattern. User beware. 00164 case TEK_Aggregate: 00165 return false; 00166 } 00167 llvm_unreachable("bad evaluation kind"); 00168 } 00169 00170 bool AtomicInfo::emitMemSetZeroIfNecessary(LValue dest) const { 00171 llvm::Value *addr = dest.getAddress(); 00172 if (!requiresMemSetZero(addr->getType()->getPointerElementType())) 00173 return false; 00174 00175 CGF.Builder.CreateMemSet(addr, llvm::ConstantInt::get(CGF.Int8Ty, 0), 00176 AtomicSizeInBits / 8, 00177 dest.getAlignment().getQuantity()); 00178 return true; 00179 } 00180 00181 static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak, 00182 llvm::Value *Dest, llvm::Value *Ptr, 00183 llvm::Value *Val1, llvm::Value *Val2, 00184 uint64_t Size, unsigned Align, 00185 llvm::AtomicOrdering SuccessOrder, 00186 llvm::AtomicOrdering FailureOrder) { 00187 // Note that cmpxchg doesn't support weak cmpxchg, at least at the moment. 00188 llvm::LoadInst *Expected = CGF.Builder.CreateLoad(Val1); 00189 Expected->setAlignment(Align); 00190 llvm::LoadInst *Desired = CGF.Builder.CreateLoad(Val2); 00191 Desired->setAlignment(Align); 00192 00193 llvm::AtomicCmpXchgInst *Pair = CGF.Builder.CreateAtomicCmpXchg( 00194 Ptr, Expected, Desired, SuccessOrder, FailureOrder); 00195 Pair->setVolatile(E->isVolatile()); 00196 Pair->setWeak(IsWeak); 00197 00198 // Cmp holds the result of the compare-exchange operation: true on success, 00199 // false on failure. 00200 llvm::Value *Old = CGF.Builder.CreateExtractValue(Pair, 0); 00201 llvm::Value *Cmp = CGF.Builder.CreateExtractValue(Pair, 1); 00202 00203 // This basic block is used to hold the store instruction if the operation 00204 // failed. 00205 llvm::BasicBlock *StoreExpectedBB = 00206 CGF.createBasicBlock("cmpxchg.store_expected", CGF.CurFn); 00207 00208 // This basic block is the exit point of the operation, we should end up 00209 // here regardless of whether or not the operation succeeded. 00210 llvm::BasicBlock *ContinueBB = 00211 CGF.createBasicBlock("cmpxchg.continue", CGF.CurFn); 00212 00213 // Update Expected if Expected isn't equal to Old, otherwise branch to the 00214 // exit point. 00215 CGF.Builder.CreateCondBr(Cmp, ContinueBB, StoreExpectedBB); 00216 00217 CGF.Builder.SetInsertPoint(StoreExpectedBB); 00218 // Update the memory at Expected with Old's value. 00219 llvm::StoreInst *StoreExpected = CGF.Builder.CreateStore(Old, Val1); 00220 StoreExpected->setAlignment(Align); 00221 // Finally, branch to the exit point. 00222 CGF.Builder.CreateBr(ContinueBB); 00223 00224 CGF.Builder.SetInsertPoint(ContinueBB); 00225 // Update the memory at Dest with Cmp's value. 00226 CGF.EmitStoreOfScalar(Cmp, CGF.MakeAddrLValue(Dest, E->getType())); 00227 return; 00228 } 00229 00230 /// Given an ordering required on success, emit all possible cmpxchg 00231 /// instructions to cope with the provided (but possibly only dynamically known) 00232 /// FailureOrder. 00233 static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E, 00234 bool IsWeak, llvm::Value *Dest, 00235 llvm::Value *Ptr, llvm::Value *Val1, 00236 llvm::Value *Val2, 00237 llvm::Value *FailureOrderVal, 00238 uint64_t Size, unsigned Align, 00239 llvm::AtomicOrdering SuccessOrder) { 00240 llvm::AtomicOrdering FailureOrder; 00241 if (llvm::ConstantInt *FO = dyn_cast<llvm::ConstantInt>(FailureOrderVal)) { 00242 switch (FO->getSExtValue()) { 00243 default: 00244 FailureOrder = llvm::Monotonic; 00245 break; 00246 case AtomicExpr::AO_ABI_memory_order_consume: 00247 case AtomicExpr::AO_ABI_memory_order_acquire: 00248 FailureOrder = llvm::Acquire; 00249 break; 00250 case AtomicExpr::AO_ABI_memory_order_seq_cst: 00251 FailureOrder = llvm::SequentiallyConsistent; 00252 break; 00253 } 00254 if (FailureOrder >= SuccessOrder) { 00255 // Don't assert on undefined behaviour. 00256 FailureOrder = 00257 llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(SuccessOrder); 00258 } 00259 emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, Align, 00260 SuccessOrder, FailureOrder); 00261 return; 00262 } 00263 00264 // Create all the relevant BB's 00265 llvm::BasicBlock *MonotonicBB = nullptr, *AcquireBB = nullptr, 00266 *SeqCstBB = nullptr; 00267 MonotonicBB = CGF.createBasicBlock("monotonic_fail", CGF.CurFn); 00268 if (SuccessOrder != llvm::Monotonic && SuccessOrder != llvm::Release) 00269 AcquireBB = CGF.createBasicBlock("acquire_fail", CGF.CurFn); 00270 if (SuccessOrder == llvm::SequentiallyConsistent) 00271 SeqCstBB = CGF.createBasicBlock("seqcst_fail", CGF.CurFn); 00272 00273 llvm::BasicBlock *ContBB = CGF.createBasicBlock("atomic.continue", CGF.CurFn); 00274 00275 llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(FailureOrderVal, MonotonicBB); 00276 00277 // Emit all the different atomics 00278 00279 // MonotonicBB is arbitrarily chosen as the default case; in practice, this 00280 // doesn't matter unless someone is crazy enough to use something that 00281 // doesn't fold to a constant for the ordering. 00282 CGF.Builder.SetInsertPoint(MonotonicBB); 00283 emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, 00284 Size, Align, SuccessOrder, llvm::Monotonic); 00285 CGF.Builder.CreateBr(ContBB); 00286 00287 if (AcquireBB) { 00288 CGF.Builder.SetInsertPoint(AcquireBB); 00289 emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, 00290 Size, Align, SuccessOrder, llvm::Acquire); 00291 CGF.Builder.CreateBr(ContBB); 00292 SI->addCase(CGF.Builder.getInt32(AtomicExpr::AO_ABI_memory_order_consume), 00293 AcquireBB); 00294 SI->addCase(CGF.Builder.getInt32(AtomicExpr::AO_ABI_memory_order_acquire), 00295 AcquireBB); 00296 } 00297 if (SeqCstBB) { 00298 CGF.Builder.SetInsertPoint(SeqCstBB); 00299 emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, 00300 Size, Align, SuccessOrder, llvm::SequentiallyConsistent); 00301 CGF.Builder.CreateBr(ContBB); 00302 SI->addCase(CGF.Builder.getInt32(AtomicExpr::AO_ABI_memory_order_seq_cst), 00303 SeqCstBB); 00304 } 00305 00306 CGF.Builder.SetInsertPoint(ContBB); 00307 } 00308 00309 static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, llvm::Value *Dest, 00310 llvm::Value *Ptr, llvm::Value *Val1, llvm::Value *Val2, 00311 llvm::Value *IsWeak, llvm::Value *FailureOrder, 00312 uint64_t Size, unsigned Align, 00313 llvm::AtomicOrdering Order) { 00314 llvm::AtomicRMWInst::BinOp Op = llvm::AtomicRMWInst::Add; 00315 llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0; 00316 00317 switch (E->getOp()) { 00318 case AtomicExpr::AO__c11_atomic_init: 00319 llvm_unreachable("Already handled!"); 00320 00321 case AtomicExpr::AO__c11_atomic_compare_exchange_strong: 00322 emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2, 00323 FailureOrder, Size, Align, Order); 00324 return; 00325 case AtomicExpr::AO__c11_atomic_compare_exchange_weak: 00326 emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2, 00327 FailureOrder, Size, Align, Order); 00328 return; 00329 case AtomicExpr::AO__atomic_compare_exchange: 00330 case AtomicExpr::AO__atomic_compare_exchange_n: { 00331 if (llvm::ConstantInt *IsWeakC = dyn_cast<llvm::ConstantInt>(IsWeak)) { 00332 emitAtomicCmpXchgFailureSet(CGF, E, IsWeakC->getZExtValue(), Dest, Ptr, 00333 Val1, Val2, FailureOrder, Size, Align, Order); 00334 } else { 00335 // Create all the relevant BB's 00336 llvm::BasicBlock *StrongBB = 00337 CGF.createBasicBlock("cmpxchg.strong", CGF.CurFn); 00338 llvm::BasicBlock *WeakBB = CGF.createBasicBlock("cmxchg.weak", CGF.CurFn); 00339 llvm::BasicBlock *ContBB = 00340 CGF.createBasicBlock("cmpxchg.continue", CGF.CurFn); 00341 00342 llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(IsWeak, WeakBB); 00343 SI->addCase(CGF.Builder.getInt1(false), StrongBB); 00344 00345 CGF.Builder.SetInsertPoint(StrongBB); 00346 emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2, 00347 FailureOrder, Size, Align, Order); 00348 CGF.Builder.CreateBr(ContBB); 00349 00350 CGF.Builder.SetInsertPoint(WeakBB); 00351 emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2, 00352 FailureOrder, Size, Align, Order); 00353 CGF.Builder.CreateBr(ContBB); 00354 00355 CGF.Builder.SetInsertPoint(ContBB); 00356 } 00357 return; 00358 } 00359 case AtomicExpr::AO__c11_atomic_load: 00360 case AtomicExpr::AO__atomic_load_n: 00361 case AtomicExpr::AO__atomic_load: { 00362 llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr); 00363 Load->setAtomic(Order); 00364 Load->setAlignment(Size); 00365 Load->setVolatile(E->isVolatile()); 00366 llvm::StoreInst *StoreDest = CGF.Builder.CreateStore(Load, Dest); 00367 StoreDest->setAlignment(Align); 00368 return; 00369 } 00370 00371 case AtomicExpr::AO__c11_atomic_store: 00372 case AtomicExpr::AO__atomic_store: 00373 case AtomicExpr::AO__atomic_store_n: { 00374 assert(!Dest && "Store does not return a value"); 00375 llvm::LoadInst *LoadVal1 = CGF.Builder.CreateLoad(Val1); 00376 LoadVal1->setAlignment(Align); 00377 llvm::StoreInst *Store = CGF.Builder.CreateStore(LoadVal1, Ptr); 00378 Store->setAtomic(Order); 00379 Store->setAlignment(Size); 00380 Store->setVolatile(E->isVolatile()); 00381 return; 00382 } 00383 00384 case AtomicExpr::AO__c11_atomic_exchange: 00385 case AtomicExpr::AO__atomic_exchange_n: 00386 case AtomicExpr::AO__atomic_exchange: 00387 Op = llvm::AtomicRMWInst::Xchg; 00388 break; 00389 00390 case AtomicExpr::AO__atomic_add_fetch: 00391 PostOp = llvm::Instruction::Add; 00392 // Fall through. 00393 case AtomicExpr::AO__c11_atomic_fetch_add: 00394 case AtomicExpr::AO__atomic_fetch_add: 00395 Op = llvm::AtomicRMWInst::Add; 00396 break; 00397 00398 case AtomicExpr::AO__atomic_sub_fetch: 00399 PostOp = llvm::Instruction::Sub; 00400 // Fall through. 00401 case AtomicExpr::AO__c11_atomic_fetch_sub: 00402 case AtomicExpr::AO__atomic_fetch_sub: 00403 Op = llvm::AtomicRMWInst::Sub; 00404 break; 00405 00406 case AtomicExpr::AO__atomic_and_fetch: 00407 PostOp = llvm::Instruction::And; 00408 // Fall through. 00409 case AtomicExpr::AO__c11_atomic_fetch_and: 00410 case AtomicExpr::AO__atomic_fetch_and: 00411 Op = llvm::AtomicRMWInst::And; 00412 break; 00413 00414 case AtomicExpr::AO__atomic_or_fetch: 00415 PostOp = llvm::Instruction::Or; 00416 // Fall through. 00417 case AtomicExpr::AO__c11_atomic_fetch_or: 00418 case AtomicExpr::AO__atomic_fetch_or: 00419 Op = llvm::AtomicRMWInst::Or; 00420 break; 00421 00422 case AtomicExpr::AO__atomic_xor_fetch: 00423 PostOp = llvm::Instruction::Xor; 00424 // Fall through. 00425 case AtomicExpr::AO__c11_atomic_fetch_xor: 00426 case AtomicExpr::AO__atomic_fetch_xor: 00427 Op = llvm::AtomicRMWInst::Xor; 00428 break; 00429 00430 case AtomicExpr::AO__atomic_nand_fetch: 00431 PostOp = llvm::Instruction::And; 00432 // Fall through. 00433 case AtomicExpr::AO__atomic_fetch_nand: 00434 Op = llvm::AtomicRMWInst::Nand; 00435 break; 00436 } 00437 00438 llvm::LoadInst *LoadVal1 = CGF.Builder.CreateLoad(Val1); 00439 LoadVal1->setAlignment(Align); 00440 llvm::AtomicRMWInst *RMWI = 00441 CGF.Builder.CreateAtomicRMW(Op, Ptr, LoadVal1, Order); 00442 RMWI->setVolatile(E->isVolatile()); 00443 00444 // For __atomic_*_fetch operations, perform the operation again to 00445 // determine the value which was written. 00446 llvm::Value *Result = RMWI; 00447 if (PostOp) 00448 Result = CGF.Builder.CreateBinOp(PostOp, RMWI, LoadVal1); 00449 if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch) 00450 Result = CGF.Builder.CreateNot(Result); 00451 llvm::StoreInst *StoreDest = CGF.Builder.CreateStore(Result, Dest); 00452 StoreDest->setAlignment(Align); 00453 } 00454 00455 // This function emits any expression (scalar, complex, or aggregate) 00456 // into a temporary alloca. 00457 static llvm::Value * 00458 EmitValToTemp(CodeGenFunction &CGF, Expr *E) { 00459 llvm::Value *DeclPtr = CGF.CreateMemTemp(E->getType(), ".atomictmp"); 00460 CGF.EmitAnyExprToMem(E, DeclPtr, E->getType().getQualifiers(), 00461 /*Init*/ true); 00462 return DeclPtr; 00463 } 00464 00465 static void 00466 AddDirectArgument(CodeGenFunction &CGF, CallArgList &Args, 00467 bool UseOptimizedLibcall, llvm::Value *Val, QualType ValTy, 00468 SourceLocation Loc, CharUnits SizeInChars) { 00469 if (UseOptimizedLibcall) { 00470 // Load value and pass it to the function directly. 00471 unsigned Align = CGF.getContext().getTypeAlignInChars(ValTy).getQuantity(); 00472 int64_t SizeInBits = CGF.getContext().toBits(SizeInChars); 00473 ValTy = 00474 CGF.getContext().getIntTypeForBitwidth(SizeInBits, /*Signed=*/false); 00475 llvm::Type *IPtrTy = llvm::IntegerType::get(CGF.getLLVMContext(), 00476 SizeInBits)->getPointerTo(); 00477 Val = CGF.EmitLoadOfScalar(CGF.Builder.CreateBitCast(Val, IPtrTy), false, 00478 Align, CGF.getContext().getPointerType(ValTy), 00479 Loc); 00480 // Coerce the value into an appropriately sized integer type. 00481 Args.add(RValue::get(Val), ValTy); 00482 } else { 00483 // Non-optimized functions always take a reference. 00484 Args.add(RValue::get(CGF.EmitCastToVoidPtr(Val)), 00485 CGF.getContext().VoidPtrTy); 00486 } 00487 } 00488 00489 RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) { 00490 QualType AtomicTy = E->getPtr()->getType()->getPointeeType(); 00491 QualType MemTy = AtomicTy; 00492 if (const AtomicType *AT = AtomicTy->getAs<AtomicType>()) 00493 MemTy = AT->getValueType(); 00494 CharUnits sizeChars = getContext().getTypeSizeInChars(AtomicTy); 00495 uint64_t Size = sizeChars.getQuantity(); 00496 CharUnits alignChars = getContext().getTypeAlignInChars(AtomicTy); 00497 unsigned Align = alignChars.getQuantity(); 00498 unsigned MaxInlineWidthInBits = 00499 getTarget().getMaxAtomicInlineWidth(); 00500 bool UseLibcall = (Size != Align || 00501 getContext().toBits(sizeChars) > MaxInlineWidthInBits); 00502 00503 llvm::Value *IsWeak = nullptr, *OrderFail = nullptr, *Val1 = nullptr, 00504 *Val2 = nullptr; 00505 llvm::Value *Ptr = EmitScalarExpr(E->getPtr()); 00506 00507 if (E->getOp() == AtomicExpr::AO__c11_atomic_init) { 00508 assert(!Dest && "Init does not return a value"); 00509 LValue lvalue = LValue::MakeAddr(Ptr, AtomicTy, alignChars, getContext()); 00510 EmitAtomicInit(E->getVal1(), lvalue); 00511 return RValue::get(nullptr); 00512 } 00513 00514 llvm::Value *Order = EmitScalarExpr(E->getOrder()); 00515 00516 switch (E->getOp()) { 00517 case AtomicExpr::AO__c11_atomic_init: 00518 llvm_unreachable("Already handled!"); 00519 00520 case AtomicExpr::AO__c11_atomic_load: 00521 case AtomicExpr::AO__atomic_load_n: 00522 break; 00523 00524 case AtomicExpr::AO__atomic_load: 00525 Dest = EmitScalarExpr(E->getVal1()); 00526 break; 00527 00528 case AtomicExpr::AO__atomic_store: 00529 Val1 = EmitScalarExpr(E->getVal1()); 00530 break; 00531 00532 case AtomicExpr::AO__atomic_exchange: 00533 Val1 = EmitScalarExpr(E->getVal1()); 00534 Dest = EmitScalarExpr(E->getVal2()); 00535 break; 00536 00537 case AtomicExpr::AO__c11_atomic_compare_exchange_strong: 00538 case AtomicExpr::AO__c11_atomic_compare_exchange_weak: 00539 case AtomicExpr::AO__atomic_compare_exchange_n: 00540 case AtomicExpr::AO__atomic_compare_exchange: 00541 Val1 = EmitScalarExpr(E->getVal1()); 00542 if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange) 00543 Val2 = EmitScalarExpr(E->getVal2()); 00544 else 00545 Val2 = EmitValToTemp(*this, E->getVal2()); 00546 OrderFail = EmitScalarExpr(E->getOrderFail()); 00547 if (E->getNumSubExprs() == 6) 00548 IsWeak = EmitScalarExpr(E->getWeak()); 00549 break; 00550 00551 case AtomicExpr::AO__c11_atomic_fetch_add: 00552 case AtomicExpr::AO__c11_atomic_fetch_sub: 00553 if (MemTy->isPointerType()) { 00554 // For pointer arithmetic, we're required to do a bit of math: 00555 // adding 1 to an int* is not the same as adding 1 to a uintptr_t. 00556 // ... but only for the C11 builtins. The GNU builtins expect the 00557 // user to multiply by sizeof(T). 00558 QualType Val1Ty = E->getVal1()->getType(); 00559 llvm::Value *Val1Scalar = EmitScalarExpr(E->getVal1()); 00560 CharUnits PointeeIncAmt = 00561 getContext().getTypeSizeInChars(MemTy->getPointeeType()); 00562 Val1Scalar = Builder.CreateMul(Val1Scalar, CGM.getSize(PointeeIncAmt)); 00563 Val1 = CreateMemTemp(Val1Ty, ".atomictmp"); 00564 EmitStoreOfScalar(Val1Scalar, MakeAddrLValue(Val1, Val1Ty)); 00565 break; 00566 } 00567 // Fall through. 00568 case AtomicExpr::AO__atomic_fetch_add: 00569 case AtomicExpr::AO__atomic_fetch_sub: 00570 case AtomicExpr::AO__atomic_add_fetch: 00571 case AtomicExpr::AO__atomic_sub_fetch: 00572 case AtomicExpr::AO__c11_atomic_store: 00573 case AtomicExpr::AO__c11_atomic_exchange: 00574 case AtomicExpr::AO__atomic_store_n: 00575 case AtomicExpr::AO__atomic_exchange_n: 00576 case AtomicExpr::AO__c11_atomic_fetch_and: 00577 case AtomicExpr::AO__c11_atomic_fetch_or: 00578 case AtomicExpr::AO__c11_atomic_fetch_xor: 00579 case AtomicExpr::AO__atomic_fetch_and: 00580 case AtomicExpr::AO__atomic_fetch_or: 00581 case AtomicExpr::AO__atomic_fetch_xor: 00582 case AtomicExpr::AO__atomic_fetch_nand: 00583 case AtomicExpr::AO__atomic_and_fetch: 00584 case AtomicExpr::AO__atomic_or_fetch: 00585 case AtomicExpr::AO__atomic_xor_fetch: 00586 case AtomicExpr::AO__atomic_nand_fetch: 00587 Val1 = EmitValToTemp(*this, E->getVal1()); 00588 break; 00589 } 00590 00591 if (!E->getType()->isVoidType() && !Dest) 00592 Dest = CreateMemTemp(E->getType(), ".atomicdst"); 00593 00594 // Use a library call. See: http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary . 00595 if (UseLibcall) { 00596 bool UseOptimizedLibcall = false; 00597 switch (E->getOp()) { 00598 case AtomicExpr::AO__c11_atomic_fetch_add: 00599 case AtomicExpr::AO__atomic_fetch_add: 00600 case AtomicExpr::AO__c11_atomic_fetch_and: 00601 case AtomicExpr::AO__atomic_fetch_and: 00602 case AtomicExpr::AO__c11_atomic_fetch_or: 00603 case AtomicExpr::AO__atomic_fetch_or: 00604 case AtomicExpr::AO__c11_atomic_fetch_sub: 00605 case AtomicExpr::AO__atomic_fetch_sub: 00606 case AtomicExpr::AO__c11_atomic_fetch_xor: 00607 case AtomicExpr::AO__atomic_fetch_xor: 00608 // For these, only library calls for certain sizes exist. 00609 UseOptimizedLibcall = true; 00610 break; 00611 default: 00612 // Only use optimized library calls for sizes for which they exist. 00613 if (Size == 1 || Size == 2 || Size == 4 || Size == 8) 00614 UseOptimizedLibcall = true; 00615 break; 00616 } 00617 00618 CallArgList Args; 00619 if (!UseOptimizedLibcall) { 00620 // For non-optimized library calls, the size is the first parameter 00621 Args.add(RValue::get(llvm::ConstantInt::get(SizeTy, Size)), 00622 getContext().getSizeType()); 00623 } 00624 // Atomic address is the first or second parameter 00625 Args.add(RValue::get(EmitCastToVoidPtr(Ptr)), getContext().VoidPtrTy); 00626 00627 std::string LibCallName; 00628 QualType LoweredMemTy = 00629 MemTy->isPointerType() ? getContext().getIntPtrType() : MemTy; 00630 QualType RetTy; 00631 bool HaveRetTy = false; 00632 switch (E->getOp()) { 00633 // There is only one libcall for compare an exchange, because there is no 00634 // optimisation benefit possible from a libcall version of a weak compare 00635 // and exchange. 00636 // bool __atomic_compare_exchange(size_t size, void *mem, void *expected, 00637 // void *desired, int success, int failure) 00638 // bool __atomic_compare_exchange_N(T *mem, T *expected, T desired, 00639 // int success, int failure) 00640 case AtomicExpr::AO__c11_atomic_compare_exchange_weak: 00641 case AtomicExpr::AO__c11_atomic_compare_exchange_strong: 00642 case AtomicExpr::AO__atomic_compare_exchange: 00643 case AtomicExpr::AO__atomic_compare_exchange_n: 00644 LibCallName = "__atomic_compare_exchange"; 00645 RetTy = getContext().BoolTy; 00646 HaveRetTy = true; 00647 Args.add(RValue::get(EmitCastToVoidPtr(Val1)), getContext().VoidPtrTy); 00648 AddDirectArgument(*this, Args, UseOptimizedLibcall, Val2, MemTy, 00649 E->getExprLoc(), sizeChars); 00650 Args.add(RValue::get(Order), getContext().IntTy); 00651 Order = OrderFail; 00652 break; 00653 // void __atomic_exchange(size_t size, void *mem, void *val, void *return, 00654 // int order) 00655 // T __atomic_exchange_N(T *mem, T val, int order) 00656 case AtomicExpr::AO__c11_atomic_exchange: 00657 case AtomicExpr::AO__atomic_exchange_n: 00658 case AtomicExpr::AO__atomic_exchange: 00659 LibCallName = "__atomic_exchange"; 00660 AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy, 00661 E->getExprLoc(), sizeChars); 00662 break; 00663 // void __atomic_store(size_t size, void *mem, void *val, int order) 00664 // void __atomic_store_N(T *mem, T val, int order) 00665 case AtomicExpr::AO__c11_atomic_store: 00666 case AtomicExpr::AO__atomic_store: 00667 case AtomicExpr::AO__atomic_store_n: 00668 LibCallName = "__atomic_store"; 00669 RetTy = getContext().VoidTy; 00670 HaveRetTy = true; 00671 AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy, 00672 E->getExprLoc(), sizeChars); 00673 break; 00674 // void __atomic_load(size_t size, void *mem, void *return, int order) 00675 // T __atomic_load_N(T *mem, int order) 00676 case AtomicExpr::AO__c11_atomic_load: 00677 case AtomicExpr::AO__atomic_load: 00678 case AtomicExpr::AO__atomic_load_n: 00679 LibCallName = "__atomic_load"; 00680 break; 00681 // T __atomic_fetch_add_N(T *mem, T val, int order) 00682 case AtomicExpr::AO__c11_atomic_fetch_add: 00683 case AtomicExpr::AO__atomic_fetch_add: 00684 LibCallName = "__atomic_fetch_add"; 00685 AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, LoweredMemTy, 00686 E->getExprLoc(), sizeChars); 00687 break; 00688 // T __atomic_fetch_and_N(T *mem, T val, int order) 00689 case AtomicExpr::AO__c11_atomic_fetch_and: 00690 case AtomicExpr::AO__atomic_fetch_and: 00691 LibCallName = "__atomic_fetch_and"; 00692 AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy, 00693 E->getExprLoc(), sizeChars); 00694 break; 00695 // T __atomic_fetch_or_N(T *mem, T val, int order) 00696 case AtomicExpr::AO__c11_atomic_fetch_or: 00697 case AtomicExpr::AO__atomic_fetch_or: 00698 LibCallName = "__atomic_fetch_or"; 00699 AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy, 00700 E->getExprLoc(), sizeChars); 00701 break; 00702 // T __atomic_fetch_sub_N(T *mem, T val, int order) 00703 case AtomicExpr::AO__c11_atomic_fetch_sub: 00704 case AtomicExpr::AO__atomic_fetch_sub: 00705 LibCallName = "__atomic_fetch_sub"; 00706 AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, LoweredMemTy, 00707 E->getExprLoc(), sizeChars); 00708 break; 00709 // T __atomic_fetch_xor_N(T *mem, T val, int order) 00710 case AtomicExpr::AO__c11_atomic_fetch_xor: 00711 case AtomicExpr::AO__atomic_fetch_xor: 00712 LibCallName = "__atomic_fetch_xor"; 00713 AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy, 00714 E->getExprLoc(), sizeChars); 00715 break; 00716 default: return EmitUnsupportedRValue(E, "atomic library call"); 00717 } 00718 00719 // Optimized functions have the size in their name. 00720 if (UseOptimizedLibcall) 00721 LibCallName += "_" + llvm::utostr(Size); 00722 // By default, assume we return a value of the atomic type. 00723 if (!HaveRetTy) { 00724 if (UseOptimizedLibcall) { 00725 // Value is returned directly. 00726 // The function returns an appropriately sized integer type. 00727 RetTy = getContext().getIntTypeForBitwidth( 00728 getContext().toBits(sizeChars), /*Signed=*/false); 00729 } else { 00730 // Value is returned through parameter before the order. 00731 RetTy = getContext().VoidTy; 00732 Args.add(RValue::get(EmitCastToVoidPtr(Dest)), 00733 getContext().VoidPtrTy); 00734 } 00735 } 00736 // order is always the last parameter 00737 Args.add(RValue::get(Order), 00738 getContext().IntTy); 00739 00740 const CGFunctionInfo &FuncInfo = 00741 CGM.getTypes().arrangeFreeFunctionCall(RetTy, Args, 00742 FunctionType::ExtInfo(), RequiredArgs::All); 00743 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FuncInfo); 00744 llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, LibCallName); 00745 RValue Res = EmitCall(FuncInfo, Func, ReturnValueSlot(), Args); 00746 if (!RetTy->isVoidType()) { 00747 if (UseOptimizedLibcall) { 00748 if (HaveRetTy) 00749 return Res; 00750 llvm::StoreInst *StoreDest = Builder.CreateStore( 00751 Res.getScalarVal(), 00752 Builder.CreateBitCast(Dest, FTy->getReturnType()->getPointerTo())); 00753 StoreDest->setAlignment(Align); 00754 } 00755 } 00756 if (E->getType()->isVoidType()) 00757 return RValue::get(nullptr); 00758 return convertTempToRValue(Dest, E->getType(), E->getExprLoc()); 00759 } 00760 00761 bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store || 00762 E->getOp() == AtomicExpr::AO__atomic_store || 00763 E->getOp() == AtomicExpr::AO__atomic_store_n; 00764 bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load || 00765 E->getOp() == AtomicExpr::AO__atomic_load || 00766 E->getOp() == AtomicExpr::AO__atomic_load_n; 00767 00768 llvm::Type *IPtrTy = 00769 llvm::IntegerType::get(getLLVMContext(), Size * 8)->getPointerTo(); 00770 llvm::Value *OrigDest = Dest; 00771 Ptr = Builder.CreateBitCast(Ptr, IPtrTy); 00772 if (Val1) Val1 = Builder.CreateBitCast(Val1, IPtrTy); 00773 if (Val2) Val2 = Builder.CreateBitCast(Val2, IPtrTy); 00774 if (Dest && !E->isCmpXChg()) Dest = Builder.CreateBitCast(Dest, IPtrTy); 00775 00776 if (isa<llvm::ConstantInt>(Order)) { 00777 int ord = cast<llvm::ConstantInt>(Order)->getZExtValue(); 00778 switch (ord) { 00779 case AtomicExpr::AO_ABI_memory_order_relaxed: 00780 EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, 00781 Size, Align, llvm::Monotonic); 00782 break; 00783 case AtomicExpr::AO_ABI_memory_order_consume: 00784 case AtomicExpr::AO_ABI_memory_order_acquire: 00785 if (IsStore) 00786 break; // Avoid crashing on code with undefined behavior 00787 EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, 00788 Size, Align, llvm::Acquire); 00789 break; 00790 case AtomicExpr::AO_ABI_memory_order_release: 00791 if (IsLoad) 00792 break; // Avoid crashing on code with undefined behavior 00793 EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, 00794 Size, Align, llvm::Release); 00795 break; 00796 case AtomicExpr::AO_ABI_memory_order_acq_rel: 00797 if (IsLoad || IsStore) 00798 break; // Avoid crashing on code with undefined behavior 00799 EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, 00800 Size, Align, llvm::AcquireRelease); 00801 break; 00802 case AtomicExpr::AO_ABI_memory_order_seq_cst: 00803 EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, 00804 Size, Align, llvm::SequentiallyConsistent); 00805 break; 00806 default: // invalid order 00807 // We should not ever get here normally, but it's hard to 00808 // enforce that in general. 00809 break; 00810 } 00811 if (E->getType()->isVoidType()) 00812 return RValue::get(nullptr); 00813 return convertTempToRValue(OrigDest, E->getType(), E->getExprLoc()); 00814 } 00815 00816 // Long case, when Order isn't obviously constant. 00817 00818 // Create all the relevant BB's 00819 llvm::BasicBlock *MonotonicBB = nullptr, *AcquireBB = nullptr, 00820 *ReleaseBB = nullptr, *AcqRelBB = nullptr, 00821 *SeqCstBB = nullptr; 00822 MonotonicBB = createBasicBlock("monotonic", CurFn); 00823 if (!IsStore) 00824 AcquireBB = createBasicBlock("acquire", CurFn); 00825 if (!IsLoad) 00826 ReleaseBB = createBasicBlock("release", CurFn); 00827 if (!IsLoad && !IsStore) 00828 AcqRelBB = createBasicBlock("acqrel", CurFn); 00829 SeqCstBB = createBasicBlock("seqcst", CurFn); 00830 llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn); 00831 00832 // Create the switch for the split 00833 // MonotonicBB is arbitrarily chosen as the default case; in practice, this 00834 // doesn't matter unless someone is crazy enough to use something that 00835 // doesn't fold to a constant for the ordering. 00836 Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false); 00837 llvm::SwitchInst *SI = Builder.CreateSwitch(Order, MonotonicBB); 00838 00839 // Emit all the different atomics 00840 Builder.SetInsertPoint(MonotonicBB); 00841 EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, 00842 Size, Align, llvm::Monotonic); 00843 Builder.CreateBr(ContBB); 00844 if (!IsStore) { 00845 Builder.SetInsertPoint(AcquireBB); 00846 EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, 00847 Size, Align, llvm::Acquire); 00848 Builder.CreateBr(ContBB); 00849 SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_consume), 00850 AcquireBB); 00851 SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_acquire), 00852 AcquireBB); 00853 } 00854 if (!IsLoad) { 00855 Builder.SetInsertPoint(ReleaseBB); 00856 EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, 00857 Size, Align, llvm::Release); 00858 Builder.CreateBr(ContBB); 00859 SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_release), 00860 ReleaseBB); 00861 } 00862 if (!IsLoad && !IsStore) { 00863 Builder.SetInsertPoint(AcqRelBB); 00864 EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, 00865 Size, Align, llvm::AcquireRelease); 00866 Builder.CreateBr(ContBB); 00867 SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_acq_rel), 00868 AcqRelBB); 00869 } 00870 Builder.SetInsertPoint(SeqCstBB); 00871 EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, 00872 Size, Align, llvm::SequentiallyConsistent); 00873 Builder.CreateBr(ContBB); 00874 SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_seq_cst), 00875 SeqCstBB); 00876 00877 // Cleanup and return 00878 Builder.SetInsertPoint(ContBB); 00879 if (E->getType()->isVoidType()) 00880 return RValue::get(nullptr); 00881 return convertTempToRValue(OrigDest, E->getType(), E->getExprLoc()); 00882 } 00883 00884 llvm::Value *AtomicInfo::emitCastToAtomicIntPointer(llvm::Value *addr) const { 00885 unsigned addrspace = 00886 cast<llvm::PointerType>(addr->getType())->getAddressSpace(); 00887 llvm::IntegerType *ty = 00888 llvm::IntegerType::get(CGF.getLLVMContext(), AtomicSizeInBits); 00889 return CGF.Builder.CreateBitCast(addr, ty->getPointerTo(addrspace)); 00890 } 00891 00892 RValue AtomicInfo::convertTempToRValue(llvm::Value *addr, 00893 AggValueSlot resultSlot, 00894 SourceLocation loc) const { 00895 if (EvaluationKind == TEK_Aggregate) 00896 return resultSlot.asRValue(); 00897 00898 // Drill into the padding structure if we have one. 00899 if (hasPadding()) 00900 addr = CGF.Builder.CreateStructGEP(addr, 0); 00901 00902 // Otherwise, just convert the temporary to an r-value using the 00903 // normal conversion routine. 00904 return CGF.convertTempToRValue(addr, getValueType(), loc); 00905 } 00906 00907 /// Emit a load from an l-value of atomic type. Note that the r-value 00908 /// we produce is an r-value of the atomic *value* type. 00909 RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc, 00910 AggValueSlot resultSlot) { 00911 AtomicInfo atomics(*this, src); 00912 00913 // Check whether we should use a library call. 00914 if (atomics.shouldUseLibcall()) { 00915 llvm::Value *tempAddr; 00916 if (!resultSlot.isIgnored()) { 00917 assert(atomics.getEvaluationKind() == TEK_Aggregate); 00918 tempAddr = resultSlot.getAddr(); 00919 } else { 00920 tempAddr = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp"); 00921 } 00922 00923 // void __atomic_load(size_t size, void *mem, void *return, int order); 00924 CallArgList args; 00925 args.add(RValue::get(atomics.getAtomicSizeValue()), 00926 getContext().getSizeType()); 00927 args.add(RValue::get(EmitCastToVoidPtr(src.getAddress())), 00928 getContext().VoidPtrTy); 00929 args.add(RValue::get(EmitCastToVoidPtr(tempAddr)), 00930 getContext().VoidPtrTy); 00931 args.add(RValue::get(llvm::ConstantInt::get( 00932 IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)), 00933 getContext().IntTy); 00934 emitAtomicLibcall(*this, "__atomic_load", getContext().VoidTy, args); 00935 00936 // Produce the r-value. 00937 return atomics.convertTempToRValue(tempAddr, resultSlot, loc); 00938 } 00939 00940 // Okay, we're doing this natively. 00941 llvm::Value *addr = atomics.emitCastToAtomicIntPointer(src.getAddress()); 00942 llvm::LoadInst *load = Builder.CreateLoad(addr, "atomic-load"); 00943 load->setAtomic(llvm::SequentiallyConsistent); 00944 00945 // Other decoration. 00946 load->setAlignment(src.getAlignment().getQuantity()); 00947 if (src.isVolatileQualified()) 00948 load->setVolatile(true); 00949 if (src.getTBAAInfo()) 00950 CGM.DecorateInstruction(load, src.getTBAAInfo()); 00951 00952 // Okay, turn that back into the original value type. 00953 QualType valueType = atomics.getValueType(); 00954 llvm::Value *result = load; 00955 00956 // If we're ignoring an aggregate return, don't do anything. 00957 if (atomics.getEvaluationKind() == TEK_Aggregate && resultSlot.isIgnored()) 00958 return RValue::getAggregate(nullptr, false); 00959 00960 // The easiest way to do this this is to go through memory, but we 00961 // try not to in some easy cases. 00962 if (atomics.getEvaluationKind() == TEK_Scalar && !atomics.hasPadding()) { 00963 llvm::Type *resultTy = CGM.getTypes().ConvertTypeForMem(valueType); 00964 if (isa<llvm::IntegerType>(resultTy)) { 00965 assert(result->getType() == resultTy); 00966 result = EmitFromMemory(result, valueType); 00967 } else if (isa<llvm::PointerType>(resultTy)) { 00968 result = Builder.CreateIntToPtr(result, resultTy); 00969 } else { 00970 result = Builder.CreateBitCast(result, resultTy); 00971 } 00972 return RValue::get(result); 00973 } 00974 00975 // Create a temporary. This needs to be big enough to hold the 00976 // atomic integer. 00977 llvm::Value *temp; 00978 bool tempIsVolatile = false; 00979 CharUnits tempAlignment; 00980 if (atomics.getEvaluationKind() == TEK_Aggregate) { 00981 assert(!resultSlot.isIgnored()); 00982 temp = resultSlot.getAddr(); 00983 tempAlignment = atomics.getValueAlignment(); 00984 tempIsVolatile = resultSlot.isVolatile(); 00985 } else { 00986 temp = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp"); 00987 tempAlignment = atomics.getAtomicAlignment(); 00988 } 00989 00990 // Slam the integer into the temporary. 00991 llvm::Value *castTemp = atomics.emitCastToAtomicIntPointer(temp); 00992 Builder.CreateAlignedStore(result, castTemp, tempAlignment.getQuantity()) 00993 ->setVolatile(tempIsVolatile); 00994 00995 return atomics.convertTempToRValue(temp, resultSlot, loc); 00996 } 00997 00998 00999 01000 /// Copy an r-value into memory as part of storing to an atomic type. 01001 /// This needs to create a bit-pattern suitable for atomic operations. 01002 void AtomicInfo::emitCopyIntoMemory(RValue rvalue, LValue dest) const { 01003 // If we have an r-value, the rvalue should be of the atomic type, 01004 // which means that the caller is responsible for having zeroed 01005 // any padding. Just do an aggregate copy of that type. 01006 if (rvalue.isAggregate()) { 01007 CGF.EmitAggregateCopy(dest.getAddress(), 01008 rvalue.getAggregateAddr(), 01009 getAtomicType(), 01010 (rvalue.isVolatileQualified() 01011 || dest.isVolatileQualified()), 01012 dest.getAlignment()); 01013 return; 01014 } 01015 01016 // Okay, otherwise we're copying stuff. 01017 01018 // Zero out the buffer if necessary. 01019 emitMemSetZeroIfNecessary(dest); 01020 01021 // Drill past the padding if present. 01022 dest = projectValue(dest); 01023 01024 // Okay, store the rvalue in. 01025 if (rvalue.isScalar()) { 01026 CGF.EmitStoreOfScalar(rvalue.getScalarVal(), dest, /*init*/ true); 01027 } else { 01028 CGF.EmitStoreOfComplex(rvalue.getComplexVal(), dest, /*init*/ true); 01029 } 01030 } 01031 01032 01033 /// Materialize an r-value into memory for the purposes of storing it 01034 /// to an atomic type. 01035 llvm::Value *AtomicInfo::materializeRValue(RValue rvalue) const { 01036 // Aggregate r-values are already in memory, and EmitAtomicStore 01037 // requires them to be values of the atomic type. 01038 if (rvalue.isAggregate()) 01039 return rvalue.getAggregateAddr(); 01040 01041 // Otherwise, make a temporary and materialize into it. 01042 llvm::Value *temp = CGF.CreateMemTemp(getAtomicType(), "atomic-store-temp"); 01043 LValue tempLV = CGF.MakeAddrLValue(temp, getAtomicType(), getAtomicAlignment()); 01044 emitCopyIntoMemory(rvalue, tempLV); 01045 return temp; 01046 } 01047 01048 /// Emit a store to an l-value of atomic type. 01049 /// 01050 /// Note that the r-value is expected to be an r-value *of the atomic 01051 /// type*; this means that for aggregate r-values, it should include 01052 /// storage for any padding that was necessary. 01053 void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, bool isInit) { 01054 // If this is an aggregate r-value, it should agree in type except 01055 // maybe for address-space qualification. 01056 assert(!rvalue.isAggregate() || 01057 rvalue.getAggregateAddr()->getType()->getPointerElementType() 01058 == dest.getAddress()->getType()->getPointerElementType()); 01059 01060 AtomicInfo atomics(*this, dest); 01061 01062 // If this is an initialization, just put the value there normally. 01063 if (isInit) { 01064 atomics.emitCopyIntoMemory(rvalue, dest); 01065 return; 01066 } 01067 01068 // Check whether we should use a library call. 01069 if (atomics.shouldUseLibcall()) { 01070 // Produce a source address. 01071 llvm::Value *srcAddr = atomics.materializeRValue(rvalue); 01072 01073 // void __atomic_store(size_t size, void *mem, void *val, int order) 01074 CallArgList args; 01075 args.add(RValue::get(atomics.getAtomicSizeValue()), 01076 getContext().getSizeType()); 01077 args.add(RValue::get(EmitCastToVoidPtr(dest.getAddress())), 01078 getContext().VoidPtrTy); 01079 args.add(RValue::get(EmitCastToVoidPtr(srcAddr)), 01080 getContext().VoidPtrTy); 01081 args.add(RValue::get(llvm::ConstantInt::get( 01082 IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)), 01083 getContext().IntTy); 01084 emitAtomicLibcall(*this, "__atomic_store", getContext().VoidTy, args); 01085 return; 01086 } 01087 01088 // Okay, we're doing this natively. 01089 llvm::Value *intValue; 01090 01091 // If we've got a scalar value of the right size, try to avoid going 01092 // through memory. 01093 if (rvalue.isScalar() && !atomics.hasPadding()) { 01094 llvm::Value *value = rvalue.getScalarVal(); 01095 if (isa<llvm::IntegerType>(value->getType())) { 01096 intValue = value; 01097 } else { 01098 llvm::IntegerType *inputIntTy = 01099 llvm::IntegerType::get(getLLVMContext(), atomics.getValueSizeInBits()); 01100 if (isa<llvm::PointerType>(value->getType())) { 01101 intValue = Builder.CreatePtrToInt(value, inputIntTy); 01102 } else { 01103 intValue = Builder.CreateBitCast(value, inputIntTy); 01104 } 01105 } 01106 01107 // Otherwise, we need to go through memory. 01108 } else { 01109 // Put the r-value in memory. 01110 llvm::Value *addr = atomics.materializeRValue(rvalue); 01111 01112 // Cast the temporary to the atomic int type and pull a value out. 01113 addr = atomics.emitCastToAtomicIntPointer(addr); 01114 intValue = Builder.CreateAlignedLoad(addr, 01115 atomics.getAtomicAlignment().getQuantity()); 01116 } 01117 01118 // Do the atomic store. 01119 llvm::Value *addr = atomics.emitCastToAtomicIntPointer(dest.getAddress()); 01120 llvm::StoreInst *store = Builder.CreateStore(intValue, addr); 01121 01122 // Initializations don't need to be atomic. 01123 if (!isInit) store->setAtomic(llvm::SequentiallyConsistent); 01124 01125 // Other decoration. 01126 store->setAlignment(dest.getAlignment().getQuantity()); 01127 if (dest.isVolatileQualified()) 01128 store->setVolatile(true); 01129 if (dest.getTBAAInfo()) 01130 CGM.DecorateInstruction(store, dest.getTBAAInfo()); 01131 } 01132 01133 void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) { 01134 AtomicInfo atomics(*this, dest); 01135 01136 switch (atomics.getEvaluationKind()) { 01137 case TEK_Scalar: { 01138 llvm::Value *value = EmitScalarExpr(init); 01139 atomics.emitCopyIntoMemory(RValue::get(value), dest); 01140 return; 01141 } 01142 01143 case TEK_Complex: { 01144 ComplexPairTy value = EmitComplexExpr(init); 01145 atomics.emitCopyIntoMemory(RValue::getComplex(value), dest); 01146 return; 01147 } 01148 01149 case TEK_Aggregate: { 01150 // Fix up the destination if the initializer isn't an expression 01151 // of atomic type. 01152 bool Zeroed = false; 01153 if (!init->getType()->isAtomicType()) { 01154 Zeroed = atomics.emitMemSetZeroIfNecessary(dest); 01155 dest = atomics.projectValue(dest); 01156 } 01157 01158 // Evaluate the expression directly into the destination. 01159 AggValueSlot slot = AggValueSlot::forLValue(dest, 01160 AggValueSlot::IsNotDestructed, 01161 AggValueSlot::DoesNotNeedGCBarriers, 01162 AggValueSlot::IsNotAliased, 01163 Zeroed ? AggValueSlot::IsZeroed : 01164 AggValueSlot::IsNotZeroed); 01165 01166 EmitAggExpr(init, slot); 01167 return; 01168 } 01169 } 01170 llvm_unreachable("bad evaluation kind"); 01171 }