Files
TheRock/rocm-systems/projects/rocprofiler-systems/external/dyninst/instructionAPI/h/BinaryFunction.h
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

416 lines
12 KiB
C++

/*
* See the dyninst/COPYRIGHT file for copyright information.
*
* We provide the Paradyn Tools (below described as "Paradyn")
* on an AS IS basis, and do not warrant its validity or performance.
* We reserve the right to update, modify, or discontinue this
* software at any time. We shall have no obligation to supply such
* updates or modifications or any other form of support to you.
*
* By your use of Paradyn, you understand and agree that we (or any
* other person or entity with proprietary rights in Paradyn) are
* under no obligation to provide either maintenance services,
* update services, notices of latent defects, or correction of
* defects for Paradyn.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined(BINARYFUNCTION_H)
#define BINARYFUNCTION_H
#include "Expression.h"
#include "Register.h"
#include "Result.h"
#include "ArchSpecificFormatters.h"
#include <assert.h>
#include <stdint.h>
#include <string>
#include <vector>
#include <sstream>
namespace Dyninst
{
namespace InstructionAPI
{
using std::vector;
/// A %BinaryFunction object represents a function that can combine two %Expressions and produce another %ValueComputation.
///
/// For the purposes of representing a single operand of an instruction, the %BinaryFunctions of interest are addition and multiplication of
/// integer values; this allows a %Expression to represent all addressing modes on the architectures currently
/// supported by the %Instruction API.
class INSTRUCTION_EXPORT BinaryFunction : public Expression
{
public:
class INSTRUCTION_EXPORT funcT
{
public:
funcT(std::string name) : m_name(name)
{
}
virtual ~funcT()
{
}
virtual Result operator()(const Result& arg1, const Result& arg2) const = 0;
std::string format() const
{
return m_name;
}
typedef dyncompat::shared_ptr<funcT> Ptr;
private:
std::string m_name;
};
class INSTRUCTION_EXPORT addResult : public funcT
{
public:
addResult() : funcT("+")
{
}
virtual ~addResult()
{
}
Result operator()(const Result& arg1, const Result& arg2) const
{
return arg1 + arg2;
}
};
class INSTRUCTION_EXPORT multResult : public funcT
{
public:
multResult() : funcT("*")
{
}
virtual ~multResult()
{
}
Result operator()(const Result& arg1, const Result& arg2) const
{
return arg1 * arg2;
}
};
class INSTRUCTION_EXPORT leftShiftResult : public funcT
{
public:
leftShiftResult() : funcT("<<")
{
}
virtual ~leftShiftResult()
{
}
Result operator()(const Result& arg1, const Result& arg2) const
{
return arg1 << arg2;
}
};
class INSTRUCTION_EXPORT rightArithmeticShiftResult : public funcT
{
public:
rightArithmeticShiftResult() : funcT("ASR")
{
}
virtual ~rightArithmeticShiftResult()
{
}
Result operator()(const Result& arg1, const Result& arg2) const
{
return arg1 >> arg2;
}
};
class INSTRUCTION_EXPORT andResult : public funcT
{
public:
andResult() : funcT("&")
{
}
virtual ~andResult()
{
}
Result operator()(const Result& arg1, const Result& arg2) const
{
return arg1 & arg2;
}
};
class INSTRUCTION_EXPORT orResult : public funcT
{
public:
orResult() : funcT("|")
{
}
virtual ~orResult()
{
}
Result operator()(const Result& arg1, const Result& arg2) const
{
return arg1 | arg2;
}
};
class INSTRUCTION_EXPORT rightLogicalShiftResult : public funcT
{
public:
rightLogicalShiftResult() : funcT("LSR")
{
}
virtual ~rightLogicalShiftResult()
{
}
Result operator()(const Result& arg1, const Result& arg2) const
{
Result mask;
switch(arg1.type)
{
case s8:
case u8:mask = Result(u8, ~0);
break;
case s16:
case u16:mask = Result(u16, ~0);
break;
case s32:
case u32:mask = Result(u32, ~0);
break;
case s48:
case u48:mask = Result(u48, ~0);
break;
case s64:
case u64:mask = Result(u64, ~0);
break;
default: assert(!"not valid");
}
return (arg1 >> arg2) & (mask >> arg2);
}
};
class INSTRUCTION_EXPORT rightRotateResult : public funcT
{
public:
rightRotateResult() : funcT("ROR")
{
}
virtual ~rightRotateResult()
{
}
Result operator()(const Result& arg1, const Result& arg2) const
{
Result leftShiftAmount;
uint64_t arg2val = arg2.convert<Result_type2type<u64>::type >();
switch(arg1.type)
{
case s8:
case u8:arg2val %= 8;
leftShiftAmount = Result(arg2.type, 8 - arg2val);
break;
case s16:
case u16:arg2val %= 16;
leftShiftAmount = Result(arg2.type, 16- arg2val);
break;
case s32:
case u32:arg2val %= 32;
leftShiftAmount = Result(arg2.type, 32- arg2val);
break;
case s48:
case u48:arg2val %= 48;
leftShiftAmount = Result(arg2.type, 48- arg2val);
break;
case s64:
case u64:arg2val %= 64;
leftShiftAmount = Result(arg2.type, 64- arg2val);
break;
default: assert(!"not valid");
}
Result one(u64, 1);
Result rot = arg1 & (Result(u64, (1ULL<<arg2val) - 1));
rightLogicalShiftResult lhsRightShift;
Result arg2mod = Result(arg2.type, arg2val);
return lhsRightShift(arg1, arg2mod) | (rot << leftShiftAmount);
}
};
/// \param arg1 first input to function
/// \param arg2 second input to function
/// \param result_type type of the function's result
/// \param func implementation of the function
///
/// The constructor for a %BinaryFunction may take a reference-counted pointer or a plain C++ pointer to each of the
/// child Expressions that represent its arguments. Since the reference-counted implementation requires explicit construction,
/// we provide overloads for all four combinations of plain and reference-counted pointers. Note that regardless of which constructor
/// is used, the pointers \c arg1 and \c arg2 become owned by the %BinaryFunction being constructed, and should not be deleted.
/// They will be cleaned up when the %BinaryFunction object is destroyed.
///
/// The \c func parameter is a binary functor on two Results. It should be derived from \c %funcT. \c addResult and
/// \c multResult, which respectively add and multiply two %Results, are provided as part of the InstructionAPI,
/// as they are necessary for representing address calculations. Other \c %funcTs may be implemented by the user if desired.
/// %funcTs have names associated with them for output and debugging purposes. The addition and multiplication functors
/// provided with the %Instruction API are named "+" and "*", respectively.
BinaryFunction(Expression::Ptr arg1, Expression::Ptr arg2, Result_Type result_type,
funcT::Ptr func) :
Expression(result_type), m_arg1(arg1), m_arg2(arg2), m_funcPtr(func)
{
}
virtual ~BinaryFunction()
{
}
/// The %BinaryFunction version of \c eval allows the \c eval mechanism to handle complex addressing modes. Like all of the %ValueComputation
/// implementations, a %BinaryFunction's \c eval will return the result of evaluating the expression it represents
/// if possible, or an empty %Result otherwise.
/// A %BinaryFunction may have arguments that can be evaluated, or arguments that cannot.
/// Additionally, it may have a real function pointer, or it may have a null function pointer.
/// If the arguments can be evaluated and the function pointer is real, a result other than an empty %Result is guaranteed to be
/// returned. This result is cached after its initial calculation; the caching mechanism also allows
/// outside information to override the results of the %BinaryFunction's internal computation.
/// If the cached result exists, it is guaranteed to be returned even if the arguments or the function
/// are not evaluable.
virtual const Result& eval() const;
/// The children of a %BinaryFunction are its two arguments.
/// \param children Appends the children of this %BinaryFunction to \c children.
virtual void getChildren(vector<InstructionAST::Ptr>& children) const
{
children.push_back(m_arg1);
children.push_back(m_arg2);
return;
}
virtual void getChildren(vector<Expression::Ptr>& children) const
{
children.push_back(m_arg1);
children.push_back(m_arg2);
return;
}
/// The use set of a %BinaryFunction is the union of the use sets of its children.
/// \param uses Appends the use set of this %BinaryFunction to \c uses.
virtual void getUses(set<InstructionAST::Ptr>& uses)
{
m_arg1->getUses(uses);
m_arg2->getUses(uses);
return;
}
/// \c isUsed returns true if \c findMe is an argument of this %BinaryFunction,
/// or if it is in the use set of either argument.
virtual bool isUsed(InstructionAST::Ptr findMe) const
{
return m_arg1->isUsed(findMe) || m_arg2->isUsed(findMe)
|| (*m_arg1 == *findMe) || (*m_arg2 == *findMe) || (*findMe == *this);
}
virtual std::string format(formatStyle how) const
{
std::string retVal;
if(how == memoryAccessStyle)
{
retVal = m_arg2->format() + "(" + m_arg1->format() + ")";
}
else
{
retVal = "("+m_arg1->format() + " " + m_funcPtr->format() + " " + m_arg2->format()+")";
}
return retVal;
}
virtual std::string format(Architecture arch, formatStyle how) const
{
std::string retVal;
if(how == memoryAccessStyle)
{
retVal = m_arg2->format(arch) + "(" + m_arg1->format(arch) + ")";
}
else
{
return ArchSpecificFormatter::getFormatter(arch).formatBinaryFunc(
m_arg1->format(arch), m_funcPtr->format(), m_arg2->format(arch));
}
return retVal;
}
virtual bool bind(Expression* expr, const Result& value);
virtual void apply(Visitor* v);
bool isAdd() const;
bool isMultiply() const;
bool isLeftShift() const;
bool isRightArithmeticShift() const;
bool isAndResult() const;
bool isOrResult() const;
bool isRightLogicalShift() const;
bool isRightRotate() const;
protected:
virtual bool isStrictEqual(const InstructionAST& rhs) const
{
const BinaryFunction& other(dynamic_cast<const BinaryFunction&>(rhs));
if(*(other.m_arg1) == *m_arg1 &&
(*other.m_arg2) == *m_arg2)
return true;
if(*(other.m_arg1) == *m_arg2 &&
(*other.m_arg2) == *m_arg1) return true;
return false;
}
private:
Expression::Ptr m_arg1;
Expression::Ptr m_arg2;
funcT::Ptr m_funcPtr;
};
}
}
#endif // !defined(BINARYFUNCTION_H)