Files
clang-p2996/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
David Spickett 57c8fee1b9 [lldb] Add dummy field to RegisterInfo for register flags use later
This structure is supposed to be trivial, so we cannot simply do
"= nullptr;" on the new member. Doing that means you are non trivial,
regardless of whether you emulate the previously implied constructor somehow.

The next option is to update every use of brace initialisation.

Given that this is some hundreds of lines, this change just adds a dummy
pointer that is set to nullptr. Subsequent changes will actually use that
to point to register flags information.

Note: This change is not clang-format-ted because it changes a bunch of
areas that are not themselves formatted. It would just add noise.

Reviewed By: jasonmolenda, JDevlieghere

Differential Revision: https://reviews.llvm.org/D145568
2023-04-13 11:30:00 +00:00

1332 lines
27 KiB
C++

//===-- ABISysV_hexagon.cpp -----------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "ABISysV_hexagon.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/TargetParser/Triple.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
using namespace lldb_private;
LLDB_PLUGIN_DEFINE_ADV(ABISysV_hexagon, ABIHexagon)
static const RegisterInfo g_register_infos[] = {
// hexagon-core.xml
{"r00",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{0, 0, LLDB_INVALID_REGNUM, 0, 0},
nullptr,
nullptr,
nullptr,
},
{"r01",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{1, 1, LLDB_INVALID_REGNUM, 1, 1},
nullptr,
nullptr,
nullptr,
},
{"r02",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{2, 2, LLDB_INVALID_REGNUM, 2, 2},
nullptr,
nullptr,
nullptr,
},
{"r03",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{3, 3, LLDB_INVALID_REGNUM, 3, 3},
nullptr,
nullptr,
nullptr,
},
{"r04",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{4, 4, LLDB_INVALID_REGNUM, 4, 4},
nullptr,
nullptr,
nullptr,
},
{"r05",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{5, 5, LLDB_INVALID_REGNUM, 5, 5},
nullptr,
nullptr,
nullptr,
},
{"r06",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{6, 6, LLDB_INVALID_REGNUM, 6, 6},
nullptr,
nullptr,
nullptr,
},
{"r07",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{7, 7, LLDB_INVALID_REGNUM, 7, 7},
nullptr,
nullptr,
nullptr,
},
{"r08",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{8, 8, LLDB_INVALID_REGNUM, 8, 8},
nullptr,
nullptr,
nullptr,
},
{"r09",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{9, 9, LLDB_INVALID_REGNUM, 9, 9},
nullptr,
nullptr,
nullptr,
},
{"r10",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{10, 10, LLDB_INVALID_REGNUM, 10, 10},
nullptr,
nullptr,
nullptr,
},
{"r11",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{11, 11, LLDB_INVALID_REGNUM, 11, 11},
nullptr,
nullptr,
nullptr,
},
{"r12",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{12, 12, LLDB_INVALID_REGNUM, 12, 12},
nullptr,
nullptr,
nullptr,
},
{"r13",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{13, 13, LLDB_INVALID_REGNUM, 13, 13},
nullptr,
nullptr,
nullptr,
},
{"r14",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{14, 14, LLDB_INVALID_REGNUM, 14, 14},
nullptr,
nullptr,
nullptr,
},
{"r15",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{15, 15, LLDB_INVALID_REGNUM, 15, 15},
nullptr,
nullptr,
nullptr,
},
{"r16",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{16, 16, LLDB_INVALID_REGNUM, 16, 16},
nullptr,
nullptr,
nullptr,
},
{"r17",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{17, 17, LLDB_INVALID_REGNUM, 17, 17},
nullptr,
nullptr,
nullptr,
},
{"r18",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{18, 18, LLDB_INVALID_REGNUM, 18, 18},
nullptr,
nullptr,
nullptr,
},
{"r19",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{19, 19, LLDB_INVALID_REGNUM, 19, 19},
nullptr,
nullptr,
nullptr,
},
{"r20",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{20, 20, LLDB_INVALID_REGNUM, 20, 20},
nullptr,
nullptr,
nullptr,
},
{"r21",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{21, 21, LLDB_INVALID_REGNUM, 21, 21},
nullptr,
nullptr,
nullptr,
},
{"r22",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{22, 22, LLDB_INVALID_REGNUM, 22, 22},
nullptr,
nullptr,
nullptr,
},
{"r23",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{23, 23, LLDB_INVALID_REGNUM, 23, 23},
nullptr,
nullptr,
nullptr,
},
{"r24",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{24, 24, LLDB_INVALID_REGNUM, 24, 24},
nullptr,
nullptr,
nullptr,
},
{"r25",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{25, 25, LLDB_INVALID_REGNUM, 25, 25},
nullptr,
nullptr,
nullptr,
},
{"r26",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{26, 26, LLDB_INVALID_REGNUM, 26, 26},
nullptr,
nullptr,
nullptr,
},
{"r27",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{27, 27, LLDB_INVALID_REGNUM, 27, 27},
nullptr,
nullptr,
nullptr,
},
{"r28",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{28, 28, LLDB_INVALID_REGNUM, 28, 28},
nullptr,
nullptr,
nullptr,
},
{"sp",
"r29",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{29, 29, LLDB_REGNUM_GENERIC_SP, 29, 29},
nullptr,
nullptr,
nullptr,
},
{"fp",
"r30",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{30, 30, LLDB_REGNUM_GENERIC_FP, 30, 30},
nullptr,
nullptr,
nullptr,
},
{"lr",
"r31",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{31, 31, LLDB_REGNUM_GENERIC_RA, 31, 31},
nullptr,
nullptr,
nullptr,
},
{"sa0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{32, 32, LLDB_INVALID_REGNUM, 32, 32},
nullptr,
nullptr,
nullptr,
},
{"lc0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{33, 33, LLDB_INVALID_REGNUM, 33, 33},
nullptr,
nullptr,
nullptr,
},
{"sa1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{34, 34, LLDB_INVALID_REGNUM, 34, 34},
nullptr,
nullptr,
nullptr,
},
{"lc1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{35, 35, LLDB_INVALID_REGNUM, 35, 35},
nullptr,
nullptr,
nullptr,
},
// --> hexagon-v4/5/55/56-sim.xml
{"p3_0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{36, 36, LLDB_INVALID_REGNUM, 36, 36},
nullptr,
nullptr,
nullptr,
},
// PADDING {
{"p00",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{37, 37, LLDB_INVALID_REGNUM, 37, 37},
nullptr,
nullptr,
nullptr,
},
// }
{"m0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{38, 38, LLDB_INVALID_REGNUM, 38, 38},
nullptr,
nullptr,
nullptr,
},
{"m1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{39, 39, LLDB_INVALID_REGNUM, 39, 39},
nullptr,
nullptr,
nullptr,
},
{"usr",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{40, 40, LLDB_INVALID_REGNUM, 40, 40},
nullptr,
nullptr,
nullptr,
},
{"pc",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{41, 41, LLDB_REGNUM_GENERIC_PC, 41, 41},
nullptr,
nullptr,
nullptr,
},
{"ugp",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{42, 42, LLDB_INVALID_REGNUM, 42, 42},
nullptr,
nullptr,
nullptr,
},
{"gp",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{43, 43, LLDB_INVALID_REGNUM, 43, 43},
nullptr,
nullptr,
nullptr,
},
{"cs0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{44, 44, LLDB_INVALID_REGNUM, 44, 44},
nullptr,
nullptr,
nullptr,
},
{"cs1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{45, 45, LLDB_INVALID_REGNUM, 45, 45},
nullptr,
nullptr,
nullptr,
},
// PADDING {
{"p01",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{46, 46, LLDB_INVALID_REGNUM, 46, 46},
nullptr,
nullptr,
nullptr,
},
{"p02",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{47, 47, LLDB_INVALID_REGNUM, 47, 47},
nullptr,
nullptr,
nullptr,
},
{"p03",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{48, 48, LLDB_INVALID_REGNUM, 48, 48},
nullptr,
nullptr,
nullptr,
},
{"p04",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{49, 49, LLDB_INVALID_REGNUM, 49, 49},
nullptr,
nullptr,
nullptr,
},
{"p05",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{50, 50, LLDB_INVALID_REGNUM, 50, 50},
nullptr,
nullptr,
nullptr,
},
{"p06",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{51, 51, LLDB_INVALID_REGNUM, 51, 51},
nullptr,
nullptr,
nullptr,
},
{"p07",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{52, 52, LLDB_INVALID_REGNUM, 52, 52},
nullptr,
nullptr,
nullptr,
},
{"p08",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{53, 53, LLDB_INVALID_REGNUM, 53, 53},
nullptr,
nullptr,
nullptr,
},
{"p09",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{54, 54, LLDB_INVALID_REGNUM, 54, 54},
nullptr,
nullptr,
nullptr,
},
{"p10",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{55, 55, LLDB_INVALID_REGNUM, 55, 55},
nullptr,
nullptr,
nullptr,
},
{"p11",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{56, 56, LLDB_INVALID_REGNUM, 56, 56},
nullptr,
nullptr,
nullptr,
},
{"p12",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{57, 57, LLDB_INVALID_REGNUM, 57, 57},
nullptr,
nullptr,
nullptr,
},
{"p13",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{58, 58, LLDB_INVALID_REGNUM, 58, 58},
nullptr,
nullptr,
nullptr,
},
{"p14",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{59, 59, LLDB_INVALID_REGNUM, 59, 59},
nullptr,
nullptr,
nullptr,
},
{"p15",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{60, 60, LLDB_INVALID_REGNUM, 60, 60},
nullptr,
nullptr,
nullptr,
},
{"p16",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{61, 61, LLDB_INVALID_REGNUM, 61, 61},
nullptr,
nullptr,
nullptr,
},
{"p17",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{62, 62, LLDB_INVALID_REGNUM, 62, 62},
nullptr,
nullptr,
nullptr,
},
{"p18",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{63, 63, LLDB_INVALID_REGNUM, 63, 63},
nullptr,
nullptr,
nullptr,
},
// }
{"sgp0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{64, 64, LLDB_INVALID_REGNUM, 64, 64},
nullptr,
nullptr,
nullptr,
},
// PADDING {
{"p19",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{65, 65, LLDB_INVALID_REGNUM, 65, 65},
nullptr,
nullptr,
nullptr,
},
// }
{"stid",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{66, 66, LLDB_INVALID_REGNUM, 66, 66},
nullptr,
nullptr,
nullptr,
},
{"elr",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{67, 67, LLDB_INVALID_REGNUM, 67, 67},
nullptr,
nullptr,
nullptr,
},
{"badva0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{68, 68, LLDB_INVALID_REGNUM, 68, 68},
nullptr,
nullptr,
nullptr,
},
{"badva1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{69, 69, LLDB_INVALID_REGNUM, 69, 69},
nullptr,
nullptr,
nullptr,
},
{"ssr",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{70, 70, LLDB_INVALID_REGNUM, 70, 70},
nullptr,
nullptr,
nullptr,
},
{"ccr",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{71, 71, LLDB_INVALID_REGNUM, 71, 71},
nullptr,
nullptr,
nullptr,
},
{"htid",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{72, 72, LLDB_INVALID_REGNUM, 72, 72},
nullptr,
nullptr,
nullptr,
},
// PADDING {
{"p20",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{73, 73, LLDB_INVALID_REGNUM, 73, 73},
nullptr,
nullptr,
nullptr,
},
// }
{"imask",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{74, 74, LLDB_INVALID_REGNUM, 74, 74},
nullptr,
nullptr,
nullptr,
},
// PADDING {
{"p21",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{75, 75, LLDB_INVALID_REGNUM, 75, 75},
nullptr,
nullptr,
nullptr,
},
{"p22",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{76, 76, LLDB_INVALID_REGNUM, 76, 76},
nullptr,
nullptr,
nullptr,
},
{"p23",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{77, 77, LLDB_INVALID_REGNUM, 77, 77},
nullptr,
nullptr,
nullptr,
},
{"p24",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{78, 78, LLDB_INVALID_REGNUM, 78, 78},
nullptr,
nullptr,
nullptr,
},
{"p25",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{79, 79, LLDB_INVALID_REGNUM, 79, 79},
nullptr,
nullptr,
nullptr,
},
// }
{"g0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{80, 80, LLDB_INVALID_REGNUM, 80, 80},
nullptr,
nullptr,
nullptr,
},
{"g1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{81, 81, LLDB_INVALID_REGNUM, 81, 81},
nullptr,
nullptr,
nullptr,
},
{"g2",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{82, 82, LLDB_INVALID_REGNUM, 82, 82},
nullptr,
nullptr,
nullptr,
},
{"g3",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{83, 83, LLDB_INVALID_REGNUM, 83, 83},
nullptr,
nullptr,
nullptr,
}};
static const uint32_t k_num_register_infos =
sizeof(g_register_infos) / sizeof(RegisterInfo);
const lldb_private::RegisterInfo *
ABISysV_hexagon::GetRegisterInfoArray(uint32_t &count) {
count = k_num_register_infos;
return g_register_infos;
}
/*
http://en.wikipedia.org/wiki/Red_zone_%28computing%29
In computing, a red zone is a fixed size area in memory beyond the stack
pointer that has not been
"allocated". This region of memory is not to be modified by
interrupt/exception/signal handlers.
This allows the space to be used for temporary data without the extra
overhead of modifying the
stack pointer. The x86-64 ABI mandates a 128 byte red zone.[1] The OpenRISC
toolchain assumes a
128 byte red zone though it is not documented.
*/
size_t ABISysV_hexagon::GetRedZoneSize() const { return 0; }
// Static Functions
ABISP
ABISysV_hexagon::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
if (arch.GetTriple().getArch() == llvm::Triple::hexagon) {
return ABISP(
new ABISysV_hexagon(std::move(process_sp), MakeMCRegisterInfo(arch)));
}
return ABISP();
}
bool ABISysV_hexagon::PrepareTrivialCall(Thread &thread, lldb::addr_t sp,
lldb::addr_t pc, lldb::addr_t ra,
llvm::ArrayRef<addr_t> args) const {
// we don't use the traditional trivial call specialized for jit
return false;
}
/*
// AD:
// . safeguard the current stack
// . how can we know that the called function will create its own frame
properly?
// . we could manually make a new stack first:
// 2. push RA
// 3. push FP
// 4. FP = SP
// 5. SP = SP ( since no locals in our temp frame )
// AD 6/05/2014
// . variable argument list parameters are not passed via registers, they are
passed on
// the stack. This presents us with a problem, since we need to know when
the valist
// starts. Currently I can find out if a function is varg, but not how many
// real parameters it takes. Thus I don't know when to start spilling the
vargs. For
// the time being, to progress, I will assume that it takes on real parameter
before
// the vargs list starts.
// AD 06/05/2014
// . how do we adhere to the stack alignment requirements
// AD 06/05/2014
// . handle 64bit values and their register / stack requirements
*/
#define HEX_ABI_DEBUG 0
bool ABISysV_hexagon::PrepareTrivialCall(
Thread &thread, lldb::addr_t sp, lldb::addr_t pc, lldb::addr_t ra,
llvm::Type &prototype, llvm::ArrayRef<ABI::CallArgument> args) const {
// default number of register passed arguments for varg functions
const int nVArgRegParams = 1;
Status error;
// grab the process so we have access to the memory for spilling
lldb::ProcessSP proc = thread.GetProcess();
// get the register context for modifying all of the registers
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return false;
uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
if (pc_reg == LLDB_INVALID_REGNUM)
return false;
uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
if (ra_reg == LLDB_INVALID_REGNUM)
return false;
uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
if (sp_reg == LLDB_INVALID_REGNUM)
return false;
// push host data onto target
for (size_t i = 0; i < args.size(); i++) {
const ABI::CallArgument &arg = args[i];
// skip over target values
if (arg.type == ABI::CallArgument::TargetValue)
continue;
// round up to 8 byte multiple
size_t argSize = (arg.size | 0x7) + 1;
// create space on the stack for this data
sp -= argSize;
// write this argument onto the stack of the host process
proc->WriteMemory(sp, arg.data_up.get(), arg.size, error);
if (error.Fail())
return false;
// update the argument with the target pointer
// XXX: This is a gross hack for getting around the const
*const_cast<lldb::addr_t *>(&arg.value) = sp;
}
#if HEX_ABI_DEBUG
// print the original stack pointer
printf("sp : %04" PRIx64 " \n", sp);
#endif
// make sure number of parameters matches prototype
assert(prototype.getFunctionNumParams() == args.size());
// check if this is a variable argument function
bool isVArg = prototype.isFunctionVarArg();
// number of arguments passed by register
int nRegArgs = nVArgRegParams;
if (!isVArg) {
// number of arguments is limited by [R0 : R5] space
nRegArgs = args.size();
if (nRegArgs > 6)
nRegArgs = 6;
}
// pass arguments that are passed via registers
for (int i = 0; i < nRegArgs; i++) {
// get the parameter as a u32
uint32_t param = (uint32_t)args[i].value;
// write argument into register
if (!reg_ctx->WriteRegisterFromUnsigned(i, param))
return false;
}
// number of arguments to spill onto stack
int nSpillArgs = args.size() - nRegArgs;
// make space on the stack for arguments
sp -= 4 * nSpillArgs;
// align stack on an 8 byte boundary
if (sp & 7)
sp -= 4;
// arguments that are passed on the stack
for (size_t i = nRegArgs, offs = 0; i < args.size(); i++) {
// get the parameter as a u32
uint32_t param = (uint32_t)args[i].value;
// write argument to stack
proc->WriteMemory(sp + offs, (void *)&param, sizeof(param), error);
if (!error.Success())
return false;
//
offs += 4;
}
// update registers with current function call state
reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc);
reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra);
reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp);
#if HEX_ABI_DEBUG
// quick and dirty stack dumper for debugging
for (int i = -8; i < 8; i++) {
uint32_t data = 0;
lldb::addr_t addr = sp + i * 4;
proc->ReadMemory(addr, (void *)&data, sizeof(data), error);
printf("\n0x%04" PRIx64 " 0x%08x ", addr, data);
if (i == 0)
printf("<<-- sp");
}
printf("\n");
#endif
return true;
}
bool ABISysV_hexagon::GetArgumentValues(Thread &thread,
ValueList &values) const {
return false;
}
Status
ABISysV_hexagon::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
lldb::ValueObjectSP &new_value_sp) {
Status error;
return error;
}
ValueObjectSP ABISysV_hexagon::GetReturnValueObjectSimple(
Thread &thread, CompilerType &return_compiler_type) const {
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
ValueObjectSP ABISysV_hexagon::GetReturnValueObjectImpl(
Thread &thread, CompilerType &return_compiler_type) const {
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
// called when we are on the first instruction of a new function for hexagon
// the return address is in RA (R31)
bool ABISysV_hexagon::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindGeneric);
unwind_plan.SetReturnAddressRegister(LLDB_REGNUM_GENERIC_RA);
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_SP, 4);
row->SetOffset(0);
// The previous PC is in the LR
row->SetRegisterLocationToRegister(LLDB_REGNUM_GENERIC_PC,
LLDB_REGNUM_GENERIC_RA, true);
unwind_plan.AppendRow(row);
unwind_plan.SetSourceName("hexagon at-func-entry default");
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
return true;
}
bool ABISysV_hexagon::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindGeneric);
uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP;
uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP;
uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC;
UnwindPlan::RowSP row(new UnwindPlan::Row);
row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_FP, 8);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, -8, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, true);
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
unwind_plan.AppendRow(row);
unwind_plan.SetSourceName("hexagon default unwind plan");
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
return true;
}
/*
Register Usage Saved By
R0 - R5 parameters(a) -
R6 - R15 Scratch(b) Caller
R16 - R27 Scratch Callee
R28 Scratch(b) Caller
R29 - R31 Stack Frames Callee(c)
P3:0 Processor State Caller
a = the caller can change parameter values
b = R14 - R15 and R28 are used by the procedure linkage table
c = R29 - R31 are saved and restored by allocframe() and deallocframe()
*/
bool ABISysV_hexagon::RegisterIsVolatile(const RegisterInfo *reg_info) {
return !RegisterIsCalleeSaved(reg_info);
}
bool ABISysV_hexagon::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
int reg = ((reg_info->byte_offset) / 4);
bool save = (reg >= 16) && (reg <= 27);
save |= (reg >= 29) && (reg <= 32);
return save;
}
void ABISysV_hexagon::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
"System V ABI for hexagon targets",
CreateInstance);
}
void ABISysV_hexagon::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
// get value object specialized to work with llvm IR types
lldb::ValueObjectSP
ABISysV_hexagon::GetReturnValueObjectImpl(lldb_private::Thread &thread,
llvm::Type &retType) const {
Value value;
ValueObjectSP vObjSP;
// get the current register context
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return vObjSP;
// for now just pop R0 to find the return value
const lldb_private::RegisterInfo *r0_info =
reg_ctx->GetRegisterInfoAtIndex(0);
if (r0_info == nullptr)
return vObjSP;
// void return type
if (retType.isVoidTy()) {
value.GetScalar() = 0;
}
// integer / pointer return type
else if (retType.isIntegerTy() || retType.isPointerTy()) {
// read r0 register value
lldb_private::RegisterValue r0_value;
if (!reg_ctx->ReadRegister(r0_info, r0_value))
return vObjSP;
// push r0 into value
uint32_t r0_u32 = r0_value.GetAsUInt32();
// account for integer size
if (retType.isIntegerTy() && retType.isSized()) {
uint64_t size = retType.getScalarSizeInBits();
uint64_t mask = (1ull << size) - 1;
// mask out higher order bits then the type we expect
r0_u32 &= mask;
}
value.GetScalar() = r0_u32;
}
// unsupported return type
else
return vObjSP;
// pack the value into a ValueObjectSP
vObjSP = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
value, ConstString(""));
return vObjSP;
}