Skip to content

Commit

Permalink
Add new AST MultiRegisterAST to instructionAPI
Browse files Browse the repository at this point in the history
This commit introduce a new ast that denotes the use of multiple
registers as a single operand.

For now, the visitor for such a class
is basically visiting the registers contained in it, in order.

The constructor of the Expression class has been restructured to
avoid redundant implementation.
  • Loading branch information
bbiiggppiigg committed Apr 30, 2024
1 parent 030cc2d commit f589bae
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 17 deletions.
1 change: 1 addition & 0 deletions instructionAPI/h/ArchSpecificFormatters.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ namespace Dyninst {
// Helper function for formatting consecutive registers that are displayed as a single operand
// Called when architecture is passed to Instruction.format.
static std::string formatRegister(MachRegister m_Reg, uint32_t num_elements, unsigned m_Low , unsigned m_High );
static std::string formatMultiRegister(MachRegister m_Reg, uint32_t size);
private:
std::map<std::string, std::string> binaryFuncModifier;
};
Expand Down
2 changes: 1 addition & 1 deletion instructionAPI/h/MultiRegister.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ namespace Dyninst

RegisterAST::Ptr getBaseRegAST() const { return m_Regs[0]; }
uint32_t length() const { return m_Regs.size(); }
const std::vector<RegisterAST::Ptr> getRegs() const { return m_Regs; }
const std::vector<RegisterAST::Ptr> &getRegs() const { return m_Regs; }
protected:

virtual bool checkRegID(MachRegister id, unsigned int low, unsigned int high) const;
Expand Down
38 changes: 38 additions & 0 deletions instructionAPI/src/ArchSpecificFormatters.C
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,44 @@ std::string AmdgpuFormatter::formatRegister(MachRegister m_Reg, uint32_t m_num_
return name;
}

std::string AmdgpuFormatter::formatMultiRegister(MachRegister m_Reg, uint32_t size) {
std::string name = m_Reg.name();
std::string::size_type substr = name.rfind("::");
if(substr != std::string::npos){
name = name.substr(substr+2,name.length());
}
assert(size > 1);
uint32_t id = m_Reg & 0xff ;
uint32_t regClass = m_Reg.regClass();

DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_LOGICAL_OP

if(regClass == amdgpu_gfx908::SGPR || regClass == amdgpu_gfx90a::SGPR ||
regClass == amdgpu_gfx940::SGPR){
return "S["+std::to_string(id) + ":" + std::to_string(id+size-1)+"]";
}

if(regClass == amdgpu_gfx908::VGPR || regClass == amdgpu_gfx90a::VGPR ||
regClass == amdgpu_gfx940::VGPR){
return "V["+std::to_string(id) + ":" + std::to_string(id+size-1)+"]";
}

if(regClass == amdgpu_gfx908::ACC_VGPR || regClass == amdgpu_gfx90a::ACC_VGPR ||
regClass == amdgpu_gfx940::ACC_VGPR){
return "ACC["+std::to_string(id) + ":" + std::to_string(id+size-1)+"]";
}

DYNINST_DIAGNOSTIC_END_SUPPRESS_LOGICAL_OP

if(m_Reg == amdgpu_gfx908::vcc_lo || m_Reg == amdgpu_gfx90a::vcc_lo ||
m_Reg == amdgpu_gfx940::vcc_lo)
return "VCC";
if(m_Reg == amdgpu_gfx908::exec_lo || m_Reg == amdgpu_gfx90a::exec_lo ||
m_Reg == amdgpu_gfx940::exec_lo)
return "EXEC";

return name;
}

/////////////////////////// x86 Formatter functions

Expand Down
6 changes: 6 additions & 0 deletions instructionAPI/src/InstructionDecoderImpl.C
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ namespace Dyninst
return make_shared(singleton_object_pool<RegisterAST>::construct(converted, 0, registerID.size() * 8,num_elements));
}

Expression::Ptr InstructionDecoderImpl::makeMultiRegisterExpression(MachRegister registerID, uint32_t num_elements )
{
return make_shared(singleton_object_pool<MultiRegisterAST>::construct(registerID, num_elements));
}



