示例#1
0
func (f *Function) BinOpLoadXY(instr *ssa.BinOp) (asm string, x *register, y *register, err *Error) {
	if isPointer(instr.Type()) {
		panic("ptr")
	}
	if ident := f.Ident(instr); ident == nil {
		return "", nil, nil, ErrorMsg2(fmt.Sprintf("Cannot alloc value: %v", instr))
	}
	if ident := f.Ident(instr.X); ident == nil {
		return "", nil, nil, ErrorMsg2(fmt.Sprintf("Cannot alloc value: %v", instr.X))
	}
	if ident := f.Ident(instr.Y); ident == nil {
		return "", nil, nil, ErrorMsg2(fmt.Sprintf("Cannot alloc value: %v", instr.Y))
	}

	var a string
	asm = "// BEGIN BinOpLoadXY\n"
	if isPointer(instr.X.Type()) {
		panic("ptr")
	}
	a, x, err = f.LoadValue(instr, instr.X, 0, f.sizeof(instr.X))
	x.inUse = true
	if err != nil {
		return "", nil, nil, err
	} else {
		asm += a
	}
	if isPointer(f.Ident(instr.Y).typ) {
		panic("ptr")
	}

	a, y, err = f.LoadValue(instr, instr.Y, 0, f.sizeof(instr.Y))
	y.inUse = true
	if err != nil {
		return "", nil, nil, err
	} else {
		asm += a
	}

	asm += "// END BinOpLoadXY\n"
	return asm, x, y, nil
}
示例#2
0
func visitBinOp(inst *ssa.BinOp, fr *frame) {
	switch inst.Op {
	case token.EQL:
		if selTuple, isSelTuple := fr.env.selIdx[inst.X]; isSelTuple {
			branchID := int(inst.Y.(*ssa.Const).Int64())
			fr.env.selTest[inst] = struct {
				idx int
				tpl ssa.Value
			}{
				branchID, selTuple,
			}
		} else {
			fmt.Fprintf(os.Stderr, "   # %s = "+red("%s")+"\n", inst.Name(), inst.String())
		}
	default:
		fmt.Fprintf(os.Stderr, "   # %s = "+red("%s")+"\n", inst.Name(), inst.String())
	}
}
示例#3
0
func (f *Function) BinOp(instr *ssa.BinOp) (string, *Error) {
	ctx := context{f, instr}
	ident := f.Ident(instr)
	if ident == nil {
		return ErrorMsg(fmt.Sprintf("Cannot alloc value: %v", instr))
	}

	var regX, regY, regVal *register
	size := f.sizeof(instr)
	xIsSigned := signed(instr.X.Type())

	var a string
	// comparison op results are size 1 byte, but that's not supported
	if size == 1 {
		a, regVal = f.allocIdentReg(instr, ident, 8*size)
	} else {
		a, regVal = f.allocIdentReg(instr, ident, size)
	}
	asm := a
	asmload, regX, regY, err := f.BinOpLoadXY(instr)
	asm += asmload

	if err != nil {
		return asm, err
	}

	size = f.sizeof(instr.X)

	switch instr.Op {
	default:
		ice(fmt.Sprintf("unknown op (%v)", instr.Op))
	case token.ADD, token.SUB, token.MUL, token.QUO, token.REM:
		optypes := GetOpDataType(instr.Type())
		asm += ArithOp(ctx, optypes, instr.Op, regX, regY, regVal)
	case token.AND, token.OR, token.XOR, token.SHL, token.SHR, token.AND_NOT:
		asm += BitwiseOp(ctx, instr.Op, xIsSigned, regX, regY, regVal, size)
	case token.EQL, token.NEQ, token.LEQ, token.GEQ, token.LSS, token.GTR:
		if size != f.sizeof(instr.Y) {
			ice("comparing two different size values")
		}
		optypes := GetOpDataType(instr.X.Type())
		asm += CmpOp(ctx, optypes, instr.Op, regX, regY, regVal)
	}
	f.freeReg(regX)
	f.freeReg(regY)

	addr, ok := f.identifiers[instr.Name()]
	if !ok {
		ice(fmt.Sprintf("unknown name (%v), instr (%v)\n", instr.Name(), instr))
	}

	a1, err := f.StoreValue(instr, addr, regVal)
	if err != nil {
		return asm, err
	} else {
		asm += a1
	}
	f.freeReg(regVal)

	asm = fmt.Sprintf("// BEGIN ssa.BinOp, %v = %v\n", instr.Name(), instr) + asm
	asm += fmt.Sprintf("// END ssa.BinOp, %v = %v\n", instr.Name(), instr)
	return asm, nil
}