Skip to content

Commit 46e081f

Browse files
authored
Merge pull request #17 from golang/master
[pull] master from golang:master
2 parents a882c08 + d5ebe81 commit 46e081f

1 file changed

Lines changed: 77 additions & 4 deletions

File tree

src/cmd/compile/internal/ssagen/intrinsics.go

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,6 +1971,11 @@ func opLen4_31(op ssa.Op, t *types.Type) func(s *state, n *ir.CallExpr, args []*
19711971
}
19721972

19731973
func immJumpTable(s *state, idx *ssa.Value, intrinsicCall *ir.CallExpr, genOp func(*state, int)) *ssa.Value {
1974+
if base.Ctxt.Retpoline {
1975+
// Note spectre=all implies retpoline which requires binary search instead of table switch.
1976+
return branchTableImm8(s, idx, intrinsicCall, genOp)
1977+
}
1978+
19741979
// Make blocks we'll need.
19751980
bEnd := s.f.NewBlock(ssa.BlockPlain)
19761981

@@ -1985,10 +1990,7 @@ func immJumpTable(s *state, idx *ssa.Value, intrinsicCall *ir.CallExpr, genOp fu
19851990
b := s.curBlock
19861991
b.Kind = ssa.BlockJumpTable
19871992
b.Pos = intrinsicCall.Pos()
1988-
if base.Flag.Cfg.SpectreIndex {
1989-
// Potential Spectre vulnerability hardening?
1990-
idx = s.newValue2(ssa.OpSpectreSliceIndex, t, idx, s.uintptrConstant(255))
1991-
}
1993+
19921994
b.SetControl(idx)
19931995
targets := [256]*ssa.Block{}
19941996
for i := range 256 {
@@ -2012,6 +2014,77 @@ func immJumpTable(s *state, idx *ssa.Value, intrinsicCall *ir.CallExpr, genOp fu
20122014
return ret
20132015
}
20142016

2017+
func branchTableImm8(s *state, idx *ssa.Value, intrinsicCall *ir.CallExpr, genOp func(*state, int)) *ssa.Value {
2018+
return branchTableN(s, idx, intrinsicCall, genOp, 256, true)
2019+
}
2020+
2021+
func branchTableN(s *state, idx *ssa.Value, intrinsicCall *ir.CallExpr, genOp func(*state, int), immLimit uint64, preChecked bool) *ssa.Value {
2022+
// Make blocks we'll need.
2023+
bEnd := s.f.NewBlock(ssa.BlockPlain)
2024+
bPanic := s.f.NewBlock(ssa.BlockPlain)
2025+
2026+
jt := s.f.NewBlock(ssa.BlockPlain)
2027+
2028+
t := types.Types[types.TUINTPTR]
2029+
idx = s.conv(nil, idx, idx.Type, t)
2030+
2031+
if !preChecked {
2032+
// Begin with a bounds check
2033+
width := s.uintptrConstant(immLimit)
2034+
cmp := s.newValue2(s.ssaOp(ir.OLT, t), types.Types[types.TBOOL], idx, width)
2035+
bb := s.endBlock()
2036+
bb.Kind = ssa.BlockIf
2037+
bb.SetControl(cmp)
2038+
bb.AddEdgeTo(jt) // in range - use jump table
2039+
bb.AddEdgeTo(bPanic) // out of range - panic
2040+
bb.Likely = ssa.BranchLikely // panic is unlikely
2041+
2042+
s.startBlock(bPanic)
2043+
s.rtcall(ir.Syms.PanicSimdImm, false, nil)
2044+
}
2045+
2046+
s.startBlock(jt)
2047+
jt.Kind = ssa.BlockPlain
2048+
jt.Pos = intrinsicCall.Pos()
2049+
2050+
branchTableNInner(s, idx, 0, immLimit, genOp, bEnd)
2051+
2052+
s.startBlock(bEnd)
2053+
ret := s.variable(intrinsicCall, intrinsicCall.Type())
2054+
return ret
2055+
}
2056+
2057+
func branchTableNInner(s *state, idx *ssa.Value, lowInclusive, len uint64, genOp func(*state, int), bEnd *ssa.Block) {
2058+
t := types.Types[types.TUINTPTR]
2059+
if len == 0 {
2060+
panic("empty branch table")
2061+
}
2062+
if len == 1 {
2063+
genOp(s, int(lowInclusive+len-1))
2064+
if s.curBlock != nil { // if genOp was "panic" then curBlock is already ended and nil
2065+
if s.curBlock.Kind != ssa.BlockExit {
2066+
s.curBlock.AddEdgeTo(bEnd)
2067+
}
2068+
s.endBlock()
2069+
}
2070+
return
2071+
}
2072+
2073+
s.curBlock.Kind = ssa.BlockIf
2074+
cmp := s.newValue2(s.ssaOp(ir.OLT, t), types.Types[types.TBOOL], idx, s.uintptrConstant(lowInclusive+len/2))
2075+
bb := s.endBlock()
2076+
bb.Kind = ssa.BlockIf
2077+
bb.SetControl(cmp)
2078+
bMatch := s.f.NewBlock(ssa.BlockPlain)
2079+
bNext := s.f.NewBlock(ssa.BlockPlain)
2080+
bb.AddEdgeTo(bMatch)
2081+
bb.AddEdgeTo(bNext)
2082+
s.startBlock(bMatch)
2083+
branchTableNInner(s, idx, lowInclusive, len/2, genOp, bEnd)
2084+
s.startBlock(bNext)
2085+
branchTableNInner(s, idx, lowInclusive+len/2, len-len/2, genOp, bEnd)
2086+
}
2087+
20152088
func opLen1Imm8(op ssa.Op, t *types.Type, offset int) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
20162089
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
20172090
if args[1].Op == ssa.OpConst8 {

0 commit comments

Comments
 (0)