Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp
39653 views
1
//===-- ABISysV_arc.cpp ---------------------------------------------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "ABISysV_arc.h"
10
11
// C Includes
12
// C++ Includes
13
#include <array>
14
#include <limits>
15
#include <type_traits>
16
17
// Other libraries and framework includes
18
#include "llvm/IR/DerivedTypes.h"
19
#include "llvm/Support/MathExtras.h"
20
#include "llvm/TargetParser/Triple.h"
21
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"
37
38
#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
39
#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
40
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.
43
44
#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \
45
{ \
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, \
50
}
51
52
#define DEFINE_REGISTER_STUB(dwarf_num, str_name) \
53
DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM)
54
55
using namespace lldb;
56
using namespace lldb_private;
57
58
LLDB_PLUGIN_DEFINE_ADV(ABISysV_arc, ABIARC)
59
60
namespace {
61
namespace dwarf {
62
enum regnums {
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
69
};
70
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)} };
136
} // namespace dwarf
137
} // namespace
138
139
const RegisterInfo *ABISysV_arc::GetRegisterInfoArray(uint32_t &count) {
140
count = dwarf::g_register_infos.size();
141
return dwarf::g_register_infos.data();
142
}
143
144
size_t ABISysV_arc::GetRedZoneSize() const { return 0; }
145
146
bool ABISysV_arc::IsRegisterFileReduced(RegisterContext &reg_ctx) const {
147
if (!m_is_reg_file_reduced) {
148
const auto *const rf_build_reg = reg_ctx.GetRegisterInfoByName("rf_build");
149
150
const auto reg_value = reg_ctx.ReadRegisterAsUnsigned(rf_build_reg,
151
/*fail_value*/ 0);
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;
155
}
156
157
return m_is_reg_file_reduced.value_or(false);
158
}
159
160
//------------------------------------------------------------------
161
// Static Functions
162
//------------------------------------------------------------------
163
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))) :
167
ABISP();
168
}
169
170
static const size_t word_size = 4U;
171
static const size_t reg_size = word_size;
172
173
static inline size_t AugmentArgSize(size_t size_in_bytes) {
174
return llvm::alignTo(size_in_bytes, word_size);
175
}
176
177
static size_t
178
TotalArgsSizeInWords(const llvm::ArrayRef<ABI::CallArgument> &args) {
179
size_t total_size = 0;
180
for (const auto &arg : args)
181
total_size +=
182
(ABI::CallArgument::TargetValue == arg.type ? AugmentArgSize(arg.size)
183
: reg_size) /
184
word_size;
185
186
return total_size;
187
}
188
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.
193
return false;
194
}
195
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();
200
if (!reg_ctx)
201
return false;
202
203
uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
204
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
205
if (pc_reg == LLDB_INVALID_REGNUM)
206
return false;
207
208
uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
209
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
210
if (ra_reg == LLDB_INVALID_REGNUM)
211
return false;
212
213
uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
214
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
215
if (sp_reg == LLDB_INVALID_REGNUM)
216
return false;
217
218
Status error;
219
ProcessSP process = thread.GetProcess();
220
if (!process)
221
return false;
222
223
// Push host data onto target.
224
for (const auto &arg : args) {
225
// Skip over target values.
226
if (arg.type == ABI::CallArgument::TargetValue)
227
continue;
228
229
// Create space on the stack for this data 4-byte aligned.
230
sp -= AugmentArgSize(arg.size);
231
232
if (process->WriteMemory(sp, arg.data_up.get(), arg.size, error) < arg.size
233
|| error.Fail())
234
return false;
235
236
// Update the argument with the target pointer.
237
*const_cast<addr_t *>(&arg.value) = sp;
238
}
239
240
// Make sure number of parameters matches prototype.
241
assert(!prototype.isFunctionVarArg());
242
assert(prototype.getFunctionNumParams() == args.size());
243
244
const size_t regs_for_args_count = IsRegisterFileReduced(*reg_ctx) ? 4U : 8U;
245
246
// Number of arguments passed on stack.
247
auto args_size = TotalArgsSizeInWords(args);
248
auto on_stack =
249
args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count;
250
auto offset = on_stack * word_size;
251
252
uint8_t reg_value[reg_size];
253
size_t reg_index = LLDB_REGNUM_GENERIC_ARG1;
254
255
for (const auto &arg : args) {
256
auto value = reinterpret_cast<const uint8_t *>(&arg.value);
257
auto size =
258
ABI::CallArgument::TargetValue == arg.type ? arg.size : reg_size;
259
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;
264
265
while (byte_index < end) {
266
reg_value[byte_index++] = *(value++);
267
--size;
268
}
269
270
while (byte_index < reg_size) {
271
reg_value[byte_index++] = 0;
272
}
273
274
RegisterValue reg_val_obj(llvm::ArrayRef(reg_value, reg_size),
275
eByteOrderLittle);
276
if (!reg_ctx->WriteRegister(
277
reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_index),
278
reg_val_obj))
279
return false;
280
281
// NOTE: It's unsafe to iterate through LLDB_REGNUM_GENERICs.
282
++reg_index;
283
}
284
285
if (reg_index < regs_for_args_count || size == 0)
286
continue;
287
288
// Remaining arguments are passed on the stack.
289
if (process->WriteMemory(sp - offset, value, size, error) < size ||
290
!error.Success())
291
return false;
292
293
offset -= AugmentArgSize(size);
294
}
295
296
// Set stack pointer immediately below arguments.
297
sp -= on_stack * word_size;
298
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);
303
304
return true;
305
}
306
307
bool ABISysV_arc::GetArgumentValues(Thread &thread, ValueList &values) const {
308
return false;
309
}
310
311
Status ABISysV_arc::SetReturnValueObject(StackFrameSP &frame_sp,
312
ValueObjectSP &new_value_sp) {
313
Status result;
314
if (!new_value_sp) {
315
result.SetErrorString("Empty value object for return value.");
316
return result;
317
}
318
319
CompilerType compiler_type = new_value_sp->GetCompilerType();
320
if (!compiler_type) {
321
result.SetErrorString("Null clang type for return value.");
322
return result;
323
}
324
325
auto &reg_ctx = *frame_sp->GetThread()->GetRegisterContext();
326
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");
331
return result;
332
}
333
334
DataExtractor data;
335
size_t num_bytes = new_value_sp->GetData(data, result);
336
337
if (result.Fail()) {
338
result.SetErrorStringWithFormat(
339
"Couldn't convert return value to raw data: %s", result.AsCString());
340
return result;
341
}
342
343
if (num_bytes <= 2 * reg_size) {
344
offset_t offset = 0;
345
uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
346
347
auto reg_info =
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",
351
reg_info->name);
352
return result;
353
}
354
355
if (num_bytes <= reg_size)
356
return result; // Successfully written.
357
358
raw_value >>= 32;
359
reg_info =
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",
363
reg_info->name);
364
}
365
366
return result;
367
}
368
369
result.SetErrorString(
370
"We don't support returning large integer values at present.");
371
return result;
372
}
373
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();
377
if (is_signed)
378
scalar = static_cast<typename std::make_signed<T>::type>(raw_value);
379
else
380
scalar = static_cast<T>(raw_value);
381
}
382
383
static bool SetSizedInteger(Scalar &scalar, uint64_t raw_value,
384
uint8_t size_in_bytes, bool is_signed) {
385
switch (size_in_bytes) {
386
default:
387
return false;
388
389
case sizeof(uint64_t):
390
SetInteger<uint64_t>(scalar, raw_value, is_signed);
391
break;
392
393
case sizeof(uint32_t):
394
SetInteger<uint32_t>(scalar, raw_value, is_signed);
395
break;
396
397
case sizeof(uint16_t):
398
SetInteger<uint16_t>(scalar, raw_value, is_signed);
399
break;
400
401
case sizeof(uint8_t):
402
SetInteger<uint8_t>(scalar, raw_value, is_signed);
403
break;
404
}
405
406
return true;
407
}
408
409
static bool SetSizedFloat(Scalar &scalar, uint64_t raw_value,
410
uint8_t size_in_bytes) {
411
switch (size_in_bytes) {
412
default:
413
return false;
414
415
case sizeof(uint64_t):
416
scalar = *reinterpret_cast<double *>(&raw_value);
417
break;
418
419
case sizeof(uint32_t):
420
scalar = *reinterpret_cast<float *>(&raw_value);
421
break;
422
}
423
424
return true;
425
}
426
427
static uint64_t ReadRawValue(const RegisterContextSP &reg_ctx,
428
uint8_t size_in_bytes) {
429
auto reg_info_r0 =
430
reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
431
432
// Extract the register context so we can read arguments from registers.
433
uint64_t raw_value =
434
reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0) & UINT32_MAX;
435
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) &
440
UINT64_MAX) << 32U;
441
442
return raw_value;
443
}
444
445
ValueObjectSP
446
ABISysV_arc::GetReturnValueObjectSimple(Thread &thread,
447
CompilerType &compiler_type) const {
448
if (!compiler_type)
449
return ValueObjectSP();
450
451
auto reg_ctx = thread.GetRegisterContext();
452
if (!reg_ctx)
453
return ValueObjectSP();
454
455
Value value;
456
value.SetCompilerType(compiler_type);
457
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);
463
464
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
465
if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed))
466
return ValueObjectSP();
467
468
value.SetValueType(Value::ValueType::Scalar);
469
}
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);
475
476
value.SetValueType(Value::ValueType::Scalar);
477
}
478
// Floating point return type.
479
else if (type_flags & eTypeIsFloat) {
480
uint32_t float_count = 0;
481
bool is_complex = false;
482
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);
487
488
if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
489
return ValueObjectSP();
490
}
491
}
492
// Unsupported return type.
493
else
494
return ValueObjectSP();
495
496
return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
497
value, ConstString(""));
498
}
499
500
ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl(
501
Thread &thread, CompilerType &return_compiler_type) const {
502
ValueObjectSP return_valobj_sp;
503
504
if (!return_compiler_type)
505
return return_valobj_sp;
506
507
ExecutionContext exe_ctx(thread.shared_from_this());
508
return GetReturnValueObjectSimple(thread, return_compiler_type);
509
}
510
511
ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl(Thread &thread,
512
llvm::Type &retType) const {
513
auto reg_ctx = thread.GetRegisterContext();
514
if (!reg_ctx)
515
return ValueObjectSP();
516
517
Value value;
518
// Void return type.
519
if (retType.isVoidTy()) {
520
value.GetScalar() = 0;
521
}
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;
527
528
auto raw_value = ReadRawValue(reg_ctx, byte_size);
529
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();
533
}
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);
540
}
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);
545
546
if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
547
return ValueObjectSP();
548
}
549
// Unsupported return type.
550
else
551
return ValueObjectSP();
552
553
return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
554
value, ConstString(""));
555
}
556
557
bool ABISysV_arc::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
558
unwind_plan.Clear();
559
unwind_plan.SetRegisterKind(eRegisterKindDWARF);
560
561
UnwindPlan::RowSP row(new UnwindPlan::Row);
562
563
// Our Call Frame Address is the stack pointer value.
564
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf::sp, 0);
565
566
// The previous PC is in the BLINK.
567
row->SetRegisterLocationToRegister(dwarf::pc, dwarf::blink, true);
568
unwind_plan.AppendRow(row);
569
570
// All other registers are the same.
571
unwind_plan.SetSourceName("arc at-func-entry default");
572
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
573
574
return true;
575
}
576
577
bool ABISysV_arc::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
578
return false;
579
}
580
581
bool ABISysV_arc::RegisterIsVolatile(const RegisterInfo *reg_info) {
582
if (nullptr == reg_info)
583
return false;
584
585
// Volatile registers are: r0..r12.
586
uint32_t regnum = reg_info->kinds[eRegisterKindDWARF];
587
if (regnum <= 12)
588
return true;
589
590
static const std::string ra_reg_name = "blink";
591
return ra_reg_name == reg_info->name;
592
}
593
594
void ABISysV_arc::Initialize() {
595
PluginManager::RegisterPlugin(GetPluginNameStatic(),
596
"System V ABI for ARC targets", CreateInstance);
597
}
598
599
void ABISysV_arc::Terminate() {
600
PluginManager::UnregisterPlugin(CreateInstance);
601
}
602
603