@@ -389,8 +389,8 @@ export class Compiler extends DiagnosticEmitter {
389
389
lazyFunctions : Set < Function > = new Set ( ) ;
390
390
/** Pending class-specific instanceof helpers. */
391
391
pendingClassInstanceOf : Set < ClassPrototype > = new Set ( ) ;
392
- /** Functions potentially involving a virtual call . */
393
- virtualCalls : Set < Function > = new Set ( ) ;
392
+ /** Virtually called stubs that may have overloads . */
393
+ virtualStubs : Set < Function > = new Set ( ) ;
394
394
/** Elements currently undergoing compilation. */
395
395
pendingElements : Set < Element > = new Set ( ) ;
396
396
/** Elements, that are module exports, already processed */
@@ -450,6 +450,7 @@ export class Compiler extends DiagnosticEmitter {
450
450
var options = this . options ;
451
451
var module = this . module ;
452
452
var program = this . program ;
453
+ var resolver = this . resolver ;
453
454
var hasShadowStack = options . stackSize > 0 ; // implies runtime=incremental
454
455
455
456
// initialize lookup maps, built-ins, imports, exports, etc.
@@ -530,26 +531,37 @@ export class Compiler extends DiagnosticEmitter {
530
531
compileClassInstanceOf ( this , prototype ) ;
531
532
}
532
533
533
- // set up virtual lookup tables
534
+ // set up virtual stubs
534
535
var functionTable = this . functionTable ;
536
+ var virtualStubs = this . virtualStubs ;
535
537
for ( let i = 0 , k = functionTable . length ; i < k ; ++ i ) {
536
538
let instance = functionTable [ i ] ;
537
539
if ( instance . is ( CommonFlags . VIRTUAL ) ) {
538
540
assert ( instance . is ( CommonFlags . INSTANCE ) ) ;
539
- functionTable [ i ] = this . ensureVirtualStub ( instance ) ; // incl. varargs
540
- this . finalizeVirtualStub ( instance ) ;
541
+ functionTable [ i ] = this . ensureVirtualStub ( instance ) ; // includes varargs stub
541
542
} else if ( instance . signature . requiredParameters < instance . signature . parameterTypes . length ) {
542
543
functionTable [ i ] = this . ensureVarargsStub ( instance ) ;
543
544
}
544
545
}
545
- var virtualCalls = this . virtualCalls ;
546
- while ( virtualCalls . size ) {
547
- // finalizing a stub may discover more virtual calls, so do this in a loop
548
- for ( let _values = Set_values ( virtualCalls ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
546
+ var virtualStubsSeen = new Set < Function > ( ) ;
547
+ do {
548
+ // virtual stubs and overloads have cross-dependencies on each other, in that compiling
549
+ // either may discover the respective other. do this in a loop until no more are found.
550
+ resolver . discoveredOverload = false ;
551
+ for ( let _values = Set_values ( virtualStubs ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
549
552
let instance = unchecked ( _values [ i ] ) ;
550
- this . finalizeVirtualStub ( instance ) ;
551
- virtualCalls . delete ( instance ) ;
553
+ let overloadInstances = resolver . resolveOverloads ( instance ) ;
554
+ if ( overloadInstances ) {
555
+ for ( let i = 0 , k = overloadInstances . length ; i < k ; ++ i ) {
556
+ this . compileFunction ( overloadInstances [ i ] ) ;
557
+ }
558
+ }
559
+ virtualStubsSeen . add ( instance ) ;
552
560
}
561
+ } while ( virtualStubs . size > virtualStubsSeen . size || resolver . discoveredOverload ) ;
562
+ virtualStubsSeen . clear ( ) ;
563
+ for ( let _values = Set_values ( virtualStubs ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
564
+ this . finalizeVirtualStub ( _values [ i ] ) ;
553
565
}
554
566
555
567
// finalize runtime features
@@ -6949,7 +6961,7 @@ export class Compiler extends DiagnosticEmitter {
6949
6961
null ,
6950
6962
module . unreachable ( )
6951
6963
) ;
6952
- this . virtualCalls . add ( original ) ;
6964
+ this . virtualStubs . add ( original ) ;
6953
6965
return stub ;
6954
6966
}
6955
6967
@@ -6958,11 +6970,7 @@ export class Compiler extends DiagnosticEmitter {
6958
6970
var stub = this . ensureVirtualStub ( instance ) ;
6959
6971
if ( stub . is ( CommonFlags . COMPILED ) ) return ;
6960
6972
6961
- // Wouldn't be here if there wasn't at least one overload
6962
- var overloadPrototypes = assert ( instance . prototype . overloads ) ;
6963
-
6964
6973
assert ( instance . parent . kind == ElementKind . CLASS || instance . parent . kind == ElementKind . INTERFACE ) ;
6965
- var parentClassInstance = < Class > instance . parent ;
6966
6974
var module = this . module ;
6967
6975
var usizeType = this . options . usizeType ;
6968
6976
var sizeTypeRef = usizeType . toRef ( ) ;
@@ -6986,106 +6994,65 @@ export class Compiler extends DiagnosticEmitter {
6986
6994
TypeRef . I32
6987
6995
)
6988
6996
) ;
6989
-
6990
- // A method's `overloads` property contains its unbound overload prototypes
6991
- // so we first have to find the concrete classes it became bound to, obtain
6992
- // their bound prototypes and make sure these are resolved and compiled as
6993
- // we are going to call them conditionally based on this's class id.
6994
- for ( let _values = Set_values ( overloadPrototypes ) , i = 0 , k = _values . length ; i < k ; ++ i ) {
6995
- let unboundOverloadPrototype = _values [ i ] ;
6996
- assert ( ! unboundOverloadPrototype . isBound ) ;
6997
- let unboundOverloadParent = unboundOverloadPrototype . parent ;
6998
- let isProperty = unboundOverloadParent . kind == ElementKind . PROPERTY_PROTOTYPE ;
6999
- let classInstances : Map < string , Class > | null ;
7000
- if ( isProperty ) {
7001
- let propertyParent = ( < PropertyPrototype > unboundOverloadParent ) . parent ;
7002
- assert ( propertyParent . kind == ElementKind . CLASS_PROTOTYPE ) ;
7003
- classInstances = ( < ClassPrototype > propertyParent ) . instances ;
7004
- } else {
7005
- assert ( unboundOverloadParent . kind == ElementKind . CLASS_PROTOTYPE ) ;
7006
- classInstances = ( < ClassPrototype > unboundOverloadParent ) . instances ;
7007
- }
7008
- if ( classInstances ) {
7009
- for ( let _values = Map_values ( classInstances ) , j = 0 , l = _values . length ; j < l ; ++ j ) {
7010
- let classInstance = _values [ j ] ;
7011
- // Chcek if the parent class is a subtype of instance's class
7012
- if ( ! classInstance . isAssignableTo ( parentClassInstance ) ) continue ;
7013
- let overloadInstance : Function | null ;
7014
- if ( isProperty ) {
7015
- let boundProperty = assert ( classInstance . members ! . get ( unboundOverloadParent . name ) ) ;
7016
- assert ( boundProperty . kind == ElementKind . PROPERTY_PROTOTYPE ) ;
7017
- let boundPropertyInstance = this . resolver . resolveProperty ( < PropertyPrototype > boundProperty ) ;
7018
- if ( ! boundPropertyInstance ) continue ;
7019
- if ( instance . is ( CommonFlags . GET ) ) {
7020
- overloadInstance = boundPropertyInstance . getterInstance ;
7021
- } else {
7022
- assert ( instance . is ( CommonFlags . SET ) ) ;
7023
- overloadInstance = boundPropertyInstance . setterInstance ;
7024
- }
7025
- } else {
7026
- let boundPrototype = assert ( classInstance . members ! . get ( unboundOverloadPrototype . name ) ) ;
7027
- assert ( boundPrototype . kind == ElementKind . FUNCTION_PROTOTYPE ) ;
7028
- overloadInstance = this . resolver . resolveFunction ( < FunctionPrototype > boundPrototype , instance . typeArguments ) ;
7029
- }
7030
- if ( ! overloadInstance || ! this . compileFunction ( overloadInstance ) ) continue ;
7031
- let overloadType = overloadInstance . type ;
7032
- let originalType = instance . type ;
7033
- if ( ! overloadType . isAssignableTo ( originalType ) ) {
7034
- this . error (
7035
- DiagnosticCode . Type_0_is_not_assignable_to_type_1 ,
7036
- overloadInstance . identifierNode . range , overloadType . toString ( ) , originalType . toString ( )
7037
- ) ;
7038
- continue ;
7039
- }
7040
- // TODO: additional optional parameters are not permitted by `isAssignableTo` yet
7041
- let overloadSignature = overloadInstance . signature ;
7042
- let overloadParameterTypes = overloadSignature . parameterTypes ;
7043
- let overloadNumParameters = overloadParameterTypes . length ;
7044
- let paramExprs = new Array < ExpressionRef > ( 1 + overloadNumParameters ) ;
7045
- paramExprs [ 0 ] = module . local_get ( 0 , sizeTypeRef ) ; // this
7046
- for ( let n = 1 ; n <= numParameters ; ++ n ) {
7047
- paramExprs [ n ] = module . local_get ( n , parameterTypes [ n - 1 ] . toRef ( ) ) ;
7048
- }
7049
- let needsVarargsStub = false ;
7050
- for ( let n = numParameters ; n < overloadNumParameters ; ++ n ) {
7051
- // TODO: inline constant initializers and skip varargs stub
7052
- paramExprs [ 1 + n ] = this . makeZero ( overloadParameterTypes [ n ] , overloadInstance . declaration ) ;
7053
- needsVarargsStub = true ;
7054
- }
7055
- let calledName = needsVarargsStub
7056
- ? this . ensureVarargsStub ( overloadInstance ) . internalName
7057
- : overloadInstance . internalName ;
7058
- let returnTypeRef = overloadSignature . returnType . toRef ( ) ;
7059
- let stmts = new Array < ExpressionRef > ( ) ;
7060
- if ( needsVarargsStub ) {
7061
- // Safe to prepend since paramExprs are local.get's
7062
- stmts . push ( module . global_set ( this . ensureArgumentsLength ( ) , module . i32 ( numParameters ) ) ) ;
7063
- }
7064
- if ( returnType == Type . void ) {
7065
- stmts . push (
6997
+ var overloadInstances = this . resolver . resolveOverloads ( instance ) ;
6998
+ if ( overloadInstances ) {
6999
+ for ( let i = 0 , k = overloadInstances . length ; i < k ; ++ i ) {
7000
+ let overloadInstance = overloadInstances [ i ] ;
7001
+ if ( ! overloadInstance . is ( CommonFlags . COMPILED ) ) continue ; // errored
7002
+ let overloadType = overloadInstance . type ;
7003
+ let originalType = instance . type ;
7004
+ if ( ! overloadType . isAssignableTo ( originalType ) ) {
7005
+ this . error (
7006
+ DiagnosticCode . Type_0_is_not_assignable_to_type_1 ,
7007
+ overloadInstance . identifierNode . range , overloadType . toString ( ) , originalType . toString ( )
7008
+ ) ;
7009
+ continue ;
7010
+ }
7011
+ // TODO: additional optional parameters are not permitted by `isAssignableTo` yet
7012
+ let overloadSignature = overloadInstance . signature ;
7013
+ let overloadParameterTypes = overloadSignature . parameterTypes ;
7014
+ let overloadNumParameters = overloadParameterTypes . length ;
7015
+ let paramExprs = new Array < ExpressionRef > ( 1 + overloadNumParameters ) ;
7016
+ paramExprs [ 0 ] = module . local_get ( 0 , sizeTypeRef ) ; // this
7017
+ for ( let n = 1 ; n <= numParameters ; ++ n ) {
7018
+ paramExprs [ n ] = module . local_get ( n , parameterTypes [ n - 1 ] . toRef ( ) ) ;
7019
+ }
7020
+ let needsVarargsStub = false ;
7021
+ for ( let n = numParameters ; n < overloadNumParameters ; ++ n ) {
7022
+ // TODO: inline constant initializers and skip varargs stub
7023
+ paramExprs [ 1 + n ] = this . makeZero ( overloadParameterTypes [ n ] , overloadInstance . declaration ) ;
7024
+ needsVarargsStub = true ;
7025
+ }
7026
+ let calledName = needsVarargsStub
7027
+ ? this . ensureVarargsStub ( overloadInstance ) . internalName
7028
+ : overloadInstance . internalName ;
7029
+ let returnTypeRef = overloadSignature . returnType . toRef ( ) ;
7030
+ let stmts = new Array < ExpressionRef > ( ) ;
7031
+ if ( needsVarargsStub ) {
7032
+ // Safe to prepend since paramExprs are local.get's
7033
+ stmts . push ( module . global_set ( this . ensureArgumentsLength ( ) , module . i32 ( numParameters ) ) ) ;
7034
+ }
7035
+ if ( returnType == Type . void ) {
7036
+ stmts . push (
7037
+ module . call ( calledName , paramExprs , returnTypeRef )
7038
+ ) ;
7039
+ stmts . push (
7040
+ module . return ( )
7041
+ ) ;
7042
+ } else {
7043
+ stmts . push (
7044
+ module . return (
7066
7045
module . call ( calledName , paramExprs , returnTypeRef )
7067
- ) ;
7068
- stmts . push (
7069
- module . return ( )
7070
- ) ;
7071
- } else {
7072
- stmts . push (
7073
- module . return (
7074
- module . call ( calledName , paramExprs , returnTypeRef )
7075
- )
7076
- ) ;
7077
- }
7078
- builder . addCase ( classInstance . id , stmts ) ;
7079
- // Also alias each extendee inheriting this exact overload
7080
- let extendees = classInstance . getAllExtendees (
7081
- isProperty
7082
- ? unboundOverloadParent . name
7083
- : instance . prototype . name
7046
+ )
7084
7047
) ;
7085
- for ( let _values = Set_values ( extendees ) , a = 0 , b = _values . length ; a < b ; ++ a ) {
7086
- let extendee = _values [ a ] ;
7087
- builder . addCase ( extendee . id , stmts ) ;
7088
- }
7048
+ }
7049
+ let classInstance = assert ( overloadInstance . getClassOrInterface ( ) ) ;
7050
+ builder . addCase ( classInstance . id , stmts ) ;
7051
+ // Also alias each extendee inheriting this exact overload
7052
+ let extendees = classInstance . getAllExtendees ( instance . declaration . name . text ) ; // without get:/set:
7053
+ for ( let _values = Set_values ( extendees ) , a = 0 , b = _values . length ; a < b ; ++ a ) {
7054
+ let extendee = _values [ a ] ;
7055
+ builder . addCase ( extendee . id , stmts ) ;
7089
7056
}
7090
7057
}
7091
7058
}
0 commit comments