1//===-- ABISysV_arc.cpp ---------------------------------------*- C++ -*-===//
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/ADT/Triple.h"
19#include "llvm/IR/DerivedTypes.h"
20#include "llvm/Support/MathExtras.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, 0                                              \
50  }
51
52#define DEFINE_REGISTER_STUB(dwarf_num, str_name) \
53  DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM)
54
55using namespace lldb;
56using namespace lldb_private;
57
58namespace {
59namespace dwarf {
60enum regnums {
61  r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16,
62  r17, r18, r19, r20, r21, r22, r23, r24, r25, r26,
63  r27, fp = r27, r28, sp = r28, r29, r30, r31, blink = r31,
64  r32, r33, r34, r35, r36, r37, r38, r39, r40, r41, r42, r43, r44, r45, r46,
65  r47, r48, r49, r50, r51, r52, r53, r54, r55, r56, r57, r58, r59, r60,
66  /*reserved,*/ /*limm indicator,*/ r63 = 63, pc = 70, status32 = 74
67};
68
69static const std::array<RegisterInfo, 64> g_register_infos = { {
70    DEFINE_GENERIC_REGISTER_STUB(r0, nullptr, LLDB_REGNUM_GENERIC_ARG1),
71    DEFINE_GENERIC_REGISTER_STUB(r1, nullptr, LLDB_REGNUM_GENERIC_ARG2),
72    DEFINE_GENERIC_REGISTER_STUB(r2, nullptr, LLDB_REGNUM_GENERIC_ARG3),
73    DEFINE_GENERIC_REGISTER_STUB(r3, nullptr, LLDB_REGNUM_GENERIC_ARG4),
74    DEFINE_GENERIC_REGISTER_STUB(r4, nullptr, LLDB_REGNUM_GENERIC_ARG5),
75    DEFINE_GENERIC_REGISTER_STUB(r5, nullptr, LLDB_REGNUM_GENERIC_ARG6),
76    DEFINE_GENERIC_REGISTER_STUB(r6, nullptr, LLDB_REGNUM_GENERIC_ARG7),
77    DEFINE_GENERIC_REGISTER_STUB(r7, nullptr, LLDB_REGNUM_GENERIC_ARG8),
78    DEFINE_REGISTER_STUB(r8, nullptr),
79    DEFINE_REGISTER_STUB(r9, nullptr),
80    DEFINE_REGISTER_STUB(r10, nullptr),
81    DEFINE_REGISTER_STUB(r11, nullptr),
82    DEFINE_REGISTER_STUB(r12, nullptr),
83    DEFINE_REGISTER_STUB(r13, nullptr),
84    DEFINE_REGISTER_STUB(r14, nullptr),
85    DEFINE_REGISTER_STUB(r15, nullptr),
86    DEFINE_REGISTER_STUB(r16, nullptr),
87    DEFINE_REGISTER_STUB(r17, nullptr),
88    DEFINE_REGISTER_STUB(r18, nullptr),
89    DEFINE_REGISTER_STUB(r19, nullptr),
90    DEFINE_REGISTER_STUB(r20, nullptr),
91    DEFINE_REGISTER_STUB(r21, nullptr),
92    DEFINE_REGISTER_STUB(r22, nullptr),
93    DEFINE_REGISTER_STUB(r23, nullptr),
94    DEFINE_REGISTER_STUB(r24, nullptr),
95    DEFINE_REGISTER_STUB(r25, nullptr),
96    DEFINE_REGISTER_STUB(r26, "gp"),
97    DEFINE_GENERIC_REGISTER_STUB(r27, "fp", LLDB_REGNUM_GENERIC_FP),
98    DEFINE_GENERIC_REGISTER_STUB(r28, "sp", LLDB_REGNUM_GENERIC_SP),
99    DEFINE_REGISTER_STUB(r29, "ilink"),
100    DEFINE_REGISTER_STUB(r30, nullptr),
101    DEFINE_GENERIC_REGISTER_STUB(r31, "blink", LLDB_REGNUM_GENERIC_RA),
102    DEFINE_REGISTER_STUB(r32, nullptr),
103    DEFINE_REGISTER_STUB(r33, nullptr),
104    DEFINE_REGISTER_STUB(r34, nullptr),
105    DEFINE_REGISTER_STUB(r35, nullptr),
106    DEFINE_REGISTER_STUB(r36, nullptr),
107    DEFINE_REGISTER_STUB(r37, nullptr),
108    DEFINE_REGISTER_STUB(r38, nullptr),
109    DEFINE_REGISTER_STUB(r39, nullptr),
110    DEFINE_REGISTER_STUB(r40, nullptr),
111    DEFINE_REGISTER_STUB(r41, nullptr),
112    DEFINE_REGISTER_STUB(r42, nullptr),
113    DEFINE_REGISTER_STUB(r43, nullptr),
114    DEFINE_REGISTER_STUB(r44, nullptr),
115    DEFINE_REGISTER_STUB(r45, nullptr),
116    DEFINE_REGISTER_STUB(r46, nullptr),
117    DEFINE_REGISTER_STUB(r47, nullptr),
118    DEFINE_REGISTER_STUB(r48, nullptr),
119    DEFINE_REGISTER_STUB(r49, nullptr),
120    DEFINE_REGISTER_STUB(r50, nullptr),
121    DEFINE_REGISTER_STUB(r51, nullptr),
122    DEFINE_REGISTER_STUB(r52, nullptr),
123    DEFINE_REGISTER_STUB(r53, nullptr),
124    DEFINE_REGISTER_STUB(r54, nullptr),
125    DEFINE_REGISTER_STUB(r55, nullptr),
126    DEFINE_REGISTER_STUB(r56, nullptr),
127    DEFINE_REGISTER_STUB(r57, nullptr),
128    DEFINE_REGISTER_STUB(r58, "accl"),
129    DEFINE_REGISTER_STUB(r59, "acch"),
130    DEFINE_REGISTER_STUB(r60, "lp_count"),
131    DEFINE_REGISTER_STUB(r63, "pcl"),
132    DEFINE_GENERIC_REGISTER_STUB(pc, nullptr, LLDB_REGNUM_GENERIC_PC),
133    DEFINE_GENERIC_REGISTER_STUB(status32, nullptr, LLDB_REGNUM_GENERIC_FLAGS)} };
134} // namespace dwarf
135} // namespace
136
137const RegisterInfo *ABISysV_arc::GetRegisterInfoArray(uint32_t &count) {
138  count = dwarf::g_register_infos.size();
139  return dwarf::g_register_infos.data();
140}
141
142size_t ABISysV_arc::GetRedZoneSize() const { return 0; }
143
144bool ABISysV_arc::IsRegisterFileReduced(RegisterContext &reg_ctx) const {
145  if (!m_is_reg_file_reduced) {
146    const auto *const rf_build_reg = reg_ctx.GetRegisterInfoByName("rf_build");
147
148    const auto reg_value = reg_ctx.ReadRegisterAsUnsigned(rf_build_reg,
149                                                          /*fail_value*/ 0);
150    // RF_BUILD "Number of Entries" bit.
151    const uint32_t rf_entries_bit = 1U << 9U;
152    m_is_reg_file_reduced = (reg_value | rf_entries_bit) != 0;
153  }
154
155  return m_is_reg_file_reduced.getValueOr(false);
156}
157
158//------------------------------------------------------------------
159// Static Functions
160//------------------------------------------------------------------
161
162ABISP ABISysV_arc::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) {
163  return llvm::Triple::arc == arch.GetTriple().getArch() ?
164      ABISP(new ABISysV_arc(std::move(process_sp), MakeMCRegisterInfo(arch))) :
165      ABISP();
166}
167
168namespace {
169const size_t word_size = 4U;
170const size_t reg_size = word_size;
171
172inline size_t AugmentArgSize(size_t size_in_bytes) {
173  return llvm::alignTo(size_in_bytes, word_size);
174}
175
176size_t TotalArgsSizeInWords(const llvm::ArrayRef<ABI::CallArgument> &args) {
177  size_t total_size = 0;
178  for (const auto &arg : args)
179    total_size +=
180        (ABI::CallArgument::TargetValue == arg.type ? AugmentArgSize(arg.size)
181                                                    : reg_size) /
182        word_size;
183
184  return total_size;
185}
186} // namespace
187
188bool ABISysV_arc::PrepareTrivialCall(Thread &thread, addr_t sp,
189                                     addr_t func_addr, addr_t return_addr,
190                                     llvm::ArrayRef<addr_t> args) const {
191  // We don't use the traditional trivial call specialized for jit.
192  return false;
193}
194
195bool ABISysV_arc::PrepareTrivialCall(Thread &thread, addr_t sp, addr_t pc,
196    addr_t ra, llvm::Type &prototype,
197    llvm::ArrayRef<ABI::CallArgument> args) const {
198  auto reg_ctx = thread.GetRegisterContext();
199  if (!reg_ctx)
200    return false;
201
202  uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
203      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
204  if (pc_reg == LLDB_INVALID_REGNUM)
205    return false;
206
207  uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
208      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
209  if (ra_reg == LLDB_INVALID_REGNUM)
210    return false;
211
212  uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
213      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
214  if (sp_reg == LLDB_INVALID_REGNUM)
215    return false;
216
217  Status error;
218  ProcessSP process = thread.GetProcess();
219  if (!process)
220    return false;
221
222  // Push host data onto target.
223  for (const auto &arg : args) {
224    // Skip over target values.
225    if (arg.type == ABI::CallArgument::TargetValue)
226      continue;
227
228    // Create space on the stack for this data 4-byte aligned.
229    sp -= AugmentArgSize(arg.size);
230
231    if (process->WriteMemory(sp, arg.data_up.get(), arg.size, error) < arg.size
232        || error.Fail())
233      return false;
234
235    // Update the argument with the target pointer.
236    *const_cast<addr_t *>(&arg.value) = sp;
237  }
238
239  // Make sure number of parameters matches prototype.
240  assert(!prototype.isFunctionVarArg());
241  assert(prototype.getFunctionNumParams() == args.size());
242
243  const size_t regs_for_args_count = IsRegisterFileReduced(*reg_ctx) ? 4U : 8U;
244
245  // Number of arguments passed on stack.
246  auto args_size = TotalArgsSizeInWords(args);
247  auto on_stack =
248      args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count;
249  auto offset = on_stack * word_size;
250
251  uint8_t reg_value[reg_size];
252  size_t reg_index = LLDB_REGNUM_GENERIC_ARG1;
253
254  for (const auto &arg : args) {
255    auto value = reinterpret_cast<const uint8_t *>(&arg.value);
256    auto size =
257        ABI::CallArgument::TargetValue == arg.type ? arg.size : reg_size;
258
259    // Pass arguments via registers.
260    while (size > 0 && reg_index < regs_for_args_count) {
261      size_t byte_index = 0;
262      auto end = size < reg_size ? size : reg_size;
263
264      while (byte_index < end) {
265        reg_value[byte_index++] = *(value++);
266        --size;
267      }
268
269      while (byte_index < reg_size) {
270        reg_value[byte_index++] = 0;
271      }
272
273      RegisterValue reg_val_obj(reg_value, reg_size, eByteOrderLittle);
274      if (!reg_ctx->WriteRegister(
275            reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_index),
276            reg_val_obj))
277        return false;
278
279      // NOTE: It's unsafe to iterate through LLDB_REGNUM_GENERICs.
280      ++reg_index;
281    }
282
283    if (reg_index < regs_for_args_count || size == 0)
284      continue;
285
286    // Remaining arguments are passed on the stack.
287    if (process->WriteMemory(sp - offset, value, size, error) < size ||
288        !error.Success())
289      return false;
290
291    offset -= AugmentArgSize(size);
292  }
293
294  // Set stack pointer immediately below arguments.
295  sp -= on_stack * word_size;
296
297  // Update registers with current function call state.
298  reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc);
299  reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra);
300  reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp);
301
302  return true;
303}
304
305bool ABISysV_arc::GetArgumentValues(Thread &thread, ValueList &values) const {
306  return false;
307}
308
309Status ABISysV_arc::SetReturnValueObject(StackFrameSP &frame_sp,
310                                         ValueObjectSP &new_value_sp) {
311  Status result;
312  if (!new_value_sp) {
313    result.SetErrorString("Empty value object for return value.");
314    return result;
315  }
316
317  CompilerType compiler_type = new_value_sp->GetCompilerType();
318  if (!compiler_type) {
319    result.SetErrorString("Null clang type for return value.");
320    return result;
321  }
322
323  auto &reg_ctx = *frame_sp->GetThread()->GetRegisterContext();
324
325  bool is_signed = false;
326  if (!compiler_type.IsIntegerOrEnumerationType(is_signed) &&
327      !compiler_type.IsPointerType()) {
328    result.SetErrorString("We don't support returning other types at present");
329    return result;
330  }
331
332  DataExtractor data;
333  size_t num_bytes = new_value_sp->GetData(data, result);
334
335  if (result.Fail()) {
336    result.SetErrorStringWithFormat(
337        "Couldn't convert return value to raw data: %s", result.AsCString());
338    return result;
339  }
340
341  if (num_bytes <= 2 * reg_size) {
342    offset_t offset = 0;
343    uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
344
345    auto reg_info =
346        reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
347    if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
348      result.SetErrorStringWithFormat("Couldn't write value to register %s",
349                                      reg_info->name);
350      return result;
351    }
352
353    if (num_bytes <= reg_size)
354      return result; // Successfully written.
355
356    raw_value >>= 32;
357    reg_info =
358        reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
359    if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
360      result.SetErrorStringWithFormat("Couldn't write value to register %s",
361                                      reg_info->name);
362    }
363
364    return result;
365  }
366
367  result.SetErrorString(
368      "We don't support returning large integer values at present.");
369  return result;
370}
371
372namespace {
373template <typename T>
374void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed) {
375  raw_value &= std::numeric_limits<T>::max();
376  if (is_signed)
377    scalar = static_cast<typename std::make_signed<T>::type>(raw_value);
378  else
379    scalar = static_cast<T>(raw_value);
380}
381
382bool SetSizedInteger(Scalar &scalar, uint64_t raw_value, uint8_t size_in_bytes,
383                     bool is_signed) {
384  switch (size_in_bytes) {
385  default:
386    return false;
387
388  case sizeof(uint64_t):
389    SetInteger<uint64_t>(scalar, raw_value, is_signed);
390    break;
391
392  case sizeof(uint32_t):
393    SetInteger<uint32_t>(scalar, raw_value, is_signed);
394    break;
395
396  case sizeof(uint16_t):
397    SetInteger<uint16_t>(scalar, raw_value, is_signed);
398    break;
399
400  case sizeof(uint8_t):
401    SetInteger<uint8_t>(scalar, raw_value, is_signed);
402    break;
403  }
404
405  return true;
406}
407
408bool SetSizedFloat(Scalar &scalar, uint64_t raw_value, uint8_t size_in_bytes) {
409  switch (size_in_bytes) {
410  default:
411    return false;
412
413  case sizeof(uint64_t):
414    scalar = *reinterpret_cast<double *>(&raw_value);
415    break;
416
417  case sizeof(uint32_t):
418    scalar = *reinterpret_cast<float *>(&raw_value);
419    break;
420  }
421
422  return true;
423}
424
425uint64_t ReadRawValue(const RegisterContextSP &reg_ctx, uint8_t size_in_bytes) {
426  auto reg_info_r0 =
427      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
428
429  // Extract the register context so we can read arguments from registers.
430  uint64_t raw_value =
431      reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0) & UINT32_MAX;
432
433  if (sizeof(uint64_t) == size_in_bytes)
434    raw_value |= (reg_ctx->ReadRegisterAsUnsigned(
435                      reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
436                                               LLDB_REGNUM_GENERIC_ARG2), 0) &
437                  UINT64_MAX) << 32U;
438
439  return raw_value;
440}
441} // namespace
442
443ValueObjectSP
444ABISysV_arc::GetReturnValueObjectSimple(Thread &thread,
445                                        CompilerType &compiler_type) const {
446  if (!compiler_type)
447    return ValueObjectSP();
448
449  auto reg_ctx = thread.GetRegisterContext();
450  if (!reg_ctx)
451    return ValueObjectSP();
452
453  Value value;
454  value.SetCompilerType(compiler_type);
455
456  const uint32_t type_flags = compiler_type.GetTypeInfo();
457  // Integer return type.
458  if (type_flags & eTypeIsInteger) {
459    const size_t byte_size = compiler_type.GetByteSize(nullptr).getValueOr(0);
460    auto raw_value = ReadRawValue(reg_ctx, byte_size);
461
462    const bool is_signed = (type_flags & eTypeIsSigned) != 0;
463    if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed))
464      return ValueObjectSP();
465
466    value.SetValueType(Value::eValueTypeScalar);
467  }
468  // Pointer return type.
469  else if (type_flags & eTypeIsPointer) {
470    auto reg_info_r0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
471                                                LLDB_REGNUM_GENERIC_ARG1);
472    value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0);
473
474    value.SetValueType(Value::eValueTypeScalar);
475  }
476  // Floating point return type.
477  else if (type_flags & eTypeIsFloat) {
478    uint32_t float_count = 0;
479    bool is_complex = false;
480
481    if (compiler_type.IsFloatingPointType(float_count, is_complex) &&
482        1 == float_count && !is_complex) {
483      const size_t byte_size = compiler_type.GetByteSize(nullptr).getValueOr(0);
484      auto raw_value = ReadRawValue(reg_ctx, byte_size);
485
486      if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
487        return ValueObjectSP();
488    }
489  }
490  // Unsupported return type.
491  else
492    return ValueObjectSP();
493
494  return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
495                                        value, ConstString(""));
496}
497
498ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl(
499    Thread &thread, CompilerType &return_compiler_type) const {
500  ValueObjectSP return_valobj_sp;
501
502  if (!return_compiler_type)
503    return return_valobj_sp;
504
505  ExecutionContext exe_ctx(thread.shared_from_this());
506  return GetReturnValueObjectSimple(thread, return_compiler_type);
507}
508
509ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl(Thread &thread,
510                                                    llvm::Type &retType) const {
511  auto reg_ctx = thread.GetRegisterContext();
512  if (!reg_ctx)
513    return ValueObjectSP();
514
515  Value value;
516  // Void return type.
517  if (retType.isVoidTy()) {
518    value.GetScalar() = 0;
519  }
520  // Integer return type.
521  else if (retType.isIntegerTy()) {
522    size_t byte_size = retType.getPrimitiveSizeInBits();
523    if (1 != byte_size) // For boolian type.
524      byte_size /= CHAR_BIT;
525
526    auto raw_value = ReadRawValue(reg_ctx, byte_size);
527
528    const bool is_signed = false; // IR Type doesn't provide this info.
529    if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed))
530      return ValueObjectSP();
531  }
532  // Pointer return type.
533  else if (retType.isPointerTy()) {
534    auto reg_info_r0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
535                                                LLDB_REGNUM_GENERIC_ARG1);
536    value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0);
537    value.SetValueType(Value::eValueTypeScalar);
538  }
539  // Floating point return type.
540  else if (retType.isFloatingPointTy()) {
541    const size_t byte_size = retType.getPrimitiveSizeInBits() / CHAR_BIT;
542    auto raw_value = ReadRawValue(reg_ctx, byte_size);
543
544    if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
545      return ValueObjectSP();
546  }
547  // Unsupported return type.
548  else
549    return ValueObjectSP();
550
551  return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
552                                        value, ConstString(""));
553}
554
555bool ABISysV_arc::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
556  unwind_plan.Clear();
557  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
558
559  UnwindPlan::RowSP row(new UnwindPlan::Row);
560
561  // Our Call Frame Address is the stack pointer value.
562  row->GetCFAValue().SetIsRegisterPlusOffset(dwarf::sp, 0);
563
564  // The previous PC is in the BLINK.
565  row->SetRegisterLocationToRegister(dwarf::pc, dwarf::blink, true);
566  unwind_plan.AppendRow(row);
567
568  // All other registers are the same.
569  unwind_plan.SetSourceName("arc at-func-entry default");
570  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
571
572  return true;
573}
574
575bool ABISysV_arc::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
576  return false;
577}
578
579bool ABISysV_arc::RegisterIsVolatile(const RegisterInfo *reg_info) {
580  if (nullptr == reg_info)
581    return false;
582
583  // Volatile registers are: r0..r12.
584  uint32_t regnum = reg_info->kinds[eRegisterKindDWARF];
585  if (regnum <= 12)
586    return true;
587
588  static const std::string ra_reg_name = "blink";
589  return ra_reg_name == reg_info->name;
590}
591
592void ABISysV_arc::Initialize() {
593  PluginManager::RegisterPlugin(GetPluginNameStatic(),
594                                "System V ABI for ARC targets", CreateInstance);
595}
596
597void ABISysV_arc::Terminate() {
598  PluginManager::UnregisterPlugin(CreateInstance);
599}
600
601ConstString ABISysV_arc::GetPluginNameStatic() {
602  static ConstString g_name("sysv-arc");
603  return g_name;
604}
605
606//------------------------------------------------------------------
607// PluginInterface protocol
608//------------------------------------------------------------------
609
610ConstString ABISysV_arc::GetPluginName() {
611  return GetPluginNameStatic();
612}
613
614uint32_t ABISysV_arc::GetPluginVersion() { return 1; }
615