203 lines
6.4 KiB
C++
203 lines
6.4 KiB
C++
//===-- PTXMachineFuctionInfo.h - PTX machine function info ------*- C++ -*-==//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file declares PTX-specific per-machine-function information.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef PTX_MACHINE_FUNCTION_INFO_H
|
|
#define PTX_MACHINE_FUNCTION_INFO_H
|
|
|
|
#include "PTX.h"
|
|
#include "PTXParamManager.h"
|
|
#include "PTXRegisterInfo.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/DenseSet.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
namespace llvm {
|
|
|
|
/// PTXMachineFunctionInfo - This class is derived from MachineFunction and
|
|
/// contains private PTX target-specific information for each MachineFunction.
|
|
///
|
|
class PTXMachineFunctionInfo : public MachineFunctionInfo {
|
|
virtual void anchor();
|
|
bool IsKernel;
|
|
DenseSet<unsigned> RegArgs;
|
|
DenseSet<unsigned> RegRets;
|
|
|
|
typedef DenseMap<int, std::string> FrameMap;
|
|
|
|
FrameMap FrameSymbols;
|
|
|
|
struct RegisterInfo {
|
|
unsigned Reg;
|
|
unsigned Type;
|
|
unsigned Space;
|
|
unsigned Offset;
|
|
unsigned Encoded;
|
|
};
|
|
|
|
typedef DenseMap<unsigned, RegisterInfo> RegisterInfoMap;
|
|
|
|
RegisterInfoMap RegInfo;
|
|
|
|
PTXParamManager ParamManager;
|
|
|
|
public:
|
|
typedef DenseSet<unsigned>::const_iterator reg_iterator;
|
|
|
|
PTXMachineFunctionInfo(MachineFunction &MF)
|
|
: IsKernel(false) {
|
|
}
|
|
|
|
/// getParamManager - Returns the PTXParamManager instance for this function.
|
|
PTXParamManager& getParamManager() { return ParamManager; }
|
|
const PTXParamManager& getParamManager() const { return ParamManager; }
|
|
|
|
/// setKernel/isKernel - Gets/sets a flag that indicates if this function is
|
|
/// a PTX kernel function.
|
|
void setKernel(bool _IsKernel=true) { IsKernel = _IsKernel; }
|
|
bool isKernel() const { return IsKernel; }
|
|
|
|
/// argreg_begin/argreg_end - Returns iterators to the set of registers
|
|
/// containing function arguments.
|
|
reg_iterator argreg_begin() const { return RegArgs.begin(); }
|
|
reg_iterator argreg_end() const { return RegArgs.end(); }
|
|
|
|
/// retreg_begin/retreg_end - Returns iterators to the set of registers
|
|
/// containing the function return values.
|
|
reg_iterator retreg_begin() const { return RegRets.begin(); }
|
|
reg_iterator retreg_end() const { return RegRets.end(); }
|
|
|
|
/// addRegister - Adds a virtual register to the set of all used registers
|
|
void addRegister(unsigned Reg, unsigned RegType, unsigned RegSpace) {
|
|
if (!RegInfo.count(Reg)) {
|
|
RegisterInfo Info;
|
|
Info.Reg = Reg;
|
|
Info.Type = RegType;
|
|
Info.Space = RegSpace;
|
|
|
|
// Determine register offset
|
|
Info.Offset = 0;
|
|
for(RegisterInfoMap::const_iterator i = RegInfo.begin(),
|
|
e = RegInfo.end(); i != e; ++i) {
|
|
const RegisterInfo& RI = i->second;
|
|
if (RI.Space == RegSpace)
|
|
if (RI.Space != PTXRegisterSpace::Reg || RI.Type == Info.Type)
|
|
Info.Offset++;
|
|
}
|
|
|
|
// Encode the register data into a single register number
|
|
Info.Encoded = (Info.Offset << 6) | (Info.Type << 3) | Info.Space;
|
|
|
|
RegInfo[Reg] = Info;
|
|
|
|
if (RegSpace == PTXRegisterSpace::Argument)
|
|
RegArgs.insert(Reg);
|
|
else if (RegSpace == PTXRegisterSpace::Return)
|
|
RegRets.insert(Reg);
|
|
}
|
|
}
|
|
|
|
/// countRegisters - Returns the number of registers of the given type and
|
|
/// space.
|
|
unsigned countRegisters(unsigned RegType, unsigned RegSpace) const {
|
|
unsigned Count = 0;
|
|
for(RegisterInfoMap::const_iterator i = RegInfo.begin(), e = RegInfo.end();
|
|
i != e; ++i) {
|
|
const RegisterInfo& RI = i->second;
|
|
if (RI.Type == RegType && RI.Space == RegSpace)
|
|
Count++;
|
|
}
|
|
return Count;
|
|
}
|
|
|
|
/// getEncodedRegister - Returns the encoded value of the register.
|
|
unsigned getEncodedRegister(unsigned Reg) const {
|
|
return RegInfo.lookup(Reg).Encoded;
|
|
}
|
|
|
|
/// addRetReg - Adds a register to the set of return-value registers.
|
|
void addRetReg(unsigned Reg) {
|
|
if (!RegRets.count(Reg)) {
|
|
RegRets.insert(Reg);
|
|
}
|
|
}
|
|
|
|
/// addArgReg - Adds a register to the set of function argument registers.
|
|
void addArgReg(unsigned Reg) {
|
|
RegArgs.insert(Reg);
|
|
}
|
|
|
|
/// getRegisterName - Returns the name of the specified virtual register. This
|
|
/// name is used during PTX emission.
|
|
std::string getRegisterName(unsigned Reg) const {
|
|
if (RegInfo.count(Reg)) {
|
|
const RegisterInfo& RI = RegInfo.lookup(Reg);
|
|
std::string Name;
|
|
raw_string_ostream NameStr(Name);
|
|
decodeRegisterName(NameStr, RI.Encoded);
|
|
NameStr.flush();
|
|
return Name;
|
|
}
|
|
else if (Reg == PTX::NoRegister)
|
|
return "%noreg";
|
|
else
|
|
llvm_unreachable("Register not in register name map");
|
|
}
|
|
|
|
/// getEncodedRegisterName - Returns the name of the encoded register.
|
|
std::string getEncodedRegisterName(unsigned EncodedReg) const {
|
|
std::string Name;
|
|
raw_string_ostream NameStr(Name);
|
|
decodeRegisterName(NameStr, EncodedReg);
|
|
NameStr.flush();
|
|
return Name;
|
|
}
|
|
|
|
/// getRegisterType - Returns the type of the specified virtual register.
|
|
unsigned getRegisterType(unsigned Reg) const {
|
|
if (RegInfo.count(Reg))
|
|
return RegInfo.lookup(Reg).Type;
|
|
else
|
|
llvm_unreachable("Unknown register");
|
|
}
|
|
|
|
/// getOffsetForRegister - Returns the offset of the virtual register
|
|
unsigned getOffsetForRegister(unsigned Reg) const {
|
|
if (RegInfo.count(Reg))
|
|
return RegInfo.lookup(Reg).Offset;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/// getFrameSymbol - Returns the symbol name for the given FrameIndex.
|
|
const char* getFrameSymbol(int FrameIndex) {
|
|
if (FrameSymbols.count(FrameIndex)) {
|
|
return FrameSymbols.lookup(FrameIndex).c_str();
|
|
} else {
|
|
std::string Name = "__local";
|
|
Name += utostr(FrameIndex);
|
|
// The whole point of caching this name is to ensure the pointer we pass
|
|
// to any getExternalSymbol() calls will remain valid for the lifetime of
|
|
// the back-end instance. This is to work around an issue in SelectionDAG
|
|
// where symbol names are expected to be life-long strings.
|
|
FrameSymbols[FrameIndex] = Name;
|
|
return FrameSymbols[FrameIndex].c_str();
|
|
}
|
|
}
|
|
}; // class PTXMachineFunctionInfo
|
|
} // namespace llvm
|
|
|
|
#endif // PTX_MACHINE_FUNCTION_INFO_H
|