Example #1
0
func (f *Function) IndexAddr(instr *ssa.IndexAddr) (string, *Error) {
	ctx := context{f, instr}
	if instr == nil {
		return ErrorMsg("nil instr")

	}

	asm := ""
	xInfo := f.identifiers[instr.X.Name()]
	assignment := f.Ident(instr)
	assignment.ptr = xInfo
	if a, e := f.spillAllIdent(xInfo, instr); e != nil {
		return a, e
	} else {
		asm += a
	}

	xReg, xOffset, _ := xInfo.Addr()
	a1, addr := f.allocIdentReg(instr, assignment, assignment.size())
	asm += a1

	a, idx, err := f.LoadValueSimple(instr, instr.Index)
	if err != nil {
		return "", err
	}
	asm += a

	asm += MulImm32RegReg(ctx, uint32(sizeofElem(xInfo.typ)), idx, idx, true)

	if isSlice(xInfo.typ) {
		// TODO: add bounds checking
		optypes := GetIntegerOpDataType(false, sizePtr())
		asm += MovMemReg(ctx, optypes, xInfo.name, xOffset, &xReg, addr, false)
	} else if isArray(xInfo.typ) {
		asm += Lea(ctx, xInfo.name, xOffset, &xReg, addr, false)
		//assignment.aliases = append(assignment.aliases, xInfo)
	} else if isSimd(xInfo.typ) {
		asm += Lea(ctx, xInfo.name, xOffset, &xReg, addr, false)
		//assignment.aliases = append(assignment.aliases, xInfo)
	} else {
		ice(fmt.Sprintf("indexing non-slice/array variable, type %v", xInfo.typ))
	}

	optypes := GetIntegerOpDataType(false, idx.size())
	asm += AddRegReg(ctx, optypes, idx, addr, false)

	a, e := f.StoreValue(instr, assignment, addr)
	if e != nil {
		return "", e
	}
	asm += a

	f.freeReg(idx)
	f.freeReg(addr)

	asm = fmt.Sprintf("// BEGIN ssa.IndexAddr: %v = %v\n", instr.Name(), instr) + asm
	asm += fmt.Sprintf("// END ssa.IndexAddr: %v = %v\n", instr.Name(), instr)
	return asm, nil
}
Example #2
0
func visitIndexAddr(instr *ssa.IndexAddr, infer *TypeInfer, ctx *Context) {
	elem, array, index := instr, instr.X, instr.Index
	// Array.
	if aType, ok := derefType(array.Type()).Underlying().(*types.Array); ok {
		aInst, ok := ctx.F.locals[array]
		if !ok {
			aInst, ok = ctx.F.Prog.globals[array]
			if !ok {
				infer.Logger.Fatalf("index-addr: %s: array %+v", ErrUnknownValue, array)
				return
			}
		}
		// Check status of instance.
		switch inst := aInst.(type) {
		case *Value: // Continue
		case *External: // External
			infer.Logger.Print(ctx.F.Sprintf(SubSymbol+"index-addr: array %+v is external", aInst))
			ctx.F.locals[elem] = inst
		case *Const:
			infer.Logger.Print(ctx.F.Sprintf(SubSymbol+"index-addr: array %+v is a constant", aInst))
			if inst.Const.IsNil() {
				ctx.F.locals[elem] = inst
			}
			return
		default:
			infer.Logger.Fatalf("index-addr: %s: array is not instance %+v", ErrUnknownValue, aInst)
			return
		}
		// Find the array.
		elems, ok := ctx.F.arrays[aInst]
		if !ok {
			elems, ok = ctx.F.Prog.arrays[aInst]
			if !ok {
				infer.Logger.Fatalf("index-addr: %s: array uninitialised %s", ErrUnknownValue, aInst)
				return
			}
		}
		infer.Logger.Print(ctx.F.Sprintf(ValSymbol+"%s = %s"+FieldSymbol+"[%s] of type %s", instr.Name(), aInst, index, aType.String()))
		if elems[index] != nil {
			infer.Logger.Print(ctx.F.Sprintf(SubSymbol+"accessed as %s", elems[index]))
		} else {
			elems[index] = &Value{elem, ctx.F.InstanceID(), ctx.L.Index}
			infer.Logger.Printf(ctx.F.Sprintf(SubSymbol+"elem uninitialised, set to %s", elem.Name()))
		}
		initNestedRefVar(infer, ctx, elems[index], false)
		ctx.F.locals[elem] = elems[index]
		return
	}
	// Slices.
	if sType, ok := derefType(array.Type()).Underlying().(*types.Slice); ok {
		sInst, ok := ctx.F.locals[array]
		if !ok {
			sInst, ok = ctx.F.Prog.globals[array]
			if !ok {
				infer.Logger.Fatalf("index-addr: %s: slice %+v", ErrUnknownValue, array)
				return
			}
		}
		// Check status of instance.
		switch inst := sInst.(type) {
		case *Value: // Continue
			if basic, ok := sType.Elem().(*types.Basic); ok && basic.Kind() == types.Byte {
				ctx.F.locals[elem] = inst
				return
			}
		case *External: // External
			infer.Logger.Print(ctx.F.Sprintf(SubSymbol+"index-addr: slice %+v is external", sInst))
			ctx.F.locals[elem] = inst
			return
		case *Const:
			infer.Logger.Print(ctx.F.Sprintf(SubSymbol+"index-addr: slice %+v is a constant", sInst))
			if inst.Const.IsNil() {
				ctx.F.locals[elem] = inst
			}
			return
		default:
			infer.Logger.Fatalf("index-addr: %s: slice is not instance %+v", ErrUnknownValue, sInst)
			return
		}
		// Find the slice.
		elems, ok := ctx.F.arrays[sInst]
		if !ok {
			elems, ok = ctx.F.Prog.arrays[sInst]
			if !ok {
				infer.Logger.Fatalf("index-addr: %s: slice uninitialised %+v", ErrUnknownValue, sInst)
				return
			}
		}
		infer.Logger.Print(ctx.F.Sprintf(ValSymbol+"%s = %s"+FieldSymbol+"[%s] (slice) of type %s", instr.Name(), sInst, index, sType.String()))
		if elems[index] != nil {
			infer.Logger.Print(ctx.F.Sprintf(SubSymbol+"accessed as %s", elems[index]))
		} else {
			elems[index] = &Value{elem, ctx.F.InstanceID(), ctx.L.Index}
			infer.Logger.Printf(ctx.F.Sprintf(SubSymbol+"elem uninitialised, set to %s", elem.Name()))
		}
		initNestedRefVar(infer, ctx, elems[index], false)
		ctx.F.locals[elem] = elems[index]
		return
	}
	infer.Logger.Fatalf("index-addr: %s: not array/slice %+v", ErrInvalidVarRead, array)
}