//===--- Atomic.h - Codegen of atomic operations ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_FRONTEND_ATOMIC_ATOMIC_H #define LLVM_FRONTEND_ATOMIC_ATOMIC_H #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" #include "llvm/Support/Compiler.h" namespace llvm { class AtomicInfo { protected: IRBuilderBase *Builder; Type *Ty; uint64_t AtomicSizeInBits; uint64_t ValueSizeInBits; Align AtomicAlign; Align ValueAlign; bool UseLibcall; IRBuilderBase::InsertPoint AllocaIP; public: AtomicInfo(IRBuilderBase *Builder, Type *Ty, uint64_t AtomicSizeInBits, uint64_t ValueSizeInBits, Align AtomicAlign, Align ValueAlign, bool UseLibcall, IRBuilderBase::InsertPoint AllocaIP) : Builder(Builder), Ty(Ty), AtomicSizeInBits(AtomicSizeInBits), ValueSizeInBits(ValueSizeInBits), AtomicAlign(AtomicAlign), ValueAlign(ValueAlign), UseLibcall(UseLibcall), AllocaIP(AllocaIP) {} virtual ~AtomicInfo() = default; Align getAtomicAlignment() const { return AtomicAlign; } uint64_t getAtomicSizeInBits() const { return AtomicSizeInBits; } uint64_t getValueSizeInBits() const { return ValueSizeInBits; } bool shouldUseLibcall() const { return UseLibcall; } Type *getAtomicTy() const { return Ty; } virtual Value *getAtomicPointer() const = 0; virtual void decorateWithTBAA(Instruction *I) = 0; virtual AllocaInst *CreateAlloca(Type *Ty, const Twine &Name) const = 0; /* * Is the atomic size larger than the underlying value type? * Note that the absence of padding does not mean that atomic * objects are completely interchangeable with non-atomic * objects: we might have promoted the alignment of a type * without making it bigger. */ bool hasPadding() const { return (ValueSizeInBits != AtomicSizeInBits); } LLVMContext &getLLVMContext() const { return Builder->getContext(); } LLVM_ABI bool shouldCastToInt(Type *ValTy, bool CmpXchg); LLVM_ABI Value *EmitAtomicLoadOp(AtomicOrdering AO, bool IsVolatile, bool CmpXchg = false); LLVM_ABI CallInst *EmitAtomicLibcall(StringRef fnName, Type *ResultType, ArrayRef Args); Value *getAtomicSizeValue() const { LLVMContext &ctx = getLLVMContext(); // TODO: Get from llvm::TargetMachine / clang::TargetInfo // if clang shares this codegen in future constexpr uint16_t SizeTBits = 64; constexpr uint16_t BitsPerByte = 8; return ConstantInt::get(IntegerType::get(ctx, SizeTBits), AtomicSizeInBits / BitsPerByte); } LLVM_ABI std::pair EmitAtomicCompareExchangeLibcall(Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success, AtomicOrdering Failure); Value *castToAtomicIntPointer(Value *addr) const { return addr; // opaque pointer } Value *getAtomicAddressAsAtomicIntPointer() const { return castToAtomicIntPointer(getAtomicPointer()); } LLVM_ABI std::pair EmitAtomicCompareExchangeOp(Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success, AtomicOrdering Failure, bool IsVolatile = false, bool IsWeak = false); LLVM_ABI std::pair EmitAtomicCompareExchange(Value *ExpectedVal, Value *DesiredVal, AtomicOrdering Success, AtomicOrdering Failure, bool IsVolatile, bool IsWeak); LLVM_ABI std::pair EmitAtomicLoadLibcall(AtomicOrdering AO); LLVM_ABI void EmitAtomicStoreLibcall(AtomicOrdering AO, Value *Source); }; } // end namespace llvm #endif /* LLVM_FRONTEND_ATOMIC_ATOMIC_H */