aboutsummaryrefslogtreecommitdiffhomepage
path: root/compiler
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2024-11-27 11:15:15 +0100
committerRon Evans <[email protected]>2024-11-27 12:16:10 +0100
commit392a709b77c82bfa98ce669ae6f781cf93835967 (patch)
treed4eb50ee542182ab2868e30c9a975115da9c8968 /compiler
parentee6fcd76f461543c67849a3b5b6cd5f8d16914d8 (diff)
downloadtinygo-392a709b77c82bfa98ce669ae6f781cf93835967.tar.gz
tinygo-392a709b77c82bfa98ce669ae6f781cf93835967.zip
runtime: use uint32 for the channel state and select index
This uses uint32 instead of uint64. The reason for this is that uint64 atomic operations aren't universally available (especially on 32-bit architectures). We could also use uintptr, but that seems needlessly complicated: it's unlikely real-world programs will use more than a billion select states (2^30).
Diffstat (limited to 'compiler')
-rw-r--r--compiler/channel.go16
1 files changed, 16 insertions, 0 deletions
diff --git a/compiler/channel.go b/compiler/channel.go
index 7e867c278..0ff2ab7f3 100644
--- a/compiler/channel.go
+++ b/compiler/channel.go
@@ -4,7 +4,9 @@ package compiler
// or pseudo-operations that are lowered during goroutine lowering.
import (
+ "fmt"
"go/types"
+ "math"
"github.com/tinygo-org/tinygo/compiler/llvmutil"
"golang.org/x/tools/go/ssa"
@@ -124,6 +126,20 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
}
}
+ const maxSelectStates = math.MaxUint32 >> 2
+ if len(expr.States) > maxSelectStates {
+ // The runtime code assumes that the number of state must fit in 30 bits
+ // (so the select index can be stored in a uint32 with two bits reserved
+ // for other purposes). It seems unlikely that a real program would have
+ // that many states, but we check for this case anyway to be sure.
+ // We use a uint32 (and not a uintptr or uint64) to avoid 64-bit atomic
+ // operations which aren't available everywhere.
+ b.addError(expr.Pos(), fmt.Sprintf("too many select states: got %d but the maximum supported number is %d", len(expr.States), maxSelectStates))
+
+ // Continue as usual (we'll generate broken code but the error will
+ // prevent the compilation to complete).
+ }
+
// This code create a (stack-allocated) slice containing all the select
// cases and then calls runtime.chanSelect to perform the actual select
// statement.