Exemple #1
0
func (f *Function) UnOp(instr *ssa.UnOp) (string, *Error) {
	var err *Error
	asm := ""
	switch instr.Op {
	default:
		ice(fmt.Sprintf("unknown Op token (%v): \"%v\"", instr.Op, instr))
	case token.NOT: // logical negation
		asm, err = f.UnOpXor(instr, 1)
	case token.XOR: //bitwise negation
		asm, err = f.UnOpXor(instr, -1)
	case token.SUB: // arithmetic negation e.g. x=>-x
		asm, err = f.UnOpSub(instr)
	case token.MUL: //pointer indirection
		asm, err = f.UnOpPointer(instr)
	}
	asm = fmt.Sprintf("// BEGIN ssa.UnOp: %v = %v\n", instr.Name(), instr) + asm
	asm += fmt.Sprintf("// END ssa.UnOp: %v = %v\n", instr.Name(), instr)
	return asm, err
}
Exemple #2
0
// arithmetic negation
func (f *Function) UnOpSub(instr *ssa.UnOp) (string, *Error) {
	ctx := context{f, instr}
	if ident := f.Ident(instr); ident == nil {
		return ErrorMsg(fmt.Sprintf("Cannot alloc value: %v", instr))
	}
	var regSubX, regX, regVal *register
	var a1, a2 string
	a1, regVal = f.allocReg(instr, regType(instr.Type()), f.sizeof(instr))
	a2, regSubX = f.allocReg(instr, regType(instr.X.Type()), f.sizeof(instr.X))

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

	a3, regX, err := f.LoadValueSimple(instr, instr.X)
	asm := a1 + a2 + a3
	if err != nil {
		return asm, err
	}

	asm += ZeroReg(ctx, regSubX)
	optypes := GetOpDataType(instr.Type())
	asm += ArithOp(ctx, optypes, token.SUB, regSubX, regX, regVal)
	f.freeReg(regX)
	f.freeReg(regSubX)

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

	f.freeReg(regVal)
	asm = fmt.Sprintf("// BEGIN ssa.UnOpSub, %v = %v\n", instr.Name(), instr) + asm
	asm += fmt.Sprintf("// END ssa.UnOpSub, %v = %v\n", instr.Name(), instr)
	return asm, nil

}
Exemple #3
0
// bitwise negation
func (f *Function) UnOpXor(instr *ssa.UnOp, xorVal int32) (string, *Error) {
	ctx := context{f, instr}
	if ident := f.Ident(instr); ident == nil {
		return ErrorMsg(fmt.Sprintf("Cannot alloc value: %v", instr))
	}

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

	asm, reg, err := f.LoadValueSimple(instr, instr.X)
	if err != nil {
		return asm, err
	}

	if reg.size() < 8 {
		asm += XorImm32Reg(ctx, xorVal, reg, reg.size(), true)
	} else {
		asm += XorImm64Reg(ctx, int64(xorVal), reg, reg.size(), true)
	}

	a, err := f.StoreValue(instr, addr, reg)
	f.freeReg(reg)

	if err != nil {
		return asm, err
	} else {
		asm += a
	}

	asm = fmt.Sprintf("// BEGIN ssa.UnOpNot, %v = %v\n", instr.Name(), instr) + asm
	asm += fmt.Sprintf("// END ssa.UnOpNot, %v = %v\n", instr.Name(), instr)
	return asm, nil
}
Exemple #4
0
//pointer indirection, in assignment such as "z = *x"
func (f *Function) UnOpPointer(instr *ssa.UnOp) (string, *Error) {
	asm := ""
	assignment := f.Ident(instr)
	if assignment == nil {
		return ErrorMsg(fmt.Sprintf("Cannot alloc value: %v", instr))
	}
	xName := instr.X.Name()
	xInfo, okX := f.identifiers[xName]
	if !xInfo.isSsaLocal() && xInfo.param == nil && xInfo.ptr == nil {
		panic("unexpected nil ptr")
	} else if !xInfo.isSsaLocal() && xInfo.param == nil {
		asm += xInfo.ptr.spillAllRegisters(instr)
	}
	// TODO add complex64/128 support
	if isComplex(instr.Type()) || isComplex(instr.X.Type()) {
		return ErrorMsg("complex64/complex128 unimplemented")
	}
	if !okX {
		msgstr := "Unknown name for UnOp X (%v), instr \"(%v)\""
		ice(fmt.Sprintf(msgstr, instr.X, instr))
	}
	if xInfo.local == nil && xInfo.param == nil && !xInfo.isPointer() {
		fmtstr := "in UnOp, X (%v) isn't a pointer, X.type (%v), instr \"(%v)\""
		msg := fmt.Sprintf(fmtstr, instr.X, instr.X.Type(), instr)
		ice(msg)
	}
	_, _, size := assignment.Addr()
	if xInfo.isSsaLocal() {
		ctx := context{f, instr}
		a, reg := xInfo.load(ctx)
		asm += a
		asm += assignment.newValue(ctx, reg, 0, xInfo.size())
		f.freeReg(reg)
	} else {
		var tmpData *register
		var a1 string
		if isXmm(instr.Type()) {
			a1, tmpData = f.allocReg(instr, XMM_REG, XmmRegSize)
		} else {
			a1, tmpData = f.allocReg(instr, regType(instr.Type()), DataRegSize)
		}
		asm += a1
		var a2 string
		var tmpAddr *register
		a2, tmpAddr = f.allocReg(instr, DATA_REG, DataRegSize)
		asm += a2

		src, ok := xInfo.storage.(*memory)
		if !ok {
			ice("cannot dereference pointer to constant")
		}
		dst, ok := assignment.storage.(*memory)
		if !ok {
			ice("cannot modify constant")
		}
		dst.removeAliases()
		ctx := context{f, instr}
		a, srcReg := src.load(ctx, src.ownerRegion())
		asm += a
		aReg, aOffset, _ := assignment.Addr()
		asm += MovRegIndirectMem(ctx, dst.optype(), srcReg, assignment.name, aOffset, &aReg, size, tmpAddr, tmpData)
		dst.setInitialized(region{0, size})
		f.freeReg(srcReg)
		f.freeReg(tmpAddr)
		f.freeReg(tmpData)
	}

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