diff options
author | Ayke van Laethem <[email protected]> | 2021-11-03 01:24:25 +0100 |
---|---|---|
committer | Ron Evans <[email protected]> | 2021-11-06 09:40:15 +0100 |
commit | edcece33caeb0453c105efad799a94239c128dff (patch) | |
tree | 5bc4d51da363f5b8a5ebb84bed2879eb2534bddf /transform/testdata | |
parent | 30bbdd5aeb6a78388db533da72ebace10545935e (diff) | |
download | tinygo-edcece33caeb0453c105efad799a94239c128dff.tar.gz tinygo-edcece33caeb0453c105efad799a94239c128dff.zip |
transform: refactor interrupt lowering
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.
Diffstat (limited to 'transform/testdata')
-rw-r--r-- | transform/testdata/interrupt-avr.ll | 33 | ||||
-rw-r--r-- | transform/testdata/interrupt-avr.out.ll | 35 | ||||
-rw-r--r-- | transform/testdata/interrupt.ll (renamed from transform/testdata/interrupt-cortexm.ll) | 42 | ||||
-rw-r--r-- | transform/testdata/interrupt.out.ll (renamed from transform/testdata/interrupt-cortexm.out.ll) | 36 |
4 files changed, 62 insertions, 84 deletions
diff --git a/transform/testdata/interrupt-avr.ll b/transform/testdata/interrupt-avr.ll deleted file mode 100644 index 80570c0bb..000000000 --- a/transform/testdata/interrupt-avr.ll +++ /dev/null @@ -1,33 +0,0 @@ -target datalayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8" -target triple = "avr-unknown-unknown" - -%"runtime/interrupt.handle" = type { %runtime.funcValue, %"runtime/interrupt.Interrupt" } %runtime.funcValue = type { i8*, i16 } -%runtime.typecodeID = type { %runtime.typecodeID*, i16 } -%runtime.funcValueWithSignature = type { i16, %runtime.typecodeID* } -%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 } - -@"reflect/types.type:func:{named:runtime/interrupt.Interrupt}{}" = external constant %runtime.typecodeID -@"(machine.UART).Configure$1$withSignature" = internal constant %runtime.funcValueWithSignature { i16 ptrtoint (void (i32, i8*, i8*) addrspace(1)* @"(machine.UART).Configure$1" to i16), %runtime.typecodeID* @"reflect/types.type:func:{named:runtime/interrupt.Interrupt}{}" } -@"runtime/interrupt.$interrupt18" = private unnamed_addr constant %"runtime/interrupt.handle" { %runtime.funcValue { i8* undef, i16 ptrtoint (%runtime.funcValueWithSignature* @"(machine.UART).Configure$1$withSignature" to i16) }, %"runtime/interrupt.Interrupt" { i32 18 } } [email protected] = internal global %machine.UART zeroinitializer -@"device/avr.init$string.18" = internal unnamed_addr constant [17 x i8] c"__vector_USART_RX" - -declare void @"(machine.UART).Configure$1"(i32, i8*, i8*) unnamed_addr addrspace(1) - -declare i32 @"runtime/interrupt.Register"(i32, i8*, i16, i8*, i8*) addrspace(1) - -declare void @"runtime/interrupt.use"(%"runtime/interrupt.Interrupt") addrspace(1) - -define void @"(machine.UART).Configure"(%machine.RingBuffer*, i32, i8, i8, i8* %context, i8* %parentHandle) unnamed_addr addrspace(1) { - call addrspace(1) void @"runtime/interrupt.use"(%"runtime/interrupt.Interrupt" { i32 ptrtoint (%"runtime/interrupt.handle"* @"runtime/interrupt.$interrupt18" to i32) }) - ret void -} - -define void @"device/avr.init"(i8* %context, i8* %parentHandle) unnamed_addr addrspace(1) { -entry: - %0 = call addrspace(1) i32 @"runtime/interrupt.Register"(i32 18, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @"device/avr.init$string.18", i32 0, i32 0), i16 17, i8* undef, i8* undef) - ret void -} diff --git a/transform/testdata/interrupt-avr.out.ll b/transform/testdata/interrupt-avr.out.ll deleted file mode 100644 index 3f3c881f1..000000000 --- a/transform/testdata/interrupt-avr.out.ll +++ /dev/null @@ -1,35 +0,0 @@ -target datalayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8" -target triple = "avr-unknown-unknown" - -%runtime.typecodeID = type { %runtime.typecodeID*, i16 } -%runtime.funcValueWithSignature = type { i16, %runtime.typecodeID* } -%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 } - -@"reflect/types.type:func:{named:runtime/interrupt.Interrupt}{}" = external constant %runtime.typecodeID -@"(machine.UART).Configure$1$withSignature" = internal constant %runtime.funcValueWithSignature { i16 ptrtoint (void (i32, i8*, i8*) addrspace(1)* @"(machine.UART).Configure$1" to i16), %runtime.typecodeID* @"reflect/types.type:func:{named:runtime/interrupt.Interrupt}{}" } [email protected] = internal global %machine.UART zeroinitializer -@"device/avr.init$string.18" = internal unnamed_addr constant [17 x i8] c"__vector_USART_RX" - -declare void @"(machine.UART).Configure$1"(i32, i8*, i8*) unnamed_addr addrspace(1) - -declare i32 @"runtime/interrupt.Register"(i32, i8*, i16, i8*, i8*) addrspace(1) - -declare void @"runtime/interrupt.use"(%"runtime/interrupt.Interrupt") addrspace(1) - -define void @"(machine.UART).Configure"(%machine.RingBuffer* %0, i32 %1, i8 %2, i8 %3, i8* %context, i8* %parentHandle) unnamed_addr addrspace(1) { - ret void -} - -define void @"device/avr.init"(i8* %context, i8* %parentHandle) unnamed_addr addrspace(1) { -entry: - ret void -} - -define avr_signalcc void @__vector_USART_RX() unnamed_addr addrspace(1) section ".text.__vector_USART_RX" { -entry: - call addrspace(1) void @"(machine.UART).Configure$1"(i32 18, i8* undef, i8* null) - ret void -} diff --git a/transform/testdata/interrupt-cortexm.ll b/transform/testdata/interrupt.ll index 2c156b5b6..e46fbe6fa 100644 --- a/transform/testdata/interrupt-cortexm.ll +++ b/transform/testdata/interrupt.ll @@ -4,27 +4,55 @@ 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.handle" = type { { i8*, void (i32, i8*, i8*)* }, %"runtime/interrupt.Interrupt" } +%"runtime/interrupt.handle" = type { i8*, i32, %"runtime/interrupt.Interrupt" } %"runtime/interrupt.Interrupt" = type { i32 } -@"runtime/interrupt.$interrupt2" = private unnamed_addr constant %"runtime/interrupt.handle" { { i8*, void (i32, i8*, i8*)* } { i8* bitcast (%machine.UART* @machine.UART0 to i8*), void (i32, i8*, i8*)* @"(*machine.UART).handleInterrupt$bound" }, %"runtime/interrupt.Interrupt" { i32 2 } } +@"runtime/interrupt.$interrupt2" = private unnamed_addr constant %"runtime/interrupt.handle" { i8* bitcast (%machine.UART* @machine.UART0 to i8*), i32 ptrtoint (void (i32, i8*, i8*)* @"(*machine.UART).handleInterrupt$bound" to i32), %"runtime/interrupt.Interrupt" { i32 2 } } @machine.UART0 = internal global %machine.UART { %machine.RingBuffer* @"machine$alloc.335" } @"machine$alloc.335" = internal global %machine.RingBuffer zeroinitializer -@"device/nrf.init$string.2" = internal unnamed_addr constant [23 x i8] c"UARTE0_UART0_IRQHandler" -@"device/nrf.init$string.3" = internal unnamed_addr constant [44 x i8] c"SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler" -declare i32 @"runtime/interrupt.Register"(i32, i8*, i32, i8*, i8*) local_unnamed_addr +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, i8* nocapture readnone) unnamed_addr { entry: - %2 = call i32 @"runtime/interrupt.Register"(i32 2, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @"device/nrf.init$string.2", i32 0, i32 0), i32 23, i8* undef, i8* undef) - %3 = call i32 @"runtime/interrupt.Register"(i32 3, i8* getelementptr inbounds ([44 x i8], [44 x i8]* @"device/nrf.init$string.3", i32 0, i32 0), i32 44, i8* undef, i8* undef) call void @"device/arm.SetPriority"(i32 ptrtoint (%"runtime/interrupt.handle"* @"runtime/interrupt.$interrupt2" to i32), i32 192, i8* undef, i8* undef) call void @"device/arm.EnableIRQ"(i32 ptrtoint (%"runtime/interrupt.handle"* @"runtime/interrupt.$interrupt2" to i32), i8* undef, i8* undef) + call void @"runtime/interrupt.use"(%"runtime/interrupt.Interrupt" { i32 ptrtoint (%"runtime/interrupt.handle"* @"runtime/interrupt.$interrupt2" to i32) }) + ret void +} + +define void @UARTE0_UART0_IRQHandler() { + call void @"runtime/interrupt.callHandlers"(i32 2, i8* undef, i8* undef) + ret void +} + +define void @NFCT_IRQHandler() { + call void @"runtime/interrupt.callHandlers"(i32 5, i8* undef, 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: + call void @"runtime/interrupt.callHandlers"(i32 2, i8* undef, i8* undef) + ret void + +switch.body5: + call void @"runtime/interrupt.callHandlers"(i32 5, i8* undef, i8* undef) + ret void + +switch.done: ret void } diff --git a/transform/testdata/interrupt-cortexm.out.ll b/transform/testdata/interrupt.out.ll index 2e35f2633..78f52ff66 100644 --- a/transform/testdata/interrupt-cortexm.out.ll +++ b/transform/testdata/interrupt.out.ll @@ -4,18 +4,19 @@ 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 -@"device/nrf.init$string.2" = internal unnamed_addr constant [23 x i8] c"UARTE0_UART0_IRQHandler" -@"device/nrf.init$string.3" = internal unnamed_addr constant [44 x i8] c"SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler" -declare i32 @"runtime/interrupt.Register"(i32, i8*, i32, i8*, i8*) local_unnamed_addr +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) @@ -23,6 +24,29 @@ entry: 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* @@ -31,9 +55,3 @@ entry: } declare void @"(*machine.UART).handleInterrupt"(%machine.UART* nocapture, i32, i8* nocapture readnone, i8* nocapture readnone) - -define void @UARTE0_UART0_IRQHandler() unnamed_addr section ".text.UARTE0_UART0_IRQHandler" { -entry: - call void @"(*machine.UART).handleInterrupt$bound"(i32 2, i8* bitcast (%machine.UART* @machine.UART0 to i8*), i8* null) - ret void -} |