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/LoongArch/ABISysV_loongarch.cpp
213845 views
1
//===-- ABISysV_loongarch.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_loongarch.h"
10
11
#include <array>
12
#include <limits>
13
#include <sstream>
14
15
#include "llvm/ADT/StringRef.h"
16
#include "llvm/IR/DerivedTypes.h"
17
#include "llvm/Support/MathExtras.h"
18
19
#include "Utility/LoongArch_DWARF_Registers.h"
20
#include "lldb/Core/PluginManager.h"
21
#include "lldb/Core/Value.h"
22
#include "lldb/Target/RegisterContext.h"
23
#include "lldb/Target/StackFrame.h"
24
#include "lldb/Target/Thread.h"
25
#include "lldb/Utility/LLDBLog.h"
26
#include "lldb/Utility/RegisterValue.h"
27
#include "lldb/ValueObject/ValueObjectConstResult.h"
28
29
#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
30
#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
31
32
// The ABI is not a source of such information as size, offset, encoding, etc.
33
// of a register. Just provides correct dwarf and eh_frame numbers.
34
35
#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, generic_num) \
36
{ \
37
DEFINE_REG_NAME(dwarf_num), \
38
DEFINE_REG_NAME_STR(nullptr), \
39
0, \
40
0, \
41
eEncodingInvalid, \
42
eFormatDefault, \
43
{dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num}, \
44
nullptr, \
45
nullptr, \
46
nullptr, \
47
}
48
49
#define DEFINE_REGISTER_STUB(dwarf_num) \
50
DEFINE_GENERIC_REGISTER_STUB(dwarf_num, LLDB_INVALID_REGNUM)
51
52
using namespace lldb;
53
using namespace lldb_private;
54
55
LLDB_PLUGIN_DEFINE_ADV(ABISysV_loongarch, ABILoongArch)
56
57
namespace {
58
namespace dwarf {
59
enum regnums {
60
r0,
61
r1,
62
ra = r1,
63
r2,
64
r3,
65
sp = r3,
66
r4,
67
r5,
68
r6,
69
r7,
70
r8,
71
r9,
72
r10,
73
r11,
74
r12,
75
r13,
76
r14,
77
r15,
78
r16,
79
r17,
80
r18,
81
r19,
82
r20,
83
r21,
84
r22,
85
fp = r22,
86
r23,
87
r24,
88
r25,
89
r26,
90
r27,
91
r28,
92
r29,
93
r30,
94
r31,
95
pc
96
};
97
98
static const std::array<RegisterInfo, 33> g_register_infos = {
99
{DEFINE_REGISTER_STUB(r0),
100
DEFINE_GENERIC_REGISTER_STUB(r1, LLDB_REGNUM_GENERIC_RA),
101
DEFINE_REGISTER_STUB(r2),
102
DEFINE_GENERIC_REGISTER_STUB(r3, LLDB_REGNUM_GENERIC_SP),
103
DEFINE_GENERIC_REGISTER_STUB(r4, LLDB_REGNUM_GENERIC_ARG1),
104
DEFINE_GENERIC_REGISTER_STUB(r5, LLDB_REGNUM_GENERIC_ARG2),
105
DEFINE_GENERIC_REGISTER_STUB(r6, LLDB_REGNUM_GENERIC_ARG3),
106
DEFINE_GENERIC_REGISTER_STUB(r7, LLDB_REGNUM_GENERIC_ARG4),
107
DEFINE_GENERIC_REGISTER_STUB(r8, LLDB_REGNUM_GENERIC_ARG5),
108
DEFINE_GENERIC_REGISTER_STUB(r9, LLDB_REGNUM_GENERIC_ARG6),
109
DEFINE_GENERIC_REGISTER_STUB(r10, LLDB_REGNUM_GENERIC_ARG7),
110
DEFINE_GENERIC_REGISTER_STUB(r11, LLDB_REGNUM_GENERIC_ARG8),
111
DEFINE_REGISTER_STUB(r12),
112
DEFINE_REGISTER_STUB(r13),
113
DEFINE_REGISTER_STUB(r14),
114
DEFINE_REGISTER_STUB(r15),
115
DEFINE_REGISTER_STUB(r16),
116
DEFINE_REGISTER_STUB(r17),
117
DEFINE_REGISTER_STUB(r18),
118
DEFINE_REGISTER_STUB(r19),
119
DEFINE_REGISTER_STUB(r20),
120
DEFINE_REGISTER_STUB(r21),
121
DEFINE_GENERIC_REGISTER_STUB(r22, LLDB_REGNUM_GENERIC_FP),
122
DEFINE_REGISTER_STUB(r23),
123
DEFINE_REGISTER_STUB(r24),
124
DEFINE_REGISTER_STUB(r25),
125
DEFINE_REGISTER_STUB(r26),
126
DEFINE_REGISTER_STUB(r27),
127
DEFINE_REGISTER_STUB(r28),
128
DEFINE_REGISTER_STUB(r29),
129
DEFINE_REGISTER_STUB(r30),
130
DEFINE_REGISTER_STUB(r31),
131
DEFINE_GENERIC_REGISTER_STUB(pc, LLDB_REGNUM_GENERIC_PC)}};
132
} // namespace dwarf
133
} // namespace
134
135
// Number of argument registers (the base integer calling convention
136
// provides 8 argument registers, a0-a7)
137
static constexpr size_t g_regs_for_args_count = 8U;
138
139
const RegisterInfo *ABISysV_loongarch::GetRegisterInfoArray(uint32_t &count) {
140
count = dwarf::g_register_infos.size();
141
return dwarf::g_register_infos.data();
142
}
143
144
//------------------------------------------------------------------
145
// Static Functions
146
//------------------------------------------------------------------
147
148
ABISP
149
ABISysV_loongarch::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) {
150
llvm::Triple::ArchType machine = arch.GetTriple().getArch();
151
152
if (llvm::Triple::loongarch32 != machine &&
153
llvm::Triple::loongarch64 != machine)
154
return ABISP();
155
156
ABISysV_loongarch *abi =
157
new ABISysV_loongarch(std::move(process_sp), MakeMCRegisterInfo(arch));
158
if (abi)
159
abi->SetIsLA64(llvm::Triple::loongarch64 == machine);
160
return ABISP(abi);
161
}
162
163
static bool UpdateRegister(RegisterContext *reg_ctx,
164
const lldb::RegisterKind reg_kind,
165
const uint32_t reg_num, const addr_t value) {
166
Log *log = GetLog(LLDBLog::Expressions);
167
168
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(reg_kind, reg_num);
169
170
LLDB_LOG(log, "Writing {0}: 0x{1:x}", reg_info->name,
171
static_cast<uint64_t>(value));
172
if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, value)) {
173
LLDB_LOG(log, "Writing {0}: failed", reg_info->name);
174
return false;
175
}
176
return true;
177
}
178
179
static void LogInitInfo(Log &log, const Thread &thread, addr_t sp,
180
addr_t func_addr, addr_t return_addr,
181
const llvm::ArrayRef<addr_t> args) {
182
std::stringstream ss;
183
ss << "ABISysV_loongarch::PrepareTrivialCall"
184
<< " (tid = 0x" << std::hex << thread.GetID() << ", sp = 0x" << sp
185
<< ", func_addr = 0x" << func_addr << ", return_addr = 0x" << return_addr;
186
187
for (auto [idx, arg] : enumerate(args))
188
ss << ", arg" << std::dec << idx << " = 0x" << std::hex << arg;
189
ss << ")";
190
log.PutString(ss.str());
191
}
192
193
bool ABISysV_loongarch::PrepareTrivialCall(Thread &thread, addr_t sp,
194
addr_t func_addr, addr_t return_addr,
195
llvm::ArrayRef<addr_t> args) const {
196
Log *log = GetLog(LLDBLog::Expressions);
197
if (log)
198
LogInitInfo(*log, thread, sp, func_addr, return_addr, args);
199
200
const auto reg_ctx_sp = thread.GetRegisterContext();
201
if (!reg_ctx_sp) {
202
LLDB_LOG(log, "Failed to get RegisterContext");
203
return false;
204
}
205
206
if (args.size() > g_regs_for_args_count) {
207
LLDB_LOG(log, "Function has {0} arguments, but only {1} are allowed!",
208
args.size(), g_regs_for_args_count);
209
return false;
210
}
211
212
// Write arguments to registers
213
for (auto [idx, arg] : enumerate(args)) {
214
const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(
215
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + idx);
216
LLDB_LOG(log, "About to write arg{0} ({1:x}) into {2}", idx, arg,
217
reg_info->name);
218
219
if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) {
220
LLDB_LOG(log, "Failed to write arg{0} ({1:x}) into {2}", idx, arg,
221
reg_info->name);
222
return false;
223
}
224
}
225
226
if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
227
LLDB_REGNUM_GENERIC_PC, func_addr))
228
return false;
229
if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
230
LLDB_REGNUM_GENERIC_SP, sp))
231
return false;
232
if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
233
LLDB_REGNUM_GENERIC_RA, return_addr))
234
return false;
235
236
LLDB_LOG(log, "ABISysV_loongarch::{0}() success", __FUNCTION__);
237
return true;
238
}
239
240
bool ABISysV_loongarch::GetArgumentValues(Thread &thread,
241
ValueList &values) const {
242
// TODO: Implement
243
return false;
244
}
245
246
Status ABISysV_loongarch::SetReturnValueObject(StackFrameSP &frame_sp,
247
ValueObjectSP &new_value_sp) {
248
Status result;
249
if (!new_value_sp) {
250
result = Status::FromErrorString("Empty value object for return value.");
251
return result;
252
}
253
254
CompilerType compiler_type = new_value_sp->GetCompilerType();
255
if (!compiler_type) {
256
result = Status::FromErrorString("Null clang type for return value.");
257
return result;
258
}
259
260
auto &reg_ctx = *frame_sp->GetThread()->GetRegisterContext();
261
262
bool is_signed = false;
263
if (!compiler_type.IsIntegerOrEnumerationType(is_signed) &&
264
!compiler_type.IsPointerType()) {
265
result = Status::FromErrorString(
266
"We don't support returning other types at present");
267
return result;
268
}
269
270
DataExtractor data;
271
size_t num_bytes = new_value_sp->GetData(data, result);
272
273
if (result.Fail()) {
274
result = Status::FromErrorStringWithFormat(
275
"Couldn't convert return value to raw data: %s", result.AsCString());
276
return result;
277
}
278
279
size_t reg_size = m_is_la64 ? 8 : 4;
280
// Currently, we only support sizeof(data) <= 2 * reg_size.
281
// 1. If the (`size` <= reg_size), the `data` will be returned through `ARG1`.
282
// 2. If the (`size` > reg_size && `size` <= 2 * reg_size), the `data` will be
283
// returned through a pair of registers (ARG1 and ARG2), and the lower-ordered
284
// bits in the `ARG1`.
285
if (num_bytes > 2 * reg_size) {
286
result = Status::FromErrorString(
287
"We don't support returning large integer values at present.");
288
return result;
289
}
290
291
offset_t offset = 0;
292
uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
293
// According to psABI, i32 (no matter signed or unsigned) should be
294
// sign-extended in register.
295
if (4 == num_bytes && m_is_la64)
296
raw_value = llvm::SignExtend64<32>(raw_value);
297
auto reg_info =
298
reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
299
if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
300
result = Status::FromErrorStringWithFormat(
301
"Couldn't write value to register %s", reg_info->name);
302
return result;
303
}
304
305
if (num_bytes <= reg_size)
306
return result; // Successfully written.
307
308
// For loongarch32, get the upper 32 bits from raw_value and write them.
309
// For loongarch64, get the next 64 bits from data and write them.
310
if (4 == reg_size)
311
raw_value >>= 32;
312
else
313
raw_value = data.GetMaxU64(&offset, num_bytes - reg_size);
314
315
reg_info =
316
reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
317
if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value))
318
result = Status::FromErrorStringWithFormat(
319
"Couldn't write value to register %s", reg_info->name);
320
321
return result;
322
}
323
324
template <typename T>
325
static void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed) {
326
static_assert(std::is_unsigned<T>::value, "T must be an unsigned type.");
327
raw_value &= std::numeric_limits<T>::max();
328
if (is_signed)
329
scalar = static_cast<typename std::make_signed<T>::type>(raw_value);
330
else
331
scalar = static_cast<T>(raw_value);
332
}
333
334
static bool SetSizedInteger(Scalar &scalar, uint64_t raw_value,
335
uint8_t size_in_bytes, bool is_signed) {
336
switch (size_in_bytes) {
337
default:
338
return false;
339
340
case sizeof(uint64_t):
341
SetInteger<uint64_t>(scalar, raw_value, is_signed);
342
break;
343
344
case sizeof(uint32_t):
345
SetInteger<uint32_t>(scalar, raw_value, is_signed);
346
break;
347
348
case sizeof(uint16_t):
349
SetInteger<uint16_t>(scalar, raw_value, is_signed);
350
break;
351
352
case sizeof(uint8_t):
353
SetInteger<uint8_t>(scalar, raw_value, is_signed);
354
break;
355
}
356
357
return true;
358
}
359
360
static bool SetSizedFloat(Scalar &scalar, uint64_t raw_value,
361
uint8_t size_in_bytes) {
362
switch (size_in_bytes) {
363
default:
364
return false;
365
366
case sizeof(uint64_t):
367
scalar = *reinterpret_cast<double *>(&raw_value);
368
break;
369
370
case sizeof(uint32_t):
371
scalar = *reinterpret_cast<float *>(&raw_value);
372
break;
373
}
374
375
return true;
376
}
377
378
static ValueObjectSP GetValObjFromIntRegs(Thread &thread,
379
const RegisterContextSP &reg_ctx,
380
llvm::Triple::ArchType machine,
381
uint32_t type_flags,
382
uint32_t byte_size) {
383
Value value;
384
ValueObjectSP return_valobj_sp;
385
auto *reg_info_a0 =
386
reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
387
auto *reg_info_a1 =
388
reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
389
uint64_t raw_value = 0;
390
391
switch (byte_size) {
392
case sizeof(uint32_t):
393
// Read a0 to get the arg
394
raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX;
395
break;
396
case sizeof(uint64_t):
397
// Read a0 to get the arg on loongarch64, a0 and a1 on loongarch32
398
if (llvm::Triple::loongarch32 == machine) {
399
raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX;
400
raw_value |=
401
(reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) & UINT32_MAX) << 32U;
402
} else {
403
raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
404
}
405
break;
406
case 16: {
407
// Read a0 and a1 to get the arg on loongarch64, not supported on
408
// loongarch32
409
if (llvm::Triple::loongarch32 == machine)
410
return return_valobj_sp;
411
412
// Create the ValueObjectSP here and return
413
std::unique_ptr<DataBufferHeap> heap_data_up(
414
new DataBufferHeap(byte_size, 0));
415
const ByteOrder byte_order = thread.GetProcess()->GetByteOrder();
416
RegisterValue reg_value_a0, reg_value_a1;
417
if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&
418
reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {
419
Status error;
420
if (reg_value_a0.GetAsMemoryData(*reg_info_a0,
421
heap_data_up->GetBytes() + 0, 8,
422
byte_order, error) &&
423
reg_value_a1.GetAsMemoryData(*reg_info_a1,
424
heap_data_up->GetBytes() + 8, 8,
425
byte_order, error)) {
426
value.SetBytes(heap_data_up.release(), byte_size);
427
return ValueObjectConstResult::Create(
428
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
429
}
430
}
431
break;
432
}
433
default:
434
return return_valobj_sp;
435
}
436
437
if (type_flags & eTypeIsInteger) {
438
if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size,
439
type_flags & eTypeIsSigned))
440
return return_valobj_sp;
441
} else if (type_flags & eTypeIsFloat) {
442
if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
443
return return_valobj_sp;
444
} else
445
return return_valobj_sp;
446
447
value.SetValueType(Value::ValueType::Scalar);
448
return_valobj_sp = ValueObjectConstResult::Create(
449
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
450
return return_valobj_sp;
451
}
452
453
static ValueObjectSP GetValObjFromFPRegs(Thread &thread,
454
const RegisterContextSP &reg_ctx,
455
llvm::Triple::ArchType machine,
456
uint32_t type_flags,
457
uint32_t byte_size) {
458
auto *reg_info_fa0 = reg_ctx->GetRegisterInfoByName("f0");
459
bool use_fp_regs = false;
460
ValueObjectSP return_valobj_sp;
461
462
if (byte_size <= 8)
463
use_fp_regs = true;
464
465
if (use_fp_regs) {
466
uint64_t raw_value;
467
Value value;
468
raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);
469
if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
470
return return_valobj_sp;
471
value.SetValueType(Value::ValueType::Scalar);
472
return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
473
value, ConstString(""));
474
}
475
// we should never reach this, but if we do, use the integer registers
476
return GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
477
}
478
479
ValueObjectSP ABISysV_loongarch::GetReturnValueObjectSimple(
480
Thread &thread, CompilerType &compiler_type) const {
481
ValueObjectSP return_valobj_sp;
482
483
if (!compiler_type)
484
return return_valobj_sp;
485
486
auto reg_ctx = thread.GetRegisterContext();
487
if (!reg_ctx)
488
return return_valobj_sp;
489
490
Value value;
491
value.SetCompilerType(compiler_type);
492
493
const uint32_t type_flags = compiler_type.GetTypeInfo();
494
const size_t byte_size =
495
llvm::expectedToOptional(compiler_type.GetByteSize(&thread)).value_or(0);
496
const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
497
const llvm::Triple::ArchType machine = arch.GetMachine();
498
499
if (type_flags & eTypeIsInteger) {
500
return_valobj_sp =
501
GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
502
return return_valobj_sp;
503
}
504
if (type_flags & eTypeIsPointer) {
505
const auto *reg_info_a0 = reg_ctx->GetRegisterInfo(
506
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
507
value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
508
value.SetValueType(Value::ValueType::Scalar);
509
return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
510
value, ConstString(""));
511
}
512
if (type_flags & eTypeIsFloat) {
513
uint32_t float_count = 0;
514
bool is_complex = false;
515
516
if (compiler_type.IsFloatingPointType(float_count, is_complex) &&
517
float_count == 1 && !is_complex) {
518
return_valobj_sp =
519
GetValObjFromFPRegs(thread, reg_ctx, machine, type_flags, byte_size);
520
return return_valobj_sp;
521
}
522
}
523
return return_valobj_sp;
524
}
525
526
ValueObjectSP ABISysV_loongarch::GetReturnValueObjectImpl(
527
Thread &thread, CompilerType &return_compiler_type) const {
528
ValueObjectSP return_valobj_sp;
529
530
if (!return_compiler_type)
531
return return_valobj_sp;
532
533
ExecutionContext exe_ctx(thread.shared_from_this());
534
return GetReturnValueObjectSimple(thread, return_compiler_type);
535
}
536
537
UnwindPlanSP ABISysV_loongarch::CreateFunctionEntryUnwindPlan() {
538
uint32_t pc_reg_num = loongarch_dwarf::dwarf_gpr_pc;
539
uint32_t sp_reg_num = loongarch_dwarf::dwarf_gpr_sp;
540
uint32_t ra_reg_num = loongarch_dwarf::dwarf_gpr_ra;
541
542
UnwindPlan::Row row;
543
544
// Define CFA as the stack pointer
545
row.GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);
546
547
// Previous frame's pc is in ra
548
row.SetRegisterLocationToRegister(pc_reg_num, ra_reg_num, true);
549
550
auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF);
551
plan_sp->AppendRow(std::move(row));
552
plan_sp->SetSourceName("loongarch function-entry unwind plan");
553
plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
554
return plan_sp;
555
}
556
557
UnwindPlanSP ABISysV_loongarch::CreateDefaultUnwindPlan() {
558
uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC;
559
uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP;
560
561
UnwindPlan::Row row;
562
563
// Define the CFA as the current frame pointer value.
564
row.GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 0);
565
566
int reg_size = 4;
567
if (m_is_la64)
568
reg_size = 8;
569
570
// Assume the ra reg (return pc) and caller's frame pointer
571
// have been spilled to stack already.
572
row.SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, reg_size * -2, true);
573
row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, reg_size * -1, true);
574
575
auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric);
576
plan_sp->AppendRow(std::move(row));
577
plan_sp->SetSourceName("loongarch default unwind plan");
578
plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
579
plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
580
return plan_sp;
581
}
582
583
bool ABISysV_loongarch::RegisterIsVolatile(const RegisterInfo *reg_info) {
584
return !RegisterIsCalleeSaved(reg_info);
585
}
586
587
bool ABISysV_loongarch::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
588
if (!reg_info)
589
return false;
590
591
const char *name = reg_info->name;
592
ArchSpec arch = GetProcessSP()->GetTarget().GetArchitecture();
593
uint32_t arch_flags = arch.GetFlags();
594
// Floating point registers are only callee saved when using
595
// F or D hardware floating point ABIs.
596
bool is_hw_fp = (arch_flags & ArchSpec::eLoongArch_abi_mask) != 0;
597
598
return llvm::StringSwitch<bool>(name)
599
// integer ABI names
600
.Cases("ra", "sp", "fp", true)
601
.Cases("s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", true)
602
// integer hardware names
603
.Cases("r1", "r3", "r22", true)
604
.Cases("r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "31", true)
605
// floating point ABI names
606
.Cases("fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", is_hw_fp)
607
// floating point hardware names
608
.Cases("f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", is_hw_fp)
609
.Default(false);
610
}
611
612
void ABISysV_loongarch::Initialize() {
613
PluginManager::RegisterPlugin(GetPluginNameStatic(),
614
"System V ABI for LoongArch targets",
615
CreateInstance);
616
}
617
618
void ABISysV_loongarch::Terminate() {
619
PluginManager::UnregisterPlugin(CreateInstance);
620
}
621
622
static uint32_t GetGenericNum(llvm::StringRef name) {
623
return llvm::StringSwitch<uint32_t>(name)
624
.Case("pc", LLDB_REGNUM_GENERIC_PC)
625
.Cases("ra", "r1", LLDB_REGNUM_GENERIC_RA)
626
.Cases("sp", "r3", LLDB_REGNUM_GENERIC_SP)
627
.Cases("fp", "r22", LLDB_REGNUM_GENERIC_FP)
628
.Cases("a0", "r4", LLDB_REGNUM_GENERIC_ARG1)
629
.Cases("a1", "r5", LLDB_REGNUM_GENERIC_ARG2)
630
.Cases("a2", "r6", LLDB_REGNUM_GENERIC_ARG3)
631
.Cases("a3", "r7", LLDB_REGNUM_GENERIC_ARG4)
632
.Cases("a4", "r8", LLDB_REGNUM_GENERIC_ARG5)
633
.Cases("a5", "r9", LLDB_REGNUM_GENERIC_ARG6)
634
.Cases("a6", "r10", LLDB_REGNUM_GENERIC_ARG7)
635
.Cases("a7", "r11", LLDB_REGNUM_GENERIC_ARG8)
636
.Default(LLDB_INVALID_REGNUM);
637
}
638
639
void ABISysV_loongarch::AugmentRegisterInfo(
640
std::vector<lldb_private::DynamicRegisterInfo::Register> &regs) {
641
lldb_private::RegInfoBasedABI::AugmentRegisterInfo(regs);
642
643
static const llvm::StringMap<llvm::StringRef> isa_to_abi_alias_map = {
644
{"r0", "zero"}, {"r1", "ra"}, {"r2", "tp"}, {"r3", "sp"},
645
{"r4", "a0"}, {"r5", "a1"}, {"r6", "a2"}, {"r7", "a3"},
646
{"r8", "a4"}, {"r9", "a5"}, {"r10", "a6"}, {"r11", "a7"},
647
{"r12", "t0"}, {"r13", "t1"}, {"r14", "t2"}, {"r15", "t3"},
648
{"r16", "t4"}, {"r17", "t5"}, {"r18", "t6"}, {"r19", "t7"},
649
{"r20", "t8"}, {"r22", "fp"}, {"r23", "s0"}, {"r24", "s1"},
650
{"r25", "s2"}, {"r26", "s3"}, {"r27", "s4"}, {"r28", "s5"},
651
{"r29", "s6"}, {"r30", "s7"}, {"r31", "s8"}};
652
653
for (auto it : llvm::enumerate(regs)) {
654
llvm::StringRef reg_name = it.value().name.GetStringRef();
655
656
// Set alt name for certain registers for convenience
657
llvm::StringRef alias_name = isa_to_abi_alias_map.lookup(reg_name);
658
if (!alias_name.empty())
659
it.value().alt_name.SetString(alias_name);
660
661
// Set generic regnum so lldb knows what the PC, etc is
662
it.value().regnum_generic = GetGenericNum(reg_name);
663
}
664
}
665
666