@@ -43,7 +43,8 @@ import {
43
43
getLocalSetIndex ,
44
44
FeatureFlags ,
45
45
needsExplicitUnreachable ,
46
- getLocalSetValue
46
+ getLocalSetValue ,
47
+ RelooperBlockRef
47
48
} from "./module" ;
48
49
49
50
import {
@@ -1313,55 +1314,10 @@ export class Compiler extends DiagnosticEmitter {
1313
1314
) ;
1314
1315
// Virtual Methods
1315
1316
} else if ( instance . is ( CommonFlags . VIRTUAL ) ) {
1316
- let func : Function = instance ;
1317
- let signature = func . signature ;
1318
- let typeRef = this . ensureFunctionType (
1319
- signature . parameterTypes ,
1320
- signature . returnType ,
1321
- signature . thisType
1322
- ) ;
1323
- let loadMethodID = module . i32 ( signature . id ) ;
1324
- // let target = this.compiler.program.instancesByName("virtual");
1325
- let loadClass = module . load (
1326
- 4 ,
1327
- false ,
1328
- module . binary (
1329
- BinaryOp . SubI32 ,
1330
- module . local_get ( 0 , NativeType . I32 ) ,
1331
- module . i32 ( 8 )
1332
- ) ,
1333
- NativeType . I32
1334
- ) ;
1335
- let callVirtual = module . call (
1336
- "~virtual" ,
1337
- [ loadMethodID , loadClass ] ,
1338
- NativeType . I32
1339
- ) ;
1340
- // module.removeFunction(member.internalName);
1341
-
1342
- let callIndirect = module . call_indirect (
1343
- callVirtual ,
1344
- func . localsByIndex . map < number > ( local =>
1345
- module . local_get ( local . index , local . type . toNativeType ( ) )
1346
- ) ,
1347
-
1348
- Signature . makeSignatureString (
1349
- func . signature . parameterTypes ,
1350
- func . signature . returnType ,
1351
- func . signature . thisType
1352
- )
1353
- ) ;
1354
-
1355
- let body = module . block (
1356
- null ,
1357
- [ callIndirect ] ,
1358
- func . signature . returnType . toNativeType ( )
1359
- ) ;
1360
-
1361
1317
funcRef = module . addFunction ( instance . internalName ,
1362
1318
typeRef ,
1363
1319
null ,
1364
- body
1320
+ module . nop ( )
1365
1321
) ;
1366
1322
// imported function
1367
1323
} else {
@@ -9195,45 +9151,128 @@ export class Compiler extends DiagnosticEmitter {
9195
9151
9196
9152
compileVirtualTable ( ) : void {
9197
9153
const interfaces = this . program . interfaces ;
9198
- const methods : Map < number , Function [ ] > = new Map ( ) ;
9154
+ const instanceMethods : Map < number , Map < number , Function > > = new Map ( ) ;
9155
+ const interfaceMethods : Map < number , Function [ ] > = new Map ( ) ;
9156
+ // Gather all instatiated interface methods
9199
9157
for ( let _interface of interfaces ) {
9200
9158
for ( let func of _interface . methodInstances ) {
9201
9159
const id = func . signature . id ;
9202
- if ( ! methods . has ( id ) ) {
9203
- methods . set ( id , [ ] ) ;
9160
+ if ( ! interfaceMethods . has ( id ) ) {
9161
+ interfaceMethods . set ( id , [ ] ) ;
9162
+ }
9163
+ interfaceMethods . get ( id ) ! . push ( func ) ;
9164
+ if ( ! instanceMethods . has ( id ) ) {
9165
+ instanceMethods . set ( id , new Map ( ) ) ;
9204
9166
}
9205
- const newFuncs : Function [ ] = < Function [ ] > _interface . getFuncPrototypeImplementation ( func ) . map (
9167
+ const currentMap = instanceMethods . get ( id ) ! ;
9168
+ < Function [ ] > _interface . getFuncImplementations ( func ) . map (
9206
9169
// tslint:disable-next-line: as-types
9207
9170
funcP => {
9171
+ // TODO: Better way to pass contextual type info
9208
9172
const newFunc = this . resolver . resolveFunction ( funcP , null , func . contextualTypeArguments ) ;
9209
9173
if ( newFunc == null ) {
9210
9174
throw new Error ( `Couldn't resolve ${ funcP . name } ` ) ;
9211
9175
}
9212
9176
this . compileFunction ( newFunc ) ;
9213
9177
this . ensureFunctionTableEntry ( newFunc ) ;
9178
+ currentMap . set ( ( < Class > newFunc . parent ) . id , newFunc ) ;
9214
9179
return newFunc ;
9215
9180
}
9216
9181
) ;
9217
- methods . get ( id ) ! . concat ( newFuncs ) ;
9218
9182
}
9219
9183
}
9220
9184
9185
+ const module = this . module ;
9186
+ // Create relooper to build table
9221
9187
const relooper = this . module . createRelooper ( ) ;
9222
- debugger ;
9223
- for ( const [ id , funcs ] of methods ) {
9224
-
9225
- }
9188
+ const iFuncs : [ number , Map < number , Function > ] [ ] = Array . from ( instanceMethods . entries ( ) ) ;
9189
+ const methodBlocks : RelooperBlockRef [ ] = [ ] ;
9190
+ const getArg = ( i : i32 ) : ExpressionRef => module . local_get ( i , Type . i32 . toNativeType ( ) ) ;
9191
+ // Condition to switch on
9192
+ const first = relooper . addBlockWithSwitch ( module . nop ( ) , getArg ( 0 ) ) ;
9193
+ const zero = relooper . addBlock ( module . drop ( module . i32 ( 0 ) ) ) ;
9194
+
9195
+ for ( let index : i32 = 0 ; index < iFuncs . length ; index ++ ) {
9196
+ const [ funcID , classes ] = iFuncs [ index ] ;
9197
+ // Compile the interface methods with index
9198
+ for ( const iFunc of interfaceMethods . get ( funcID ) ! ) {
9199
+ iFunc . finalize ( module , this . compileInterfaceMethod ( iFunc , index ) ) ;
9200
+ }
9201
+ const innerBlock = relooper . addBlock ( module . nop ( ) ) ;
9202
+ relooper . addBranchForSwitch ( first , innerBlock , [ index ] ) ;
9203
+ for ( const [ classID , func ] of classes . entries ( ) ) {
9204
+ const methodCase = relooper . addBlock ( module . return ( module . i32 ( func . functionTableIndex ) ) ) ;
9205
+ const condition = module . binary ( BinaryOp . EqI32 , getArg ( 1 ) , module . i32 ( classID ) ) ;
9206
+ relooper . addBranch ( innerBlock , methodCase , condition ) ;
9207
+ }
9208
+ relooper . addBranch ( innerBlock , zero , 0 , module . unreachable ( ) ) ;
9209
+ }
9210
+ relooper . addBranchForSwitch ( first , zero , [ ] , module . unreachable ( ) ) ;
9211
+
9226
9212
var typeRef = this . ensureFunctionType ( [ Type . u32 , Type . u32 ] , Type . u32 , null ) ;
9227
9213
9214
+ const body = module . block (
9215
+ null ,
9216
+ [ relooper . renderAndDispose ( first , 0 ) , module . i32 ( 0 ) ] ,
9217
+ Type . u32 . toNativeType ( )
9218
+ ) ; ;
9219
+ const hardCoded = this . module . i32 ( 1 ) ;
9220
+ this . module . addFunction ( "~virtual" , typeRef , null , body ) ;
9228
9221
9229
- // let body = this.module.
9230
- this . module . addFunction ( "~virtual" , typeRef , null , this . module . i32 ( 1 ) ) ;
9222
+ }
9231
9223
9224
+ compileInterfaceMethod ( func : Function , methodID : i32 ) : ExpressionRef {
9225
+ const signature = func . signature ;
9226
+ const module = this . module ;
9227
+ const typeRef = this . ensureFunctionType (
9228
+ signature . parameterTypes ,
9229
+ signature . returnType ,
9230
+ signature . thisType
9231
+ ) ;
9232
+ const loadMethodID = module . i32 ( methodID ) ;
9233
+ // let target = this.compiler.program.instancesByName("virtual");
9234
+ const loadClass = module . load (
9235
+ 4 ,
9236
+ false ,
9237
+ module . binary (
9238
+ BinaryOp . SubI32 ,
9239
+ module . local_get ( 0 , NativeType . I32 ) ,
9240
+ module . i32 ( 8 )
9241
+ ) ,
9242
+ NativeType . I32
9243
+ ) ;
9244
+ const callVirtual = module . call (
9245
+ "~virtual" ,
9246
+ [ loadMethodID , loadClass ] ,
9247
+ NativeType . I32
9248
+ ) ;
9249
+ // module.removeFunction(member.internalName);
9250
+
9251
+ const callIndirect = module . call_indirect (
9252
+ callVirtual ,
9253
+ func . localsByIndex . map < number > ( local =>
9254
+ module . local_get ( local . index , local . type . toNativeType ( ) )
9255
+ ) ,
9256
+ Signature . makeSignatureString (
9257
+ func . signature . parameterTypes ,
9258
+ func . signature . returnType ,
9259
+ func . signature . thisType
9260
+ )
9261
+ ) ;
9262
+
9263
+ const body = module . block (
9264
+ null ,
9265
+ [ callIndirect ] ,
9266
+ func . signature . returnType . toNativeType ( )
9267
+ ) ;
9268
+ module . removeFunction ( func . internalName ) ;
9269
+ return module . addFunction ( func . internalName , typeRef , null , body ) ;
9232
9270
}
9233
9271
}
9234
9272
9235
9273
// helpers
9236
9274
9275
+
9237
9276
function mangleImportName (
9238
9277
element : Element ,
9239
9278
declaration : DeclarationStatement
0 commit comments