Files
gps/tools/local/circt/include/llvm/Frontend/Atomic/Atomic.h
T
2026-07-12 11:01:51 +03:00

108 lines
4.0 KiB
C++

//===--- 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<Value *> 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<Value *, Value *>
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<Value *, Value *>
EmitAtomicCompareExchangeOp(Value *ExpectedVal, Value *DesiredVal,
AtomicOrdering Success, AtomicOrdering Failure,
bool IsVolatile = false, bool IsWeak = false);
LLVM_ABI std::pair<Value *, Value *>
EmitAtomicCompareExchange(Value *ExpectedVal, Value *DesiredVal,
AtomicOrdering Success, AtomicOrdering Failure,
bool IsVolatile, bool IsWeak);
LLVM_ABI std::pair<LoadInst *, AllocaInst *>
EmitAtomicLoadLibcall(AtomicOrdering AO);
LLVM_ABI void EmitAtomicStoreLibcall(AtomicOrdering AO, Value *Source);
};
} // end namespace llvm
#endif /* LLVM_FRONTEND_ATOMIC_ATOMIC_H */