func emitScanFunc()

in x86/x86map/map.go [968:1116]


func emitScanFunc(p *Prog, out *[]uint16) uint16 {
	keys := p.keys()
	text := treeText(p)
	if off, ok := scanCache[text]; ok {
		return off
	}
	start := uint16(len(*out))
	scanCache[text] = start
	switch p.Action {
	case "decode":
		if keys[0][0] != '/' {
			*out = append(*out, scanSwitchByte)
			off := len(*out)
			for i := 0; i < 256; i++ {
				*out = append(*out, 0)
			}
			for _, key := range keys {
				val, n := decodeKeyPlus(key)
				dst := emitScanFunc(p.Child[key], out)
				for j := 0; j < n; j++ {
					(*out)[off+val+j] = dst
				}
			}
			return start
		}

		n := len(keys)
		for n > 0 && keys[n-1][0] != '/' {
			n--
		}
		total := 0
		for i := n; i < len(keys); i++ {
			key := keys[i]
			_, n := decodeKeyPlus(key)
			total += n
		}
		*out = append(*out, scanSwitchSlash, uint16(total))
		off := len(*out)
		for i := 0; i < total; i++ {
			*out = append(*out, 0, 0)
		}
		for i := 0; i < 8; i++ {
			*out = append(*out, 0)
		}
		for i := n; i < len(keys); i++ {
			key := keys[i]
			val, valn := decodeKeyPlus(key)
			targ := emitScanFunc(p.Child[key], out)
			for j := 0; j < valn; j++ {
				(*out)[off] = uint16(val + j)
				off++
				(*out)[off] = targ
				off++
			}
		}
		for i := 0; i < n; i++ {
			key := keys[i]
			if len(key) != 2 || key[0] != '/' || key[1] < '0' || '8' <= key[1] {
				log.Fatalf("unexpected decode key %q", key)
			}
			(*out)[off+int(key[1]-'0')] = emitScanFunc(p.Child[key], out)
		}
		return start

	case "read":
		switch keys[0] {
		default:
			log.Fatalf("unexpected read %q", keys[0])
		case "/r":
			*out = append(*out, scanReadModRM)
		case "ib":
			*out = append(*out, scanReadIB)
		case "iw":
			*out = append(*out, scanReadIW)
		case "cb":
			*out = append(*out, scanReadCB)
		case "cm":
			*out = append(*out, scanReadCM)
		case "iwd/d":
			*out = append(*out, scanReadIWD)
		case "iwdo/d":
			*out = append(*out, scanReadIWDO)
		case "cwd/d":
			*out = append(*out, scanReadCWD)
		case "cdp/d":
			*out = append(*out, scanReadCDP)
		}
		next := p.Child[keys[0]]
		if next.Action == "match" {
			*out = append(*out, scanMatch)
		} else {
			*out = append(*out, scanJump, 0)
			off := len(*out)
			(*out)[off-1] = emitScanFunc(next, out)
		}
		return start

	case "match":
		*out = append(*out, scanMatch)
		return start

	case "is64":
		*out = append(*out, scanSwitchIs64, 0, 0)
		if next := p.Child["0"]; next != nil {
			(*out)[start+1] = emitScanFunc(next, out)
		}
		if next := p.Child["1"]; next != nil {
			(*out)[start+2] = emitScanFunc(next, out)
		}
		return start

	case "ismem":
		*out = append(*out, scanSwitchIsMem, 0, 0)
		if next := p.Child["0"]; next != nil {
			(*out)[start+1] = emitScanFunc(next, out)
		}
		if next := p.Child["1"]; next != nil {
			(*out)[start+2] = emitScanFunc(next, out)
		}
		return start

	case "datasize":
		*out = append(*out, scanSwitchDatasize, 0, 0, 0)
		if next := p.Child["16"]; next != nil {
			(*out)[start+1] = emitScanFunc(next, out)
		}
		if next := p.Child["32"]; next != nil {
			(*out)[start+2] = emitScanFunc(next, out)
		}
		if next := p.Child["64"]; next != nil {
			(*out)[start+3] = emitScanFunc(next, out)
		}
		return start
	case "prefix":
		*out = append(*out, scanSwitchPrefix, uint16(len(keys)))
		n := len(keys)
		for i := 0; i < n; i++ {
			*out = append(*out, uint16(decodeKey(keys[i])), 0)
		}
		for i := 0; i < n; i++ {
			(*out)[int(start)+2+2*i+1] = emitScanFunc(p.Child[keys[i]], out)
		}
		return start

	}

	log.Fatalf("unexpected action %q", p.Action)
	return start
}