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 ®_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 ®_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 ®_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