Commit 93447c73 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent daa5bbe8
......@@ -126,16 +126,14 @@ func main() {
// prologue
f := fv[0] // proto.go comes first
buf := Buffer{}
// XXX vvv -> emit
buf.WriteString(`// DO NOT EDIT - AUTOGENERATED (by protogen.go)
buf.emit(`// DO NOT EDIT - AUTOGENERATED (by protogen.go)
package neo
import (
"encoding/binary"
"reflect"
"sort"
)
`)
)`)
pktTypeRegistry := map[int]string{} // pktCode -> typename
......@@ -474,6 +472,7 @@ type decoder struct {
n int // current read position in data.
nread int // numeric part of total nread return
nreadStk []int // stack to push/pop nread on loops
// overflow check state and size that will be checked for overflow at
// current overflow check point
......@@ -529,7 +528,6 @@ func (d *decoder) resetPos() {
}
}
// XXX place?
// mark current place for delayed insertion of overflow check code
//
// delayed: because we go forward in decode path scanning ahead as far as we
......@@ -543,8 +541,8 @@ func (d *decoder) resetPos() {
//
// it is inserted
// - before reading a variable sized item
// - in the beginning of a loop inside
// - right after loop exit
// - in the beginning of a loop inside (via overflowCheckLoopEntry)
// - right after loop exit (via overflowCheckLoopExit)
func (d *decoder) overflowCheck() {
// nop if we know overflow was already checked
if d.overflow.checked {
......@@ -561,7 +559,7 @@ func (d *decoder) overflowCheck() {
// otherwise accumulate into var(nread) at runtime.
// we do not break runtime accumulation into numeric & symbolic
// parts, because just above whole expression num + symbolic
// was just given to compiler so compiler shoud have it just computed.
// was just given to compiler so compiler should have it just computed.
// XXX recheck ^^^ actually good with the compiler
if d.overflow.checkSize.IsNumeric() {
d.nread += d.overflow.checkSize.num
......@@ -576,6 +574,39 @@ func (d *decoder) overflowCheck() {
d.buf.Reset()
}
// overflowCheck variant that should be called at the beginning of a loop inside
func (d *decoder) overflowCheckLoopEntry() {
if d.overflow.checked {
return
}
d.overflowCheck()
// upon entering a loop organize new nread, because what was statically
// read inside loop should be multiplied by loop len in parent context.
d.nreadStk = append(d.nreadStk, d.nread)
d.nread = 0
}
// overflowCheck variant that should be called right after loop exit
func (d *decoder) overflowCheckLoopExit(loopLenExpr string) {
if d.overflow.checked {
return
}
d.overflowCheck()
// merge-in numeric nread updates from loop
if d.nread != 0 {
d.emit("%v += %v * %v", d.var_("nread"), loopLenExpr, d.nread)
}
l := len(d.nreadStk)
d.nread = d.nreadStk[l-1]
d.nreadStk = d.nreadStk[:l-1]
}
func (d *decoder) generatedCode() string {
// flush for last overflow check point
d.overflowCheck()
......@@ -590,7 +621,6 @@ func (d *decoder) generatedCode() string {
code.Write(d.bufDone.Bytes())
// epilogue
//retexpr := fmt.Sprintf("%v", d.n)
retexpr := fmt.Sprintf("%v", d.nread)
if d.varUsed["nread"] {
retexpr += fmt.Sprintf(" + int(%v)", d.var_("nread"))
......@@ -772,28 +802,13 @@ func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object)
d.emit("%v= make(%v, l)", assignto, typeName(typ))
d.emit("for i := 0; uint32(i) < l; i++ {")
d.emit("a := &%s[i]", assignto)
d.overflowCheck() // -> overflowCheckLoopEntry ?
var nreadCur int
if !d.overflow.checked { // TODO merge-in into overflow checker
nreadCur = d.nread
d.nread = 0
}
d.overflowCheckLoopEntry()
codegenType("(*a)", typ.Elem(), obj, d)
d.resetPos()
d.emit("}")
d.overflowCheck() // -> overflowCheckPointLoopExit("l") ?
// merge-in numeric nread updates from loop
if !d.overflow.checked {
if d.nread != 0 {
d.emit("%v += l * %v", d.var_("nread"), d.nread)
}
d.nread = nreadCur
}
d.overflowCheckLoopExit("l")
d.emit("}")
}
......@@ -871,13 +886,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
d.emit("%v= make(%v, l)", assignto, typeName(typ))
d.emit("m := %v", assignto)
d.emit("for i := 0; uint32(i) < l; i++ {")
d.overflowCheck() // -> overflowCheckPointLoopEntry ?
var nreadCur int
if !d.overflow.checked { // TODO merge-in into overflow checker
nreadCur = d.nread
d.nread = 0
}
d.overflowCheckLoopEntry()
codegenType("key:", typ.Key(), obj, d)
......@@ -894,17 +903,8 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
}
d.resetPos()
d.emit("}")
d.overflowCheck() // -> overflowCheckPointLoopExit("l") ?
// merge-in numeric nread updates from loop
if !d.overflow.checked {
if d.nread != 0 {
d.emit("%v += l * %v", d.var_("nread"), d.nread)
}
d.nread = nreadCur
}
d.overflowCheckLoopExit("l")
d.emit("}")
}
......@@ -912,7 +912,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
// top-level driver for emitting size/encode/decode code for a type
//
// obj is object that uses this type in source program (so in case of an error
// we can point to source location for where it happenned)
// we can point to source location for where it happened)
func codegenType(path string, typ types.Type, obj types.Object, codegen CodeGenerator) {
switch u := typ.Underlying().(type) {
case *types.Basic:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment