@@ -24,6 +24,19 @@ fn main() {
2424 )
2525 . unwrap ( ) ;
2626 }
27+
28+ #[ cfg( feature = "jit" ) ]
29+ jit:: generate ( ) ;
30+
31+ #[ cfg( not( feature = "jit" ) ) ]
32+ {
33+ let out_dir = std:: env:: var ( "OUT_DIR" ) . unwrap ( ) ;
34+ std:: fs:: write (
35+ std:: path:: Path :: new ( & out_dir) . join ( "stencils_generated.rs" ) ,
36+ "" ,
37+ )
38+ . unwrap ( ) ;
39+ }
2740}
2841
2942#[ cfg( feature = "component-tests" ) ]
@@ -607,3 +620,79 @@ mod spec_tests {
607620 rendered. map ( |v| v. join ( ", " ) )
608621 }
609622}
623+
624+ #[ cfg( feature = "jit" ) ]
625+ mod jit {
626+ use std:: { env, fs, path:: Path } ;
627+
628+ use object:: { Object , ObjectSection , ObjectSymbol , SymbolKind } ;
629+
630+ const STENCIL_NAMES : & [ & str ] = & [ "nop" , "i32_const" , "return_" ] ;
631+
632+ pub fn generate ( ) {
633+ println ! ( "cargo::rerun-if-changed=../gabagool-stencils/src/stencils.c" ) ;
634+ println ! ( "cargo::rerun-if-changed=../gabagool-stencils/src/stencil_context.h" ) ;
635+
636+ let out_dir = env:: var ( "OUT_DIR" ) . unwrap ( ) ;
637+
638+ let objects = cc:: Build :: new ( )
639+ . file ( "../gabagool-stencils/src/stencils.c" )
640+ . include ( "../gabagool-stencils/src" )
641+ . opt_level ( 3 )
642+ . flag ( "-fno-stack-protector" )
643+ . flag ( "-fno-asynchronous-unwind-tables" )
644+ . flag ( "-fno-exceptions" )
645+ . cargo_metadata ( false )
646+ . compile_intermediates ( ) ;
647+
648+ let objects = objects. first ( ) . expect ( "expect .o file" ) ;
649+
650+ let obj_data = fs:: read ( objects) . expect ( "should exist" ) ;
651+ let obj_file = object:: File :: parse ( & * obj_data) . expect ( "should parse" ) ;
652+
653+ let text_section = obj_file
654+ . sections ( )
655+ . find ( |s| s. name ( ) == Ok ( "__text" ) || s. name ( ) == Ok ( ".text" ) )
656+ . expect ( "text section should exist" ) ;
657+
658+ let text_data = text_section. data ( ) . unwrap ( ) ;
659+ let text_addr = text_section. address ( ) ;
660+
661+ let mut sym_addrs = obj_file
662+ . symbols ( )
663+ . filter ( |s| s. kind ( ) == SymbolKind :: Text && s. section_index ( ) . is_some ( ) )
664+ . filter_map ( |s| Some ( ( s. name ( ) . ok ( ) ?, s. address ( ) ) ) )
665+ . collect :: < Vec < _ > > ( ) ;
666+
667+ sym_addrs. sort_by_key ( |& ( _, a) | a) ;
668+
669+ let mut generated = String :: new ( ) ;
670+
671+ for stencil in STENCIL_NAMES {
672+ let prefixed = format ! ( "_{}" , stencil) ;
673+ let idx = sym_addrs
674+ . iter ( )
675+ . position ( |& ( name, _addr) | name == * stencil || name == prefixed)
676+ . unwrap_or_else ( || panic ! ( "symbol {stencil} not found" ) ) ;
677+
678+ let addr = sym_addrs[ idx] . 1 ;
679+ let next_addr = sym_addrs
680+ . get ( idx + 1 )
681+ . map ( |s| s. 1 )
682+ . unwrap_or ( text_addr + text_data. len ( ) as u64 ) ;
683+
684+ let offset = ( addr - text_addr) as usize ;
685+ let size = ( next_addr - addr) as usize ;
686+
687+ let bs = text_data. get ( offset..offset + size) . expect ( "valid bytes" ) ;
688+
689+ generated. push_str ( & format ! (
690+ "pub const STENCIL_{}: &[u8] = &{:?};\n " ,
691+ stencil. to_uppercase( ) ,
692+ bs,
693+ ) ) ;
694+ }
695+
696+ fs:: write ( Path :: new ( & out_dir) . join ( "stencils_generated.rs" ) , generated) . unwrap ( ) ;
697+ }
698+ }
0 commit comments