in internal/compile/compile.go [733:819]
func (fcomp *fcomp) generate(blocks []*block, codelen uint32) {
code := make([]byte, 0, codelen)
var pclinetab []uint16
prev := pclinecol{
pc: 0,
line: fcomp.fn.Pos.Line,
col: fcomp.fn.Pos.Col,
}
for _, b := range blocks {
if Disassemble {
fmt.Fprintf(os.Stderr, "%d:\n", b.index)
}
pc := b.addr
for _, insn := range b.insns {
if insn.line != 0 {
// Instruction has a source position. Delta-encode it.
// See Funcode.Position for the encoding.
for {
var incomplete uint16
// Δpc, uint4
deltapc := pc - prev.pc
if deltapc > 0x0f {
deltapc = 0x0f
incomplete = 1
}
prev.pc += deltapc
// Δline, int5
deltaline, ok := clip(insn.line-prev.line, -0x10, 0x0f)
if !ok {
incomplete = 1
}
prev.line += deltaline
// Δcol, int6
deltacol, ok := clip(insn.col-prev.col, -0x20, 0x1f)
if !ok {
incomplete = 1
}
prev.col += deltacol
entry := uint16(deltapc<<12) | uint16(deltaline&0x1f)<<7 | uint16(deltacol&0x3f)<<1 | incomplete
pclinetab = append(pclinetab, entry)
if incomplete == 0 {
break
}
}
if Disassemble {
fmt.Fprintf(os.Stderr, "\t\t\t\t\t; %s:%d:%d\n",
filepath.Base(fcomp.fn.Pos.Filename()), insn.line, insn.col)
}
}
if Disassemble {
PrintOp(fcomp.fn, pc, insn.op, insn.arg)
}
code = append(code, byte(insn.op))
pc++
if insn.op >= OpcodeArgMin {
if insn.op == CJMP || insn.op == ITERJMP {
code = addUint32(code, insn.arg, 4) // pad arg to 4 bytes
} else {
code = addUint32(code, insn.arg, 0)
}
pc = uint32(len(code))
}
}
if b.jmp != nil && b.jmp.index != b.index+1 {
addr := b.jmp.addr
if Disassemble {
fmt.Fprintf(os.Stderr, "\t%d\tjmp\t\t%d\t; block %d\n",
pc, addr, b.jmp.index)
}
code = append(code, byte(JMP))
code = addUint32(code, addr, 4)
}
}
if len(code) != int(codelen) {
panic("internal error: wrong code length")
}
fcomp.fn.pclinetab = pclinetab
fcomp.fn.Code = code
}