
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)
|