func (v *Variable) readFunctionPtr() { val, err := v.mem.readMemory(v.Addr, v.dbp.arch.PtrSize()) if err != nil { v.Unreadable = err return } // dereference pointer to find function pc fnaddr := uintptr(binary.LittleEndian.Uint64(val)) if fnaddr == 0 { v.Base = 0 v.Value = constant.MakeString("") return } val, err = v.mem.readMemory(fnaddr, v.dbp.arch.PtrSize()) if err != nil { v.Unreadable = err return } v.Base = uintptr(binary.LittleEndian.Uint64(val)) fn := v.dbp.goSymTable.PCToFunc(uint64(v.Base)) if fn == nil { v.Unreadable = fmt.Errorf("could not find function for %#v", v.Base) return } v.Value = constant.MakeString(fn.Name) }
// zeroConst returns a new "zero" constant of the specified type, // which must not be an array or struct type: the zero values of // aggregates are well-defined but cannot be represented by Const. // func zeroConst(t types.Type) *Const { switch t := t.(type) { case *types.Basic: switch { case t.Info()&types.IsBoolean != 0: return NewConst(exact.MakeBool(false), t) case t.Info()&types.IsNumeric != 0: return NewConst(exact.MakeInt64(0), t) case t.Info()&types.IsString != 0: return NewConst(exact.MakeString(""), t) case t.Kind() == types.UnsafePointer: fallthrough case t.Kind() == types.UntypedNil: return nilConst(t) default: panic(fmt.Sprint("zeroConst for unexpected type:", t)) } case *types.Pointer, *types.Slice, *types.Interface, *types.Chan, *types.Map, *types.Signature: return nilConst(t) case *types.Named: return NewConst(zeroConst(t.Underlying()).Value, t) case *types.Array, *types.Struct, *types.Tuple: panic(fmt.Sprint("zeroConst applied to aggregate:", t)) } panic(fmt.Sprint("zeroConst: unexpected ", t)) }
func (c *funcContext) zeroValue(ty types.Type) ast.Expr { switch t := ty.Underlying().(type) { case *types.Basic: switch { case isBoolean(t): return c.newConst(ty, constant.MakeBool(false)) case isNumeric(t): return c.newConst(ty, constant.MakeInt64(0)) case isString(t): return c.newConst(ty, constant.MakeString("")) case t.Kind() == types.UnsafePointer: // fall through to "nil" case t.Kind() == types.UntypedNil: panic("Zero value for untyped nil.") default: panic(fmt.Sprintf("Unhandled basic type: %v\n", t)) } case *types.Array, *types.Struct: return c.setType(&ast.CompositeLit{}, ty) case *types.Chan, *types.Interface, *types.Map, *types.Signature, *types.Slice, *types.Pointer: // fall through to "nil" default: panic(fmt.Sprintf("Unhandled type: %T\n", t)) } id := c.newIdent("nil", ty) c.p.Uses[id] = nilObj return id }
// Conversion type-checks the conversion T(x). // The result is in x. func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ var ok bool switch { case constArg && isConstType(T): // constant conversion switch t := T.Underlying().(*Basic); { case representableConst(x.val, check.conf, t.kind, &x.val): ok = true case isInteger(x.typ) && isString(t): codepoint := int64(-1) if i, ok := constant.Int64Val(x.val); ok { codepoint = i } // If codepoint < 0 the absolute value is too large (or unknown) for // conversion. This is the same as converting any other out-of-range // value - let string(codepoint) do the work. x.val = constant.MakeString(string(codepoint)) ok = true } case x.convertibleTo(check.conf, T): // non-constant conversion x.mode = value ok = true } if !ok { check.errorf(x.pos(), "cannot convert %s to %s", x, T) x.mode = invalid return } // The conversion argument types are final. For untyped values the // conversion provides the type, per the spec: "A constant may be // given a type explicitly by a constant declaration or conversion,...". final := x.typ if isUntyped(x.typ) { final = T // - For conversions to interfaces, use the argument's default type. // - For conversions of untyped constants to non-constant types, also // use the default type (e.g., []byte("foo") should report string // not []byte as type for the constant "foo"). // - Keep untyped nil for untyped nil arguments. if IsInterface(T) || constArg && !isConstType(T) { final = defaultType(x.typ) } check.updateExprType(x.expr, final, true) } x.typ = T }
func (p *importer) value() constant.Value { switch tag := p.tagOrIndex(); tag { case falseTag: return constant.MakeBool(false) case trueTag: return constant.MakeBool(true) case int64Tag: return constant.MakeInt64(p.int64()) case floatTag: return p.float() case complexTag: re := p.float() im := p.float() return constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) case stringTag: return constant.MakeString(p.string()) default: panic(fmt.Sprintf("unexpected value tag %d", tag)) } }
func (p *importer) value() constant.Value { switch kind := constant.Kind(p.int()); kind { case falseTag: return constant.MakeBool(false) case trueTag: return constant.MakeBool(true) case int64Tag: return constant.MakeInt64(p.int64()) case floatTag: return p.float() case complexTag: re := p.float() im := p.float() return constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) case stringTag: return constant.MakeString(p.string()) default: panic(fmt.Sprintf("unexpected value kind %d", kind)) } }
// ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) . // FloatOrComplex = float ["i" | ("+"|"-") float "i"] . func (p *parser) parseConstValue() (val constant.Value, typ types.Type) { switch p.tok { case scanner.String: str := p.parseString() val = constant.MakeString(str) typ = types.Typ[types.UntypedString] return case scanner.Ident: b := false switch p.lit { case "false": case "true": b = true default: p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) } p.next() val = constant.MakeBool(b) typ = types.Typ[types.UntypedBool] return } sign := "" if p.tok == '-' { p.next() sign = "-" } switch p.tok { case scanner.Int: val = constant.MakeFromLiteral(sign+p.lit, token.INT, 0) if val == nil { p.error("could not parse integer literal") } p.next() if p.tok == '\'' { p.next() typ = types.Typ[types.UntypedRune] } else { typ = types.Typ[types.UntypedInt] } case scanner.Float: re := sign + p.lit p.next() var im string switch p.tok { case '+': p.next() im = p.expect(scanner.Float) case '-': p.next() im = "-" + p.expect(scanner.Float) case scanner.Ident: // re is in fact the imaginary component. Expect "i" below. im = re re = "0" default: val = constant.MakeFromLiteral(re, token.FLOAT, 0) if val == nil { p.error("could not parse float literal") } typ = types.Typ[types.UntypedFloat] return } p.expectKeyword("i") reval := constant.MakeFromLiteral(re, token.FLOAT, 0) if reval == nil { p.error("could not parse real component of complex literal") } imval := constant.MakeFromLiteral(im+"i", token.IMAG, 0) if imval == nil { p.error("could not parse imag component of complex literal") } val = constant.BinaryOp(reval, token.ADD, imval) typ = types.Typ[types.UntypedComplex] default: p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) } return }
func compare(a, b interface{}, tok token.Token) bool { vala := reflect.ValueOf(a) valb := reflect.ValueOf(b) ak := vala.Kind() bk := valb.Kind() switch { case ak >= reflect.Int && ak <= reflect.Int64: if bk >= reflect.Int && bk <= reflect.Int64 { return constant.Compare(constant.MakeInt64(vala.Int()), tok, constant.MakeInt64(valb.Int())) } if bk == reflect.Float32 || bk == reflect.Float64 { return constant.Compare(constant.MakeFloat64(float64(vala.Int())), tok, constant.MakeFloat64(valb.Float())) } if bk == reflect.String { bla, err := strconv.ParseFloat(valb.String(), 64) if err != nil { return false } return constant.Compare(constant.MakeFloat64(float64(vala.Int())), tok, constant.MakeFloat64(bla)) } case ak == reflect.Float32 || ak == reflect.Float64: if bk == reflect.Float32 || bk == reflect.Float64 { return constant.Compare(constant.MakeFloat64(vala.Float()), tok, constant.MakeFloat64(valb.Float())) } if bk >= reflect.Int && bk <= reflect.Int64 { return constant.Compare(constant.MakeFloat64(vala.Float()), tok, constant.MakeFloat64(float64(valb.Int()))) } if bk == reflect.String { bla, err := strconv.ParseFloat(valb.String(), 64) if err != nil { return false } return constant.Compare(constant.MakeFloat64(vala.Float()), tok, constant.MakeFloat64(bla)) } case ak == reflect.String: if bk == reflect.String { return constant.Compare(constant.MakeString(vala.String()), tok, constant.MakeString(valb.String())) } } if reflect.TypeOf(a).String() == "time.Time" && reflect.TypeOf(b).String() == "time.Time" { var x, y int64 x = 1 if vala.MethodByName("Equal").Call([]reflect.Value{valb})[0].Bool() { y = 1 } else if vala.MethodByName("Before").Call([]reflect.Value{valb})[0].Bool() { y = 2 } return constant.Compare(constant.MakeInt64(x), tok, constant.MakeInt64(y)) } if tok == token.EQL { return reflect.DeepEqual(a, b) } return false }
// stringConst returns a 'string' constant that evaluates to s. func stringConst(s string) *Const { return NewConst(exact.MakeString(s), tString) }
func (v *Variable) loadValueInternal(recurseLevel int, cfg LoadConfig) { if v.Unreadable != nil || v.loaded || (v.Addr == 0 && v.Base == 0) { return } v.loaded = true switch v.Kind { case reflect.Ptr, reflect.UnsafePointer: v.Len = 1 v.Children = []Variable{*v.maybeDereference()} if cfg.FollowPointers { // Don't increase the recursion level when dereferencing pointers v.Children[0].loadValueInternal(recurseLevel, cfg) } else { v.Children[0].OnlyAddr = true } case reflect.Chan: sv := v.clone() sv.RealType = resolveTypedef(&(sv.RealType.(*dwarf.ChanType).TypedefType)) sv = sv.maybeDereference() sv.loadValueInternal(0, loadFullValue) v.Children = sv.Children v.Len = sv.Len v.Base = sv.Addr case reflect.Map: if recurseLevel <= cfg.MaxVariableRecurse { v.loadMap(recurseLevel, cfg) } case reflect.String: var val string val, v.Unreadable = readStringValue(v.mem, v.Base, v.Len, cfg) v.Value = constant.MakeString(val) case reflect.Slice, reflect.Array: v.loadArrayValues(recurseLevel, cfg) case reflect.Struct: v.mem = cacheMemory(v.mem, v.Addr, int(v.RealType.Size())) t := v.RealType.(*dwarf.StructType) v.Len = int64(len(t.Field)) // Recursively call extractValue to grab // the value of all the members of the struct. if recurseLevel <= cfg.MaxVariableRecurse { v.Children = make([]Variable, 0, len(t.Field)) for i, field := range t.Field { if cfg.MaxStructFields >= 0 && len(v.Children) >= cfg.MaxStructFields { break } f, _ := v.toField(field) v.Children = append(v.Children, *f) v.Children[i].Name = field.Name v.Children[i].loadValueInternal(recurseLevel+1, cfg) } } case reflect.Interface: v.loadInterface(recurseLevel, true, cfg) case reflect.Complex64, reflect.Complex128: v.readComplex(v.RealType.(*dwarf.ComplexType).ByteSize) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: var val int64 val, v.Unreadable = readIntRaw(v.mem, v.Addr, v.RealType.(*dwarf.IntType).ByteSize) v.Value = constant.MakeInt64(val) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: var val uint64 val, v.Unreadable = readUintRaw(v.mem, v.Addr, v.RealType.(*dwarf.UintType).ByteSize) v.Value = constant.MakeUint64(val) case reflect.Bool: val, err := v.mem.readMemory(v.Addr, 1) v.Unreadable = err if err == nil { v.Value = constant.MakeBool(val[0] != 0) } case reflect.Float32, reflect.Float64: var val float64 val, v.Unreadable = v.readFloatRaw(v.RealType.(*dwarf.FloatType).ByteSize) v.Value = constant.MakeFloat64(val) case reflect.Func: v.readFunctionPtr() default: v.Unreadable = fmt.Errorf("unknown or unsupported kind: \"%s\"", v.Kind.String()) } }
func (v *Variable) loadValueInternal(recurseLevel int) { if v.Unreadable != nil || v.loaded || (v.Addr == 0 && v.base == 0) { return } v.loaded = true switch v.Kind { case reflect.Ptr, reflect.UnsafePointer: v.Len = 1 v.Children = []Variable{*v.maybeDereference()} // Don't increase the recursion level when dereferencing pointers v.Children[0].loadValueInternal(recurseLevel) case reflect.Chan: sv := v.maybeDereference() sv.loadValueInternal(recurseLevel) v.Children = sv.Children v.Len = sv.Len v.base = sv.Addr case reflect.Map: v.loadMap(recurseLevel) case reflect.String: var val string val, v.Unreadable = v.thread.readStringValue(v.base, v.Len) v.Value = constant.MakeString(val) case reflect.Slice, reflect.Array: v.loadArrayValues(recurseLevel) case reflect.Struct: t := v.RealType.(*dwarf.StructType) v.Len = int64(len(t.Field)) // Recursively call extractValue to grab // the value of all the members of the struct. if recurseLevel <= maxVariableRecurse { v.Children = make([]Variable, 0, len(t.Field)) for i, field := range t.Field { f, _ := v.toField(field) v.Children = append(v.Children, *f) v.Children[i].Name = field.Name v.Children[i].loadValueInternal(recurseLevel + 1) } } case reflect.Complex64, reflect.Complex128: v.readComplex(v.RealType.(*dwarf.ComplexType).ByteSize) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: var val int64 val, v.Unreadable = v.thread.readIntRaw(v.Addr, v.RealType.(*dwarf.IntType).ByteSize) v.Value = constant.MakeInt64(val) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: var val uint64 val, v.Unreadable = v.thread.readUintRaw(v.Addr, v.RealType.(*dwarf.UintType).ByteSize) v.Value = constant.MakeUint64(val) case reflect.Bool: val, err := v.thread.readMemory(v.Addr, 1) v.Unreadable = err if err == nil { v.Value = constant.MakeBool(val[0] != 0) } case reflect.Float32, reflect.Float64: var val float64 val, v.Unreadable = v.readFloatRaw(v.RealType.(*dwarf.FloatType).ByteSize) v.Value = constant.MakeFloat64(val) case reflect.Func: v.readFunctionPtr() default: v.Unreadable = fmt.Errorf("unknown or unsupported kind: \"%s\"", v.Kind.String()) } }
// CreateTestMainPackage creates and returns a synthetic "main" // package that runs all the tests of the supplied packages, similar // to the one that would be created by the 'go test' tool. // // It returns nil if the program contains no tests. // func (prog *Program) CreateTestMainPackage(pkgs ...*Package) *Package { pkgs, tests, benchmarks, examples := FindTests(pkgs) if len(pkgs) == 0 { return nil } testmain := &Package{ Prog: prog, Members: make(map[string]Member), values: make(map[types.Object]Value), Pkg: types.NewPackage("test$main", "main"), } // Build package's init function. init := &Function{ name: "init", Signature: new(types.Signature), Synthetic: "package initializer", Pkg: testmain, Prog: prog, } init.startBody() if testMainStartBodyHook != nil { testMainStartBodyHook(init) } // Initialize packages to test. var pkgpaths []string for _, pkg := range pkgs { var v Call v.Call.Value = pkg.init v.setType(types.NewTuple()) init.emit(&v) pkgpaths = append(pkgpaths, pkg.Pkg.Path()) } sort.Strings(pkgpaths) init.emit(new(Return)) init.finishBody() testmain.init = init testmain.Pkg.MarkComplete() testmain.Members[init.name] = init // For debugging convenience, define an unexported const // that enumerates the packages. packagesConst := types.NewConst(token.NoPos, testmain.Pkg, "packages", tString, exact.MakeString(strings.Join(pkgpaths, " "))) memberFromObject(testmain, packagesConst, nil) // Create main *types.Func and *ssa.Function mainFunc := types.NewFunc(token.NoPos, testmain.Pkg, "main", new(types.Signature)) memberFromObject(testmain, mainFunc, nil) main := testmain.Func("main") main.Synthetic = "test main function" main.startBody() if testMainStartBodyHook != nil { testMainStartBodyHook(main) } if testingPkg := prog.ImportedPackage("testing"); testingPkg != nil { testingMain := testingPkg.Func("Main") testingMainParams := testingMain.Signature.Params() // The generated code is as if compiled from this: // // func main() { // match := func(_, _ string) (bool, error) { return true, nil } // tests := []testing.InternalTest{{"TestFoo", TestFoo}, ...} // benchmarks := []testing.InternalBenchmark{...} // examples := []testing.InternalExample{...} // testing.Main(match, tests, benchmarks, examples) // } matcher := &Function{ name: "matcher", Signature: testingMainParams.At(0).Type().(*types.Signature), Synthetic: "test matcher predicate", parent: main, Pkg: testmain, Prog: prog, } main.AnonFuncs = append(main.AnonFuncs, matcher) matcher.startBody() matcher.emit(&Return{Results: []Value{vTrue, nilConst(types.Universe.Lookup("error").Type())}}) matcher.finishBody() // Emit call: testing.Main(matcher, tests, benchmarks, examples). var c Call c.Call.Value = testingMain c.Call.Args = []Value{ matcher, testMainSlice(main, tests, testingMainParams.At(1).Type()), testMainSlice(main, benchmarks, testingMainParams.At(2).Type()), testMainSlice(main, examples, testingMainParams.At(3).Type()), } emitTailCall(main, &c) } else { // The program does not import "testing", but FindTests // returned non-nil, which must mean there were Examples // but no Tests or Benchmarks. // We'll simply call them from testmain.main; this will // ensure they don't panic, but will not check any // "Output:" comments. for _, eg := range examples { var c Call c.Call.Value = eg c.setType(types.NewTuple()) main.emit(&c) } main.emit(&Return{}) main.currentBlock = nil } main.finishBody() testmain.Members["main"] = main if prog.mode&PrintPackages != 0 { printMu.Lock() testmain.WriteTo(os.Stdout) printMu.Unlock() } if prog.mode&SanityCheckFunctions != 0 { sanityCheckPackage(testmain) } prog.packages[testmain.Pkg] = testmain return testmain }