コード例 #1
0
ファイル: sort.go プロジェクト: NickDaison/e8vm
func (s *Sorter) push(log lex8.Logger, node *node) {
	node.queuing = true
	name := node.name

	for _, dep := range node.deps {
		if dep == name {
			log.Errorf(node.tok.Pos, "%s %s depends on itself",
				s.typ, name,
			)
			s.err = true
			continue
		}

		depNode := s.m[dep]
		if depNode == nil || depNode.queued {
			continue
		}

		if depNode.queuing {
			log.Errorf(node.tok.Pos,
				"%s %s circular depends on %s %s",
				s.typ, node.tok.Lit, s.typ, dep,
			)
			s.err = true
			continue
		}

		s.push(log, depNode)
	}

	node.queuing = false
	node.queued = true
	s.order = append(s.order, node.name)
}
コード例 #2
0
ファイル: arg.go プロジェクト: NickDaison/e8vm
func argCount(log lex8.Logger, ops []*lex8.Token, n int) bool {
	if len(ops) == n+1 {
		return true
	}

	log.Errorf(ops[0].Pos, "%q needs %d arguments", ops[0].Lit, n)
	return false
}
コード例 #3
0
ファイル: check_type.go プロジェクト: NickDaison/e8vm
func checkTypeAll(p lex8.Logger, toks []*lex8.Token, typ int) bool {
	for _, t := range toks {
		if t.Type != typ {
			p.Errorf(t.Pos, "expect operand, got %s", parse.TypeStr(t.Type))
			return false
		}
	}
	return true
}
コード例 #4
0
ファイル: inst.go プロジェクト: NickDaison/e8vm
func (rs instResolvers) resolve(log lex8.Logger, ops []*lex8.Token) *inst {
	for _, r := range rs {
		if i, hit := r(log, ops); hit {
			return i
		}
	}

	op0 := ops[0]
	log.Errorf(op0.Pos, "invalid asm instruction %q", op0.Lit)
	return nil
}
コード例 #5
0
ファイル: reg.go プロジェクト: NickDaison/e8vm
func resolveReg(p lex8.Logger, op *lex8.Token) uint32 {
	if op.Type != parse.Operand {
		panic("not an operand")
	}

	ret, found := regNameMap[op.Lit]
	if !found {
		p.Errorf(op.Pos, "invalid register name %q", op.Lit)
		return 0
	}
	return ret
}
コード例 #6
0
ファイル: inst_imm.go プロジェクト: 272489711/e8vm
// parseImu parses an unsigned 16-bit immediate
func parseImu(p lex8.Logger, op *lex8.Token) uint32 {
	ret, e := strconv.ParseUint(op.Lit, 0, 32)
	if e != nil {
		p.Errorf(op.Pos, "invalid unsigned immediate %q: %s", op.Lit, e)
		return 0
	}

	if (ret & 0xffff) != ret {
		p.Errorf(op.Pos, "immediate too large: %s", op.Lit)
		return 0
	}

	return uint32(ret)
}
コード例 #7
0
ファイル: inst_imm.go プロジェクト: 272489711/e8vm
// parseImm parses an unsigned 16-bit immediate
func parseImm(p lex8.Logger, op *lex8.Token) uint32 {
	ret, e := strconv.ParseInt(op.Lit, 0, 32)
	if e != nil {
		p.Errorf(op.Pos, "invalid signed immediate %q: %s", op.Lit, e)
		return 0
	}

	if ret > 0xffff || ret < -0x8000 {
		p.Errorf(op.Pos, "immediate out of 16-bit range: %s", op.Lit)
		return 0
	}

	return uint32(ret) & 0xffff
}
コード例 #8
0
ファイル: inst_reg.go プロジェクト: 272489711/e8vm
func parseShift(p lex8.Logger, op *lex8.Token) uint32 {
	ret, e := strconv.ParseUint(op.Lit, 0, 32)
	if e != nil {
		p.Errorf(op.Pos, "invalid shift %q: %s", op.Lit, e)
		return 0
	}

	if (ret & 0x1f) != ret {
		p.Errorf(op.Pos, "shift too large: %s", op.Lit)
		return 0
	}

	return uint32(ret)
}
コード例 #9
0
ファイル: label.go プロジェクト: NickDaison/e8vm
func checkLabel(log lex8.Logger, t *lex8.Token) bool {
	if t.Type != parse.Operand {
		panic("not an operand")
	}

	lab := t.Lit
	if !isLabelStart(lab) {
		return false
	}

	if !isLabel(lab) {
		log.Errorf(t.Pos, "invalid label: %q", lab)
	}

	return true
}
コード例 #10
0
ファイル: data_nums.go プロジェクト: NickDaison/e8vm
func parseDataNums(p lex8.Logger, args []*lex8.Token, mode int) (
	[]byte, uint32,
) {
	if !checkTypeAll(p, args, parse.Operand) {
		return nil, 0
	}

	var ui uint32
	nbit := 8
	if mode&modeWord != 0 {
		nbit = 32
	}
	var e error

	buf := new(bytes.Buffer)
	for _, arg := range args {
		if mode&modeFloat != 0 {
			var f float64
			f, e = strconv.ParseFloat(arg.Lit, 32)
			ui = math.Float32bits(float32(f))
		} else if mode&modeSigned != 0 {
			var i int64
			i, e = strconv.ParseInt(arg.Lit, 0, nbit)
			ui = uint32(i)
		} else {
			var ui64 uint64
			ui64, e = strconv.ParseUint(arg.Lit, 0, nbit)
			ui = uint32(ui64)
		}
		if e != nil {
			p.Errorf(arg.Pos, "%s", e)
			return nil, 0
		}

		if nbit == 8 {
			buf.WriteByte(byte(ui))
		} else if nbit == 32 {
			var bs [4]byte
			arch8.Endian.PutUint32(bs[:], ui)
			buf.Write(bs[:])
		}
	}

	return buf.Bytes(), nbitAlign(nbit)
}
コード例 #11
0
ファイル: func_stmt.go プロジェクト: 272489711/e8vm
func resolveFuncStmt(log lex8.Logger, s *ast.FuncStmt) *funcStmt {
	ops := s.Ops
	op0 := ops[0]
	lead := op0.Lit
	if lead == "" {
		panic("empty operand")
	}

	if checkLabel(log, op0) {
		if len(ops) > 1 {
			log.Errorf(op0.Pos, "label should take the entire line")
			return nil
		}
		return &funcStmt{label: lead, FuncStmt: s}
	}

	return &funcStmt{inst: resolveInst(log, ops), FuncStmt: s}
}
コード例 #12
0
ファイル: data_hex.go プロジェクト: NickDaison/e8vm
func parseDataHex(p lex8.Logger, args []*lex8.Token) ([]byte, uint32) {
	if !checkTypeAll(p, args, parse.Operand) {
		return nil, 0
	}

	buf := new(bytes.Buffer)
	for _, arg := range args {
		b, e := strconv.ParseUint(arg.Lit, 16, 8)
		if e != nil {
			p.Errorf(arg.Pos, "%s", e)
			return nil, 0
		}

		buf.WriteByte(byte(b))
	}

	return buf.Bytes(), 0
}
コード例 #13
0
ファイル: import_decl.go プロジェクト: NickDaison/e8vm
func resolveImportDecl(log lex8.Logger, imp *ast.Import) *importDecl {
	ret := new(importDecl)
	ret.Import = imp
	ret.stmts = make(map[string]*importStmt)

	for _, stmt := range imp.Stmts {
		r := resolveImportStmt(log, stmt)

		if other, found := ret.stmts[r.as]; found {
			log.Errorf(r.pos(), "%s already imported", r.as)
			log.Errorf(other.pos(), "  previously imported here")
			continue
		}

		ret.stmts[r.as] = r
	}

	return ret
}
コード例 #14
0
ファイル: sym_chk.go プロジェクト: NickDaison/e8vm
func parseSym(p lex8.Logger, t *lex8.Token) (pack, sym string) {
	if t.Type != parse.Operand {
		panic("symbol not an operand")
	}

	sym = t.Lit
	dot := strings.Index(sym, ".")
	if dot >= 0 {
		pack, sym = sym[:dot], sym[dot+1:]
	}

	if dot >= 0 && !lex8.IsPkgName(pack) {
		p.Errorf(t.Pos, "invalid package name: %q", pack)
	} else if !parse.IsIdent(sym) {
		p.Errorf(t.Pos, "invalid symbol: %q", t.Lit)
	}

	return pack, sym
}
コード例 #15
0
ファイル: import_stmt.go プロジェクト: 272489711/e8vm
func resolveImportStmt(log lex8.Logger, imp *ast.ImportStmt) *importStmt {
	ret := new(importStmt)
	ret.ImportStmt = imp

	s, e := strconv.Unquote(imp.Path.Lit)
	if e != nil {
		log.Errorf(imp.Path.Pos, "invalid string %s", imp.Path.Lit)
		return nil
	}

	ret.path = s

	if imp.As != nil {
		ret.as = imp.As.Lit
	} else {
		ret.as = path.Base(ret.path)
	}

	return ret
}
コード例 #16
0
ファイル: data_str.go プロジェクト: 272489711/e8vm
func parseDataStr(p lex8.Logger, args []*lex8.Token) ([]byte, uint32) {
	if !checkTypeAll(p, args, parse.String) {
		return nil, 0
	}

	buf := new(bytes.Buffer)

	for _, arg := range args {
		if arg.Lit[0] != '"' {
			p.Errorf(arg.Pos, "expect string for string data")
			return nil, 0
		}

		s, e := strconv.Unquote(arg.Lit)
		if e != nil {
			p.Errorf(arg.Pos, "invalid string %s", arg.Lit)
			return nil, 0
		}
		buf.Write([]byte(s))
	}

	return buf.Bytes(), 0
}
コード例 #17
0
ファイル: var_stmt.go プロジェクト: NickDaison/e8vm
func resolveData(p lex8.Logger, t *lex8.Token, args []*lex8.Token) (
	[]byte, uint32,
) {
	switch t.Lit {
	case "str":
		return parseDataStr(p, args)
	case "x":
		return parseDataHex(p, args)
	case "u32":
		return parseDataNums(p, args, modeWord)
	case "i32":
		return parseDataNums(p, args, modeWord|modeSigned)
	case "u8", "byte":
		return parseDataNums(p, args, 0)
	case "i8":
		return parseDataNums(p, args, modeSigned)
	case "f32":
		return parseDataNums(p, args, modeWord|modeFloat)
	default:
		p.Errorf(t.Pos, "unknown data type %q", t.Lit)
		return nil, 0
	}
}
コード例 #18
0
ファイル: inst_br.go プロジェクト: NickDaison/e8vm
func resolveInstBr(p lex8.Logger, ops []*lex8.Token) (*inst, bool) {
	op0 := ops[0]
	opName := op0.Lit
	args := ops[1:]

	var (
		op, s1, s2 uint32
		lab        string
		symTok     *lex8.Token

		found bool
	)

	if op, found = opBrMap[opName]; found {
		// op reg reg label
		if argCount(p, ops, 3) {
			s1 = resolveReg(p, args[0])
			s2 = resolveReg(p, args[1])
			symTok = args[2]
			if checkLabel(p, symTok) {
				lab = symTok.Lit
			} else {
				p.Errorf(symTok.Pos, "expects a label for %s", opName)
			}
		}
	} else {
		return nil, false
	}

	ret := makeInstBr(op, s1, s2)
	ret.sym = lab
	ret.fill = fillLabel
	ret.symTok = symTok

	return ret, true
}