diff options
author | Ayke van Laethem <[email protected]> | 2024-11-27 11:15:15 +0100 |
---|---|---|
committer | Ron Evans <[email protected]> | 2024-11-27 12:16:10 +0100 |
commit | 392a709b77c82bfa98ce669ae6f781cf93835967 (patch) | |
tree | d4eb50ee542182ab2868e30c9a975115da9c8968 /compiler | |
parent | ee6fcd76f461543c67849a3b5b6cd5f8d16914d8 (diff) | |
download | tinygo-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.go | 16 |
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. |