1+ use std:: cell:: RefCell ;
12use std:: collections:: BTreeMap ;
3+ use std:: mem;
24use std:: sync:: { Arc , OnceLock } ;
35
46use cranelift_codegen:: control:: ControlPlane ;
57use cranelift_codegen:: entity:: SecondaryMap ;
6- use cranelift_codegen:: ir:: { Signature , UserExternalName } ;
8+ use cranelift_codegen:: ir:: function:: FunctionParameters ;
9+ use cranelift_codegen:: ir:: { ExternalName , Signature , UserExternalName } ;
710use cranelift_codegen:: isa:: TargetIsa ;
11+ use cranelift_codegen:: { Final , FinalizedMachReloc , FinalizedRelocTarget , MachBufferFinalized } ;
812use cranelift_module:: {
913 DataId , ModuleDeclarations , ModuleError , ModuleReloc , ModuleRelocTarget , ModuleResult ,
1014} ;
@@ -18,14 +22,20 @@ pub(super) struct SerializableModule {
1822 serialized : OnceLock < Vec < u8 > > ,
1923}
2024
21- #[ derive( Debug , serde:: Serialize , serde:: Deserialize ) ]
25+ #[ derive( serde:: Serialize , serde:: Deserialize ) ]
2226struct SerializableModuleInner {
2327 declarations : ModuleDeclarations ,
24- functions : BTreeMap < FuncId , Function > ,
28+ functions : BTreeMap < FuncId , RefCell < FunctionMaybeCompiled > > ,
2529 data_objects : BTreeMap < DataId , DataDescription > ,
2630 global_asm : String ,
2731}
2832
33+ #[ derive( serde:: Serialize , serde:: Deserialize ) ]
34+ enum FunctionMaybeCompiled {
35+ Ir ( Function ) ,
36+ Compiled ( MachBufferFinalized < Final > , FunctionParameters ) ,
37+ }
38+
2939impl StableHash for SerializableModule {
3040 fn stable_hash < Hcx : StableHashCtxt > ( & self , hcx : & mut Hcx , hasher : & mut StableHasher ) {
3141 self . serialize ( ) . stable_hash ( hcx, hasher) ;
@@ -47,6 +57,7 @@ impl SerializableModule {
4757 }
4858
4959 pub ( crate ) fn serialize ( & self ) -> & [ u8 ] {
60+ self . compile_funcs ( ) ;
5061 self . serialized . get_or_init ( || postcard:: to_stdvec ( & self . inner ) . unwrap ( ) )
5162 }
5263
@@ -63,7 +74,26 @@ impl SerializableModule {
6374 self . inner . global_asm . push_str ( asm) ;
6475 }
6576
77+ fn compile_funcs ( & self ) {
78+ let mut ctx = Context :: new ( ) ;
79+ for func in self . inner . functions . values ( ) {
80+ let mut func = func. borrow_mut ( ) ;
81+ match & mut * func {
82+ FunctionMaybeCompiled :: Ir ( ir_func) => {
83+ // FIXME lazily do this during serialize/apply_to
84+ ctx. func = mem:: replace ( ir_func, Function :: new ( ) ) ;
85+ let res = ctx. compile ( & * self . isa , & mut ControlPlane :: default ( ) ) . unwrap ( ) ;
86+
87+ let buffer = res. buffer . clone ( ) ;
88+ * func = FunctionMaybeCompiled :: Compiled ( buffer, ctx. func . params ) ;
89+ }
90+ FunctionMaybeCompiled :: Compiled ( _, _) => { }
91+ }
92+ }
93+ }
94+
6695 pub ( crate ) fn apply_to ( self , module : & mut dyn Module ) -> String {
96+ self . compile_funcs ( ) ;
6797 let mut function_map: SecondaryMap < FuncId , Option < FuncId > > = SecondaryMap :: new ( ) ;
6898 let mut data_object_map: SecondaryMap < DataId , Option < DataId > > = SecondaryMap :: new ( ) ;
6999
@@ -93,41 +123,62 @@ impl SerializableModule {
93123 data_object_map[ data_id] . unwrap ( )
94124 } ;
95125
96- for ( func_id, mut func) in self . inner . functions {
126+ for ( func_id, func) in self . inner . functions {
97127 let func_id = remap_func_id ( module, & self . inner . declarations , func_id) ;
98- let user_named_funcs = func. params . user_named_funcs ( ) . clone ( ) ;
99- for ( ext_name_ref, ext_name) in user_named_funcs {
100- if ext_name. namespace == 0 {
101- func. params . reset_user_func_name (
102- ext_name_ref,
103- UserExternalName :: new (
104- 0 ,
105- remap_func_id (
106- module,
107- & self . inner . declarations ,
108- FuncId :: from_u32 ( ext_name. index ) ,
128+
129+ let FunctionMaybeCompiled :: Compiled ( buffer, params) = & * func. borrow ( ) else {
130+ unreachable ! ( )
131+ } ;
132+
133+ let remap_reloc = |reloc : & FinalizedMachReloc | {
134+ let name = match reloc. target {
135+ FinalizedRelocTarget :: ExternalName ( ExternalName :: User ( reff) ) => {
136+ let ext_name = & params. user_named_funcs ( ) [ reff] ;
137+ let ext_name = if ext_name. namespace == 0 {
138+ UserExternalName :: new (
139+ 0 ,
140+ remap_func_id (
141+ module,
142+ & self . inner . declarations ,
143+ FuncId :: from_u32 ( ext_name. index ) ,
144+ )
145+ . as_u32 ( ) ,
109146 )
110- . as_u32 ( ) ,
111- ) ,
112- ) ;
113- } else if ext_name. namespace == 1 {
114- func. params . reset_user_func_name (
115- ext_name_ref,
116- UserExternalName :: new (
117- 1 ,
118- remap_data_id (
119- module,
120- & self . inner . declarations ,
121- DataId :: from_u32 ( ext_name. index ) ,
147+ } else if ext_name. namespace == 1 {
148+ UserExternalName :: new (
149+ 1 ,
150+ remap_data_id (
151+ module,
152+ & self . inner . declarations ,
153+ DataId :: from_u32 ( ext_name. index ) ,
154+ )
155+ . as_u32 ( ) ,
122156 )
123- . as_u32 ( ) ,
124- ) ,
125- ) ;
126- } else {
127- unreachable ! ( ) ;
128- }
129- }
130- module. define_function ( func_id, & mut Context :: for_function ( func) ) . unwrap ( ) ;
157+ } else {
158+ unreachable ! ( ) ;
159+ } ;
160+ ModuleRelocTarget :: user ( ext_name. namespace , ext_name. index )
161+ }
162+ FinalizedRelocTarget :: ExternalName ( ExternalName :: TestCase ( _) ) => {
163+ unimplemented ! ( )
164+ }
165+ FinalizedRelocTarget :: ExternalName ( ExternalName :: LibCall ( libcall) ) => {
166+ ModuleRelocTarget :: LibCall ( libcall)
167+ }
168+ FinalizedRelocTarget :: ExternalName ( ExternalName :: KnownSymbol ( ks) ) => {
169+ ModuleRelocTarget :: KnownSymbol ( ks)
170+ }
171+ FinalizedRelocTarget :: Func ( offset) => {
172+ ModuleRelocTarget :: FunctionOffset ( func_id, offset)
173+ }
174+ } ;
175+ ModuleReloc { offset : reloc. offset , kind : reloc. kind , name, addend : reloc. addend }
176+ } ;
177+
178+ let relocs = buffer. relocs ( ) . iter ( ) . map ( remap_reloc) . collect :: < Vec < _ > > ( ) ;
179+ module
180+ . define_function_bytes ( func_id, buffer. alignment as u64 , buffer. data ( ) , & relocs)
181+ . unwrap ( ) ;
131182 }
132183
133184 for ( data_id, mut data) in self . inner . data_objects {
@@ -214,7 +265,7 @@ impl Module for SerializableModule {
214265 & mut self ,
215266 func_id : FuncId ,
216267 ctx : & mut Context ,
217- ctrl_plane : & mut ControlPlane ,
268+ _ctrl_plane : & mut ControlPlane ,
218269 ) -> ModuleResult < ( ) > {
219270 let decl = self . inner . declarations . get_function_decl ( func_id) ;
220271 if !decl. linkage . is_definable ( ) {
@@ -229,12 +280,9 @@ impl Module for SerializableModule {
229280 ) ) ;
230281 }
231282
232- ctx. verify_if ( & * self . isa ) ?;
233- ctx. optimize ( & * self . isa , ctrl_plane) ?;
234-
235- // FIXME compile to machine code
236-
237- self . inner . functions . insert ( func_id, ctx. func . clone ( ) ) ;
283+ self . inner
284+ . functions
285+ . insert ( func_id, RefCell :: new ( FunctionMaybeCompiled :: Ir ( ctx. func . clone ( ) ) ) ) ;
238286
239287 Ok ( ( ) )
240288 }
0 commit comments