Instead of doing everything in the interrupt lowering pass, generate
some more code in gen-device to declare interrupt handler functions and
do some work in the compiler so that interrupt lowering becomes a lot
simpler.
This has several benefits:
- Overall code is smaller, in particular the interrupt lowering pass.
- The code should be a bit less "magical" and instead a bit easier to
read. In particular, instead of having a magic
runtime.callInterruptHandler (that is fully written by the interrupt
lowering pass), the runtime calls a generated function like
device/sifive.InterruptHandler where this switch already exists in
code.
- Debug information is improved. This can be helpful during actual
debugging but is also useful for other uses of DWARF debug
information.
For an example on debug information improvement, this is what a
backtrace might look like before this commit:
Breakpoint 1, 0x00000b46 in UART0_IRQHandler ()
(gdb) bt
#0 0x00000b46 in UART0_IRQHandler ()
#1 <signal handler called>
[..etc]
Notice that the debugger doesn't see the source code location where it
has stopped.
After this commit, breaking at the same line might look like this:
Breakpoint 1, (*machine.UART).handleInterrupt (arg1=..., uart=<optimized out>) at /home/ayke/src/github.com/tinygo-org/tinygo/src/machine/machine_nrf.go:200
200 uart.Receive(byte(nrf.UART0.RXD.Get()))
(gdb) bt
#0 (*machine.UART).handleInterrupt (arg1=..., uart=<optimized out>) at /home/ayke/src/github.com/tinygo-org/tinygo/src/machine/machine_nrf.go:200
#1 UART0_IRQHandler () at /home/ayke/src/github.com/tinygo-org/tinygo/src/device/nrf/nrf51.go:176
#2 <signal handler called>
[..etc]
By now, the debugger sees an actual source location for UART0_IRQHandler
(in the generated file) and an inlined function.
57 строки
2,2 КиБ
LLVM
57 строки
2,2 КиБ
LLVM
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
|
|
target triple = "armv7em-none-eabi"
|
|
|
|
%machine.UART = type { %machine.RingBuffer* }
|
|
%machine.RingBuffer = type { [128 x %"runtime/volatile.Register8"], %"runtime/volatile.Register8", %"runtime/volatile.Register8" }
|
|
%"runtime/volatile.Register8" = type { i8 }
|
|
%"runtime/interrupt.Interrupt" = type { i32 }
|
|
|
|
@machine.UART0 = internal global %machine.UART { %machine.RingBuffer* @"machine$alloc.335" }
|
|
@"machine$alloc.335" = internal global %machine.RingBuffer zeroinitializer
|
|
|
|
declare void @"runtime/interrupt.callHandlers"(i32, i8*, i8*) local_unnamed_addr
|
|
|
|
declare void @"device/arm.EnableIRQ"(i32, i8* nocapture readnone, i8* nocapture readnone)
|
|
|
|
declare void @"device/arm.SetPriority"(i32, i32, i8* nocapture readnone, i8* nocapture readnone)
|
|
|
|
declare void @"runtime/interrupt.use"(%"runtime/interrupt.Interrupt")
|
|
|
|
define void @runtime.initAll(i8* nocapture readnone %0, i8* nocapture readnone %1) unnamed_addr {
|
|
entry:
|
|
call void @"device/arm.SetPriority"(i32 2, i32 192, i8* undef, i8* undef)
|
|
call void @"device/arm.EnableIRQ"(i32 2, i8* undef, i8* undef)
|
|
ret void
|
|
}
|
|
|
|
define void @UARTE0_UART0_IRQHandler() {
|
|
call void @"(*machine.UART).handleInterrupt$bound"(i32 2, i8* bitcast (%machine.UART* @machine.UART0 to i8*), i8* undef)
|
|
ret void
|
|
}
|
|
|
|
define internal void @interruptSWVector(i32 %num) {
|
|
entry:
|
|
switch i32 %num, label %switch.done [
|
|
i32 2, label %switch.body2
|
|
i32 5, label %switch.body5
|
|
]
|
|
|
|
switch.body2: ; preds = %entry
|
|
call void @"(*machine.UART).handleInterrupt$bound"(i32 2, i8* bitcast (%machine.UART* @machine.UART0 to i8*), i8* undef)
|
|
ret void
|
|
|
|
switch.body5: ; preds = %entry
|
|
unreachable
|
|
|
|
switch.done: ; preds = %entry
|
|
ret void
|
|
}
|
|
|
|
define internal void @"(*machine.UART).handleInterrupt$bound"(i32 %0, i8* nocapture %context, i8* nocapture readnone %parentHandle) {
|
|
entry:
|
|
%unpack.ptr = bitcast i8* %context to %machine.UART*
|
|
call void @"(*machine.UART).handleInterrupt"(%machine.UART* %unpack.ptr, i32 %0, i8* undef, i8* undef)
|
|
ret void
|
|
}
|
|
|
|
declare void @"(*machine.UART).handleInterrupt"(%machine.UART* nocapture, i32, i8* nocapture readnone, i8* nocapture readnone)
|