1 //===-- ABISysV_hexagon.cpp -------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "ABISysV_hexagon.h"
11 #include "llvm/ADT/Triple.h"
12 #include "llvm/IR/DerivedTypes.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/Value.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/Core/ValueObjectMemory.h"
19 #include "lldb/Core/ValueObjectRegister.h"
20 #include "lldb/Symbol/UnwindPlan.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/StackFrame.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/Thread.h"
26 #include "lldb/Utility/ConstString.h"
27 #include "lldb/Utility/DataExtractor.h"
28 #include "lldb/Utility/Log.h"
29 #include "lldb/Utility/RegisterValue.h"
30 #include "lldb/Utility/Status.h"
33 using namespace lldb_private;
35 static RegisterInfo g_register_infos[] = {
43 {0, 0, LLDB_INVALID_REGNUM, 0, 0},
54 {1, 1, LLDB_INVALID_REGNUM, 1, 1},
65 {2, 2, LLDB_INVALID_REGNUM, 2, 2},
76 {3, 3, LLDB_INVALID_REGNUM, 3, 3},
87 {4, 4, LLDB_INVALID_REGNUM, 4, 4},
98 {5, 5, LLDB_INVALID_REGNUM, 5, 5},
109 {6, 6, LLDB_INVALID_REGNUM, 6, 6},
120 {7, 7, LLDB_INVALID_REGNUM, 7, 7},
131 {8, 8, LLDB_INVALID_REGNUM, 8, 8},
142 {9, 9, LLDB_INVALID_REGNUM, 9, 9},
153 {10, 10, LLDB_INVALID_REGNUM, 10, 10},
164 {11, 11, LLDB_INVALID_REGNUM, 11, 11},
175 {12, 12, LLDB_INVALID_REGNUM, 12, 12},
186 {13, 13, LLDB_INVALID_REGNUM, 13, 13},
197 {14, 14, LLDB_INVALID_REGNUM, 14, 14},
208 {15, 15, LLDB_INVALID_REGNUM, 15, 15},
219 {16, 16, LLDB_INVALID_REGNUM, 16, 16},
230 {17, 17, LLDB_INVALID_REGNUM, 17, 17},
241 {18, 18, LLDB_INVALID_REGNUM, 18, 18},
252 {19, 19, LLDB_INVALID_REGNUM, 19, 19},
263 {20, 20, LLDB_INVALID_REGNUM, 20, 20},
274 {21, 21, LLDB_INVALID_REGNUM, 21, 21},
285 {22, 22, LLDB_INVALID_REGNUM, 22, 22},
296 {23, 23, LLDB_INVALID_REGNUM, 23, 23},
307 {24, 24, LLDB_INVALID_REGNUM, 24, 24},
318 {25, 25, LLDB_INVALID_REGNUM, 25, 25},
329 {26, 26, LLDB_INVALID_REGNUM, 26, 26},
340 {27, 27, LLDB_INVALID_REGNUM, 27, 27},
351 {28, 28, LLDB_INVALID_REGNUM, 28, 28},
362 {29, 29, LLDB_REGNUM_GENERIC_SP, 29, 29},
373 {30, 30, LLDB_REGNUM_GENERIC_FP, 30, 30},
384 {31, 31, LLDB_REGNUM_GENERIC_RA, 31, 31},
395 {32, 32, LLDB_INVALID_REGNUM, 32, 32},
406 {33, 33, LLDB_INVALID_REGNUM, 33, 33},
417 {34, 34, LLDB_INVALID_REGNUM, 34, 34},
428 {35, 35, LLDB_INVALID_REGNUM, 35, 35},
433 // --> hexagon-v4/5/55/56-sim.xml
440 {36, 36, LLDB_INVALID_REGNUM, 36, 36},
452 {37, 37, LLDB_INVALID_REGNUM, 37, 37},
464 {38, 38, LLDB_INVALID_REGNUM, 38, 38},
475 {39, 39, LLDB_INVALID_REGNUM, 39, 39},
486 {40, 40, LLDB_INVALID_REGNUM, 40, 40},
497 {41, 41, LLDB_REGNUM_GENERIC_PC, 41, 41},
508 {42, 42, LLDB_INVALID_REGNUM, 42, 42},
519 {43, 43, LLDB_INVALID_REGNUM, 43, 43},
530 {44, 44, LLDB_INVALID_REGNUM, 44, 44},
541 {45, 45, LLDB_INVALID_REGNUM, 45, 45},
553 {46, 46, LLDB_INVALID_REGNUM, 46, 46},
564 {47, 47, LLDB_INVALID_REGNUM, 47, 47},
575 {48, 48, LLDB_INVALID_REGNUM, 48, 48},
586 {49, 49, LLDB_INVALID_REGNUM, 49, 49},
597 {50, 50, LLDB_INVALID_REGNUM, 50, 50},
608 {51, 51, LLDB_INVALID_REGNUM, 51, 51},
619 {52, 52, LLDB_INVALID_REGNUM, 52, 52},
630 {53, 53, LLDB_INVALID_REGNUM, 53, 53},
641 {54, 54, LLDB_INVALID_REGNUM, 54, 54},
652 {55, 55, LLDB_INVALID_REGNUM, 55, 55},
663 {56, 56, LLDB_INVALID_REGNUM, 56, 56},
674 {57, 57, LLDB_INVALID_REGNUM, 57, 57},
685 {58, 58, LLDB_INVALID_REGNUM, 58, 58},
696 {59, 59, LLDB_INVALID_REGNUM, 59, 59},
707 {60, 60, LLDB_INVALID_REGNUM, 60, 60},
718 {61, 61, LLDB_INVALID_REGNUM, 61, 61},
729 {62, 62, LLDB_INVALID_REGNUM, 62, 62},
740 {63, 63, LLDB_INVALID_REGNUM, 63, 63},
752 {64, 64, LLDB_INVALID_REGNUM, 64, 64},
764 {65, 65, LLDB_INVALID_REGNUM, 65, 65},
776 {66, 66, LLDB_INVALID_REGNUM, 66, 66},
787 {67, 67, LLDB_INVALID_REGNUM, 67, 67},
798 {68, 68, LLDB_INVALID_REGNUM, 68, 68},
809 {69, 69, LLDB_INVALID_REGNUM, 69, 69},
820 {70, 70, LLDB_INVALID_REGNUM, 70, 70},
831 {71, 71, LLDB_INVALID_REGNUM, 71, 71},
842 {72, 72, LLDB_INVALID_REGNUM, 72, 72},
854 {73, 73, LLDB_INVALID_REGNUM, 73, 73},
866 {74, 74, LLDB_INVALID_REGNUM, 74, 74},
878 {75, 75, LLDB_INVALID_REGNUM, 75, 75},
889 {76, 76, LLDB_INVALID_REGNUM, 76, 76},
900 {77, 77, LLDB_INVALID_REGNUM, 77, 77},
911 {78, 78, LLDB_INVALID_REGNUM, 78, 78},
922 {79, 79, LLDB_INVALID_REGNUM, 79, 79},
934 {80, 80, LLDB_INVALID_REGNUM, 80, 80},
945 {81, 81, LLDB_INVALID_REGNUM, 81, 81},
956 {82, 82, LLDB_INVALID_REGNUM, 82, 82},
967 {83, 83, LLDB_INVALID_REGNUM, 83, 83},
973 static const uint32_t k_num_register_infos =
974 sizeof(g_register_infos) / sizeof(RegisterInfo);
975 static bool g_register_info_names_constified = false;
977 const lldb_private::RegisterInfo *
978 ABISysV_hexagon::GetRegisterInfoArray(uint32_t &count) {
979 // Make the C-string names and alt_names for the register infos into const
980 // C-string values by having the ConstString unique the names in the global
981 // constant C-string pool.
982 if (!g_register_info_names_constified) {
983 g_register_info_names_constified = true;
984 for (uint32_t i = 0; i < k_num_register_infos; ++i) {
985 if (g_register_infos[i].name)
986 g_register_infos[i].name =
987 ConstString(g_register_infos[i].name).GetCString();
988 if (g_register_infos[i].alt_name)
989 g_register_infos[i].alt_name =
990 ConstString(g_register_infos[i].alt_name).GetCString();
993 count = k_num_register_infos;
994 return g_register_infos;
998 http://en.wikipedia.org/wiki/Red_zone_%28computing%29
1000 In computing, a red zone is a fixed size area in memory beyond the stack
1001 pointer that has not been
1002 "allocated". This region of memory is not to be modified by
1003 interrupt/exception/signal handlers.
1004 This allows the space to be used for temporary data without the extra
1005 overhead of modifying the
1006 stack pointer. The x86-64 ABI mandates a 128 byte red zone.[1] The OpenRISC
1008 128 byte red zone though it is not documented.
1010 size_t ABISysV_hexagon::GetRedZoneSize() const { return 0; }
1015 ABISysV_hexagon::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
1016 if (arch.GetTriple().getArch() == llvm::Triple::hexagon) {
1017 return ABISP(new ABISysV_hexagon(process_sp));
1022 bool ABISysV_hexagon::PrepareTrivialCall(Thread &thread, lldb::addr_t sp,
1023 lldb::addr_t pc, lldb::addr_t ra,
1024 llvm::ArrayRef<addr_t> args) const {
1025 // we don't use the traditional trivial call specialized for jit
1032 // . safeguard the current stack
1033 // . how can we know that the called function will create its own frame
1035 // . we could manually make a new stack first:
1039 // 5. SP = SP ( since no locals in our temp frame )
1042 // . variable argument list parameters are not passed via registers, they are
1044 // the stack. This presents us with a problem, since we need to know when
1046 // starts. Currently I can find out if a function is varg, but not how many
1047 // real parameters it takes. Thus I don't know when to start spilling the
1049 // the time being, to progress, I will assume that it takes on real parameter
1051 // the vargs list starts.
1054 // . how do we adhere to the stack alignment requirements
1057 // . handle 64bit values and their register / stack requirements
1060 #define HEX_ABI_DEBUG 0
1061 bool ABISysV_hexagon::PrepareTrivialCall(
1062 Thread &thread, lldb::addr_t sp, lldb::addr_t pc, lldb::addr_t ra,
1063 llvm::Type &prototype, llvm::ArrayRef<ABI::CallArgument> args) const {
1064 // default number of register passed arguments for varg functions
1065 const int nVArgRegParams = 1;
1068 // grab the process so we have access to the memory for spilling
1069 lldb::ProcessSP proc = thread.GetProcess();
1071 // get the register context for modifying all of the registers
1072 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
1076 uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1077 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1078 if (pc_reg == LLDB_INVALID_REGNUM)
1081 uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1082 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
1083 if (ra_reg == LLDB_INVALID_REGNUM)
1086 uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1087 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1088 if (sp_reg == LLDB_INVALID_REGNUM)
1091 // push host data onto target
1092 for (size_t i = 0; i < args.size(); i++) {
1093 const ABI::CallArgument &arg = args[i];
1094 // skip over target values
1095 if (arg.type == ABI::CallArgument::TargetValue)
1097 // round up to 8 byte multiple
1098 size_t argSize = (arg.size | 0x7) + 1;
1100 // create space on the stack for this data
1103 // write this argument onto the stack of the host process
1104 proc->WriteMemory(sp, arg.data_up.get(), arg.size, error);
1108 // update the argument with the target pointer
1109 // XXX: This is a gross hack for getting around the const
1110 *const_cast<lldb::addr_t *>(&arg.value) = sp;
1114 // print the original stack pointer
1115 printf("sp : %04" PRIx64 " \n", sp);
1118 // make sure number of parameters matches prototype
1119 assert(prototype.getFunctionNumParams() == args.size());
1121 // check if this is a variable argument function
1122 bool isVArg = prototype.isFunctionVarArg();
1124 // number of arguments passed by register
1125 int nRegArgs = nVArgRegParams;
1127 // number of arguments is limited by [R0 : R5] space
1128 nRegArgs = args.size();
1133 // pass arguments that are passed via registers
1134 for (int i = 0; i < nRegArgs; i++) {
1135 // get the parameter as a u32
1136 uint32_t param = (uint32_t)args[i].value;
1137 // write argument into register
1138 if (!reg_ctx->WriteRegisterFromUnsigned(i, param))
1142 // number of arguments to spill onto stack
1143 int nSpillArgs = args.size() - nRegArgs;
1144 // make space on the stack for arguments
1145 sp -= 4 * nSpillArgs;
1146 // align stack on an 8 byte boundary
1150 // arguments that are passed on the stack
1151 for (size_t i = nRegArgs, offs = 0; i < args.size(); i++) {
1152 // get the parameter as a u32
1153 uint32_t param = (uint32_t)args[i].value;
1154 // write argument to stack
1155 proc->WriteMemory(sp + offs, (void *)¶m, sizeof(param), error);
1156 if (!error.Success())
1162 // update registers with current function call state
1163 reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc);
1164 reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra);
1165 reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp);
1168 // quick and dirty stack dumper for debugging
1169 for (int i = -8; i < 8; i++) {
1171 lldb::addr_t addr = sp + i * 4;
1172 proc->ReadMemory(addr, (void *)&data, sizeof(data), error);
1173 printf("\n0x%04" PRIx64 " 0x%08x ", addr, data);
1183 bool ABISysV_hexagon::GetArgumentValues(Thread &thread,
1184 ValueList &values) const {
1189 ABISysV_hexagon::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
1190 lldb::ValueObjectSP &new_value_sp) {
1195 ValueObjectSP ABISysV_hexagon::GetReturnValueObjectSimple(
1196 Thread &thread, CompilerType &return_compiler_type) const {
1197 ValueObjectSP return_valobj_sp;
1198 return return_valobj_sp;
1201 ValueObjectSP ABISysV_hexagon::GetReturnValueObjectImpl(
1202 Thread &thread, CompilerType &return_compiler_type) const {
1203 ValueObjectSP return_valobj_sp;
1204 return return_valobj_sp;
1207 // called when we are on the first instruction of a new function for hexagon
1208 // the return address is in RA (R31)
1209 bool ABISysV_hexagon::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
1210 unwind_plan.Clear();
1211 unwind_plan.SetRegisterKind(eRegisterKindGeneric);
1212 unwind_plan.SetReturnAddressRegister(LLDB_REGNUM_GENERIC_RA);
1214 UnwindPlan::RowSP row(new UnwindPlan::Row);
1216 // Our Call Frame Address is the stack pointer value
1217 row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_SP, 4);
1220 // The previous PC is in the LR
1221 row->SetRegisterLocationToRegister(LLDB_REGNUM_GENERIC_PC,
1222 LLDB_REGNUM_GENERIC_RA, true);
1223 unwind_plan.AppendRow(row);
1225 unwind_plan.SetSourceName("hexagon at-func-entry default");
1226 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1230 bool ABISysV_hexagon::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
1231 unwind_plan.Clear();
1232 unwind_plan.SetRegisterKind(eRegisterKindGeneric);
1234 uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP;
1235 uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP;
1236 uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC;
1238 UnwindPlan::RowSP row(new UnwindPlan::Row);
1240 row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_FP, 8);
1242 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, -8, true);
1243 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, true);
1244 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
1246 unwind_plan.AppendRow(row);
1247 unwind_plan.SetSourceName("hexagon default unwind plan");
1248 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1249 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1254 Register Usage Saved By
1256 R0 - R5 parameters(a) -
1257 R6 - R15 Scratch(b) Caller
1258 R16 - R27 Scratch Callee
1259 R28 Scratch(b) Caller
1260 R29 - R31 Stack Frames Callee(c)
1261 P3:0 Processor State Caller
1263 a = the caller can change parameter values
1264 b = R14 - R15 and R28 are used by the procedure linkage table
1265 c = R29 - R31 are saved and restored by allocframe() and deallocframe()
1267 bool ABISysV_hexagon::RegisterIsVolatile(const RegisterInfo *reg_info) {
1268 return !RegisterIsCalleeSaved(reg_info);
1271 bool ABISysV_hexagon::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1272 int reg = ((reg_info->byte_offset) / 4);
1274 bool save = (reg >= 16) && (reg <= 27);
1275 save |= (reg >= 29) && (reg <= 32);
1280 void ABISysV_hexagon::Initialize() {
1281 PluginManager::RegisterPlugin(GetPluginNameStatic(),
1282 "System V ABI for hexagon targets",
1286 void ABISysV_hexagon::Terminate() {
1287 PluginManager::UnregisterPlugin(CreateInstance);
1290 lldb_private::ConstString ABISysV_hexagon::GetPluginNameStatic() {
1291 static ConstString g_name("sysv-hexagon");
1295 // PluginInterface protocol
1297 lldb_private::ConstString ABISysV_hexagon::GetPluginName() {
1298 return GetPluginNameStatic();
1301 uint32_t ABISysV_hexagon::GetPluginVersion() { return 1; }
1303 // get value object specialized to work with llvm IR types
1305 ABISysV_hexagon::GetReturnValueObjectImpl(lldb_private::Thread &thread,
1306 llvm::Type &retType) const {
1308 ValueObjectSP vObjSP;
1310 // get the current register context
1311 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
1315 // for now just pop R0 to find the return value
1316 const lldb_private::RegisterInfo *r0_info =
1317 reg_ctx->GetRegisterInfoAtIndex(0);
1318 if (r0_info == nullptr)
1322 if (retType.isVoidTy()) {
1323 value.GetScalar() = 0;
1325 // integer / pointer return type
1326 else if (retType.isIntegerTy() || retType.isPointerTy()) {
1327 // read r0 register value
1328 lldb_private::RegisterValue r0_value;
1329 if (!reg_ctx->ReadRegister(r0_info, r0_value))
1332 // push r0 into value
1333 uint32_t r0_u32 = r0_value.GetAsUInt32();
1335 // account for integer size
1336 if (retType.isIntegerTy() && retType.isSized()) {
1337 uint64_t size = retType.getScalarSizeInBits();
1338 uint64_t mask = (1ull << size) - 1;
1339 // mask out higher order bits then the type we expect
1343 value.GetScalar() = r0_u32;
1345 // unsupported return type
1349 // pack the value into a ValueObjectSP
1350 vObjSP = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
1351 value, ConstString(""));