Beispiel #1
0
func visitIndex(instr *ssa.Index, infer *TypeInfer, ctx *Context) {
	elem, array, index := instr, instr.X, instr.Index
	// Array.
	if aType, ok := 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: %s: array %+v", ErrUnknownValue, array)
				return
			}
		}
		elems, ok := ctx.F.arrays[aInst]
		if !ok {
			elems, ok = ctx.F.Prog.arrays[aInst]
			if !ok {
				infer.Logger.Fatalf("index: %s: not an array %+v", 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
	}
}
Beispiel #2
0
func visitIndex(inst *ssa.Index, fr *frame) {
	elem := inst
	array := inst.X
	index := inst.Index
	_, isArray := array.Type().Underlying().(*types.Array)
	_, isSlice := array.Type().Underlying().(*types.Slice)

	if isArray || isSlice {
		switch vd, kind := fr.get(array); kind {
		case Array:
			fmt.Fprintf(os.Stderr, "   %s = %s(=%s)[%d] of type %s\n", cyan(reg(elem)), array.Name(), vd.String(), index, elem.Type().String())
			if fr.env.arrays[vd][index] == nil { // First use
				vdelem := utils.NewDef(elem)
				fr.env.arrays[vd][index] = vdelem
				fmt.Fprintf(os.Stderr, "     ^ accessed for the first time: use %s as elem definition\n", elem.Name())
			} else if fr.env.arrays[vd][index].Var != elem { // Previously defined
				fmt.Fprintf(os.Stderr, "     ^ elem %s previously defined as %s\n", elem.Name(), reg(fr.env.arrays[vd][index].Var))
			} // else Accessed before (and unchanged)
			fr.locals[elem] = fr.env.arrays[vd][index]

		case LocalArray:
			fmt.Fprintf(os.Stderr, "   %s = %s(=%s)[%d] (local) of type %s\n", cyan(reg(elem)), array.Name(), vd.String(), index, elem.Type().String())
			if fr.arrays[vd][index] == nil { // First use
				vdElem := utils.NewDef(elem)
				fr.arrays[vd][index] = vdElem
				fmt.Fprintf(os.Stderr, "     ^ accessed for the first time: use %s as elem definition\n", elem.Name())
			} else if fr.arrays[vd][index].Var != elem { // Previously defined
				fmt.Fprintf(os.Stderr, "     ^ elem %s previously defined as %s\n", elem.Name(), reg(fr.arrays[vd][index].Var))
			} // else Accessed before (and unchanged)
			fr.locals[elem] = fr.arrays[vd][index]

		case Nothing, Untracked:
			// Nothing: Very likely external struct.
			// Untracked: likely branches of return values (e.g. returning nil)
			fmt.Fprintf(os.Stderr, "   %s = %s(=%s)[%d] (external) of type %s\n", cyan(reg(elem)), inst.X.Name(), vd.String(), index, elem.Type().String())
			vd := utils.NewDef(array) // New external array
			fr.locals[array] = vd
			fr.env.arrays[vd] = make(Elems)
			vdElem := utils.NewDef(elem) // New external elem
			fr.env.arrays[vd][index] = vdElem
			fr.locals[elem] = vdElem
			fmt.Fprintf(os.Stderr, "     ^ accessed for the first time: use %s as elem definition of type %s\n", elem.Name(), inst.Type().(*types.Pointer).Elem().Underlying().String())

		default:
			panic(fmt.Sprintf("Index: Cannot access non-array %s", reg(array)))
		}
	} else {
		panic(fmt.Sprintf("Index: Cannot access element - %s not an array", reg(array)))
	}
}