1+ import * as types from '../frontend/types.js'
12import { tag } from '../frontend/types.js'
23import * as mods from '../frontend/modules.js'
34import { Interpreter , interpreter } from '../middle/interpret.js'
45import { MatchMethods } from '../middle/patterns.js'
56import { Inferred , Redirect } from '../middle/abstract.js'
67import { Expanded } from '../middle/expand.js'
78import { Inlined , opcount } from '../middle/inline.js'
8- import { refcounts } from '../middle/refcount.js'
9+ import { isreftype , release_method , refcounts } from '../middle/refcount.js'
910import * as wasm from './wasm.js'
1011import { irfunc } from '../wasm/ir.js'
1112import { reset , pipe , Caching , withtime } from '../utils/cache.js'
@@ -14,6 +15,7 @@ import { binding, options } from '../utils/options.js'
1415import { assigned_globals } from '../frontend/lower.js'
1516import { core } from '../middle/primitives.js'
1617import { only } from '../utils/map.js'
18+ import { Def } from '../dwarf/index.js'
1719
1820export { Pipeline , Compiler , emit , withEmit }
1921
@@ -57,10 +59,26 @@ class Pipeline implements Caching {
5759 for ( const [ b , T ] of gs ) this . sources . set ( b , T )
5860 if ( gs . size > 0 ) reset ( this )
5961 if ( opcount ( ir ) <= 0 ) return
62+ if ( em instanceof wasm . BatchEmitter ) this . destructors ( gs , em )
6063 wir = wasm . lowerwasm_globals ( wir , this . wasm . globals )
6164 em . emit ( fns , irfunc ( name , wir ) )
6265 }
6366
67+ private destructors ( gs : Map < mods . Binding , types . Type > , em : wasm . BatchEmitter ) {
68+ for ( const [ b , T ] of gs ) {
69+ if ( ! isreftype ( T ) ) continue
70+ const ids = this . wasm . globals . get ( b )
71+ const fname = `__release_global.${ ids [ 0 ] } `
72+ const code = mods . MIR ( Def ( fname ) )
73+ const value = code . push ( code . stmt ( mods . xglobal ( b ) , { type : T } ) )
74+ code . return ( code . push ( code . stmt ( new mods . Invoke ( release_method , [ value ] ) , { type : types . nil } ) ) )
75+ const wir = this . wasm . lower ( code )
76+ const func = irfunc ( fname , wir )
77+ const calls = wasm . calltree ( this . wasm , func )
78+ em . destructor ( calls , func )
79+ }
80+ }
81+
6482 async loadcommon ( emitter : wasm . Emitter , load : Loader ) : Promise < this> {
6583 const emit = ( m : mods . Method ) => {
6684 reset ( this )
@@ -117,6 +135,7 @@ class Compiler {
117135 await withEmit ( emitIR , async ( ) => { await reload ( this . pipe . sources , src , this . load ) } )
118136 reset ( this . pipe )
119137 if ( options ( ) . memcheck && em . funcs . some ( fn => fn . name . startsWith ( 'common.malloc!' ) ) ) {
138+ em . main . push ( ...em . destructors )
120139 const checks = this . pipe . defs . methods ( tag ( 'common.checkAllocations' ) )
121140 this . pipe . emit ( only ( checks ) , em )
122141 }
0 commit comments