func (p *exporter) field(f *types.Var) { if !f.IsField() { log.Fatalf("gcimporter: field expected") } p.pos(f) p.fieldName(f) p.typ(f.Type()) }
func (b *Builder) addVariable(u types.Universe, useName *types.Name, in *tc.Var) *types.Type { name := tcVarNameToName(in.String()) if useName != nil { name = *useName } out := u.Variable(name) out.Kind = types.DeclarationOf out.Underlying = b.walkType(u, nil, in.Type()) return out }
func (g *ObjcGen) genSetter(oName string, f *types.Var) { t := f.Type() g.Printf("- (void)set%s:(%s)v {\n", f.Name(), g.objcType(t)) g.Indent() g.Printf("int32_t refnum = go_seq_go_to_refnum(self._ref);\n") g.genWrite("v", f.Type(), modeRetained) g.Printf("proxy%s_%s_%s_Set(refnum, _v);\n", g.pkgPrefix, oName, f.Name()) g.genRelease("v", f.Type(), modeRetained) g.Outdent() g.Printf("}\n\n") }
func (g *ObjcGen) genGetter(oName string, f *types.Var) { t := f.Type() g.Printf("- (%s)%s {\n", g.objcType(t), objcNameReplacer(lowerFirst(f.Name()))) g.Indent() g.Printf("int32_t refnum = go_seq_go_to_refnum(self._ref);\n") g.Printf("%s r0 = ", g.cgoType(f.Type())) g.Printf("proxy%s_%s_%s_Get(refnum);\n", g.pkgPrefix, oName, f.Name()) g.genRead("_r0", "r0", f.Type(), modeRetained) g.Printf("return _r0;\n") g.Outdent() g.Printf("}\n\n") }
func (g *javaGen) genVar(o *types.Var) { if t := o.Type(); !g.isSupported(t) { g.Printf("// skipped variable %s with unsupported type: %T\n\n", o.Name(), t) return } jType := g.javaType(o.Type()) // setter g.Printf("public static native void set%s(%s v);\n", o.Name(), jType) // getter g.Printf("public static native %s get%s();\n\n", jType, o.Name()) }
func (c *funcContext) varPtrName(o *types.Var) string { if isPkgLevel(o) && o.Exported() { return c.pkgVar(o.Pkg()) + "." + o.Name() + "$ptr" } name, ok := c.p.varPtrNames[o] if !ok { name = c.newVariableWithLevel(o.Name()+"$ptr", isPkgLevel(o)) c.p.varPtrNames[o] = name } return name }
func (p *exporter) field(f *types.Var) { // anonymous fields have "" name name := "" if !f.Anonymous() { name = f.Name() } // qualifiedName will always emit the field package for // anonymous fields because "" is not an exported name. p.qualifiedName(f.Pkg(), name) p.typ(f.Type()) }
// fieldName is like qualifiedName but it doesn't record the package // for blank (_) or exported names. func (p *exporter) fieldName(f *types.Var) { name := f.Name() // anonymous field with unexported base type name: use "?" as field name // (bname != "" per spec, but we are conservative in case of errors) if f.Anonymous() { base := f.Type() if ptr, ok := base.(*types.Pointer); ok { base = ptr.Elem() } if named, ok := base.(*types.Named); ok && !named.Obj().Exported() { name = "?" } } p.string(name) if name == "?" || name != "_" && !f.Exported() { p.pkg(f.Pkg(), false) } }
func (g *goGen) genVar(o *types.Var) { // TODO(hyangah): non-struct pointer types (*int), struct type. v := fmt.Sprintf("%s.%s", g.pkg.Name(), o.Name()) // var I int // // func var_setI(out, in *seq.Buffer) g.Printf("func var_set%s(out, in *seq.Buffer) {\n", o.Name()) g.Indent() g.genRead("v", "in", o.Type()) g.Printf("%s = v\n", v) g.Outdent() g.Printf("}\n") // func var_getI(out, in *seq.Buffer) g.Printf("func var_get%s(out, in *seq.Buffer) {\n", o.Name()) g.Indent() g.genWrite(v, "out", o.Type()) g.Outdent() g.Printf("}\n") }
func checkVarValue(t *testing.T, prog *ssa.Program, pkg *ssa.Package, ref []ast.Node, obj *types.Var, expKind string, wantAddr bool) { // The prefix of all assertions messages. prefix := fmt.Sprintf("VarValue(%s @ L%d)", obj, prog.Fset.Position(ref[0].Pos()).Line) v, gotAddr := prog.VarValue(obj, pkg, ref) // Kind is the concrete type of the ssa Value. gotKind := "nil" if v != nil { gotKind = fmt.Sprintf("%T", v)[len("*ssa."):] } // fmt.Printf("%s = %v (kind %q; expect %q) wantAddr=%t gotAddr=%t\n", prefix, v, gotKind, expKind, wantAddr, gotAddr) // debugging // Check the kinds match. // "nil" indicates expected failure (e.g. optimized away). if expKind != gotKind { t.Errorf("%s concrete type == %s, want %s", prefix, gotKind, expKind) } // Check the types match. // If wantAddr, the expected type is the object's address. if v != nil { expType := obj.Type() if wantAddr { expType = types.NewPointer(expType) if !gotAddr { t.Errorf("%s: got value, want address", prefix) } } else if gotAddr { t.Errorf("%s: got address, want value", prefix) } if !types.Identical(v.Type(), expType) { t.Errorf("%s.Type() == %s, want %s", prefix, v.Type(), expType) } } }
// VarValue returns the SSA Value that corresponds to a specific // identifier denoting the source-level named variable obj. // // VarValue returns nil if a local variable was not found, perhaps // because its package was not built, the debug information was not // requested during SSA construction, or the value was optimized away. // // ref is the path to an ast.Ident (e.g. from PathEnclosingInterval), // and that ident must resolve to obj. // // pkg is the package enclosing the reference. (A reference to a var // always occurs within a function, so we need to know where to find it.) // // If the identifier is a field selector and its base expression is // non-addressable, then VarValue returns the value of that field. // For example: // func f() struct {x int} // f().x // VarValue(x) returns a *Field instruction of type int // // All other identifiers denote addressable locations (variables). // For them, VarValue may return either the variable's address or its // value, even when the expression is evaluated only for its value; the // situation is reported by isAddr, the second component of the result. // // If !isAddr, the returned value is the one associated with the // specific identifier. For example, // var x int // VarValue(x) returns Const 0 here // x = 1 // VarValue(x) returns Const 1 here // // It is not specified whether the value or the address is returned in // any particular case, as it may depend upon optimizations performed // during SSA code generation, such as registerization, constant // folding, avoidance of materialization of subexpressions, etc. // func (prog *Program) VarValue(obj *types.Var, pkg *Package, ref []ast.Node) (value Value, isAddr bool) { // All references to a var are local to some function, possibly init. fn := EnclosingFunction(pkg, ref) if fn == nil { return // e.g. def of struct field; SSA not built? } id := ref[0].(*ast.Ident) // Defining ident of a parameter? if id.Pos() == obj.Pos() { for _, param := range fn.Params { if param.Object() == obj { return param, false } } } // Other ident? for _, b := range fn.Blocks { for _, instr := range b.Instrs { if dr, ok := instr.(*DebugRef); ok { if dr.Pos() == id.Pos() { return dr.X, dr.IsAddr } } } } // Defining ident of package-level var? if v := prog.packageLevelValue(obj); v != nil { return v.(*Global), true } return // e.g. debug info not requested, or var optimized away }
func (tr *Transformer) matchWildcard(xobj *types.Var, y ast.Expr) bool { name := xobj.Name() if tr.verbose { fmt.Fprintf(os.Stderr, "%s: wildcard %s -> %s?: ", tr.fset.Position(y.Pos()), name, astString(tr.fset, y)) } // Check that y is assignable to the declared type of the param. yt := tr.info.TypeOf(y) if yt == nil { // y has no type. // Perhaps it is an *ast.Ellipsis in [...]T{}, or // an *ast.KeyValueExpr in T{k: v}. // Clearly these pseudo-expressions cannot match a // wildcard, but it would nice if we had a way to ignore // the difference between T{v} and T{k:v} for structs. return false } if !types.AssignableTo(yt, xobj.Type()) { if tr.verbose { fmt.Fprintf(os.Stderr, "%s not assignable to %s\n", yt, xobj.Type()) } return false } // A wildcard matches any expression. // If it appears multiple times in the pattern, it must match // the same expression each time. if old, ok := tr.env[name]; ok { // found existing binding tr.allowWildcards = false r := tr.matchExpr(old, y) if tr.verbose { fmt.Fprintf(os.Stderr, "%t secondary match, primary was %s\n", r, astString(tr.fset, old)) } tr.allowWildcards = true return r } if tr.verbose { fmt.Fprintf(os.Stderr, "primary match\n") } tr.env[name] = y // record binding return true }
func (c *converter) convertVar(v *gotypes.Var) *types.Var { if v == nil { return nil } if v, ok := c.converted[v]; ok { return v.(*types.Var) } ret := types.NewVar( token.Pos(v.Pos()), c.ret, v.Name(), c.convertType(v.Type()), ) c.converted[v] = ret return ret }
func (g *objcGen) genSetter(desc string, f *types.Var) { t := f.Type() if isErrorType(t) { t = types.Typ[types.String] } s := &funcSummary{ name: "set" + f.Name(), ret: "void", params: []paramInfo{{typ: t, name: "v"}}, } g.Printf("- %s {\n", s.asMethod(g)) g.Indent() g.genFunc(desc+"_DESCRIPTOR_", desc+"_FIELD_"+f.Name()+"_SET_", s, true) g.Outdent() g.Printf("}\n\n") }
func (g *objcGen) genGetter(desc string, f *types.Var) { t := f.Type() if isErrorType(t) { t = types.Typ[types.String] } s := &funcSummary{ name: lowerFirst(f.Name()), ret: g.objcType(t), retParams: []paramInfo{{typ: t, name: "ret_"}}, } g.Printf("- %s {\n", s.asMethod(g)) g.Indent() g.genFunc(desc+"_DESCRIPTOR_", desc+"_FIELD_"+f.Name()+"_GET_", s, true) g.Outdent() g.Printf("}\n\n") }
func (g *objcGen) genVarM(o *types.Var) { varDesc := fmt.Sprintf("%q", g.pkg.Name()+"."+o.Name()) objcType := g.objcType(o.Type()) // setter s1 := &funcSummary{ name: g.namePrefix + "_set" + o.Name(), ret: "void", params: []paramInfo{{typ: o.Type(), name: "v"}}, } g.Printf("void %s(%s v) {\n", s1.name, objcType) g.Indent() g.genFunc(varDesc, "1", s1, false) g.Outdent() g.Printf("}\n\n") // getter s2 := &funcSummary{ name: g.namePrefix + o.Name(), ret: objcType, retParams: []paramInfo{{typ: o.Type(), name: "ret"}}, } g.Printf("%s %s() {\n", s2.ret, s2.name) g.Indent() g.genFunc(varDesc, "2", s2, false) g.Outdent() g.Printf("}\n\n") }
// makeWrapper returns a synthetic method that delegates to the // declared method denoted by meth.Obj(), first performing any // necessary pointer indirections or field selections implied by meth. // // The resulting method's receiver type is meth.Recv(). // // This function is versatile but quite subtle! Consider the // following axes of variation when making changes: // - optional receiver indirection // - optional implicit field selections // - meth.Obj() may denote a concrete or an interface method // - the result may be a thunk or a wrapper. // // EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu) // func makeWrapper(prog *Program, sel *types.Selection) *Function { obj := sel.Obj().(*types.Func) // the declared function sig := sel.Type().(*types.Signature) // type of this wrapper var recv *types.Var // wrapper's receiver or thunk's params[0] name := obj.Name() var description string var start int // first regular param if sel.Kind() == types.MethodExpr { name += "$thunk" description = "thunk" recv = sig.Params().At(0) start = 1 } else { description = "wrapper" recv = sig.Recv() } description = fmt.Sprintf("%s for %s", description, sel.Obj()) if prog.mode&LogSource != 0 { defer logStack("make %s to (%s)", description, recv.Type())() } fn := &Function{ name: name, method: sel, object: obj, Signature: sig, Synthetic: description, Prog: prog, pos: obj.Pos(), } fn.startBody() fn.addSpilledParam(recv) createParams(fn, start) indices := sel.Index() var v Value = fn.Locals[0] // spilled receiver if isPointer(sel.Recv()) { v = emitLoad(fn, v) // For simple indirection wrappers, perform an informative nil-check: // "value method (T).f called using nil *T pointer" if len(indices) == 1 && !isPointer(recvType(obj)) { var c Call c.Call.Value = &Builtin{ name: "ssa:wrapnilchk", sig: types.NewSignature(nil, types.NewTuple(anonVar(sel.Recv()), anonVar(tString), anonVar(tString)), types.NewTuple(anonVar(sel.Recv())), false), } c.Call.Args = []Value{ v, stringConst(deref(sel.Recv()).String()), stringConst(sel.Obj().Name()), } c.setType(v.Type()) v = fn.emit(&c) } } // Invariant: v is a pointer, either // value of *A receiver param, or // address of A spilled receiver. // We use pointer arithmetic (FieldAddr possibly followed by // Load) in preference to value extraction (Field possibly // preceded by Load). v = emitImplicitSelections(fn, v, indices[:len(indices)-1]) // Invariant: v is a pointer, either // value of implicit *C field, or // address of implicit C field. var c Call if r := recvType(obj); !isInterface(r) { // concrete method if !isPointer(r) { v = emitLoad(fn, v) } c.Call.Value = prog.declaredFunc(obj) c.Call.Args = append(c.Call.Args, v) } else { c.Call.Method = obj c.Call.Value = emitLoad(fn, v) } for _, arg := range fn.Params[1:] { c.Call.Args = append(c.Call.Args, arg) } emitTailCall(fn, &c) fn.finishBody() return fn }
func (g *ObjcGen) genVarM(o *types.Var) { if t := o.Type(); !g.isSupported(t) { g.Printf("// skipped variable %s with unsupported type: %T\n\n", o.Name(), t) return } objcType := g.objcType(o.Type()) // setter g.Printf("+ (void) set%s:(%s)v {\n", o.Name(), objcType) g.Indent() g.genWrite("v", o.Type(), modeRetained) g.Printf("var_set%s_%s(_v);\n", g.pkgPrefix, o.Name()) g.genRelease("v", o.Type(), modeRetained) g.Outdent() g.Printf("}\n\n") // getter g.Printf("+ (%s) %s {\n", objcType, objcNameReplacer(lowerFirst(o.Name()))) g.Indent() g.Printf("%s r0 = ", g.cgoType(o.Type())) g.Printf("var_get%s_%s();\n", g.pkgPrefix, o.Name()) g.genRead("_r0", "r0", o.Type(), modeRetained) g.Printf("return _r0;\n") g.Outdent() g.Printf("}\n\n") }
// checkStructField checks that the field renaming will not cause // conflicts at its declaration, or ambiguity or changes to any selection. func (r *renamer) checkStructField(from *types.Var) { // Check that the struct declaration is free of field conflicts, // and field/method conflicts. // go/types offers no easy way to get from a field (or interface // method) to its declaring struct (or interface), so we must // ascend the AST. info, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos()) // path matches this pattern: // [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File] // Ascend to FieldList. var i int for { if _, ok := path[i].(*ast.FieldList); ok { break } i++ } i++ tStruct := path[i].(*ast.StructType) i++ // Ascend past parens (unlikely). for { _, ok := path[i].(*ast.ParenExpr) if !ok { break } i++ } if spec, ok := path[i].(*ast.TypeSpec); ok { // This struct is also a named type. // We must check for direct (non-promoted) field/field // and method/field conflicts. named := info.Defs[spec.Name].Type() prev, indices, _ := types.LookupFieldOrMethod(named, true, info.Pkg, r.to) if len(indices) == 1 { r.errorf(from.Pos(), "renaming this field %q to %q", from.Name(), r.to) r.errorf(prev.Pos(), "\twould conflict with this %s", objectKind(prev)) return // skip checkSelections to avoid redundant errors } } else { // This struct is not a named type. // We need only check for direct (non-promoted) field/field conflicts. T := info.Types[tStruct].Type.Underlying().(*types.Struct) for i := 0; i < T.NumFields(); i++ { if prev := T.Field(i); prev.Name() == r.to { r.errorf(from.Pos(), "renaming this field %q to %q", from.Name(), r.to) r.errorf(prev.Pos(), "\twould conflict with this field") return // skip checkSelections to avoid redundant errors } } } // Renaming an anonymous field requires renaming the type too. e.g. // print(s.T) // if we rename T to U, // type T int // this and // var s struct {T} // this must change too. if from.Anonymous() { if named, ok := from.Type().(*types.Named); ok { r.check(named.Obj()) } else if named, ok := deref(from.Type()).(*types.Named); ok { r.check(named.Obj()) } } // Check integrity of existing (field and method) selections. r.checkSelections(from) }
func (g *javaGen) genVar(o *types.Var) { jType := g.javaType(o.Type()) varDesc := fmt.Sprintf("%s.%s", g.pkg.Name(), o.Name()) // setter g.Printf("public static void set%s(%s v) {\n", o.Name(), jType) g.Indent() g.Printf("Seq in = new Seq();\n") g.Printf("Seq out = new Seq();\n") g.Printf("in.write%s;\n", seqWrite(o.Type(), "v")) g.Printf("Seq.send(%q, 1, in, out);\n", varDesc) g.Outdent() g.Printf("}\n") g.Printf("\n") // getter g.Printf("public static %s get%s() {\n", jType, o.Name()) g.Indent() g.Printf("Seq in = new Seq();\n") g.Printf("Seq out = new Seq();\n") g.Printf("Seq.send(%q, 2, in, out);\n", varDesc) g.Printf("%s ", jType) g.genRead("v", "out", o.Type()) g.Printf("return v;\n") g.Outdent() g.Printf("}\n") g.Printf("\n") }
func (g *javaGen) genJNIField(o *types.TypeName, f *types.Var) { if t := f.Type(); !g.isSupported(t) { g.Printf("// skipped field %s with unsupported type: %T\n\n", o.Name(), t) return } // setter g.Printf("JNIEXPORT void JNICALL\n") g.Printf("Java_%s_%s_00024%s_set%s(JNIEnv *env, jobject this, %s v) {\n", g.jniPkgName(), g.className(), o.Name(), f.Name(), g.jniType(f.Type())) g.Indent() g.Printf("int32_t o = go_seq_to_refnum(env, this);\n") g.genJavaToC("v", f.Type(), modeRetained) g.Printf("proxy%s_%s_%s_Set(o, _v);\n", g.pkgPrefix, o.Name(), f.Name()) g.genRelease("v", f.Type(), modeRetained) g.Outdent() g.Printf("}\n\n") // getter g.Printf("JNIEXPORT %s JNICALL\n", g.jniType(f.Type())) g.Printf("Java_%s_%s_00024%s_get%s(JNIEnv *env, jobject this) {\n", g.jniPkgName(), g.className(), o.Name(), f.Name()) g.Indent() g.Printf("int32_t o = go_seq_to_refnum(env, this);\n") g.Printf("%s r0 = ", g.cgoType(f.Type())) g.Printf("proxy%s_%s_%s_Get(o);\n", g.pkgPrefix, o.Name(), f.Name()) g.genCToJava("_r0", "r0", f.Type(), modeRetained) g.Printf("return _r0;\n") g.Outdent() g.Printf("}\n\n") }
func (g *goGen) genVar(o *types.Var) { if t := o.Type(); !g.isSupported(t) { g.Printf("// skipped variable %s with unsupported type %T\n\n", o.Name(), t) return } // TODO(hyangah): non-struct pointer types (*int), struct type. v := fmt.Sprintf("%s%s", g.pkgName(g.Pkg), o.Name()) // var I int // // func var_setI(v int) g.Printf("//export var_set%s_%s\n", g.pkgPrefix, o.Name()) g.Printf("func var_set%s_%s(v C.%s) {\n", g.pkgPrefix, o.Name(), g.cgoType(o.Type())) g.Indent() g.genRead("_v", "v", o.Type(), modeRetained) g.Printf("%s = _v\n", v) g.Outdent() g.Printf("}\n") // func var_getI() int g.Printf("//export var_get%s_%s\n", g.pkgPrefix, o.Name()) g.Printf("func var_get%s_%s() C.%s {\n", g.pkgPrefix, o.Name(), g.cgoType(o.Type())) g.Indent() g.Printf("v := %s\n", v) g.genWrite("_v", "v", o.Type(), modeRetained) g.Printf("return _v\n") g.Outdent() g.Printf("}\n") }
func (g *javaGen) genJNIVar(o *types.Var) { if t := o.Type(); !g.isSupported(t) { g.Printf("// skipped variable %s with unsupported type: %T\n\n", o.Name(), t) return } // setter g.Printf("JNIEXPORT void JNICALL\n") g.Printf("Java_%s_%s_set%s(JNIEnv *env, jclass clazz, %s v) {\n", g.jniPkgName(), g.className(), o.Name(), g.jniType(o.Type())) g.Indent() g.genJavaToC("v", o.Type(), modeRetained) g.Printf("var_set%s_%s(_v);\n", g.pkgPrefix, o.Name()) g.genRelease("v", o.Type(), modeRetained) g.Outdent() g.Printf("}\n\n") // getter g.Printf("JNIEXPORT %s JNICALL\n", g.jniType(o.Type())) g.Printf("Java_%s_%s_get%s(JNIEnv *env, jclass clazz) {\n", g.jniPkgName(), g.className(), o.Name()) g.Indent() g.Printf("%s r0 = ", g.cgoType(o.Type())) g.Printf("var_get%s_%s();\n", g.pkgPrefix, o.Name()) g.genCToJava("_r0", "r0", o.Type(), modeRetained) g.Printf("return _r0;\n") g.Outdent() g.Printf("}\n\n") }
func (p *exporter) param(v *types.Var) { p.string(v.Name()) p.typ(v.Type()) }
func newVarFrom(p *Package, v *types.Var) *Var { return newVar(p, v.Type(), v.Name(), v.Name(), p.getDoc("", v)) }
func (g *objcGen) genVarM(o *types.Var) { varDesc := fmt.Sprintf("%q", g.pkg.Name()+"."+o.Name()) objcType := g.objcType(o.Type()) // setter s1 := &funcSummary{ name: "set" + o.Name(), ret: "void", params: []paramInfo{{typ: o.Type(), name: "v"}}, } g.Printf("+ (void) %s:(%s)v {\n", s1.name, objcType) g.Indent() g.genFunc(varDesc, "1", s1, false) // false: not instance method. g.Outdent() g.Printf("}\n\n") // getter s2 := &funcSummary{ name: lowerFirst(o.Name()), ret: objcType, retParams: []paramInfo{{typ: o.Type(), name: "ret"}}, } g.Printf("+ (%s) %s {\n", s2.ret, s2.name) g.Indent() g.genFunc(varDesc, "2", s2, false) g.Outdent() g.Printf("}\n\n") }