15ffd83dbSDimitry Andric //===-- ABISysV_arc.cpp ---------------------------------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric
95ffd83dbSDimitry Andric #include "ABISysV_arc.h"
105ffd83dbSDimitry Andric
115ffd83dbSDimitry Andric // C Includes
125ffd83dbSDimitry Andric // C++ Includes
135ffd83dbSDimitry Andric #include <array>
145ffd83dbSDimitry Andric #include <limits>
155ffd83dbSDimitry Andric #include <type_traits>
165ffd83dbSDimitry Andric
175ffd83dbSDimitry Andric // Other libraries and framework includes
185ffd83dbSDimitry Andric #include "llvm/IR/DerivedTypes.h"
195ffd83dbSDimitry Andric #include "llvm/Support/MathExtras.h"
20*06c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
215ffd83dbSDimitry Andric
225ffd83dbSDimitry Andric #include "lldb/Core/Module.h"
235ffd83dbSDimitry Andric #include "lldb/Core/PluginManager.h"
245ffd83dbSDimitry Andric #include "lldb/Core/Value.h"
255ffd83dbSDimitry Andric #include "lldb/Core/ValueObjectConstResult.h"
265ffd83dbSDimitry Andric #include "lldb/Core/ValueObjectMemory.h"
275ffd83dbSDimitry Andric #include "lldb/Core/ValueObjectRegister.h"
285ffd83dbSDimitry Andric #include "lldb/Symbol/UnwindPlan.h"
295ffd83dbSDimitry Andric #include "lldb/Target/Process.h"
305ffd83dbSDimitry Andric #include "lldb/Target/RegisterContext.h"
315ffd83dbSDimitry Andric #include "lldb/Target/StackFrame.h"
325ffd83dbSDimitry Andric #include "lldb/Target/Target.h"
335ffd83dbSDimitry Andric #include "lldb/Target/Thread.h"
345ffd83dbSDimitry Andric #include "lldb/Utility/ConstString.h"
355ffd83dbSDimitry Andric #include "lldb/Utility/RegisterValue.h"
365ffd83dbSDimitry Andric #include "lldb/Utility/Status.h"
375ffd83dbSDimitry Andric
385ffd83dbSDimitry Andric #define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
395ffd83dbSDimitry Andric #define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
405ffd83dbSDimitry Andric
415ffd83dbSDimitry Andric // The ABI is not a source of such information as size, offset, encoding, etc.
425ffd83dbSDimitry Andric // of a register. Just provides correct dwarf and eh_frame numbers.
435ffd83dbSDimitry Andric
445ffd83dbSDimitry Andric #define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \
455ffd83dbSDimitry Andric { \
465ffd83dbSDimitry Andric DEFINE_REG_NAME(dwarf_num), DEFINE_REG_NAME_STR(str_name), \
475ffd83dbSDimitry Andric 0, 0, eEncodingInvalid, eFormatDefault, \
485ffd83dbSDimitry Andric { dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num }, \
49*06c3fb27SDimitry Andric nullptr, nullptr, nullptr, \
505ffd83dbSDimitry Andric }
515ffd83dbSDimitry Andric
525ffd83dbSDimitry Andric #define DEFINE_REGISTER_STUB(dwarf_num, str_name) \
535ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM)
545ffd83dbSDimitry Andric
555ffd83dbSDimitry Andric using namespace lldb;
565ffd83dbSDimitry Andric using namespace lldb_private;
575ffd83dbSDimitry Andric
585ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE_ADV(ABISysV_arc, ABIARC)
595ffd83dbSDimitry Andric
605ffd83dbSDimitry Andric namespace {
615ffd83dbSDimitry Andric namespace dwarf {
625ffd83dbSDimitry Andric enum regnums {
635ffd83dbSDimitry Andric r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16,
645ffd83dbSDimitry Andric r17, r18, r19, r20, r21, r22, r23, r24, r25, r26,
655ffd83dbSDimitry Andric r27, fp = r27, r28, sp = r28, r29, r30, r31, blink = r31,
665ffd83dbSDimitry Andric r32, r33, r34, r35, r36, r37, r38, r39, r40, r41, r42, r43, r44, r45, r46,
675ffd83dbSDimitry Andric r47, r48, r49, r50, r51, r52, r53, r54, r55, r56, r57, r58, r59, r60,
685ffd83dbSDimitry Andric /*reserved,*/ /*limm indicator,*/ r63 = 63, pc = 70, status32 = 74
695ffd83dbSDimitry Andric };
705ffd83dbSDimitry Andric
715ffd83dbSDimitry Andric static const std::array<RegisterInfo, 64> g_register_infos = { {
725ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r0, nullptr, LLDB_REGNUM_GENERIC_ARG1),
735ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r1, nullptr, LLDB_REGNUM_GENERIC_ARG2),
745ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r2, nullptr, LLDB_REGNUM_GENERIC_ARG3),
755ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r3, nullptr, LLDB_REGNUM_GENERIC_ARG4),
765ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r4, nullptr, LLDB_REGNUM_GENERIC_ARG5),
775ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r5, nullptr, LLDB_REGNUM_GENERIC_ARG6),
785ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r6, nullptr, LLDB_REGNUM_GENERIC_ARG7),
795ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r7, nullptr, LLDB_REGNUM_GENERIC_ARG8),
805ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r8, nullptr),
815ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r9, nullptr),
825ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r10, nullptr),
835ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r11, nullptr),
845ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r12, nullptr),
855ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r13, nullptr),
865ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r14, nullptr),
875ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r15, nullptr),
885ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r16, nullptr),
895ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r17, nullptr),
905ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r18, nullptr),
915ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r19, nullptr),
925ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r20, nullptr),
935ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r21, nullptr),
945ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r22, nullptr),
955ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r23, nullptr),
965ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r24, nullptr),
975ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r25, nullptr),
985ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r26, "gp"),
995ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r27, "fp", LLDB_REGNUM_GENERIC_FP),
1005ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r28, "sp", LLDB_REGNUM_GENERIC_SP),
1015ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r29, "ilink"),
1025ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r30, nullptr),
1035ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(r31, "blink", LLDB_REGNUM_GENERIC_RA),
1045ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r32, nullptr),
1055ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r33, nullptr),
1065ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r34, nullptr),
1075ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r35, nullptr),
1085ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r36, nullptr),
1095ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r37, nullptr),
1105ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r38, nullptr),
1115ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r39, nullptr),
1125ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r40, nullptr),
1135ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r41, nullptr),
1145ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r42, nullptr),
1155ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r43, nullptr),
1165ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r44, nullptr),
1175ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r45, nullptr),
1185ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r46, nullptr),
1195ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r47, nullptr),
1205ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r48, nullptr),
1215ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r49, nullptr),
1225ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r50, nullptr),
1235ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r51, nullptr),
1245ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r52, nullptr),
1255ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r53, nullptr),
1265ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r54, nullptr),
1275ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r55, nullptr),
1285ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r56, nullptr),
1295ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r57, nullptr),
1305ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r58, "accl"),
1315ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r59, "acch"),
1325ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r60, "lp_count"),
1335ffd83dbSDimitry Andric DEFINE_REGISTER_STUB(r63, "pcl"),
1345ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(pc, nullptr, LLDB_REGNUM_GENERIC_PC),
1355ffd83dbSDimitry Andric DEFINE_GENERIC_REGISTER_STUB(status32, nullptr, LLDB_REGNUM_GENERIC_FLAGS)} };
1365ffd83dbSDimitry Andric } // namespace dwarf
1375ffd83dbSDimitry Andric } // namespace
1385ffd83dbSDimitry Andric
GetRegisterInfoArray(uint32_t & count)1395ffd83dbSDimitry Andric const RegisterInfo *ABISysV_arc::GetRegisterInfoArray(uint32_t &count) {
1405ffd83dbSDimitry Andric count = dwarf::g_register_infos.size();
1415ffd83dbSDimitry Andric return dwarf::g_register_infos.data();
1425ffd83dbSDimitry Andric }
1435ffd83dbSDimitry Andric
GetRedZoneSize() const1445ffd83dbSDimitry Andric size_t ABISysV_arc::GetRedZoneSize() const { return 0; }
1455ffd83dbSDimitry Andric
IsRegisterFileReduced(RegisterContext & reg_ctx) const1465ffd83dbSDimitry Andric bool ABISysV_arc::IsRegisterFileReduced(RegisterContext ®_ctx) const {
1475ffd83dbSDimitry Andric if (!m_is_reg_file_reduced) {
1485ffd83dbSDimitry Andric const auto *const rf_build_reg = reg_ctx.GetRegisterInfoByName("rf_build");
1495ffd83dbSDimitry Andric
1505ffd83dbSDimitry Andric const auto reg_value = reg_ctx.ReadRegisterAsUnsigned(rf_build_reg,
1515ffd83dbSDimitry Andric /*fail_value*/ 0);
1525ffd83dbSDimitry Andric // RF_BUILD "Number of Entries" bit.
1535ffd83dbSDimitry Andric const uint32_t rf_entries_bit = 1U << 9U;
154bdd1243dSDimitry Andric m_is_reg_file_reduced = (reg_value & rf_entries_bit) != 0;
1555ffd83dbSDimitry Andric }
1565ffd83dbSDimitry Andric
15781ad6265SDimitry Andric return m_is_reg_file_reduced.value_or(false);
1585ffd83dbSDimitry Andric }
1595ffd83dbSDimitry Andric
1605ffd83dbSDimitry Andric //------------------------------------------------------------------
1615ffd83dbSDimitry Andric // Static Functions
1625ffd83dbSDimitry Andric //------------------------------------------------------------------
1635ffd83dbSDimitry Andric
CreateInstance(ProcessSP process_sp,const ArchSpec & arch)1645ffd83dbSDimitry Andric ABISP ABISysV_arc::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) {
1655ffd83dbSDimitry Andric return llvm::Triple::arc == arch.GetTriple().getArch() ?
1665ffd83dbSDimitry Andric ABISP(new ABISysV_arc(std::move(process_sp), MakeMCRegisterInfo(arch))) :
1675ffd83dbSDimitry Andric ABISP();
1685ffd83dbSDimitry Andric }
1695ffd83dbSDimitry Andric
170349cc55cSDimitry Andric static const size_t word_size = 4U;
171349cc55cSDimitry Andric static const size_t reg_size = word_size;
1725ffd83dbSDimitry Andric
AugmentArgSize(size_t size_in_bytes)173349cc55cSDimitry Andric static inline size_t AugmentArgSize(size_t size_in_bytes) {
1745ffd83dbSDimitry Andric return llvm::alignTo(size_in_bytes, word_size);
1755ffd83dbSDimitry Andric }
1765ffd83dbSDimitry Andric
177349cc55cSDimitry Andric static size_t
TotalArgsSizeInWords(const llvm::ArrayRef<ABI::CallArgument> & args)178349cc55cSDimitry Andric TotalArgsSizeInWords(const llvm::ArrayRef<ABI::CallArgument> &args) {
1795ffd83dbSDimitry Andric size_t total_size = 0;
1805ffd83dbSDimitry Andric for (const auto &arg : args)
1815ffd83dbSDimitry Andric total_size +=
1825ffd83dbSDimitry Andric (ABI::CallArgument::TargetValue == arg.type ? AugmentArgSize(arg.size)
1835ffd83dbSDimitry Andric : reg_size) /
1845ffd83dbSDimitry Andric word_size;
1855ffd83dbSDimitry Andric
1865ffd83dbSDimitry Andric return total_size;
1875ffd83dbSDimitry Andric }
1885ffd83dbSDimitry Andric
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t func_addr,addr_t return_addr,llvm::ArrayRef<addr_t> args) const1895ffd83dbSDimitry Andric bool ABISysV_arc::PrepareTrivialCall(Thread &thread, addr_t sp,
1905ffd83dbSDimitry Andric addr_t func_addr, addr_t return_addr,
1915ffd83dbSDimitry Andric llvm::ArrayRef<addr_t> args) const {
1925ffd83dbSDimitry Andric // We don't use the traditional trivial call specialized for jit.
1935ffd83dbSDimitry Andric return false;
1945ffd83dbSDimitry Andric }
1955ffd83dbSDimitry Andric
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t pc,addr_t ra,llvm::Type & prototype,llvm::ArrayRef<ABI::CallArgument> args) const1965ffd83dbSDimitry Andric bool ABISysV_arc::PrepareTrivialCall(Thread &thread, addr_t sp, addr_t pc,
1975ffd83dbSDimitry Andric addr_t ra, llvm::Type &prototype,
1985ffd83dbSDimitry Andric llvm::ArrayRef<ABI::CallArgument> args) const {
1995ffd83dbSDimitry Andric auto reg_ctx = thread.GetRegisterContext();
2005ffd83dbSDimitry Andric if (!reg_ctx)
2015ffd83dbSDimitry Andric return false;
2025ffd83dbSDimitry Andric
2035ffd83dbSDimitry Andric uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
2045ffd83dbSDimitry Andric eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
2055ffd83dbSDimitry Andric if (pc_reg == LLDB_INVALID_REGNUM)
2065ffd83dbSDimitry Andric return false;
2075ffd83dbSDimitry Andric
2085ffd83dbSDimitry Andric uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
2095ffd83dbSDimitry Andric eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
2105ffd83dbSDimitry Andric if (ra_reg == LLDB_INVALID_REGNUM)
2115ffd83dbSDimitry Andric return false;
2125ffd83dbSDimitry Andric
2135ffd83dbSDimitry Andric uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
2145ffd83dbSDimitry Andric eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
2155ffd83dbSDimitry Andric if (sp_reg == LLDB_INVALID_REGNUM)
2165ffd83dbSDimitry Andric return false;
2175ffd83dbSDimitry Andric
2185ffd83dbSDimitry Andric Status error;
2195ffd83dbSDimitry Andric ProcessSP process = thread.GetProcess();
2205ffd83dbSDimitry Andric if (!process)
2215ffd83dbSDimitry Andric return false;
2225ffd83dbSDimitry Andric
2235ffd83dbSDimitry Andric // Push host data onto target.
2245ffd83dbSDimitry Andric for (const auto &arg : args) {
2255ffd83dbSDimitry Andric // Skip over target values.
2265ffd83dbSDimitry Andric if (arg.type == ABI::CallArgument::TargetValue)
2275ffd83dbSDimitry Andric continue;
2285ffd83dbSDimitry Andric
2295ffd83dbSDimitry Andric // Create space on the stack for this data 4-byte aligned.
2305ffd83dbSDimitry Andric sp -= AugmentArgSize(arg.size);
2315ffd83dbSDimitry Andric
2325ffd83dbSDimitry Andric if (process->WriteMemory(sp, arg.data_up.get(), arg.size, error) < arg.size
2335ffd83dbSDimitry Andric || error.Fail())
2345ffd83dbSDimitry Andric return false;
2355ffd83dbSDimitry Andric
2365ffd83dbSDimitry Andric // Update the argument with the target pointer.
2375ffd83dbSDimitry Andric *const_cast<addr_t *>(&arg.value) = sp;
2385ffd83dbSDimitry Andric }
2395ffd83dbSDimitry Andric
2405ffd83dbSDimitry Andric // Make sure number of parameters matches prototype.
2415ffd83dbSDimitry Andric assert(!prototype.isFunctionVarArg());
2425ffd83dbSDimitry Andric assert(prototype.getFunctionNumParams() == args.size());
2435ffd83dbSDimitry Andric
2445ffd83dbSDimitry Andric const size_t regs_for_args_count = IsRegisterFileReduced(*reg_ctx) ? 4U : 8U;
2455ffd83dbSDimitry Andric
2465ffd83dbSDimitry Andric // Number of arguments passed on stack.
2475ffd83dbSDimitry Andric auto args_size = TotalArgsSizeInWords(args);
2485ffd83dbSDimitry Andric auto on_stack =
2495ffd83dbSDimitry Andric args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count;
2505ffd83dbSDimitry Andric auto offset = on_stack * word_size;
2515ffd83dbSDimitry Andric
2525ffd83dbSDimitry Andric uint8_t reg_value[reg_size];
2535ffd83dbSDimitry Andric size_t reg_index = LLDB_REGNUM_GENERIC_ARG1;
2545ffd83dbSDimitry Andric
2555ffd83dbSDimitry Andric for (const auto &arg : args) {
2565ffd83dbSDimitry Andric auto value = reinterpret_cast<const uint8_t *>(&arg.value);
2575ffd83dbSDimitry Andric auto size =
2585ffd83dbSDimitry Andric ABI::CallArgument::TargetValue == arg.type ? arg.size : reg_size;
2595ffd83dbSDimitry Andric
2605ffd83dbSDimitry Andric // Pass arguments via registers.
2615ffd83dbSDimitry Andric while (size > 0 && reg_index < regs_for_args_count) {
2625ffd83dbSDimitry Andric size_t byte_index = 0;
2635ffd83dbSDimitry Andric auto end = size < reg_size ? size : reg_size;
2645ffd83dbSDimitry Andric
2655ffd83dbSDimitry Andric while (byte_index < end) {
2665ffd83dbSDimitry Andric reg_value[byte_index++] = *(value++);
2675ffd83dbSDimitry Andric --size;
2685ffd83dbSDimitry Andric }
2695ffd83dbSDimitry Andric
2705ffd83dbSDimitry Andric while (byte_index < reg_size) {
2715ffd83dbSDimitry Andric reg_value[byte_index++] = 0;
2725ffd83dbSDimitry Andric }
2735ffd83dbSDimitry Andric
274bdd1243dSDimitry Andric RegisterValue reg_val_obj(llvm::ArrayRef(reg_value, reg_size),
275e8d8bef9SDimitry Andric eByteOrderLittle);
2765ffd83dbSDimitry Andric if (!reg_ctx->WriteRegister(
2775ffd83dbSDimitry Andric reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_index),
2785ffd83dbSDimitry Andric reg_val_obj))
2795ffd83dbSDimitry Andric return false;
2805ffd83dbSDimitry Andric
2815ffd83dbSDimitry Andric // NOTE: It's unsafe to iterate through LLDB_REGNUM_GENERICs.
2825ffd83dbSDimitry Andric ++reg_index;
2835ffd83dbSDimitry Andric }
2845ffd83dbSDimitry Andric
2855ffd83dbSDimitry Andric if (reg_index < regs_for_args_count || size == 0)
2865ffd83dbSDimitry Andric continue;
2875ffd83dbSDimitry Andric
2885ffd83dbSDimitry Andric // Remaining arguments are passed on the stack.
2895ffd83dbSDimitry Andric if (process->WriteMemory(sp - offset, value, size, error) < size ||
2905ffd83dbSDimitry Andric !error.Success())
2915ffd83dbSDimitry Andric return false;
2925ffd83dbSDimitry Andric
2935ffd83dbSDimitry Andric offset -= AugmentArgSize(size);
2945ffd83dbSDimitry Andric }
2955ffd83dbSDimitry Andric
2965ffd83dbSDimitry Andric // Set stack pointer immediately below arguments.
2975ffd83dbSDimitry Andric sp -= on_stack * word_size;
2985ffd83dbSDimitry Andric
2995ffd83dbSDimitry Andric // Update registers with current function call state.
3005ffd83dbSDimitry Andric reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc);
3015ffd83dbSDimitry Andric reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra);
3025ffd83dbSDimitry Andric reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp);
3035ffd83dbSDimitry Andric
3045ffd83dbSDimitry Andric return true;
3055ffd83dbSDimitry Andric }
3065ffd83dbSDimitry Andric
GetArgumentValues(Thread & thread,ValueList & values) const3075ffd83dbSDimitry Andric bool ABISysV_arc::GetArgumentValues(Thread &thread, ValueList &values) const {
3085ffd83dbSDimitry Andric return false;
3095ffd83dbSDimitry Andric }
3105ffd83dbSDimitry Andric
SetReturnValueObject(StackFrameSP & frame_sp,ValueObjectSP & new_value_sp)3115ffd83dbSDimitry Andric Status ABISysV_arc::SetReturnValueObject(StackFrameSP &frame_sp,
3125ffd83dbSDimitry Andric ValueObjectSP &new_value_sp) {
3135ffd83dbSDimitry Andric Status result;
3145ffd83dbSDimitry Andric if (!new_value_sp) {
3155ffd83dbSDimitry Andric result.SetErrorString("Empty value object for return value.");
3165ffd83dbSDimitry Andric return result;
3175ffd83dbSDimitry Andric }
3185ffd83dbSDimitry Andric
3195ffd83dbSDimitry Andric CompilerType compiler_type = new_value_sp->GetCompilerType();
3205ffd83dbSDimitry Andric if (!compiler_type) {
3215ffd83dbSDimitry Andric result.SetErrorString("Null clang type for return value.");
3225ffd83dbSDimitry Andric return result;
3235ffd83dbSDimitry Andric }
3245ffd83dbSDimitry Andric
3255ffd83dbSDimitry Andric auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext();
3265ffd83dbSDimitry Andric
3275ffd83dbSDimitry Andric bool is_signed = false;
3285ffd83dbSDimitry Andric if (!compiler_type.IsIntegerOrEnumerationType(is_signed) &&
3295ffd83dbSDimitry Andric !compiler_type.IsPointerType()) {
3305ffd83dbSDimitry Andric result.SetErrorString("We don't support returning other types at present");
3315ffd83dbSDimitry Andric return result;
3325ffd83dbSDimitry Andric }
3335ffd83dbSDimitry Andric
3345ffd83dbSDimitry Andric DataExtractor data;
3355ffd83dbSDimitry Andric size_t num_bytes = new_value_sp->GetData(data, result);
3365ffd83dbSDimitry Andric
3375ffd83dbSDimitry Andric if (result.Fail()) {
3385ffd83dbSDimitry Andric result.SetErrorStringWithFormat(
3395ffd83dbSDimitry Andric "Couldn't convert return value to raw data: %s", result.AsCString());
3405ffd83dbSDimitry Andric return result;
3415ffd83dbSDimitry Andric }
3425ffd83dbSDimitry Andric
3435ffd83dbSDimitry Andric if (num_bytes <= 2 * reg_size) {
3445ffd83dbSDimitry Andric offset_t offset = 0;
3455ffd83dbSDimitry Andric uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
3465ffd83dbSDimitry Andric
3475ffd83dbSDimitry Andric auto reg_info =
3485ffd83dbSDimitry Andric reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
3495ffd83dbSDimitry Andric if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
3505ffd83dbSDimitry Andric result.SetErrorStringWithFormat("Couldn't write value to register %s",
3515ffd83dbSDimitry Andric reg_info->name);
3525ffd83dbSDimitry Andric return result;
3535ffd83dbSDimitry Andric }
3545ffd83dbSDimitry Andric
3555ffd83dbSDimitry Andric if (num_bytes <= reg_size)
3565ffd83dbSDimitry Andric return result; // Successfully written.
3575ffd83dbSDimitry Andric
3585ffd83dbSDimitry Andric raw_value >>= 32;
3595ffd83dbSDimitry Andric reg_info =
3605ffd83dbSDimitry Andric reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
3615ffd83dbSDimitry Andric if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
3625ffd83dbSDimitry Andric result.SetErrorStringWithFormat("Couldn't write value to register %s",
3635ffd83dbSDimitry Andric reg_info->name);
3645ffd83dbSDimitry Andric }
3655ffd83dbSDimitry Andric
3665ffd83dbSDimitry Andric return result;
3675ffd83dbSDimitry Andric }
3685ffd83dbSDimitry Andric
3695ffd83dbSDimitry Andric result.SetErrorString(
3705ffd83dbSDimitry Andric "We don't support returning large integer values at present.");
3715ffd83dbSDimitry Andric return result;
3725ffd83dbSDimitry Andric }
3735ffd83dbSDimitry Andric
3745ffd83dbSDimitry Andric template <typename T>
SetInteger(Scalar & scalar,uint64_t raw_value,bool is_signed)375349cc55cSDimitry Andric static void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed) {
3765ffd83dbSDimitry Andric raw_value &= std::numeric_limits<T>::max();
3775ffd83dbSDimitry Andric if (is_signed)
3785ffd83dbSDimitry Andric scalar = static_cast<typename std::make_signed<T>::type>(raw_value);
3795ffd83dbSDimitry Andric else
3805ffd83dbSDimitry Andric scalar = static_cast<T>(raw_value);
3815ffd83dbSDimitry Andric }
3825ffd83dbSDimitry Andric
SetSizedInteger(Scalar & scalar,uint64_t raw_value,uint8_t size_in_bytes,bool is_signed)383349cc55cSDimitry Andric static bool SetSizedInteger(Scalar &scalar, uint64_t raw_value,
384349cc55cSDimitry Andric uint8_t size_in_bytes, bool is_signed) {
3855ffd83dbSDimitry Andric switch (size_in_bytes) {
3865ffd83dbSDimitry Andric default:
3875ffd83dbSDimitry Andric return false;
3885ffd83dbSDimitry Andric
3895ffd83dbSDimitry Andric case sizeof(uint64_t):
3905ffd83dbSDimitry Andric SetInteger<uint64_t>(scalar, raw_value, is_signed);
3915ffd83dbSDimitry Andric break;
3925ffd83dbSDimitry Andric
3935ffd83dbSDimitry Andric case sizeof(uint32_t):
3945ffd83dbSDimitry Andric SetInteger<uint32_t>(scalar, raw_value, is_signed);
3955ffd83dbSDimitry Andric break;
3965ffd83dbSDimitry Andric
3975ffd83dbSDimitry Andric case sizeof(uint16_t):
3985ffd83dbSDimitry Andric SetInteger<uint16_t>(scalar, raw_value, is_signed);
3995ffd83dbSDimitry Andric break;
4005ffd83dbSDimitry Andric
4015ffd83dbSDimitry Andric case sizeof(uint8_t):
4025ffd83dbSDimitry Andric SetInteger<uint8_t>(scalar, raw_value, is_signed);
4035ffd83dbSDimitry Andric break;
4045ffd83dbSDimitry Andric }
4055ffd83dbSDimitry Andric
4065ffd83dbSDimitry Andric return true;
4075ffd83dbSDimitry Andric }
4085ffd83dbSDimitry Andric
SetSizedFloat(Scalar & scalar,uint64_t raw_value,uint8_t size_in_bytes)409349cc55cSDimitry Andric static bool SetSizedFloat(Scalar &scalar, uint64_t raw_value,
410349cc55cSDimitry Andric uint8_t size_in_bytes) {
4115ffd83dbSDimitry Andric switch (size_in_bytes) {
4125ffd83dbSDimitry Andric default:
4135ffd83dbSDimitry Andric return false;
4145ffd83dbSDimitry Andric
4155ffd83dbSDimitry Andric case sizeof(uint64_t):
4165ffd83dbSDimitry Andric scalar = *reinterpret_cast<double *>(&raw_value);
4175ffd83dbSDimitry Andric break;
4185ffd83dbSDimitry Andric
4195ffd83dbSDimitry Andric case sizeof(uint32_t):
4205ffd83dbSDimitry Andric scalar = *reinterpret_cast<float *>(&raw_value);
4215ffd83dbSDimitry Andric break;
4225ffd83dbSDimitry Andric }
4235ffd83dbSDimitry Andric
4245ffd83dbSDimitry Andric return true;
4255ffd83dbSDimitry Andric }
4265ffd83dbSDimitry Andric
ReadRawValue(const RegisterContextSP & reg_ctx,uint8_t size_in_bytes)427349cc55cSDimitry Andric static uint64_t ReadRawValue(const RegisterContextSP ®_ctx,
428349cc55cSDimitry Andric uint8_t size_in_bytes) {
4295ffd83dbSDimitry Andric auto reg_info_r0 =
4305ffd83dbSDimitry Andric reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
4315ffd83dbSDimitry Andric
4325ffd83dbSDimitry Andric // Extract the register context so we can read arguments from registers.
4335ffd83dbSDimitry Andric uint64_t raw_value =
4345ffd83dbSDimitry Andric reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0) & UINT32_MAX;
4355ffd83dbSDimitry Andric
4365ffd83dbSDimitry Andric if (sizeof(uint64_t) == size_in_bytes)
4375ffd83dbSDimitry Andric raw_value |= (reg_ctx->ReadRegisterAsUnsigned(
4385ffd83dbSDimitry Andric reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
4395ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_ARG2), 0) &
4405ffd83dbSDimitry Andric UINT64_MAX) << 32U;
4415ffd83dbSDimitry Andric
4425ffd83dbSDimitry Andric return raw_value;
4435ffd83dbSDimitry Andric }
4445ffd83dbSDimitry Andric
4455ffd83dbSDimitry Andric ValueObjectSP
GetReturnValueObjectSimple(Thread & thread,CompilerType & compiler_type) const4465ffd83dbSDimitry Andric ABISysV_arc::GetReturnValueObjectSimple(Thread &thread,
4475ffd83dbSDimitry Andric CompilerType &compiler_type) const {
4485ffd83dbSDimitry Andric if (!compiler_type)
4495ffd83dbSDimitry Andric return ValueObjectSP();
4505ffd83dbSDimitry Andric
4515ffd83dbSDimitry Andric auto reg_ctx = thread.GetRegisterContext();
4525ffd83dbSDimitry Andric if (!reg_ctx)
4535ffd83dbSDimitry Andric return ValueObjectSP();
4545ffd83dbSDimitry Andric
4555ffd83dbSDimitry Andric Value value;
4565ffd83dbSDimitry Andric value.SetCompilerType(compiler_type);
4575ffd83dbSDimitry Andric
4585ffd83dbSDimitry Andric const uint32_t type_flags = compiler_type.GetTypeInfo();
4595ffd83dbSDimitry Andric // Integer return type.
4605ffd83dbSDimitry Andric if (type_flags & eTypeIsInteger) {
46181ad6265SDimitry Andric const size_t byte_size = compiler_type.GetByteSize(&thread).value_or(0);
4625ffd83dbSDimitry Andric auto raw_value = ReadRawValue(reg_ctx, byte_size);
4635ffd83dbSDimitry Andric
4645ffd83dbSDimitry Andric const bool is_signed = (type_flags & eTypeIsSigned) != 0;
4655ffd83dbSDimitry Andric if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed))
4665ffd83dbSDimitry Andric return ValueObjectSP();
4675ffd83dbSDimitry Andric
468fe6060f1SDimitry Andric value.SetValueType(Value::ValueType::Scalar);
4695ffd83dbSDimitry Andric }
4705ffd83dbSDimitry Andric // Pointer return type.
4715ffd83dbSDimitry Andric else if (type_flags & eTypeIsPointer) {
4725ffd83dbSDimitry Andric auto reg_info_r0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
4735ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_ARG1);
4745ffd83dbSDimitry Andric value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0);
4755ffd83dbSDimitry Andric
476fe6060f1SDimitry Andric value.SetValueType(Value::ValueType::Scalar);
4775ffd83dbSDimitry Andric }
4785ffd83dbSDimitry Andric // Floating point return type.
4795ffd83dbSDimitry Andric else if (type_flags & eTypeIsFloat) {
4805ffd83dbSDimitry Andric uint32_t float_count = 0;
4815ffd83dbSDimitry Andric bool is_complex = false;
4825ffd83dbSDimitry Andric
4835ffd83dbSDimitry Andric if (compiler_type.IsFloatingPointType(float_count, is_complex) &&
4845ffd83dbSDimitry Andric 1 == float_count && !is_complex) {
48581ad6265SDimitry Andric const size_t byte_size = compiler_type.GetByteSize(&thread).value_or(0);
4865ffd83dbSDimitry Andric auto raw_value = ReadRawValue(reg_ctx, byte_size);
4875ffd83dbSDimitry Andric
4885ffd83dbSDimitry Andric if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
4895ffd83dbSDimitry Andric return ValueObjectSP();
4905ffd83dbSDimitry Andric }
4915ffd83dbSDimitry Andric }
4925ffd83dbSDimitry Andric // Unsupported return type.
4935ffd83dbSDimitry Andric else
4945ffd83dbSDimitry Andric return ValueObjectSP();
4955ffd83dbSDimitry Andric
4965ffd83dbSDimitry Andric return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
4975ffd83dbSDimitry Andric value, ConstString(""));
4985ffd83dbSDimitry Andric }
4995ffd83dbSDimitry Andric
GetReturnValueObjectImpl(Thread & thread,CompilerType & return_compiler_type) const5005ffd83dbSDimitry Andric ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl(
5015ffd83dbSDimitry Andric Thread &thread, CompilerType &return_compiler_type) const {
5025ffd83dbSDimitry Andric ValueObjectSP return_valobj_sp;
5035ffd83dbSDimitry Andric
5045ffd83dbSDimitry Andric if (!return_compiler_type)
5055ffd83dbSDimitry Andric return return_valobj_sp;
5065ffd83dbSDimitry Andric
5075ffd83dbSDimitry Andric ExecutionContext exe_ctx(thread.shared_from_this());
5085ffd83dbSDimitry Andric return GetReturnValueObjectSimple(thread, return_compiler_type);
5095ffd83dbSDimitry Andric }
5105ffd83dbSDimitry Andric
GetReturnValueObjectImpl(Thread & thread,llvm::Type & retType) const5115ffd83dbSDimitry Andric ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl(Thread &thread,
5125ffd83dbSDimitry Andric llvm::Type &retType) const {
5135ffd83dbSDimitry Andric auto reg_ctx = thread.GetRegisterContext();
5145ffd83dbSDimitry Andric if (!reg_ctx)
5155ffd83dbSDimitry Andric return ValueObjectSP();
5165ffd83dbSDimitry Andric
5175ffd83dbSDimitry Andric Value value;
5185ffd83dbSDimitry Andric // Void return type.
5195ffd83dbSDimitry Andric if (retType.isVoidTy()) {
5205ffd83dbSDimitry Andric value.GetScalar() = 0;
5215ffd83dbSDimitry Andric }
5225ffd83dbSDimitry Andric // Integer return type.
5235ffd83dbSDimitry Andric else if (retType.isIntegerTy()) {
5245ffd83dbSDimitry Andric size_t byte_size = retType.getPrimitiveSizeInBits();
5255ffd83dbSDimitry Andric if (1 != byte_size) // For boolean type.
5265ffd83dbSDimitry Andric byte_size /= CHAR_BIT;
5275ffd83dbSDimitry Andric
5285ffd83dbSDimitry Andric auto raw_value = ReadRawValue(reg_ctx, byte_size);
5295ffd83dbSDimitry Andric
5305ffd83dbSDimitry Andric const bool is_signed = false; // IR Type doesn't provide this info.
5315ffd83dbSDimitry Andric if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed))
5325ffd83dbSDimitry Andric return ValueObjectSP();
5335ffd83dbSDimitry Andric }
5345ffd83dbSDimitry Andric // Pointer return type.
5355ffd83dbSDimitry Andric else if (retType.isPointerTy()) {
5365ffd83dbSDimitry Andric auto reg_info_r0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
5375ffd83dbSDimitry Andric LLDB_REGNUM_GENERIC_ARG1);
5385ffd83dbSDimitry Andric value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0);
539fe6060f1SDimitry Andric value.SetValueType(Value::ValueType::Scalar);
5405ffd83dbSDimitry Andric }
5415ffd83dbSDimitry Andric // Floating point return type.
5425ffd83dbSDimitry Andric else if (retType.isFloatingPointTy()) {
5435ffd83dbSDimitry Andric const size_t byte_size = retType.getPrimitiveSizeInBits() / CHAR_BIT;
5445ffd83dbSDimitry Andric auto raw_value = ReadRawValue(reg_ctx, byte_size);
5455ffd83dbSDimitry Andric
5465ffd83dbSDimitry Andric if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
5475ffd83dbSDimitry Andric return ValueObjectSP();
5485ffd83dbSDimitry Andric }
5495ffd83dbSDimitry Andric // Unsupported return type.
5505ffd83dbSDimitry Andric else
5515ffd83dbSDimitry Andric return ValueObjectSP();
5525ffd83dbSDimitry Andric
5535ffd83dbSDimitry Andric return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
5545ffd83dbSDimitry Andric value, ConstString(""));
5555ffd83dbSDimitry Andric }
5565ffd83dbSDimitry Andric
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)5575ffd83dbSDimitry Andric bool ABISysV_arc::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
5585ffd83dbSDimitry Andric unwind_plan.Clear();
5595ffd83dbSDimitry Andric unwind_plan.SetRegisterKind(eRegisterKindDWARF);
5605ffd83dbSDimitry Andric
5615ffd83dbSDimitry Andric UnwindPlan::RowSP row(new UnwindPlan::Row);
5625ffd83dbSDimitry Andric
5635ffd83dbSDimitry Andric // Our Call Frame Address is the stack pointer value.
5645ffd83dbSDimitry Andric row->GetCFAValue().SetIsRegisterPlusOffset(dwarf::sp, 0);
5655ffd83dbSDimitry Andric
5665ffd83dbSDimitry Andric // The previous PC is in the BLINK.
5675ffd83dbSDimitry Andric row->SetRegisterLocationToRegister(dwarf::pc, dwarf::blink, true);
5685ffd83dbSDimitry Andric unwind_plan.AppendRow(row);
5695ffd83dbSDimitry Andric
5705ffd83dbSDimitry Andric // All other registers are the same.
5715ffd83dbSDimitry Andric unwind_plan.SetSourceName("arc at-func-entry default");
5725ffd83dbSDimitry Andric unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
5735ffd83dbSDimitry Andric
5745ffd83dbSDimitry Andric return true;
5755ffd83dbSDimitry Andric }
5765ffd83dbSDimitry Andric
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)5775ffd83dbSDimitry Andric bool ABISysV_arc::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
5785ffd83dbSDimitry Andric return false;
5795ffd83dbSDimitry Andric }
5805ffd83dbSDimitry Andric
RegisterIsVolatile(const RegisterInfo * reg_info)5815ffd83dbSDimitry Andric bool ABISysV_arc::RegisterIsVolatile(const RegisterInfo *reg_info) {
5825ffd83dbSDimitry Andric if (nullptr == reg_info)
5835ffd83dbSDimitry Andric return false;
5845ffd83dbSDimitry Andric
5855ffd83dbSDimitry Andric // Volatile registers are: r0..r12.
5865ffd83dbSDimitry Andric uint32_t regnum = reg_info->kinds[eRegisterKindDWARF];
5875ffd83dbSDimitry Andric if (regnum <= 12)
5885ffd83dbSDimitry Andric return true;
5895ffd83dbSDimitry Andric
5905ffd83dbSDimitry Andric static const std::string ra_reg_name = "blink";
5915ffd83dbSDimitry Andric return ra_reg_name == reg_info->name;
5925ffd83dbSDimitry Andric }
5935ffd83dbSDimitry Andric
Initialize()5945ffd83dbSDimitry Andric void ABISysV_arc::Initialize() {
5955ffd83dbSDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(),
5965ffd83dbSDimitry Andric "System V ABI for ARC targets", CreateInstance);
5975ffd83dbSDimitry Andric }
5985ffd83dbSDimitry Andric
Terminate()5995ffd83dbSDimitry Andric void ABISysV_arc::Terminate() {
6005ffd83dbSDimitry Andric PluginManager::UnregisterPlugin(CreateInstance);
6015ffd83dbSDimitry Andric }
602