@@ -147,7 +147,7 @@ type lowerInterfacesPass struct {
147147// emitted by the compiler as higher-level intrinsics. They need some lowering
148148// before LLVM can work on them. This is done so that a few cleanup passes can
149149// run before assigning the final type codes.
150- func LowerInterfaces (mod llvm.Module ) {
150+ func LowerInterfaces (mod llvm.Module ) error {
151151 p := & lowerInterfacesPass {
152152 mod : mod ,
153153 builder : mod .Context ().NewBuilder (),
@@ -157,11 +157,11 @@ func LowerInterfaces(mod llvm.Module) {
157157 signatures : make (map [string ]* signatureInfo ),
158158 interfaces : make (map [string ]* interfaceInfo ),
159159 }
160- p .run ()
160+ return p .run ()
161161}
162162
163163// run runs the pass itself.
164- func (p * lowerInterfacesPass ) run () {
164+ func (p * lowerInterfacesPass ) run () error {
165165 // Collect all type codes.
166166 typecodeIDPtr := llvm .PointerType (p .mod .GetTypeByName ("runtime.typecodeID" ), 0 )
167167 typeInInterfacePtr := llvm .PointerType (p .mod .GetTypeByName ("runtime.typeInInterface" ), 0 )
@@ -303,19 +303,22 @@ func (p *lowerInterfacesPass) run() {
303303 } else if len (itf .types ) == 1 {
304304 // There is only one implementation of the given type.
305305 // Call that function directly.
306- p .replaceInvokeWithCall (use , itf .types [0 ], signature )
306+ err := p .replaceInvokeWithCall (use , itf .types [0 ], signature )
307+ if err != nil {
308+ return err
309+ }
307310 } else {
308311 // There are multiple types implementing this interface, thus there
309312 // are multiple possible functions to call. Delegate calling the
310313 // right function to a special wrapper function.
311314 inttoptrs := getUses (use )
312315 if len (inttoptrs ) != 1 || inttoptrs [0 ].IsAIntToPtrInst ().IsNil () {
313- panic ( " expected exactly one inttoptr use of runtime.interfaceMethod" )
316+ return errorAt ( use , "internal error: expected exactly one inttoptr use of runtime.interfaceMethod" )
314317 }
315318 inttoptr := inttoptrs [0 ]
316319 calls := getUses (inttoptr )
317320 if len (calls ) != 1 || calls [0 ].IsACallInst ().IsNil () {
318- panic ( " expected exactly one call use of runtime.interfaceMethod" )
321+ return errorAt ( use , "internal error: expected exactly one call use of runtime.interfaceMethod" )
319322 }
320323 call := calls [0 ]
321324
@@ -369,11 +372,6 @@ func (p *lowerInterfacesPass) run() {
369372 }
370373 sort .Sort (sort .Reverse (typeSlice ))
371374
372- // A type code must fit in 16 bits.
373- if len (typeSlice ) >= 1 << 16 {
374- panic ("typecode does not fit in a uint16: too many types in this program" )
375- }
376-
377375 // Assign a type code for each type.
378376 assignTypeCodes (p .mod , typeSlice )
379377
@@ -433,6 +431,7 @@ func (p *lowerInterfacesPass) run() {
433431 typ .methodSet = llvm.Value {}
434432 }
435433 }
434+ return nil
436435}
437436
438437// addTypeMethods reads the method set of the given type info struct. It
@@ -493,10 +492,10 @@ func (p *lowerInterfacesPass) getSignature(name string) *signatureInfo {
493492// replaceInvokeWithCall replaces a runtime.interfaceMethod + inttoptr with a
494493// concrete method. This can be done when only one type implements the
495494// interface.
496- func (p * lowerInterfacesPass ) replaceInvokeWithCall (use llvm.Value , typ * typeInfo , signature * signatureInfo ) {
495+ func (p * lowerInterfacesPass ) replaceInvokeWithCall (use llvm.Value , typ * typeInfo , signature * signatureInfo ) error {
497496 inttoptrs := getUses (use )
498497 if len (inttoptrs ) != 1 || inttoptrs [0 ].IsAIntToPtrInst ().IsNil () {
499- panic ( " expected exactly one inttoptr use of runtime.interfaceMethod" )
498+ return errorAt ( use , "internal error: expected exactly one inttoptr use of runtime.interfaceMethod" )
500499 }
501500 inttoptr := inttoptrs [0 ]
502501 function := typ .getMethod (signature ).function
@@ -511,7 +510,7 @@ func (p *lowerInterfacesPass) replaceInvokeWithCall(use llvm.Value, typ *typeInf
511510 // function.
512511 for _ , call := range getUses (inttoptr ) {
513512 if call .IsACallInst ().IsNil () || call .CalledValue () != inttoptr {
514- panic ( " expected the inttoptr to be called as a method, this is not a method call" )
513+ return errorAt ( call , "internal error: expected the inttoptr to be called as a method, this is not a method call" )
515514 }
516515 operands := make ([]llvm.Value , call .OperandsCount ()- 1 )
517516 for i := range operands {
@@ -522,7 +521,7 @@ func (p *lowerInterfacesPass) replaceInvokeWithCall(use llvm.Value, typ *typeInf
522521 methodParamTypes := paramTypes [len (paramTypes )- (len (operands )- 1 ):]
523522 for i , methodParamType := range methodParamTypes {
524523 if methodParamType != operands [i + 1 ].Type () {
525- panic ( " expected method call param type and function param type to be the same" )
524+ return errorAt ( call , "internal error: expected method call param type and function param type to be the same" )
526525 }
527526 }
528527 p .builder .SetInsertPointBefore (call )
@@ -536,6 +535,7 @@ func (p *lowerInterfacesPass) replaceInvokeWithCall(use llvm.Value, typ *typeInf
536535 }
537536 inttoptr .EraseFromParentAsInstruction ()
538537 use .EraseFromParentAsInstruction ()
538+ return nil
539539}
540540
541541// getInterfaceImplementsFunc returns a function that checks whether a given
0 commit comments