Example #1
0
func (f *File) methodSet(set *types.MethodSet) {
	// Build the set of things we're looking for.
	methods := make([]method, 0, set.Len())
	docs := make([]string, set.Len())
	for i := 0; i < set.Len(); i++ {
		if ast.IsExported(set.At(i).Obj().Name()) {
			m := method{
				i,
				set.At(i),
			}
			methods = append(methods, m)
		}
	}
	if len(methods) == 0 {
		return
	}
	// Collect the docs.
	for _, file := range f.allFiles {
		visitor := &methodVisitor{
			File:    file,
			methods: methods,
			docs:    docs,
		}
		ast.Walk(visitor, file.file)
		methods = visitor.methods
	}
	// Print them in order. The incoming method set is sorted by name.
	for _, doc := range docs {
		if doc != "" {
			fmt.Print(doc)
		}
	}
}
Example #2
0
// containsAllIdsOf reports whether the method identifiers of T are a
// superset of those in U.  If U belongs to an interface type, the
// result is equal to types.Assignable(T, U), but is cheaper to compute.
//
// TODO(gri): make this a method of *types.MethodSet.
//
func containsAllIdsOf(T, U *types.MethodSet) bool {
	t, tlen := 0, T.Len()
	u, ulen := 0, U.Len()
	for t < tlen && u < ulen {
		tMeth := T.At(t).Obj()
		uMeth := U.At(u).Obj()
		tId := tMeth.Id()
		uId := uMeth.Id()
		if tId > uId {
			// U has a method T lacks: fail.
			return false
		}
		if tId < uId {
			// T has a method U lacks: ignore it.
			t++
			continue
		}
		// U and T both have a method of this Id.  Check types.
		if !types.Identical(tMeth.Type(), uMeth.Type()) {
			return false // type mismatch
		}
		u++
		t++
	}
	return u == ulen
}
Example #3
0
// p != nil iff we're generatig the uncommonType for a pointer type.
func (tm *TypeMap) uncommonType(n *types.Named, p *types.Pointer) llvm.Value {
	uncommonTypeInit := llvm.ConstNull(tm.runtime.uncommonType.llvm)
	namePtr := tm.globalStringPtr(n.Obj().Name())
	uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, namePtr, []uint32{0})
	var path string
	if pkg := n.Obj().Pkg(); pkg != nil {
		path = pkg.Path()
	}
	pkgpathPtr := tm.globalStringPtr(path)
	uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, pkgpathPtr, []uint32{1})

	// If we're dealing with an interface, stop now;
	// we store interface methods on the interface
	// type.
	if _, ok := n.Underlying().(*types.Interface); ok {
		return uncommonTypeInit
	}

	var methodset, pmethodset *types.MethodSet
	if p != nil {
		methodset = tm.MethodSet(p)
	} else {
		methodset = tm.MethodSet(n)
	}

	// Store methods. All methods must be stored, not only exported ones;
	// this is to allow satisfying of interfaces with non-exported methods.
	methods := make([]llvm.Value, methodset.Len())
	for i := range methods {
		sel := methodset.At(i)
		mname := sel.Obj().Name()
		mfunc := tm.methodResolver.ResolveMethod(sel)
		ftyp := mfunc.Type().(*types.Signature)

		method := llvm.ConstNull(tm.runtime.method.llvm)
		name := tm.globalStringPtr(mname)
		name = llvm.ConstBitCast(name, tm.runtime.method.llvm.StructElementTypes()[0])
		// name
		method = llvm.ConstInsertValue(method, name, []uint32{0})
		// pkgPath
		method = llvm.ConstInsertValue(method, pkgpathPtr, []uint32{1})
		// mtyp (method type, no receiver)
		{
			ftyp := types.NewSignature(nil, nil, ftyp.Params(), ftyp.Results(), ftyp.Variadic())
			mtyp := tm.ToRuntime(ftyp)
			method = llvm.ConstInsertValue(method, mtyp, []uint32{2})
		}
		// typ (function type, with receiver)
		typ := tm.ToRuntime(ftyp)
		method = llvm.ConstInsertValue(method, typ, []uint32{3})

		// tfn (standard method/function pointer for plain method calls)
		tfn := llvm.ConstPtrToInt(mfunc.LLVMValue(), tm.target.IntPtrType())

		// ifn (single-word receiver function pointer for interface calls)
		ifn := tfn
		if p == nil {
			if tm.Sizeof(n) > int64(tm.target.PointerSize()) {
				if pmethodset == nil {
					pmethodset = tm.MethodSet(types.NewPointer(n))
				}
				pmfunc := tm.methodResolver.ResolveMethod(pmethodset.Lookup(sel.Obj().Pkg(), mname))
				ifn = llvm.ConstPtrToInt(pmfunc.LLVMValue(), tm.target.IntPtrType())
			} else if _, ok := n.Underlying().(*types.Pointer); !ok {
				// Create a wrapper function that takes an *int8,
				// and coerces to the receiver type.
				ifn = tm.interfaceFuncWrapper(mfunc.LLVMValue())
				ifn = llvm.ConstPtrToInt(ifn, tm.target.IntPtrType())
			}
		}

		method = llvm.ConstInsertValue(method, ifn, []uint32{4})
		method = llvm.ConstInsertValue(method, tfn, []uint32{5})
		methods[i] = method
	}
	methodsSliceType := tm.runtime.uncommonType.llvm.StructElementTypes()[2]
	methodsSlice := tm.makeSlice(methods, methodsSliceType)
	uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, methodsSlice, []uint32{2})
	return uncommonTypeInit
}