1
+ use std:: cell:: RefCell ;
1
2
use std:: collections:: BTreeMap ;
3
+ use std:: mem;
2
4
use std:: sync:: { Arc , OnceLock } ;
3
5
4
6
use cranelift_codegen:: control:: ControlPlane ;
5
7
use 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 } ;
7
10
use cranelift_codegen:: isa:: TargetIsa ;
11
+ use cranelift_codegen:: { Final , FinalizedMachReloc , FinalizedRelocTarget , MachBufferFinalized } ;
8
12
use cranelift_module:: {
9
13
DataId , ModuleDeclarations , ModuleError , ModuleReloc , ModuleRelocTarget , ModuleResult ,
10
14
} ;
@@ -18,14 +22,20 @@ pub(super) struct SerializableModule {
18
22
serialized : OnceLock < Vec < u8 > > ,
19
23
}
20
24
21
- #[ derive( Debug , serde:: Serialize , serde:: Deserialize ) ]
25
+ #[ derive( serde:: Serialize , serde:: Deserialize ) ]
22
26
struct SerializableModuleInner {
23
27
declarations : ModuleDeclarations ,
24
- functions : BTreeMap < FuncId , Function > ,
28
+ functions : BTreeMap < FuncId , RefCell < FunctionMaybeCompiled > > ,
25
29
data_objects : BTreeMap < DataId , DataDescription > ,
26
30
global_asm : String ,
27
31
}
28
32
33
+ #[ derive( serde:: Serialize , serde:: Deserialize ) ]
34
+ enum FunctionMaybeCompiled {
35
+ Ir ( Function ) ,
36
+ Compiled ( MachBufferFinalized < Final > , FunctionParameters ) ,
37
+ }
38
+
29
39
impl < CTX > HashStable < CTX > for SerializableModule {
30
40
fn hash_stable (
31
41
& self ,
@@ -52,6 +62,7 @@ impl SerializableModule {
52
62
}
53
63
54
64
pub ( crate ) fn serialize ( & self ) -> Vec < u8 > {
65
+ self . compile_funcs ( ) ;
55
66
postcard:: to_stdvec ( & self . inner ) . unwrap ( )
56
67
}
57
68
@@ -68,7 +79,26 @@ impl SerializableModule {
68
79
self . inner . global_asm . push_str ( asm) ;
69
80
}
70
81
82
+ fn compile_funcs ( & self ) {
83
+ let mut ctx = Context :: new ( ) ;
84
+ for func in self . inner . functions . values ( ) {
85
+ let mut func = func. borrow_mut ( ) ;
86
+ match & mut * func {
87
+ FunctionMaybeCompiled :: Ir ( ir_func) => {
88
+ // FIXME lazily do this during serialize/apply_to
89
+ ctx. func = mem:: replace ( ir_func, Function :: new ( ) ) ;
90
+ let res = ctx. compile ( & * self . isa , & mut ControlPlane :: default ( ) ) . unwrap ( ) ;
91
+
92
+ let buffer = res. buffer . clone ( ) ;
93
+ * func = FunctionMaybeCompiled :: Compiled ( buffer, ctx. func . params ) ;
94
+ }
95
+ FunctionMaybeCompiled :: Compiled ( _, _) => { }
96
+ }
97
+ }
98
+ }
99
+
71
100
pub ( crate ) fn apply_to ( self , module : & mut dyn Module ) -> String {
101
+ self . compile_funcs ( ) ;
72
102
let mut function_map: SecondaryMap < FuncId , Option < FuncId > > = SecondaryMap :: new ( ) ;
73
103
let mut data_object_map: SecondaryMap < DataId , Option < DataId > > = SecondaryMap :: new ( ) ;
74
104
@@ -98,41 +128,62 @@ impl SerializableModule {
98
128
data_object_map[ data_id] . unwrap ( )
99
129
} ;
100
130
101
- for ( func_id, mut func) in self . inner . functions {
131
+ for ( func_id, func) in self . inner . functions {
102
132
let func_id = remap_func_id ( module, & self . inner . declarations , func_id) ;
103
- let user_named_funcs = func. params . user_named_funcs ( ) . clone ( ) ;
104
- for ( ext_name_ref, ext_name) in user_named_funcs {
105
- if ext_name. namespace == 0 {
106
- func. params . reset_user_func_name (
107
- ext_name_ref,
108
- UserExternalName :: new (
109
- 0 ,
110
- remap_func_id (
111
- module,
112
- & self . inner . declarations ,
113
- FuncId :: from_u32 ( ext_name. index ) ,
133
+
134
+ let FunctionMaybeCompiled :: Compiled ( buffer, params) = & * func. borrow ( ) else {
135
+ unreachable ! ( )
136
+ } ;
137
+
138
+ let remap_reloc = |reloc : & FinalizedMachReloc | {
139
+ let name = match reloc. target {
140
+ FinalizedRelocTarget :: ExternalName ( ExternalName :: User ( reff) ) => {
141
+ let ext_name = & params. user_named_funcs ( ) [ reff] ;
142
+ let ext_name = if ext_name. namespace == 0 {
143
+ UserExternalName :: new (
144
+ 0 ,
145
+ remap_func_id (
146
+ module,
147
+ & self . inner . declarations ,
148
+ FuncId :: from_u32 ( ext_name. index ) ,
149
+ )
150
+ . as_u32 ( ) ,
114
151
)
115
- . as_u32 ( ) ,
116
- ) ,
117
- ) ;
118
- } else if ext_name. namespace == 1 {
119
- func. params . reset_user_func_name (
120
- ext_name_ref,
121
- UserExternalName :: new (
122
- 1 ,
123
- remap_data_id (
124
- module,
125
- & self . inner . declarations ,
126
- DataId :: from_u32 ( ext_name. index ) ,
152
+ } else if ext_name. namespace == 1 {
153
+ UserExternalName :: new (
154
+ 1 ,
155
+ remap_data_id (
156
+ module,
157
+ & self . inner . declarations ,
158
+ DataId :: from_u32 ( ext_name. index ) ,
159
+ )
160
+ . as_u32 ( ) ,
127
161
)
128
- . as_u32 ( ) ,
129
- ) ,
130
- ) ;
131
- } else {
132
- unreachable ! ( ) ;
133
- }
134
- }
135
- module. define_function ( func_id, & mut Context :: for_function ( func) ) . unwrap ( ) ;
162
+ } else {
163
+ unreachable ! ( ) ;
164
+ } ;
165
+ ModuleRelocTarget :: user ( ext_name. namespace , ext_name. index )
166
+ }
167
+ FinalizedRelocTarget :: ExternalName ( ExternalName :: TestCase ( _) ) => {
168
+ unimplemented ! ( )
169
+ }
170
+ FinalizedRelocTarget :: ExternalName ( ExternalName :: LibCall ( libcall) ) => {
171
+ ModuleRelocTarget :: LibCall ( libcall)
172
+ }
173
+ FinalizedRelocTarget :: ExternalName ( ExternalName :: KnownSymbol ( ks) ) => {
174
+ ModuleRelocTarget :: KnownSymbol ( ks)
175
+ }
176
+ FinalizedRelocTarget :: Func ( offset) => {
177
+ ModuleRelocTarget :: FunctionOffset ( func_id, offset)
178
+ }
179
+ } ;
180
+ ModuleReloc { offset : reloc. offset , kind : reloc. kind , name, addend : reloc. addend }
181
+ } ;
182
+
183
+ let relocs = buffer. relocs ( ) . iter ( ) . map ( remap_reloc) . collect :: < Vec < _ > > ( ) ;
184
+ module
185
+ . define_function_bytes ( func_id, buffer. alignment as u64 , buffer. data ( ) , & relocs)
186
+ . unwrap ( ) ;
136
187
}
137
188
138
189
for ( data_id, mut data) in self . inner . data_objects {
@@ -219,7 +270,7 @@ impl Module for SerializableModule {
219
270
& mut self ,
220
271
func_id : FuncId ,
221
272
ctx : & mut Context ,
222
- ctrl_plane : & mut ControlPlane ,
273
+ _ctrl_plane : & mut ControlPlane ,
223
274
) -> ModuleResult < ( ) > {
224
275
let decl = self . inner . declarations . get_function_decl ( func_id) ;
225
276
if !decl. linkage . is_definable ( ) {
@@ -234,12 +285,9 @@ impl Module for SerializableModule {
234
285
) ) ;
235
286
}
236
287
237
- ctx. verify_if ( & * self . isa ) ?;
238
- ctx. optimize ( & * self . isa , ctrl_plane) ?;
239
-
240
- // FIXME compile to machine code
241
-
242
- self . inner . functions . insert ( func_id, ctx. func . clone ( ) ) ;
288
+ self . inner
289
+ . functions
290
+ . insert ( func_id, RefCell :: new ( FunctionMaybeCompiled :: Ir ( ctx. func . clone ( ) ) ) ) ;
243
291
244
292
Ok ( ( ) )
245
293
}
0 commit comments