mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 11:07:46 +00:00
interp: add support for switch statement
A switch statement is not normally emitted by the compiler package, but LLVM function passes may convert a series of if/else pairs to a switch statement. A future change will run function passes in the package compile phase, so the interp package (which is also run after all modules are merged together) will need to deal with these new switch statements.
This commit is contained in:
committed by
Ron Evans
parent
0b7957d612
commit
04d12bf2ba
@@ -135,6 +135,15 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
|
||||
default:
|
||||
panic("unknown number of operands")
|
||||
}
|
||||
case llvm.Switch:
|
||||
// A switch is an array of (value, label) pairs, of which the
|
||||
// first one indicates the to-switch value and the default
|
||||
// label.
|
||||
numOperands := llvmInst.OperandsCount()
|
||||
for i := 0; i < numOperands; i += 2 {
|
||||
inst.operands = append(inst.operands, r.getValue(llvmInst.Operand(i)))
|
||||
inst.operands = append(inst.operands, literalValue{uint32(blockIndices[llvmInst.Operand(i+1)])})
|
||||
}
|
||||
case llvm.PHI:
|
||||
inst.name = llvmInst.Name()
|
||||
incomingCount := inst.llvmInst.IncomingCount()
|
||||
|
||||
+18
-1
@@ -103,7 +103,24 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
||||
default:
|
||||
panic("unknown operands length")
|
||||
}
|
||||
break // continue with next block
|
||||
case llvm.Switch:
|
||||
// Switch statement: [value, defaultLabel, case0, label0, case1, label1, ...]
|
||||
value := operands[0].Uint()
|
||||
targetLabel := operands[1].Uint() // default label
|
||||
// Do a lazy switch by iterating over all cases.
|
||||
for i := 2; i < len(operands); i += 2 {
|
||||
if value == operands[i].Uint() {
|
||||
targetLabel = operands[i+1].Uint()
|
||||
break
|
||||
}
|
||||
}
|
||||
lastBB = currentBB
|
||||
currentBB = int(targetLabel)
|
||||
bb = fn.blocks[currentBB]
|
||||
instIndex = -1 // start at 0 the next cycle
|
||||
if r.debug {
|
||||
fmt.Fprintln(os.Stderr, indent+"switch", operands, "->", currentBB)
|
||||
}
|
||||
case llvm.PHI:
|
||||
var result value
|
||||
for i := 0; i < len(inst.operands); i += 2 {
|
||||
|
||||
Vendored
+25
@@ -65,6 +65,12 @@ entry:
|
||||
call void @modifyExternal(i32* bitcast (void ()* @willModifyGlobal to i32*))
|
||||
store i16 7, i16* @main.exposedValue2
|
||||
|
||||
; Test switch statement.
|
||||
%switch1 = call i64 @testSwitch(i64 1) ; 1 returns 6
|
||||
%switch2 = call i64 @testSwitch(i64 9) ; 9 returns the default value -1
|
||||
call void @runtime.printint64(i64 %switch1)
|
||||
call void @runtime.printint64(i64 %switch2)
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -87,3 +93,22 @@ entry:
|
||||
store i16 8, i16* @main.exposedValue2
|
||||
ret void
|
||||
}
|
||||
|
||||
define i64 @testSwitch(i64 %val) {
|
||||
entry:
|
||||
; Test switch statement.
|
||||
switch i64 %val, label %otherwise [ i64 0, label %zero
|
||||
i64 1, label %one
|
||||
i64 2, label %two ]
|
||||
zero:
|
||||
ret i64 5
|
||||
|
||||
one:
|
||||
ret i64 6
|
||||
|
||||
two:
|
||||
ret i64 7
|
||||
|
||||
otherwise:
|
||||
ret i64 -1
|
||||
}
|
||||
|
||||
Vendored
+23
@@ -25,6 +25,8 @@ entry:
|
||||
store i16 5, i16* @main.exposedValue1
|
||||
call void @modifyExternal(i32* bitcast (void ()* @willModifyGlobal to i32*))
|
||||
store i16 7, i16* @main.exposedValue2
|
||||
call void @runtime.printint64(i64 6)
|
||||
call void @runtime.printint64(i64 -1)
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -44,3 +46,24 @@ entry:
|
||||
store i16 8, i16* @main.exposedValue2
|
||||
ret void
|
||||
}
|
||||
|
||||
define i64 @testSwitch(i64 %val) local_unnamed_addr {
|
||||
entry:
|
||||
switch i64 %val, label %otherwise [
|
||||
i64 0, label %zero
|
||||
i64 1, label %one
|
||||
i64 2, label %two
|
||||
]
|
||||
|
||||
zero: ; preds = %entry
|
||||
ret i64 5
|
||||
|
||||
one: ; preds = %entry
|
||||
ret i64 6
|
||||
|
||||
two: ; preds = %entry
|
||||
ret i64 7
|
||||
|
||||
otherwise: ; preds = %entry
|
||||
ret i64 -1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user