/// EmitStoreOfComplex - Store the specified real/imag parts into the /// specified value pointer. void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue, bool isInit) { if (lvalue.getType()->isAtomicType() || (!isInit && CGF.LValueIsSuitableForInlineAtomic(lvalue))) return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit); Address Ptr = lvalue.getAddress(); Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType()); Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType()); Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified()); Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified()); }
/// EmitStoreOfComplex - Store the specified real/imag parts into the /// specified value pointer. void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue, bool isInit) { if (lvalue.getType()->isAtomicType()) return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit); llvm::Value *Ptr = lvalue.getAddress(); llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, "real"); llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, "imag"); // TODO: alignment Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified()); Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified()); }
ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) { ComplexPairTy Val; LValue LV = EmitBinAssignLValue(E, Val); // The result of an assignment in C is the assigned r-value. if (!CGF.getContext().getLangOptions().CPlusPlus) return Val; // If the lvalue is non-volatile, return the computed value of the assignment. if (!LV.isVolatileQualified()) return Val; return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified()); }
void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { // For an assignment to work, the value on the right has // to be compatible with the value on the left. assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(), E->getRHS()->getType()) && "Invalid assignment"); LValue LHS = CGF.EmitLValue(E->getLHS()); // We have to special case property setters, otherwise we must have // a simple lvalue (no aggregates inside vectors, bitfields). if (LHS.isPropertyRef()) { llvm::Value *AggLoc = DestPtr; if (!AggLoc) AggLoc = CGF.CreateMemTemp(E->getRHS()->getType()); CGF.EmitAggExpr(E->getRHS(), AggLoc, VolatileDest); CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), RValue::getAggregate(AggLoc, VolatileDest)); } else if (LHS.isKVCRef()) { llvm::Value *AggLoc = DestPtr; if (!AggLoc) AggLoc = CGF.CreateMemTemp(E->getRHS()->getType()); CGF.EmitAggExpr(E->getRHS(), AggLoc, VolatileDest); CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), RValue::getAggregate(AggLoc, VolatileDest)); } else { bool RequiresGCollection = false; if (CGF.getContext().getLangOptions().getGCMode()) RequiresGCollection = TypeRequiresGCollection(E->getLHS()->getType()); // Codegen the RHS so that it stores directly into the LHS. CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), LHS.isVolatileQualified(), false, false, RequiresGCollection); EmitFinalDestCopy(E, LHS, true); } }
/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) { assert(Src.isSimple() && "Can't have aggregate bitfield, vector, etc"); EmitFinalDestCopy(E, RValue::getAggregate(Src.getAddress(), Src.isVolatileQualified()), Ignore); }
/// Copy an r-value into memory as part of storing to an atomic type. /// This needs to create a bit-pattern suitable for atomic operations. void AtomicInfo::emitCopyIntoMemory(RValue rvalue, LValue dest) const { // If we have an r-value, the rvalue should be of the atomic type, // which means that the caller is responsible for having zeroed // any padding. Just do an aggregate copy of that type. if (rvalue.isAggregate()) { CGF.EmitAggregateCopy(dest.getAddress(), rvalue.getAggregateAddr(), getAtomicType(), (rvalue.isVolatileQualified() || dest.isVolatileQualified()), dest.getAlignment()); return; } // Okay, otherwise we're copying stuff. // Zero out the buffer if necessary. emitMemSetZeroIfNecessary(dest); // Drill past the padding if present. dest = projectValue(dest); // Okay, store the rvalue in. if (rvalue.isScalar()) { CGF.EmitStoreOfScalar(rvalue.getScalarVal(), dest, /*init*/ true); } else { CGF.EmitStoreOfComplex(rvalue.getComplexVal(), dest, /*init*/ true); } }
LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) { assert(hasAggregateLLVMType(E->getType()) && "Invalid argument!"); llvm::Value *Temp = CreateMemTemp(E->getType()); LValue LV = MakeAddrLValue(Temp, E->getType()); EmitAggExpr(E, Temp, LV.isVolatileQualified()); return LV; }
/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to /// load the real and imaginary pieces, returning them as Real/Imag. ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue, SourceLocation loc) { assert(lvalue.isSimple() && "non-simple complex l-value?"); if (lvalue.getType()->isAtomicType()) return CGF.EmitAtomicLoad(lvalue, loc).getComplexVal(); llvm::Value *SrcPtr = lvalue.getAddress(); bool isVolatile = lvalue.isVolatileQualified(); unsigned AlignR = lvalue.getAlignment().getQuantity(); ASTContext &C = CGF.getContext(); QualType ComplexTy = lvalue.getType(); unsigned ComplexAlign = C.getTypeAlignInChars(ComplexTy).getQuantity(); unsigned AlignI = std::min(AlignR, ComplexAlign); llvm::Value *Real=nullptr, *Imag=nullptr; if (!IgnoreReal || isVolatile) { llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0, SrcPtr->getName() + ".realp"); Real = Builder.CreateAlignedLoad(RealP, AlignR, isVolatile, SrcPtr->getName() + ".real"); } if (!IgnoreImag || isVolatile) { llvm::Value *ImagP = Builder.CreateStructGEP(SrcPtr, 1, SrcPtr->getName() + ".imagp"); Imag = Builder.CreateAlignedLoad(ImagP, AlignI, isVolatile, SrcPtr->getName() + ".imag"); } return ComplexPairTy(Real, Imag); }
/// EmitStoreOfComplex - Store the specified real/imag parts into the /// specified value pointer. void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue, bool isInit) { if (lvalue.getType()->isAtomicType()) return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit); llvm::Value *Ptr = lvalue.getAddress(); llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, "real"); llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, "imag"); unsigned AlignR = lvalue.getAlignment().getQuantity(); ASTContext &C = CGF.getContext(); QualType ComplexTy = lvalue.getType(); unsigned ComplexAlign = C.getTypeAlignInChars(ComplexTy).getQuantity(); unsigned AlignI = std::min(AlignR, ComplexAlign); Builder.CreateAlignedStore(Val.first, RealPtr, AlignR, lvalue.isVolatileQualified()); Builder.CreateAlignedStore(Val.second, ImagPtr, AlignI, lvalue.isVolatileQualified()); }
// Compound assignments. ComplexPairTy ComplexExprEmitter:: EmitCompoundAssign(const CompoundAssignOperator *E, ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)) { ComplexPairTy Val; LValue LV = EmitCompoundAssignLValue(E, Func, Val); // The result of an assignment in C is the assigned r-value. if (!CGF.getContext().getLangOptions().CPlusPlus) return Val; // Objective-C property assignment never reloads the value following a store. if (LV.isPropertyRef()) return Val; // If the lvalue is non-volatile, return the computed value of the assignment. if (!LV.isVolatileQualified()) return Val; return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified()); }
/// Emit a store to an l-value of atomic type. /// /// Note that the r-value is expected to be an r-value *of the atomic /// type*; this means that for aggregate r-values, it should include /// storage for any padding that was necessary. void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, bool isInit) { // If this is an aggregate r-value, it should agree in type except // maybe for address-space qualification. assert(!rvalue.isAggregate() || rvalue.getAggregateAddr()->getType()->getPointerElementType() == dest.getAddress()->getType()->getPointerElementType()); AtomicInfo atomics(*this, dest); // If this is an initialization, just put the value there normally. if (isInit) { atomics.emitCopyIntoMemory(rvalue, dest); return; } // Check whether we should use a library call. if (atomics.shouldUseLibcall()) { // Produce a source address. llvm::Value *srcAddr = atomics.materializeRValue(rvalue); // void __atomic_store(size_t size, void *mem, void *val, int order) CallArgList args; args.add(RValue::get(atomics.getAtomicSizeValue()), getContext().getSizeType()); args.add(RValue::get(EmitCastToVoidPtr(dest.getAddress())), getContext().VoidPtrTy); args.add(RValue::get(EmitCastToVoidPtr(srcAddr)), getContext().VoidPtrTy); args.add(RValue::get(llvm::ConstantInt::get( IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)), getContext().IntTy); emitAtomicLibcall(*this, "__atomic_store", getContext().VoidTy, args); return; } // Okay, we're doing this natively. llvm::Value *intValue = atomics.convertRValueToInt(rvalue); // Do the atomic store. llvm::Value *addr = atomics.emitCastToAtomicIntPointer(dest.getAddress()); llvm::StoreInst *store = Builder.CreateStore(intValue, addr); // Initializations don't need to be atomic. if (!isInit) store->setAtomic(llvm::SequentiallyConsistent); // Other decoration. store->setAlignment(dest.getAlignment().getQuantity()); if (dest.isVolatileQualified()) store->setVolatile(true); if (dest.getTBAAInfo()) CGM.DecorateInstruction(store, dest.getTBAAInfo()); }
/// Emit a load from an l-value of atomic type. Note that the r-value /// we produce is an r-value of the atomic *value* type. RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc, AggValueSlot resultSlot) { AtomicInfo atomics(*this, src); // Check whether we should use a library call. if (atomics.shouldUseLibcall()) { llvm::Value *tempAddr; if (!resultSlot.isIgnored()) { assert(atomics.getEvaluationKind() == TEK_Aggregate); tempAddr = resultSlot.getAddr(); } else { tempAddr = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp"); } // void __atomic_load(size_t size, void *mem, void *return, int order); CallArgList args; args.add(RValue::get(atomics.getAtomicSizeValue()), getContext().getSizeType()); args.add(RValue::get(EmitCastToVoidPtr(src.getAddress())), getContext().VoidPtrTy); args.add(RValue::get(EmitCastToVoidPtr(tempAddr)), getContext().VoidPtrTy); args.add(RValue::get(llvm::ConstantInt::get( IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)), getContext().IntTy); emitAtomicLibcall(*this, "__atomic_load", getContext().VoidTy, args); // Produce the r-value. return atomics.convertTempToRValue(tempAddr, resultSlot, loc); } // Okay, we're doing this natively. llvm::Value *addr = atomics.emitCastToAtomicIntPointer(src.getAddress()); llvm::LoadInst *load = Builder.CreateLoad(addr, "atomic-load"); load->setAtomic(llvm::SequentiallyConsistent); // Other decoration. load->setAlignment(src.getAlignment().getQuantity()); if (src.isVolatileQualified()) load->setVolatile(true); if (src.getTBAAInfo()) CGM.DecorateInstruction(load, src.getTBAAInfo()); // If we're ignoring an aggregate return, don't do anything. if (atomics.getEvaluationKind() == TEK_Aggregate && resultSlot.isIgnored()) return RValue::getAggregate(nullptr, false); // Okay, turn that back into the original value type. return atomics.convertIntToValue(load, resultSlot, loc); }
// Compound assignments. ComplexPairTy ComplexExprEmitter:: EmitCompoundAssign(const CompoundAssignOperator *E, ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){ ComplexPairTy Val; LValue LV = EmitCompoundAssignLValue(E, Func, Val); // The result of an assignment in C is the assigned r-value. if (!CGF.getLangOpts().CPlusPlus) return Val; // If the lvalue is non-volatile, return the computed value of the assignment. if (!LV.isVolatileQualified()) return Val; return EmitLoadOfLValue(LV); }
/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to /// load the real and imaginary pieces, returning them as Real/Imag. ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue, SourceLocation loc) { assert(lvalue.isSimple() && "non-simple complex l-value?"); if (lvalue.getType()->isAtomicType()) return CGF.EmitAtomicLoad(lvalue, loc).getComplexVal(); Address SrcPtr = lvalue.getAddress(); bool isVolatile = lvalue.isVolatileQualified(); llvm::Value *Real = nullptr, *Imag = nullptr; if (!IgnoreReal || isVolatile) { Address RealP = CGF.emitAddrOfRealComponent(SrcPtr, lvalue.getType()); Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr.getName() + ".real"); } if (!IgnoreImag || isVolatile) { Address ImagP = CGF.emitAddrOfImagComponent(SrcPtr, lvalue.getType()); Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr.getName() + ".imag"); } return ComplexPairTy(Real, Imag); }
/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to /// load the real and imaginary pieces, returning them as Real/Imag. ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue) { assert(lvalue.isSimple() && "non-simple complex l-value?"); if (lvalue.getType()->isAtomicType()) return CGF.EmitAtomicLoad(lvalue).getComplexVal(); llvm::Value *SrcPtr = lvalue.getAddress(); bool isVolatile = lvalue.isVolatileQualified(); llvm::Value *Real=0, *Imag=0; if (!IgnoreReal || isVolatile) { llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0, SrcPtr->getName() + ".realp"); Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr->getName() + ".real"); } if (!IgnoreImag || isVolatile) { llvm::Value *ImagP = Builder.CreateStructGEP(SrcPtr, 1, SrcPtr->getName() + ".imagp"); Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr->getName() + ".imag"); } return ComplexPairTy(Real, Imag); }
/// Emit a compare-and-exchange op for atomic type. /// std::pair<RValue, RValue> CodeGenFunction::EmitAtomicCompareExchange( LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc, llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak, AggValueSlot Slot) { // If this is an aggregate r-value, it should agree in type except // maybe for address-space qualification. assert(!Expected.isAggregate() || Expected.getAggregateAddr()->getType()->getPointerElementType() == Obj.getAddress()->getType()->getPointerElementType()); assert(!Desired.isAggregate() || Desired.getAggregateAddr()->getType()->getPointerElementType() == Obj.getAddress()->getType()->getPointerElementType()); AtomicInfo Atomics(*this, Obj); if (Failure >= Success) // Don't assert on undefined behavior. Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(Success); auto Alignment = Atomics.getValueAlignment(); // Check whether we should use a library call. if (Atomics.shouldUseLibcall()) { auto *ExpectedAddr = Atomics.materializeRValue(Expected); // Produce a source address. auto *DesiredAddr = Atomics.materializeRValue(Desired); // bool __atomic_compare_exchange(size_t size, void *obj, void *expected, // void *desired, int success, int failure); CallArgList Args; Args.add(RValue::get(Atomics.getAtomicSizeValue()), getContext().getSizeType()); Args.add(RValue::get(EmitCastToVoidPtr(Obj.getAddress())), getContext().VoidPtrTy); Args.add(RValue::get(EmitCastToVoidPtr(ExpectedAddr)), getContext().VoidPtrTy); Args.add(RValue::get(EmitCastToVoidPtr(DesiredAddr)), getContext().VoidPtrTy); Args.add(RValue::get(llvm::ConstantInt::get(IntTy, Success)), getContext().IntTy); Args.add(RValue::get(llvm::ConstantInt::get(IntTy, Failure)), getContext().IntTy); auto SuccessFailureRVal = emitAtomicLibcall( *this, "__atomic_compare_exchange", getContext().BoolTy, Args); auto *PreviousVal = Builder.CreateAlignedLoad(ExpectedAddr, Alignment.getQuantity()); return std::make_pair(RValue::get(PreviousVal), SuccessFailureRVal); } // If we've got a scalar value of the right size, try to avoid going // through memory. auto *ExpectedIntVal = Atomics.convertRValueToInt(Expected); auto *DesiredIntVal = Atomics.convertRValueToInt(Desired); // Do the atomic store. auto *Addr = Atomics.emitCastToAtomicIntPointer(Obj.getAddress()); auto *Inst = Builder.CreateAtomicCmpXchg(Addr, ExpectedIntVal, DesiredIntVal, Success, Failure); // Other decoration. Inst->setVolatile(Obj.isVolatileQualified()); Inst->setWeak(IsWeak); // Okay, turn that back into the original value type. auto *PreviousVal = Builder.CreateExtractValue(Inst, /*Idxs=*/0); auto *SuccessFailureVal = Builder.CreateExtractValue(Inst, /*Idxs=*/1); return std::make_pair(Atomics.convertIntToValue(PreviousVal, Slot, Loc), RValue::get(SuccessFailureVal)); }
/// Emit a store to an l-value of atomic type. /// /// Note that the r-value is expected to be an r-value *of the atomic /// type*; this means that for aggregate r-values, it should include /// storage for any padding that was necessary. void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, bool isInit) { // If this is an aggregate r-value, it should agree in type except // maybe for address-space qualification. assert(!rvalue.isAggregate() || rvalue.getAggregateAddr()->getType()->getPointerElementType() == dest.getAddress()->getType()->getPointerElementType()); AtomicInfo atomics(*this, dest); // If this is an initialization, just put the value there normally. if (isInit) { atomics.emitCopyIntoMemory(rvalue, dest); return; } // Check whether we should use a library call. if (atomics.shouldUseLibcall()) { // Produce a source address. llvm::Value *srcAddr = atomics.materializeRValue(rvalue); // void __atomic_store(size_t size, void *mem, void *val, int order) CallArgList args; args.add(RValue::get(atomics.getAtomicSizeValue()), getContext().getSizeType()); args.add(RValue::get(EmitCastToVoidPtr(dest.getAddress())), getContext().VoidPtrTy); args.add(RValue::get(EmitCastToVoidPtr(srcAddr)), getContext().VoidPtrTy); args.add(RValue::get(llvm::ConstantInt::get( IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)), getContext().IntTy); emitAtomicLibcall(*this, "__atomic_store", getContext().VoidTy, args); return; } // Okay, we're doing this natively. llvm::Value *intValue; // If we've got a scalar value of the right size, try to avoid going // through memory. if (rvalue.isScalar() && !atomics.hasPadding()) { llvm::Value *value = rvalue.getScalarVal(); if (isa<llvm::IntegerType>(value->getType())) { intValue = value; } else { llvm::IntegerType *inputIntTy = llvm::IntegerType::get(getLLVMContext(), atomics.getValueSizeInBits()); if (isa<llvm::PointerType>(value->getType())) { intValue = Builder.CreatePtrToInt(value, inputIntTy); } else { intValue = Builder.CreateBitCast(value, inputIntTy); } } // Otherwise, we need to go through memory. } else { // Put the r-value in memory. llvm::Value *addr = atomics.materializeRValue(rvalue); // Cast the temporary to the atomic int type and pull a value out. addr = atomics.emitCastToAtomicIntPointer(addr); intValue = Builder.CreateAlignedLoad(addr, atomics.getAtomicAlignment().getQuantity()); } // Do the atomic store. llvm::Value *addr = atomics.emitCastToAtomicIntPointer(dest.getAddress()); llvm::StoreInst *store = Builder.CreateStore(intValue, addr); // Initializations don't need to be atomic. if (!isInit) store->setAtomic(llvm::SequentiallyConsistent); // Other decoration. store->setAlignment(dest.getAlignment().getQuantity()); if (dest.isVolatileQualified()) store->setVolatile(true); if (dest.getTBAAInfo()) CGM.DecorateInstruction(store, dest.getTBAAInfo()); }
/// Emit a load from an l-value of atomic type. Note that the r-value /// we produce is an r-value of the atomic *value* type. RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc, AggValueSlot resultSlot) { AtomicInfo atomics(*this, src); // Check whether we should use a library call. if (atomics.shouldUseLibcall()) { llvm::Value *tempAddr; if (!resultSlot.isIgnored()) { assert(atomics.getEvaluationKind() == TEK_Aggregate); tempAddr = resultSlot.getAddr(); } else { tempAddr = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp"); } // void __atomic_load(size_t size, void *mem, void *return, int order); CallArgList args; args.add(RValue::get(atomics.getAtomicSizeValue()), getContext().getSizeType()); args.add(RValue::get(EmitCastToVoidPtr(src.getAddress())), getContext().VoidPtrTy); args.add(RValue::get(EmitCastToVoidPtr(tempAddr)), getContext().VoidPtrTy); args.add(RValue::get(llvm::ConstantInt::get( IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)), getContext().IntTy); emitAtomicLibcall(*this, "__atomic_load", getContext().VoidTy, args); // Produce the r-value. return atomics.convertTempToRValue(tempAddr, resultSlot, loc); } // Okay, we're doing this natively. llvm::Value *addr = atomics.emitCastToAtomicIntPointer(src.getAddress()); llvm::LoadInst *load = Builder.CreateLoad(addr, "atomic-load"); load->setAtomic(llvm::SequentiallyConsistent); // Other decoration. load->setAlignment(src.getAlignment().getQuantity()); if (src.isVolatileQualified()) load->setVolatile(true); if (src.getTBAAInfo()) CGM.DecorateInstruction(load, src.getTBAAInfo()); // Okay, turn that back into the original value type. QualType valueType = atomics.getValueType(); llvm::Value *result = load; // If we're ignoring an aggregate return, don't do anything. if (atomics.getEvaluationKind() == TEK_Aggregate && resultSlot.isIgnored()) return RValue::getAggregate(0, false); // The easiest way to do this this is to go through memory, but we // try not to in some easy cases. if (atomics.getEvaluationKind() == TEK_Scalar && !atomics.hasPadding()) { llvm::Type *resultTy = CGM.getTypes().ConvertTypeForMem(valueType); if (isa<llvm::IntegerType>(resultTy)) { assert(result->getType() == resultTy); result = EmitFromMemory(result, valueType); } else if (isa<llvm::PointerType>(resultTy)) { result = Builder.CreateIntToPtr(result, resultTy); } else { result = Builder.CreateBitCast(result, resultTy); } return RValue::get(result); } // Create a temporary. This needs to be big enough to hold the // atomic integer. llvm::Value *temp; bool tempIsVolatile = false; CharUnits tempAlignment; if (atomics.getEvaluationKind() == TEK_Aggregate) { assert(!resultSlot.isIgnored()); temp = resultSlot.getAddr(); tempAlignment = atomics.getValueAlignment(); tempIsVolatile = resultSlot.isVolatile(); } else { temp = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp"); tempAlignment = atomics.getAtomicAlignment(); } // Slam the integer into the temporary. llvm::Value *castTemp = atomics.emitCastToAtomicIntPointer(temp); Builder.CreateAlignedStore(result, castTemp, tempAlignment.getQuantity()) ->setVolatile(tempIsVolatile); return atomics.convertTempToRValue(temp, resultSlot, loc); }