1 //===-- ABISysV_arc.cpp ---------------------------------------------------===//
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_arc.h"
15 #include <type_traits>
17 // Other libraries and framework includes
18 #include "llvm/IR/DerivedTypes.h"
19 #include "llvm/Support/MathExtras.h"
20 #include "llvm/TargetParser/Triple.h"
22 #include "lldb/Core/Module.h"
23 #include "lldb/Core/PluginManager.h"
24 #include "lldb/Core/Value.h"
25 #include "lldb/Core/ValueObjectConstResult.h"
26 #include "lldb/Core/ValueObjectMemory.h"
27 #include "lldb/Core/ValueObjectRegister.h"
28 #include "lldb/Symbol/UnwindPlan.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/RegisterContext.h"
31 #include "lldb/Target/StackFrame.h"
32 #include "lldb/Target/Target.h"
33 #include "lldb/Target/Thread.h"
34 #include "lldb/Utility/ConstString.h"
35 #include "lldb/Utility/RegisterValue.h"
36 #include "lldb/Utility/Status.h"
38 #define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
39 #define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
41 // The ABI is not a source of such information as size, offset, encoding, etc.
42 // of a register. Just provides correct dwarf and eh_frame numbers.
44 #define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \
46 DEFINE_REG_NAME(dwarf_num), DEFINE_REG_NAME_STR(str_name), \
47 0, 0, eEncodingInvalid, eFormatDefault, \
48 { dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num }, \
49 nullptr, nullptr, nullptr, \
52 #define DEFINE_REGISTER_STUB(dwarf_num, str_name) \
53 DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM)
56 using namespace lldb_private
;
58 LLDB_PLUGIN_DEFINE_ADV(ABISysV_arc
, ABIARC
)
63 r0
, r1
, r2
, r3
, r4
, r5
, r6
, r7
, r8
, r9
, r10
, r11
, r12
, r13
, r14
, r15
, r16
,
64 r17
, r18
, r19
, r20
, r21
, r22
, r23
, r24
, r25
, r26
,
65 r27
, fp
= r27
, r28
, sp
= r28
, r29
, r30
, r31
, blink
= r31
,
66 r32
, r33
, r34
, r35
, r36
, r37
, r38
, r39
, r40
, r41
, r42
, r43
, r44
, r45
, r46
,
67 r47
, r48
, r49
, r50
, r51
, r52
, r53
, r54
, r55
, r56
, r57
, r58
, r59
, r60
,
68 /*reserved,*/ /*limm indicator,*/ r63
= 63, pc
= 70, status32
= 74
71 static const std::array
<RegisterInfo
, 64> g_register_infos
= { {
72 DEFINE_GENERIC_REGISTER_STUB(r0
, nullptr, LLDB_REGNUM_GENERIC_ARG1
),
73 DEFINE_GENERIC_REGISTER_STUB(r1
, nullptr, LLDB_REGNUM_GENERIC_ARG2
),
74 DEFINE_GENERIC_REGISTER_STUB(r2
, nullptr, LLDB_REGNUM_GENERIC_ARG3
),
75 DEFINE_GENERIC_REGISTER_STUB(r3
, nullptr, LLDB_REGNUM_GENERIC_ARG4
),
76 DEFINE_GENERIC_REGISTER_STUB(r4
, nullptr, LLDB_REGNUM_GENERIC_ARG5
),
77 DEFINE_GENERIC_REGISTER_STUB(r5
, nullptr, LLDB_REGNUM_GENERIC_ARG6
),
78 DEFINE_GENERIC_REGISTER_STUB(r6
, nullptr, LLDB_REGNUM_GENERIC_ARG7
),
79 DEFINE_GENERIC_REGISTER_STUB(r7
, nullptr, LLDB_REGNUM_GENERIC_ARG8
),
80 DEFINE_REGISTER_STUB(r8
, nullptr),
81 DEFINE_REGISTER_STUB(r9
, nullptr),
82 DEFINE_REGISTER_STUB(r10
, nullptr),
83 DEFINE_REGISTER_STUB(r11
, nullptr),
84 DEFINE_REGISTER_STUB(r12
, nullptr),
85 DEFINE_REGISTER_STUB(r13
, nullptr),
86 DEFINE_REGISTER_STUB(r14
, nullptr),
87 DEFINE_REGISTER_STUB(r15
, nullptr),
88 DEFINE_REGISTER_STUB(r16
, nullptr),
89 DEFINE_REGISTER_STUB(r17
, nullptr),
90 DEFINE_REGISTER_STUB(r18
, nullptr),
91 DEFINE_REGISTER_STUB(r19
, nullptr),
92 DEFINE_REGISTER_STUB(r20
, nullptr),
93 DEFINE_REGISTER_STUB(r21
, nullptr),
94 DEFINE_REGISTER_STUB(r22
, nullptr),
95 DEFINE_REGISTER_STUB(r23
, nullptr),
96 DEFINE_REGISTER_STUB(r24
, nullptr),
97 DEFINE_REGISTER_STUB(r25
, nullptr),
98 DEFINE_REGISTER_STUB(r26
, "gp"),
99 DEFINE_GENERIC_REGISTER_STUB(r27
, "fp", LLDB_REGNUM_GENERIC_FP
),
100 DEFINE_GENERIC_REGISTER_STUB(r28
, "sp", LLDB_REGNUM_GENERIC_SP
),
101 DEFINE_REGISTER_STUB(r29
, "ilink"),
102 DEFINE_REGISTER_STUB(r30
, nullptr),
103 DEFINE_GENERIC_REGISTER_STUB(r31
, "blink", LLDB_REGNUM_GENERIC_RA
),
104 DEFINE_REGISTER_STUB(r32
, nullptr),
105 DEFINE_REGISTER_STUB(r33
, nullptr),
106 DEFINE_REGISTER_STUB(r34
, nullptr),
107 DEFINE_REGISTER_STUB(r35
, nullptr),
108 DEFINE_REGISTER_STUB(r36
, nullptr),
109 DEFINE_REGISTER_STUB(r37
, nullptr),
110 DEFINE_REGISTER_STUB(r38
, nullptr),
111 DEFINE_REGISTER_STUB(r39
, nullptr),
112 DEFINE_REGISTER_STUB(r40
, nullptr),
113 DEFINE_REGISTER_STUB(r41
, nullptr),
114 DEFINE_REGISTER_STUB(r42
, nullptr),
115 DEFINE_REGISTER_STUB(r43
, nullptr),
116 DEFINE_REGISTER_STUB(r44
, nullptr),
117 DEFINE_REGISTER_STUB(r45
, nullptr),
118 DEFINE_REGISTER_STUB(r46
, nullptr),
119 DEFINE_REGISTER_STUB(r47
, nullptr),
120 DEFINE_REGISTER_STUB(r48
, nullptr),
121 DEFINE_REGISTER_STUB(r49
, nullptr),
122 DEFINE_REGISTER_STUB(r50
, nullptr),
123 DEFINE_REGISTER_STUB(r51
, nullptr),
124 DEFINE_REGISTER_STUB(r52
, nullptr),
125 DEFINE_REGISTER_STUB(r53
, nullptr),
126 DEFINE_REGISTER_STUB(r54
, nullptr),
127 DEFINE_REGISTER_STUB(r55
, nullptr),
128 DEFINE_REGISTER_STUB(r56
, nullptr),
129 DEFINE_REGISTER_STUB(r57
, nullptr),
130 DEFINE_REGISTER_STUB(r58
, "accl"),
131 DEFINE_REGISTER_STUB(r59
, "acch"),
132 DEFINE_REGISTER_STUB(r60
, "lp_count"),
133 DEFINE_REGISTER_STUB(r63
, "pcl"),
134 DEFINE_GENERIC_REGISTER_STUB(pc
, nullptr, LLDB_REGNUM_GENERIC_PC
),
135 DEFINE_GENERIC_REGISTER_STUB(status32
, nullptr, LLDB_REGNUM_GENERIC_FLAGS
)} };
139 const RegisterInfo
*ABISysV_arc::GetRegisterInfoArray(uint32_t &count
) {
140 count
= dwarf::g_register_infos
.size();
141 return dwarf::g_register_infos
.data();
144 size_t ABISysV_arc::GetRedZoneSize() const { return 0; }
146 bool ABISysV_arc::IsRegisterFileReduced(RegisterContext
®_ctx
) const {
147 if (!m_is_reg_file_reduced
) {
148 const auto *const rf_build_reg
= reg_ctx
.GetRegisterInfoByName("rf_build");
150 const auto reg_value
= reg_ctx
.ReadRegisterAsUnsigned(rf_build_reg
,
152 // RF_BUILD "Number of Entries" bit.
153 const uint32_t rf_entries_bit
= 1U << 9U;
154 m_is_reg_file_reduced
= (reg_value
& rf_entries_bit
) != 0;
157 return m_is_reg_file_reduced
.value_or(false);
160 //------------------------------------------------------------------
162 //------------------------------------------------------------------
164 ABISP
ABISysV_arc::CreateInstance(ProcessSP process_sp
, const ArchSpec
&arch
) {
165 return llvm::Triple::arc
== arch
.GetTriple().getArch() ?
166 ABISP(new ABISysV_arc(std::move(process_sp
), MakeMCRegisterInfo(arch
))) :
170 static const size_t word_size
= 4U;
171 static const size_t reg_size
= word_size
;
173 static inline size_t AugmentArgSize(size_t size_in_bytes
) {
174 return llvm::alignTo(size_in_bytes
, word_size
);
178 TotalArgsSizeInWords(const llvm::ArrayRef
<ABI::CallArgument
> &args
) {
179 size_t total_size
= 0;
180 for (const auto &arg
: args
)
182 (ABI::CallArgument::TargetValue
== arg
.type
? AugmentArgSize(arg
.size
)
189 bool ABISysV_arc::PrepareTrivialCall(Thread
&thread
, addr_t sp
,
190 addr_t func_addr
, addr_t return_addr
,
191 llvm::ArrayRef
<addr_t
> args
) const {
192 // We don't use the traditional trivial call specialized for jit.
196 bool ABISysV_arc::PrepareTrivialCall(Thread
&thread
, addr_t sp
, addr_t pc
,
197 addr_t ra
, llvm::Type
&prototype
,
198 llvm::ArrayRef
<ABI::CallArgument
> args
) const {
199 auto reg_ctx
= thread
.GetRegisterContext();
203 uint32_t pc_reg
= reg_ctx
->ConvertRegisterKindToRegisterNumber(
204 eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
205 if (pc_reg
== LLDB_INVALID_REGNUM
)
208 uint32_t ra_reg
= reg_ctx
->ConvertRegisterKindToRegisterNumber(
209 eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_RA
);
210 if (ra_reg
== LLDB_INVALID_REGNUM
)
213 uint32_t sp_reg
= reg_ctx
->ConvertRegisterKindToRegisterNumber(
214 eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_SP
);
215 if (sp_reg
== LLDB_INVALID_REGNUM
)
219 ProcessSP process
= thread
.GetProcess();
223 // Push host data onto target.
224 for (const auto &arg
: args
) {
225 // Skip over target values.
226 if (arg
.type
== ABI::CallArgument::TargetValue
)
229 // Create space on the stack for this data 4-byte aligned.
230 sp
-= AugmentArgSize(arg
.size
);
232 if (process
->WriteMemory(sp
, arg
.data_up
.get(), arg
.size
, error
) < arg
.size
236 // Update the argument with the target pointer.
237 *const_cast<addr_t
*>(&arg
.value
) = sp
;
240 // Make sure number of parameters matches prototype.
241 assert(!prototype
.isFunctionVarArg());
242 assert(prototype
.getFunctionNumParams() == args
.size());
244 const size_t regs_for_args_count
= IsRegisterFileReduced(*reg_ctx
) ? 4U : 8U;
246 // Number of arguments passed on stack.
247 auto args_size
= TotalArgsSizeInWords(args
);
249 args_size
<= regs_for_args_count
? 0 : args_size
- regs_for_args_count
;
250 auto offset
= on_stack
* word_size
;
252 uint8_t reg_value
[reg_size
];
253 size_t reg_index
= LLDB_REGNUM_GENERIC_ARG1
;
255 for (const auto &arg
: args
) {
256 auto value
= reinterpret_cast<const uint8_t *>(&arg
.value
);
258 ABI::CallArgument::TargetValue
== arg
.type
? arg
.size
: reg_size
;
260 // Pass arguments via registers.
261 while (size
> 0 && reg_index
< regs_for_args_count
) {
262 size_t byte_index
= 0;
263 auto end
= size
< reg_size
? size
: reg_size
;
265 while (byte_index
< end
) {
266 reg_value
[byte_index
++] = *(value
++);
270 while (byte_index
< reg_size
) {
271 reg_value
[byte_index
++] = 0;
274 RegisterValue
reg_val_obj(llvm::ArrayRef(reg_value
, reg_size
),
276 if (!reg_ctx
->WriteRegister(
277 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, reg_index
),
281 // NOTE: It's unsafe to iterate through LLDB_REGNUM_GENERICs.
285 if (reg_index
< regs_for_args_count
|| size
== 0)
288 // Remaining arguments are passed on the stack.
289 if (process
->WriteMemory(sp
- offset
, value
, size
, error
) < size
||
293 offset
-= AugmentArgSize(size
);
296 // Set stack pointer immediately below arguments.
297 sp
-= on_stack
* word_size
;
299 // Update registers with current function call state.
300 reg_ctx
->WriteRegisterFromUnsigned(pc_reg
, pc
);
301 reg_ctx
->WriteRegisterFromUnsigned(ra_reg
, ra
);
302 reg_ctx
->WriteRegisterFromUnsigned(sp_reg
, sp
);
307 bool ABISysV_arc::GetArgumentValues(Thread
&thread
, ValueList
&values
) const {
311 Status
ABISysV_arc::SetReturnValueObject(StackFrameSP
&frame_sp
,
312 ValueObjectSP
&new_value_sp
) {
315 result
.SetErrorString("Empty value object for return value.");
319 CompilerType compiler_type
= new_value_sp
->GetCompilerType();
320 if (!compiler_type
) {
321 result
.SetErrorString("Null clang type for return value.");
325 auto ®_ctx
= *frame_sp
->GetThread()->GetRegisterContext();
327 bool is_signed
= false;
328 if (!compiler_type
.IsIntegerOrEnumerationType(is_signed
) &&
329 !compiler_type
.IsPointerType()) {
330 result
.SetErrorString("We don't support returning other types at present");
335 size_t num_bytes
= new_value_sp
->GetData(data
, result
);
338 result
.SetErrorStringWithFormat(
339 "Couldn't convert return value to raw data: %s", result
.AsCString());
343 if (num_bytes
<= 2 * reg_size
) {
345 uint64_t raw_value
= data
.GetMaxU64(&offset
, num_bytes
);
348 reg_ctx
.GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG1
);
349 if (!reg_ctx
.WriteRegisterFromUnsigned(reg_info
, raw_value
)) {
350 result
.SetErrorStringWithFormat("Couldn't write value to register %s",
355 if (num_bytes
<= reg_size
)
356 return result
; // Successfully written.
360 reg_ctx
.GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG2
);
361 if (!reg_ctx
.WriteRegisterFromUnsigned(reg_info
, raw_value
)) {
362 result
.SetErrorStringWithFormat("Couldn't write value to register %s",
369 result
.SetErrorString(
370 "We don't support returning large integer values at present.");
374 template <typename T
>
375 static void SetInteger(Scalar
&scalar
, uint64_t raw_value
, bool is_signed
) {
376 raw_value
&= std::numeric_limits
<T
>::max();
378 scalar
= static_cast<typename
std::make_signed
<T
>::type
>(raw_value
);
380 scalar
= static_cast<T
>(raw_value
);
383 static bool SetSizedInteger(Scalar
&scalar
, uint64_t raw_value
,
384 uint8_t size_in_bytes
, bool is_signed
) {
385 switch (size_in_bytes
) {
389 case sizeof(uint64_t):
390 SetInteger
<uint64_t>(scalar
, raw_value
, is_signed
);
393 case sizeof(uint32_t):
394 SetInteger
<uint32_t>(scalar
, raw_value
, is_signed
);
397 case sizeof(uint16_t):
398 SetInteger
<uint16_t>(scalar
, raw_value
, is_signed
);
401 case sizeof(uint8_t):
402 SetInteger
<uint8_t>(scalar
, raw_value
, is_signed
);
409 static bool SetSizedFloat(Scalar
&scalar
, uint64_t raw_value
,
410 uint8_t size_in_bytes
) {
411 switch (size_in_bytes
) {
415 case sizeof(uint64_t):
416 scalar
= *reinterpret_cast<double *>(&raw_value
);
419 case sizeof(uint32_t):
420 scalar
= *reinterpret_cast<float *>(&raw_value
);
427 static uint64_t ReadRawValue(const RegisterContextSP
®_ctx
,
428 uint8_t size_in_bytes
) {
430 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG1
);
432 // Extract the register context so we can read arguments from registers.
434 reg_ctx
->ReadRegisterAsUnsigned(reg_info_r0
, 0) & UINT32_MAX
;
436 if (sizeof(uint64_t) == size_in_bytes
)
437 raw_value
|= (reg_ctx
->ReadRegisterAsUnsigned(
438 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
,
439 LLDB_REGNUM_GENERIC_ARG2
), 0) &
446 ABISysV_arc::GetReturnValueObjectSimple(Thread
&thread
,
447 CompilerType
&compiler_type
) const {
449 return ValueObjectSP();
451 auto reg_ctx
= thread
.GetRegisterContext();
453 return ValueObjectSP();
456 value
.SetCompilerType(compiler_type
);
458 const uint32_t type_flags
= compiler_type
.GetTypeInfo();
459 // Integer return type.
460 if (type_flags
& eTypeIsInteger
) {
461 const size_t byte_size
= compiler_type
.GetByteSize(&thread
).value_or(0);
462 auto raw_value
= ReadRawValue(reg_ctx
, byte_size
);
464 const bool is_signed
= (type_flags
& eTypeIsSigned
) != 0;
465 if (!SetSizedInteger(value
.GetScalar(), raw_value
, byte_size
, is_signed
))
466 return ValueObjectSP();
468 value
.SetValueType(Value::ValueType::Scalar
);
470 // Pointer return type.
471 else if (type_flags
& eTypeIsPointer
) {
472 auto reg_info_r0
= reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
,
473 LLDB_REGNUM_GENERIC_ARG1
);
474 value
.GetScalar() = reg_ctx
->ReadRegisterAsUnsigned(reg_info_r0
, 0);
476 value
.SetValueType(Value::ValueType::Scalar
);
478 // Floating point return type.
479 else if (type_flags
& eTypeIsFloat
) {
480 uint32_t float_count
= 0;
481 bool is_complex
= false;
483 if (compiler_type
.IsFloatingPointType(float_count
, is_complex
) &&
484 1 == float_count
&& !is_complex
) {
485 const size_t byte_size
= compiler_type
.GetByteSize(&thread
).value_or(0);
486 auto raw_value
= ReadRawValue(reg_ctx
, byte_size
);
488 if (!SetSizedFloat(value
.GetScalar(), raw_value
, byte_size
))
489 return ValueObjectSP();
492 // Unsupported return type.
494 return ValueObjectSP();
496 return ValueObjectConstResult::Create(thread
.GetStackFrameAtIndex(0).get(),
497 value
, ConstString(""));
500 ValueObjectSP
ABISysV_arc::GetReturnValueObjectImpl(
501 Thread
&thread
, CompilerType
&return_compiler_type
) const {
502 ValueObjectSP return_valobj_sp
;
504 if (!return_compiler_type
)
505 return return_valobj_sp
;
507 ExecutionContext
exe_ctx(thread
.shared_from_this());
508 return GetReturnValueObjectSimple(thread
, return_compiler_type
);
511 ValueObjectSP
ABISysV_arc::GetReturnValueObjectImpl(Thread
&thread
,
512 llvm::Type
&retType
) const {
513 auto reg_ctx
= thread
.GetRegisterContext();
515 return ValueObjectSP();
519 if (retType
.isVoidTy()) {
520 value
.GetScalar() = 0;
522 // Integer return type.
523 else if (retType
.isIntegerTy()) {
524 size_t byte_size
= retType
.getPrimitiveSizeInBits();
525 if (1 != byte_size
) // For boolean type.
526 byte_size
/= CHAR_BIT
;
528 auto raw_value
= ReadRawValue(reg_ctx
, byte_size
);
530 const bool is_signed
= false; // IR Type doesn't provide this info.
531 if (!SetSizedInteger(value
.GetScalar(), raw_value
, byte_size
, is_signed
))
532 return ValueObjectSP();
534 // Pointer return type.
535 else if (retType
.isPointerTy()) {
536 auto reg_info_r0
= reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
,
537 LLDB_REGNUM_GENERIC_ARG1
);
538 value
.GetScalar() = reg_ctx
->ReadRegisterAsUnsigned(reg_info_r0
, 0);
539 value
.SetValueType(Value::ValueType::Scalar
);
541 // Floating point return type.
542 else if (retType
.isFloatingPointTy()) {
543 const size_t byte_size
= retType
.getPrimitiveSizeInBits() / CHAR_BIT
;
544 auto raw_value
= ReadRawValue(reg_ctx
, byte_size
);
546 if (!SetSizedFloat(value
.GetScalar(), raw_value
, byte_size
))
547 return ValueObjectSP();
549 // Unsupported return type.
551 return ValueObjectSP();
553 return ValueObjectConstResult::Create(thread
.GetStackFrameAtIndex(0).get(),
554 value
, ConstString(""));
557 bool ABISysV_arc::CreateFunctionEntryUnwindPlan(UnwindPlan
&unwind_plan
) {
559 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
561 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
563 // Our Call Frame Address is the stack pointer value.
564 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf::sp
, 0);
566 // The previous PC is in the BLINK.
567 row
->SetRegisterLocationToRegister(dwarf::pc
, dwarf::blink
, true);
568 unwind_plan
.AppendRow(row
);
570 // All other registers are the same.
571 unwind_plan
.SetSourceName("arc at-func-entry default");
572 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
577 bool ABISysV_arc::CreateDefaultUnwindPlan(UnwindPlan
&unwind_plan
) {
581 bool ABISysV_arc::RegisterIsVolatile(const RegisterInfo
*reg_info
) {
582 if (nullptr == reg_info
)
585 // Volatile registers are: r0..r12.
586 uint32_t regnum
= reg_info
->kinds
[eRegisterKindDWARF
];
590 static const std::string ra_reg_name
= "blink";
591 return ra_reg_name
== reg_info
->name
;
594 void ABISysV_arc::Initialize() {
595 PluginManager::RegisterPlugin(GetPluginNameStatic(),
596 "System V ABI for ARC targets", CreateInstance
);
599 void ABISysV_arc::Terminate() {
600 PluginManager::UnregisterPlugin(CreateInstance
);