[Lldb-commits] [lldb] [llvm] [lldb][RISCV] function calls support in lldb expressions (PR #99336)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Jul 22 05:28:28 PDT 2024
dlav-sc wrote:
> Thanks for the patches (if we end up going down this route you'll probably want to split out the LLVM JIT changes into a separate PR).
>
> Not very familiar with RISCV. Could you elaborate on the exact failures you were seeing and why we need the extra IR pass?
>
> > Also it adds RISCV specific DirectToIndirectFunctionCallsReplacement IR pass, that allows to make assembly jumps at any 64bit address without RISCV large code model, which has not been implemented yet.
>
> I guess this summarizes it, but would be good to see actual example failures
> I guess this summarizes it, but would be good to see actual example failures
Consider a simple function call:
`main.cpp`:
```
void foo() {
int a = 42;
}
int main() {
foo();
return 0;
}
```
```
(lldb) file main.x
(lldb) b main
(lldb) run
(lldb) expr foo()
```
Before patch:
Lldb generates a wrapper, obtains its IR and tries to interpret it with IRInterpreter, but fails on a function call:
IR:
```
lldb Module as passed in to IRForTarget:
"; ModuleID = '$__lldb_module'
source_filename = "$__lldb_module"
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"
; Function Attrs: convergent mustprogress noinline nounwind optnone
define dso_local void @"_Z12$__lldb_exprPv"(ptr %"$__lldb_arg") #0 {
entry:
%"$__lldb_arg.addr" = alloca ptr, align 8, !clang.decl.ptr !8
store ptr %"$__lldb_arg", ptr %"$__lldb_arg.addr", align 8
call void @_Z3foov() #2
ret void
}
; Function Attrs: convergent
declare void @_Z3foov() #1
attributes #0 = { convergent mustprogress noinline nounwind optnone "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-features"="+64bit" }
attributes #1 = { convergent "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-features"="+64bit" }
attributes #2 = { convergent "no-builtins" }
!llvm.module.flags = !{!0, !1, !2, !3, !4}
!clang.global.decl.ptrs = !{!5, !6}
!llvm.ident = !{!7}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"target-abi", !"lp64"}
!2 = !{i32 7, !"direct-access-external-data", i32 0}
!3 = !{i32 7, !"frame-pointer", i32 2}
!4 = !{i32 8, !"SmallDataLimit", i32 0}
!5 = !{ptr @"_Z12$__lldb_exprPv", i64 94163729942528}
!6 = !{ptr @_Z3foov, i64 94163729942816}
!7 = !{!"Syntacore clang version 18.1.4-sc (SC git:/tools/llvm/llvm-project/ fefe1910746c1b7e0e23cd64767b3f08ba788cf1)"}
!8 = !{i64 94163729942296}
"
```
Output:
```
lldb Couldn't find result variable
lldb MaybeHandleCallArguments( call void @_Z3foov() #2)
lldb Element arrangement:
lldb Arg: "ptr %"$__lldb_arg""
lldb Total structure [align 8, size 0]
lldb Saw function with body: _Z12$__lldb_exprPv
lldb Unsupported instruction: call void @_Z3foov() #2
lldb [ClangASTImporter] Forgetting destination (ASTContext*)0x000055A433716B10
lldb [ClangASTImporter] Forgetting source->dest (ASTContext*)0x000055A433716B10->(ASTContext*)0x000055A433A119D0
error: Can't evaluate the expression without a running target due to: Interpreter doesn't handle one of the expression's opcodes
```
After patch:
Lldb also generates a wrapper, obtains its IR but sends it to a JIT compiler instead of IRInterpreter. MCJIT generates an assembly, puts it into a process stack memory, resolves relocations and finally executes:
IR the same.
Assembly:
```
lldb Function disassembly:
0x3ff7fdd040: 13 01 01 fe unknown addi sp, sp, -0x20
0x3ff7fdd044: 23 3c 11 00 unknown sd ra, 0x18(sp)
0x3ff7fdd048: 23 38 81 00 unknown sd s0, 0x10(sp)
0x3ff7fdd04c: 23 34 91 00 unknown sd s1, 0x8(sp)
0x3ff7fdd050: 13 04 01 02 unknown addi s0, sp, 0x20
0x3ff7fdd054: 93 04 05 00 unknown mv s1, a0
0x3ff7fdd058: 37 85 ff 03 unknown lui a0, 0x3ff8
0x3ff7fdd05c: 1b 05 d5 fd unknown addiw a0, a0, -0x23
0x3ff7fdd060: 93 15 c5 00 unknown slli a1, a0, 0xc
0x3ff7fdd064: 13 05 04 fe unknown addi a0, s0, -0x20
0x3ff7fdd068: e7 80 05 00 unknown jalr a1
0x3ff7fdd06c: 23 30 94 fe unknown sd s1, -0x20(s0)
0x3ff7fdd070: 37 55 55 01 unknown lui a0, 0x1555
0x3ff7fdd074: 1b 05 55 55 unknown addiw a0, a0, 0x555
0x3ff7fdd078: 13 15 d5 00 unknown slli a0, a0, 0xd
0x3ff7fdd07c: 13 05 85 62 unknown addi a0, a0, 0x628
0x3ff7fdd080: e7 00 05 00 unknown jalr a0
0x3ff7fdd084: 83 30 81 01 unknown ld ra, 0x18(sp)
0x3ff7fdd088: 03 34 01 01 unknown ld s0, 0x10(sp)
0x3ff7fdd08c: 83 34 81 00 unknown ld s1, 0x8(sp)
0x3ff7fdd090: 13 01 01 02 unknown addi sp, sp, 0x20
0x3ff7fdd094: 67 80 00 00 unknown ret
```
Puts assembly into a stack memory:
```
lldb IRMemoryMap::Malloc (91, 0x4, 0x6, eAllocationPolicyProcessOnly) -> 0x3ff7fdd040
lldb IRMemoryMap::Malloc (111, 0x1, 0x2, eAllocationPolicyProcessOnly) -> 0x3ff7fdc760
lldb IRMemoryMap::Malloc (28, 0x1, 0x2, eAllocationPolicyProcessOnly) -> 0x3ff7fdc7d0
lldb IRMemoryMap::Malloc (1, 0x1, 0x2, eAllocationPolicyProcessOnly) -> 0x3ff7fdc7f0
lldb IRMemoryMap::Malloc (115, 0x1, 0x2, eAllocationPolicyProcessOnly) -> 0x3ff7fdc800
lldb IRMemoryMap::Malloc (1, 0x1, 0x2, eAllocationPolicyProcessOnly) -> 0x3ff7fdc880
lldb IRMemoryMap::Malloc (151, 0x8, 0x2, eAllocationPolicyProcessOnly) -> 0x3ff7fdc890
lldb IRMemoryMap::WriteMemory (0x3ff7fdd040, 0x7f5352f50000, 0x88) went to [0x3ff7fdd040..0x3ff7fdd09b)
lldb IRMemoryMap::WriteMemory (0x3ff7fdc760, 0x7f5352eea000, 0x111) went to [0x3ff7fdc760..0x3ff7fdc7cf)
lldb IRMemoryMap::WriteMemory (0x3ff7fdc7d0, 0x7f5352eea06f, 0x28) went to [0x3ff7fdc7d0..0x3ff7fdc7ec)
lldb IRMemoryMap::WriteMemory (0x3ff7fdc7f0, 0x7f5352eea08b, 0x1) went to [0x3ff7fdc7f0..0x3ff7fdc7f1)
lldb IRMemoryMap::WriteMemory (0x3ff7fdc800, 0x7f5352eea08c, 0x115) went to [0x3ff7fdc800..0x3ff7fdc873)
lldb IRMemoryMap::WriteMemory (0x3ff7fdc880, 0x7f5352eea0ff, 0x1) went to [0x3ff7fdc880..0x3ff7fdc881)
lldb IRMemoryMap::WriteMemory (0x3ff7fdc890, 0x7f5352eea100, 0x144) went to [0x3ff7fdc890..0x3ff7fdc927)
```
Result:
```
lldb -- [UserExpression::Execute] Execution of expression begins --
lldb -- [UserExpression::Execute] Execution of expression completed --
lldb -- [UserExpression::FinalizeJITExecution] Dematerializing after execution --
lldb Materializer::Dematerialize (frame_sp = 0x55bcbe861a80, process_address = 0x3ff7fdb000) about to dematerialize:
lldb == [UserExpression::Evaluate] Execution completed normally with no result ==
```
https://github.com/llvm/llvm-project/pull/99336
More information about the lldb-commits
mailing list