Expression::Ptr InstructionDecoderImpl::makeRegisterExpression(MachRegister registerID, unsigned int start , unsigned int end)
{
Expand Down
2 changes: 2 additions & 0 deletions instructionAPI/src/InstructionDecoderImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include <stdint.h>
#include "Expression.h"
#include "MultiRegister.h"
#include "Architecture.h"
#include "Operation_impl.h"
#include "entryIDs.h"
Expand Down Expand Up @@ -71,6 +72,7 @@ class InstructionDecoderImpl



virtual Expression::Ptr makeMultiRegisterExpression(MachRegister reg, uint32_t num_elements);
virtual Expression::Ptr makeRegisterExpression(MachRegister reg, uint32_t num_elements = 1);
// added version to support loading partial values out of register
virtual Expression::Ptr makeRegisterExpression(MachRegister reg, unsigned int start , unsigned int end);
Expand Down
26 changes: 13 additions & 13 deletions instructionAPI/src/MultiRegister.C
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ namespace Dyninst
}
bool MultiRegisterAST::isUsed(InstructionAST::Ptr findMe) const
{
for (const auto regAST : m_Regs) {
for (const auto &regAST : m_Regs) {
if (findMe->checkRegID(regAST->getID(), regAST->lowBit(), regAST->highBit()))
return true;
}
Expand All @@ -89,24 +89,24 @@ namespace Dyninst

std::string MultiRegisterAST::format(Architecture arch, formatStyle) const
{
/*if(arch == Arch_amdgpu_gfx908 || arch == Arch_amdgpu_gfx90a || arch == Arch_amdgpu_gfx940){
return AmdgpuFormatter::formatRegister(m_Reg,m_num_elements,m_Low,m_High);
}*/
return ArchSpecificFormatter::getFormatter(arch).formatRegister(m_Regs[0]->getID().name());
if(arch == Arch_amdgpu_gfx908 || arch == Arch_amdgpu_gfx90a || arch == Arch_amdgpu_gfx940){
return AmdgpuFormatter::formatMultiRegister(m_Regs[0]->getID(),m_Regs.size());
}
assert(0 && " multi register currently defined for amdgpu formats only ");
return std::string("");
}

std::string MultiRegisterAST::format(formatStyle) const
{
std::string name = m_Regs[0]->getID().name();
std::string::size_type substr = name.rfind("::");
if(substr != std::string::npos)
{
name = name.substr(substr + 2, name.length());
std::string ret("[");
ret.append(m_Regs[0]->format());
for (uint32_t i = 1; i < m_Regs.size(); i++){
ret.append(std::string(","));
ret.append(m_Regs[i]->format());
}
/* we have moved to AT&T syntax (lowercase registers) */
for(char &c : name) c = std::toupper(c);
ret.append(std::string("]"));

return name;
return ret;
}

bool MultiRegisterAST::operator<(const MultiRegisterAST& rhs) const
Expand Down
31 changes: 28 additions & 3 deletions instructionAPI/src/Operand.C
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "../h/Operand.h"
#include "../h/Dereference.h"
#include "../h/Register.h"
#include "../h/MultiRegister.h"
#include "../h/Immediate.h"
#include "../h/Expression.h"
#include "../h/BinaryFunction.h"
Expand All @@ -56,15 +57,39 @@ namespace Dyninst
{
if(m_isRead || !(*tmp == *op_value))
regsRead.insert(tmp);
}else{

MultiRegisterAST::Ptr multitmp = boost::dynamic_pointer_cast<MultiRegisterAST>(*curUse);
if(tmp)
{
for (auto reg : multitmp->getRegs()){
if(m_isRead || !(*reg == *op_value))
regsRead.insert(reg);
}
}

}
}
}
INSTRUCTION_EXPORT void Operand::getWriteSet(std::set<RegisterAST::Ptr>& regsWritten) const
{
RegisterAST::Ptr op_as_reg = boost::dynamic_pointer_cast<RegisterAST>(op_value);
if(m_isWritten && op_as_reg)
if(m_isWritten)
{
regsWritten.insert(op_as_reg);
RegisterAST::Ptr op_as_reg = boost::dynamic_pointer_cast<RegisterAST>(op_value);
if(op_as_reg){
regsWritten.insert(op_as_reg);
}else
{

MultiRegisterAST::Ptr op_as_multireg = boost::dynamic_pointer_cast<MultiRegisterAST>(op_value);
if(op_as_reg)
{
for (auto reg : op_as_multireg->getRegs()){
regsWritten.insert(reg);
}

}
}
}
}

Expand Down

0 comments on commit f589bae

Please sign in to comment.