func()

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
}