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 } }
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))) } }