github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/transform/interface-lowering.go (about)

     1  package transform
     2  
     3  // This file provides function to lower interface intrinsics to their final LLVM
     4  // form, optimizing them in the process.
     5  //
     6  // During SSA construction, the following pseudo-call is created (see
     7  // src/runtime/interface.go):
     8  //     runtime.typeAssert(typecode, assertedType)
     9  // Additionally, interface type asserts and interface invoke functions are
    10  // declared but not defined, so the optimizer will leave them alone.
    11  //
    12  // This pass lowers these functions to their final form:
    13  //
    14  // typeAssert:
    15  //     Replaced with an icmp instruction so it can be directly used in a type
    16  //     switch.
    17  //
    18  // interface type assert:
    19  //     These functions are defined by creating a big type switch over all the
    20  //     concrete types implementing this interface.
    21  //
    22  // interface invoke:
    23  //     These functions are defined with a similar type switch, but instead of
    24  //     checking for the appropriate type, these functions will call the
    25  //     underlying method instead.
    26  //
    27  // Note that this way of implementing interfaces is very different from how the
    28  // main Go compiler implements them. For more details on how the main Go
    29  // compiler does it: https://research.swtch.com/interfaces
    30  
    31  import (
    32  	"sort"
    33  	"strings"
    34  
    35  	"github.com/tinygo-org/tinygo/compileopts"
    36  	"tinygo.org/x/go-llvm"
    37  )
    38  
    39  // signatureInfo is a Go signature of an interface method. It does not represent
    40  // any method in particular.
    41  type signatureInfo struct {
    42  	name       string
    43  	methods    []*methodInfo
    44  	interfaces []*interfaceInfo
    45  }
    46  
    47  // methodInfo describes a single method on a concrete type.
    48  type methodInfo struct {
    49  	*signatureInfo
    50  	function llvm.Value
    51  }
    52  
    53  // typeInfo describes a single concrete Go type, which can be a basic or a named
    54  // type. If it is a named type, it may have methods.
    55  type typeInfo struct {
    56  	name        string
    57  	typecode    llvm.Value
    58  	typecodeGEP llvm.Value
    59  	methodSet   llvm.Value
    60  	methods     []*methodInfo
    61  }
    62  
    63  // getMethod looks up the method on this type with the given signature and
    64  // returns it. The method must exist on this type, otherwise getMethod will
    65  // panic.
    66  func (t *typeInfo) getMethod(signature *signatureInfo) *methodInfo {
    67  	for _, method := range t.methods {
    68  		if method.signatureInfo == signature {
    69  			return method
    70  		}
    71  	}
    72  	panic("could not find method")
    73  }
    74  
    75  // interfaceInfo keeps information about a Go interface type, including all
    76  // methods it has.
    77  type interfaceInfo struct {
    78  	name       string                    // "tinygo-methods" attribute
    79  	signatures map[string]*signatureInfo // method set
    80  	types      []*typeInfo               // types this interface implements
    81  }
    82  
    83  // lowerInterfacesPass keeps state related to the interface lowering pass. The
    84  // pass has been implemented as an object type because of its complexity, but
    85  // should be seen as a regular function call (see LowerInterfaces).
    86  type lowerInterfacesPass struct {
    87  	mod         llvm.Module
    88  	config      *compileopts.Config
    89  	builder     llvm.Builder
    90  	dibuilder   *llvm.DIBuilder
    91  	difiles     map[string]llvm.Metadata
    92  	ctx         llvm.Context
    93  	uintptrType llvm.Type
    94  	targetData  llvm.TargetData
    95  	ptrType     llvm.Type
    96  	types       map[string]*typeInfo
    97  	signatures  map[string]*signatureInfo
    98  	interfaces  map[string]*interfaceInfo
    99  }
   100  
   101  // LowerInterfaces lowers all intermediate interface calls and globals that are
   102  // emitted by the compiler as higher-level intrinsics. They need some lowering
   103  // before LLVM can work on them. This is done so that a few cleanup passes can
   104  // run before assigning the final type codes.
   105  func LowerInterfaces(mod llvm.Module, config *compileopts.Config) error {
   106  	ctx := mod.Context()
   107  	targetData := llvm.NewTargetData(mod.DataLayout())
   108  	defer targetData.Dispose()
   109  	p := &lowerInterfacesPass{
   110  		mod:         mod,
   111  		config:      config,
   112  		builder:     ctx.NewBuilder(),
   113  		ctx:         ctx,
   114  		targetData:  targetData,
   115  		uintptrType: mod.Context().IntType(targetData.PointerSize() * 8),
   116  		ptrType:     llvm.PointerType(ctx.Int8Type(), 0),
   117  		types:       make(map[string]*typeInfo),
   118  		signatures:  make(map[string]*signatureInfo),
   119  		interfaces:  make(map[string]*interfaceInfo),
   120  	}
   121  	defer p.builder.Dispose()
   122  
   123  	if config.Debug() {
   124  		p.dibuilder = llvm.NewDIBuilder(mod)
   125  		defer p.dibuilder.Destroy()
   126  		defer p.dibuilder.Finalize()
   127  		p.difiles = make(map[string]llvm.Metadata)
   128  	}
   129  
   130  	return p.run()
   131  }
   132  
   133  // run runs the pass itself.
   134  func (p *lowerInterfacesPass) run() error {
   135  	if p.dibuilder != nil {
   136  		p.dibuilder.CreateCompileUnit(llvm.DICompileUnit{
   137  			Language:  0xb, // DW_LANG_C99 (0xc, off-by-one?)
   138  			File:      "<unknown>",
   139  			Dir:       "",
   140  			Producer:  "TinyGo",
   141  			Optimized: true,
   142  		})
   143  	}
   144  
   145  	// Collect all type codes.
   146  	for global := p.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
   147  		if strings.HasPrefix(global.Name(), "reflect/types.type:") {
   148  			// Retrieve Go type information based on an opaque global variable.
   149  			// Only the name of the global is relevant, the object itself is
   150  			// discarded afterwards.
   151  			name := strings.TrimPrefix(global.Name(), "reflect/types.type:")
   152  			if _, ok := p.types[name]; !ok {
   153  				t := &typeInfo{
   154  					name:     name,
   155  					typecode: global,
   156  				}
   157  				p.types[name] = t
   158  				initializer := global.Initializer()
   159  				firstField := p.builder.CreateExtractValue(initializer, 0, "")
   160  				if firstField.Type() != p.ctx.Int8Type() {
   161  					// This type has a method set at index 0. Change the GEP to
   162  					// point to index 1 (the meta byte).
   163  					t.typecodeGEP = llvm.ConstGEP(global.GlobalValueType(), global, []llvm.Value{
   164  						llvm.ConstInt(p.ctx.Int32Type(), 0, false),
   165  						llvm.ConstInt(p.ctx.Int32Type(), 1, false),
   166  					})
   167  					methodSet := stripPointerCasts(firstField)
   168  					if !strings.HasSuffix(methodSet.Name(), "$methodset") {
   169  						panic("expected method set")
   170  					}
   171  					p.addTypeMethods(t, methodSet)
   172  				} else {
   173  					// This type has no method set.
   174  					t.typecodeGEP = llvm.ConstGEP(global.GlobalValueType(), global, []llvm.Value{
   175  						llvm.ConstInt(p.ctx.Int32Type(), 0, false),
   176  						llvm.ConstInt(p.ctx.Int32Type(), 0, false),
   177  					})
   178  				}
   179  			}
   180  		}
   181  	}
   182  
   183  	// Find all interface type asserts and interface method thunks.
   184  	var interfaceAssertFunctions []llvm.Value
   185  	var interfaceInvokeFunctions []llvm.Value
   186  	for fn := p.mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {
   187  		methodsAttr := fn.GetStringAttributeAtIndex(-1, "tinygo-methods")
   188  		if methodsAttr.IsNil() {
   189  			continue
   190  		}
   191  		if !hasUses(fn) {
   192  			// Don't bother defining this function.
   193  			continue
   194  		}
   195  		p.addInterface(methodsAttr.GetStringValue())
   196  		invokeAttr := fn.GetStringAttributeAtIndex(-1, "tinygo-invoke")
   197  		if invokeAttr.IsNil() {
   198  			// Type assert.
   199  			interfaceAssertFunctions = append(interfaceAssertFunctions, fn)
   200  		} else {
   201  			// Interface invoke.
   202  			interfaceInvokeFunctions = append(interfaceInvokeFunctions, fn)
   203  		}
   204  	}
   205  
   206  	// Find all the interfaces that are implemented per type.
   207  	for _, t := range p.types {
   208  		// This type has no methods, so don't spend time calculating them.
   209  		if len(t.methods) == 0 {
   210  			continue
   211  		}
   212  
   213  		// Pre-calculate a set of signatures that this type has, for easy
   214  		// lookup/check.
   215  		typeSignatureSet := make(map[*signatureInfo]struct{})
   216  		for _, method := range t.methods {
   217  			typeSignatureSet[method.signatureInfo] = struct{}{}
   218  		}
   219  
   220  		// A set of interfaces, mapped from the name to the info.
   221  		// When the name maps to a nil pointer, one of the methods of this type
   222  		// exists in the given interface but not all of them so this type
   223  		// doesn't implement the interface.
   224  		satisfiesInterfaces := make(map[string]*interfaceInfo)
   225  
   226  		for _, method := range t.methods {
   227  			for _, itf := range method.interfaces {
   228  				if _, ok := satisfiesInterfaces[itf.name]; ok {
   229  					// interface already checked with a different method
   230  					continue
   231  				}
   232  				// check whether this interface satisfies this type
   233  				satisfies := true
   234  				for _, itfSignature := range itf.signatures {
   235  					if _, ok := typeSignatureSet[itfSignature]; !ok {
   236  						satisfiesInterfaces[itf.name] = nil // does not satisfy
   237  						satisfies = false
   238  						break
   239  					}
   240  				}
   241  				if !satisfies {
   242  					continue
   243  				}
   244  				satisfiesInterfaces[itf.name] = itf
   245  			}
   246  		}
   247  
   248  		// Add this type to all interfaces that satisfy this type.
   249  		for _, itf := range satisfiesInterfaces {
   250  			if itf == nil {
   251  				// Interface does not implement this type, but one of the
   252  				// methods on this type also exists on the interface.
   253  				continue
   254  			}
   255  			itf.types = append(itf.types, t)
   256  		}
   257  	}
   258  
   259  	// Sort all types added to the interfaces.
   260  	for _, itf := range p.interfaces {
   261  		sort.Slice(itf.types, func(i, j int) bool {
   262  			return itf.types[i].name > itf.types[j].name
   263  		})
   264  	}
   265  
   266  	// Define all interface invoke thunks.
   267  	for _, fn := range interfaceInvokeFunctions {
   268  		methodsAttr := fn.GetStringAttributeAtIndex(-1, "tinygo-methods")
   269  		invokeAttr := fn.GetStringAttributeAtIndex(-1, "tinygo-invoke")
   270  		itf := p.interfaces[methodsAttr.GetStringValue()]
   271  		signature := itf.signatures[invokeAttr.GetStringValue()]
   272  		p.defineInterfaceMethodFunc(fn, itf, signature)
   273  	}
   274  
   275  	// Define all interface type assert functions.
   276  	for _, fn := range interfaceAssertFunctions {
   277  		methodsAttr := fn.GetStringAttributeAtIndex(-1, "tinygo-methods")
   278  		itf := p.interfaces[methodsAttr.GetStringValue()]
   279  		p.defineInterfaceImplementsFunc(fn, itf)
   280  	}
   281  
   282  	// Replace each type assert with an actual type comparison or (if the type
   283  	// assert is impossible) the constant false.
   284  	llvmFalse := llvm.ConstInt(p.ctx.Int1Type(), 0, false)
   285  	for _, use := range getUses(p.mod.NamedFunction("runtime.typeAssert")) {
   286  		actualType := use.Operand(0)
   287  		name := strings.TrimPrefix(use.Operand(1).Name(), "reflect/types.typeid:")
   288  		gepOffset := uint64(0)
   289  		for strings.HasPrefix(name, "pointer:pointer:") {
   290  			// This is a type like **int, which has the name pointer:pointer:int
   291  			// but is encoded using pointer tagging.
   292  			// Calculate the pointer tag, which is emitted as a GEP instruction.
   293  			name = name[len("pointer:"):]
   294  			gepOffset++
   295  		}
   296  
   297  		if t, ok := p.types[name]; ok {
   298  			// The type exists in the program, so lower to a regular pointer
   299  			// comparison.
   300  			p.builder.SetInsertPointBefore(use)
   301  			typecodeGEP := t.typecodeGEP
   302  			if gepOffset != 0 {
   303  				// This is a tagged pointer.
   304  				typecodeGEP = llvm.ConstInBoundsGEP(p.ctx.Int8Type(), typecodeGEP, []llvm.Value{
   305  					llvm.ConstInt(p.ctx.Int64Type(), gepOffset, false),
   306  				})
   307  			}
   308  			commaOk := p.builder.CreateICmp(llvm.IntEQ, typecodeGEP, actualType, "typeassert.ok")
   309  			use.ReplaceAllUsesWith(commaOk)
   310  		} else {
   311  			// The type does not exist in the program, so lower to a constant
   312  			// false. This is trivially further optimized.
   313  			// TODO: eventually it'll be necessary to handle reflect.PtrTo and
   314  			// reflect.New calls which create new types not present in the
   315  			// original program.
   316  			use.ReplaceAllUsesWith(llvmFalse)
   317  		}
   318  		use.EraseFromParentAsInstruction()
   319  	}
   320  
   321  	// Create a sorted list of type names, for predictable iteration.
   322  	var typeNames []string
   323  	for name := range p.types {
   324  		typeNames = append(typeNames, name)
   325  	}
   326  	sort.Strings(typeNames)
   327  
   328  	// Remove all method sets, which are now unnecessary and inhibit later
   329  	// optimizations if they are left in place.
   330  	zero := llvm.ConstInt(p.ctx.Int32Type(), 0, false)
   331  	for _, name := range typeNames {
   332  		t := p.types[name]
   333  		if !t.methodSet.IsNil() {
   334  			initializer := t.typecode.Initializer()
   335  			var newInitializerFields []llvm.Value
   336  			for i := 1; i < initializer.Type().StructElementTypesCount(); i++ {
   337  				newInitializerFields = append(newInitializerFields, p.builder.CreateExtractValue(initializer, i, ""))
   338  			}
   339  			newInitializer := p.ctx.ConstStruct(newInitializerFields, false)
   340  			typecodeName := t.typecode.Name()
   341  			newGlobal := llvm.AddGlobal(p.mod, newInitializer.Type(), typecodeName+".tmp")
   342  			newGlobal.SetInitializer(newInitializer)
   343  			newGlobal.SetLinkage(t.typecode.Linkage())
   344  			newGlobal.SetGlobalConstant(true)
   345  			newGlobal.SetAlignment(t.typecode.Alignment())
   346  			for _, use := range getUses(t.typecode) {
   347  				if !use.IsAConstantExpr().IsNil() {
   348  					opcode := use.Opcode()
   349  					if opcode == llvm.GetElementPtr && use.OperandsCount() == 3 {
   350  						if use.Operand(1).ZExtValue() == 0 && use.Operand(2).ZExtValue() == 1 {
   351  							gep := p.builder.CreateInBoundsGEP(newGlobal.GlobalValueType(), newGlobal, []llvm.Value{zero, zero}, "")
   352  							use.ReplaceAllUsesWith(gep)
   353  						}
   354  					}
   355  				}
   356  			}
   357  			// Fallback.
   358  			if hasUses(t.typecode) {
   359  				negativeOffset := -int64(p.targetData.TypeAllocSize(p.ptrType))
   360  				gep := p.builder.CreateInBoundsGEP(p.ctx.Int8Type(), newGlobal, []llvm.Value{llvm.ConstInt(p.ctx.Int32Type(), uint64(negativeOffset), true)}, "")
   361  				t.typecode.ReplaceAllUsesWith(gep)
   362  			}
   363  			t.typecode.EraseFromParentAsGlobal()
   364  			newGlobal.SetName(typecodeName)
   365  			t.typecode = newGlobal
   366  		}
   367  	}
   368  
   369  	return nil
   370  }
   371  
   372  // addTypeMethods reads the method set of the given type info struct. It
   373  // retrieves the signatures and the references to the method functions
   374  // themselves for later type<->interface matching.
   375  func (p *lowerInterfacesPass) addTypeMethods(t *typeInfo, methodSet llvm.Value) {
   376  	if !t.methodSet.IsNil() {
   377  		// no methods or methods already read
   378  		return
   379  	}
   380  
   381  	// This type has methods, collect all methods of this type.
   382  	t.methodSet = methodSet
   383  	set := methodSet.Initializer() // get value from global
   384  	signatures := p.builder.CreateExtractValue(set, 1, "")
   385  	wrappers := p.builder.CreateExtractValue(set, 2, "")
   386  	numMethods := signatures.Type().ArrayLength()
   387  	for i := 0; i < numMethods; i++ {
   388  		signatureGlobal := p.builder.CreateExtractValue(signatures, i, "")
   389  		function := p.builder.CreateExtractValue(wrappers, i, "")
   390  		function = stripPointerCasts(function) // strip bitcasts
   391  		signatureName := signatureGlobal.Name()
   392  		signature := p.getSignature(signatureName)
   393  		method := &methodInfo{
   394  			function:      function,
   395  			signatureInfo: signature,
   396  		}
   397  		signature.methods = append(signature.methods, method)
   398  		t.methods = append(t.methods, method)
   399  	}
   400  }
   401  
   402  // addInterface reads information about an interface, which is the
   403  // fully-qualified name and the signatures of all methods it has.
   404  func (p *lowerInterfacesPass) addInterface(methodsString string) {
   405  	if _, ok := p.interfaces[methodsString]; ok {
   406  		return
   407  	}
   408  	t := &interfaceInfo{
   409  		name:       methodsString,
   410  		signatures: make(map[string]*signatureInfo),
   411  	}
   412  	p.interfaces[methodsString] = t
   413  	for _, method := range strings.Split(methodsString, "; ") {
   414  		signature := p.getSignature(method)
   415  		signature.interfaces = append(signature.interfaces, t)
   416  		t.signatures[method] = signature
   417  	}
   418  }
   419  
   420  // getSignature returns a new *signatureInfo, creating it if it doesn't already
   421  // exist.
   422  func (p *lowerInterfacesPass) getSignature(name string) *signatureInfo {
   423  	if _, ok := p.signatures[name]; !ok {
   424  		p.signatures[name] = &signatureInfo{
   425  			name: name,
   426  		}
   427  	}
   428  	return p.signatures[name]
   429  }
   430  
   431  // defineInterfaceImplementsFunc defines the interface type assert function. It
   432  // checks whether the given interface type (passed as an argument) is one of the
   433  // types it implements.
   434  //
   435  // The type match is implemented using an if/else chain over all possible types.
   436  // This if/else chain is easily converted to a big switch over all possible
   437  // types by the LLVM simplifycfg pass.
   438  func (p *lowerInterfacesPass) defineInterfaceImplementsFunc(fn llvm.Value, itf *interfaceInfo) {
   439  	// Create the function and function signature.
   440  	fn.Param(0).SetName("actualType")
   441  	fn.SetLinkage(llvm.InternalLinkage)
   442  	fn.SetUnnamedAddr(true)
   443  	AddStandardAttributes(fn, p.config)
   444  
   445  	// Start the if/else chain at the entry block.
   446  	entry := p.ctx.AddBasicBlock(fn, "entry")
   447  	thenBlock := p.ctx.AddBasicBlock(fn, "then")
   448  	p.builder.SetInsertPointAtEnd(entry)
   449  
   450  	if p.dibuilder != nil {
   451  		difile := p.getDIFile("<Go interface assert>")
   452  		diFuncType := p.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
   453  			File: difile,
   454  		})
   455  		difunc := p.dibuilder.CreateFunction(difile, llvm.DIFunction{
   456  			Name:         "(Go interface assert)",
   457  			File:         difile,
   458  			Line:         0,
   459  			Type:         diFuncType,
   460  			LocalToUnit:  true,
   461  			IsDefinition: true,
   462  			ScopeLine:    0,
   463  			Flags:        llvm.FlagPrototyped,
   464  			Optimized:    true,
   465  		})
   466  		fn.SetSubprogram(difunc)
   467  		p.builder.SetCurrentDebugLocation(0, 0, difunc, llvm.Metadata{})
   468  	}
   469  
   470  	// Iterate over all possible types.  Each iteration creates a new branch
   471  	// either to the 'then' block (success) or the .next block, for the next
   472  	// check.
   473  	actualType := fn.Param(0)
   474  	for _, typ := range itf.types {
   475  		nextBlock := p.ctx.AddBasicBlock(fn, typ.name+".next")
   476  		cmp := p.builder.CreateICmp(llvm.IntEQ, actualType, typ.typecodeGEP, typ.name+".icmp")
   477  		p.builder.CreateCondBr(cmp, thenBlock, nextBlock)
   478  		p.builder.SetInsertPointAtEnd(nextBlock)
   479  	}
   480  
   481  	// The builder is now inserting at the last *.next block.  Once we reach
   482  	// this point, all types have been checked so the type assert will have
   483  	// failed.
   484  	p.builder.CreateRet(llvm.ConstInt(p.ctx.Int1Type(), 0, false))
   485  
   486  	// Fill 'then' block (type assert was successful).
   487  	p.builder.SetInsertPointAtEnd(thenBlock)
   488  	p.builder.CreateRet(llvm.ConstInt(p.ctx.Int1Type(), 1, false))
   489  }
   490  
   491  // defineInterfaceMethodFunc defines this thunk by calling the concrete method
   492  // of the type that implements this interface.
   493  //
   494  // Matching the actual type is implemented using an if/else chain over all
   495  // possible types.  This is later converted to a switch statement by the LLVM
   496  // simplifycfg pass.
   497  func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *interfaceInfo, signature *signatureInfo) {
   498  	context := fn.LastParam()
   499  	actualType := llvm.PrevParam(context)
   500  	returnType := fn.GlobalValueType().ReturnType()
   501  	context.SetName("context")
   502  	actualType.SetName("actualType")
   503  	fn.SetLinkage(llvm.InternalLinkage)
   504  	fn.SetUnnamedAddr(true)
   505  	AddStandardAttributes(fn, p.config)
   506  
   507  	// Collect the params that will be passed to the functions to call.
   508  	// These params exclude the receiver (which may actually consist of multiple
   509  	// parts).
   510  	params := make([]llvm.Value, fn.ParamsCount()-3)
   511  	for i := range params {
   512  		params[i] = fn.Param(i + 1)
   513  	}
   514  	params = append(params,
   515  		llvm.Undef(p.ptrType),
   516  	)
   517  
   518  	// Start chain in the entry block.
   519  	entry := p.ctx.AddBasicBlock(fn, "entry")
   520  	p.builder.SetInsertPointAtEnd(entry)
   521  
   522  	if p.dibuilder != nil {
   523  		difile := p.getDIFile("<Go interface method>")
   524  		diFuncType := p.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
   525  			File: difile,
   526  		})
   527  		difunc := p.dibuilder.CreateFunction(difile, llvm.DIFunction{
   528  			Name:         "(Go interface method)",
   529  			File:         difile,
   530  			Line:         0,
   531  			Type:         diFuncType,
   532  			LocalToUnit:  true,
   533  			IsDefinition: true,
   534  			ScopeLine:    0,
   535  			Flags:        llvm.FlagPrototyped,
   536  			Optimized:    true,
   537  		})
   538  		fn.SetSubprogram(difunc)
   539  		p.builder.SetCurrentDebugLocation(0, 0, difunc, llvm.Metadata{})
   540  	}
   541  
   542  	// Define all possible functions that can be called.
   543  	for _, typ := range itf.types {
   544  		// Create type check (if/else).
   545  		bb := p.ctx.AddBasicBlock(fn, typ.name)
   546  		next := p.ctx.AddBasicBlock(fn, typ.name+".next")
   547  		cmp := p.builder.CreateICmp(llvm.IntEQ, actualType, typ.typecodeGEP, typ.name+".icmp")
   548  		p.builder.CreateCondBr(cmp, bb, next)
   549  
   550  		// The function we will redirect to when the interface has this type.
   551  		function := typ.getMethod(signature).function
   552  
   553  		p.builder.SetInsertPointAtEnd(bb)
   554  		receiver := fn.FirstParam()
   555  
   556  		paramTypes := []llvm.Type{receiver.Type()}
   557  		for _, param := range params {
   558  			paramTypes = append(paramTypes, param.Type())
   559  		}
   560  		functionType := llvm.FunctionType(returnType, paramTypes, false)
   561  		retval := p.builder.CreateCall(functionType, function, append([]llvm.Value{receiver}, params...), "")
   562  		if retval.Type().TypeKind() == llvm.VoidTypeKind {
   563  			p.builder.CreateRetVoid()
   564  		} else {
   565  			p.builder.CreateRet(retval)
   566  		}
   567  
   568  		// Start next comparison in the 'next' block (which is jumped to when
   569  		// the type doesn't match).
   570  		p.builder.SetInsertPointAtEnd(next)
   571  	}
   572  
   573  	// The builder now points to the last *.then block, after all types have
   574  	// been checked. Call runtime.nilPanic here.
   575  	// The only other possible value remaining is nil for nil interfaces. We
   576  	// could panic with a different message here such as "nil interface" but
   577  	// that would increase code size and "nil panic" is close enough. Most
   578  	// importantly, it avoids undefined behavior when accidentally calling a
   579  	// method on a nil interface.
   580  	nilPanic := p.mod.NamedFunction("runtime.nilPanic")
   581  	p.builder.CreateCall(nilPanic.GlobalValueType(), nilPanic, []llvm.Value{
   582  		llvm.Undef(p.ptrType),
   583  	}, "")
   584  	p.builder.CreateUnreachable()
   585  }
   586  
   587  func (p *lowerInterfacesPass) getDIFile(file string) llvm.Metadata {
   588  	difile, ok := p.difiles[file]
   589  	if !ok {
   590  		difile = p.dibuilder.CreateFile(file, "")
   591  		p.difiles[file] = difile
   592  	}
   593  	return difile
   594  }