@@ -76,63 +76,162 @@ pub fn write_compressed_metadata<'tcx>(
7676 }
7777}
7878
79+ fn new_global < ' ll > (
80+ name : & [ & str ] ,
81+ llmod : & ' ll llvm:: Module ,
82+ llvalue : & ' ll llvm:: Value ,
83+ linkage : llvm:: Linkage ,
84+ section : & str ,
85+ ) -> & ' ll llvm:: Value {
86+ let name = CString :: new ( name. join ( "." ) ) . unwrap ( ) ;
87+ let section = SmallCStr :: new ( section) ;
88+
89+ unsafe {
90+ let llglobal = llvm:: LLVMAddGlobal ( llmod, common:: val_ty ( llvalue) , name. as_ptr ( ) ) ;
91+
92+ llvm:: LLVMSetInitializer ( llglobal, llvalue) ;
93+ llvm:: LLVMRustSetLinkage ( llglobal, linkage) ;
94+ llvm:: LLVMSetSection ( llglobal, section. as_ptr ( ) ) ;
95+
96+ llglobal
97+ }
98+ }
99+
79100pub fn write_idata_sections < ' tcx > (
80101 _tcx : TyCtxt < ' tcx > ,
81102 raw_dylibs : & [ RawDylibImports ] ,
82103 llvm_module : & mut ModuleLlvm ,
83104) {
84105 let ( idata_llctx, idata_llmod) = ( & * llvm_module. llcx , llvm_module. llmod ( ) ) ;
106+ let llint32 = unsafe { llvm:: LLVMInt32TypeInContext ( idata_llctx) } ;
107+ let llbyte_ptr = unsafe { llvm:: LLVMPointerType ( llvm:: LLVMInt8TypeInContext ( idata_llctx) , 0 ) } ;
108+
109+ // import directory table types
110+ let lldir_ty = unsafe {
111+ let llint32 = llvm:: LLVMInt32TypeInContext ( idata_llctx) ;
112+ let lldir_ty_name = SmallCStr :: new ( ".win32.image_import_desc" ) ;
113+ let lldir_ty = llvm:: LLVMStructCreateNamed ( idata_llctx, lldir_ty_name. as_ptr ( ) ) ;
114+ llvm:: LLVMStructSetBody (
115+ lldir_ty,
116+ [ llbyte_ptr, llint32, llint32, llbyte_ptr, llbyte_ptr] . as_ptr ( ) ,
117+ 5 ,
118+ 0 ,
119+ ) ;
120+
121+ lldir_ty
122+ } ;
85123
86- let idata_7 = SmallCStr :: new ( ".idata$7" ) ;
87- let idata_6 = SmallCStr :: new ( ".idata$6" ) ;
124+ let mut dir_entries = vec ! [ ] ;
88125
89126 for raw_dylib in raw_dylibs {
90127 debug ! ( "creating raw dylib idata secions - {:?}" , raw_dylib) ;
91128
92129 let name = CString :: new ( & * raw_dylib. name . as_str ( ) ) . unwrap ( ) ;
93130 let llname = common:: bytes_in_context ( idata_llctx, name. as_bytes ( ) ) ;
94131
95- let buf = format ! ( "import.{}.dll_name" , raw_dylib. name) ;
96- let buf = CString :: new ( buf) . unwrap ( ) ;
97- unsafe {
98- let llglobal = llvm:: LLVMAddGlobal ( idata_llmod, common:: val_ty ( llname) , buf. as_ptr ( ) ) ;
99-
100- llvm:: LLVMSetInitializer ( llglobal, llname) ;
101- llvm:: LLVMSetGlobalConstant ( & llglobal, 1 ) ;
102- llvm:: LLVMRustSetLinkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
103- llvm:: LLVMSetSection ( llglobal, idata_7. as_ptr ( ) ) ;
132+ let lldll_name = new_global (
133+ & [ "import" , & * raw_dylib. name . as_str ( ) , "dll_name" ] ,
134+ idata_llmod,
135+ llname,
136+ llvm:: Linkage :: PrivateLinkage ,
137+ "idata$7" ,
138+ ) ;
104139
105- for item in & raw_dylib. items {
106- match item {
107- RawDylibImportName :: Name ( s) => {
108- let mut buf = vec ! [ 0 , 0 ] ;
109- buf. extend ( s. as_str ( ) . as_bytes ( ) ) ;
110-
111- if buf. len ( ) % 2 == 1 {
112- buf. push ( 0 ) ;
140+ unsafe {
141+ llvm:: LLVMSetGlobalConstant ( & lldll_name, 1 ) ;
142+
143+ let mut lookup_table = raw_dylib
144+ . items
145+ . iter ( )
146+ . map ( |item| {
147+ match item {
148+ RawDylibImportName :: Name ( s) => {
149+ let mut buf = vec ! [ 0 , 0 ] ;
150+ buf. extend ( s. as_str ( ) . as_bytes ( ) ) ;
151+
152+ if buf. len ( ) % 2 == 1 {
153+ buf. push ( 0 ) ;
154+ }
155+
156+ let llname = common:: bytes_in_context ( idata_llctx, & buf) ;
157+
158+ let llglobal = new_global (
159+ & [ "import" , & * raw_dylib. name . as_str ( ) , "fn" , & * s. as_str ( ) ] ,
160+ idata_llmod,
161+ llname,
162+ llvm:: Linkage :: PrivateLinkage ,
163+ "idata$6" ,
164+ ) ;
165+
166+ llvm:: LLVMSetGlobalConstant ( & llglobal, 1 ) ;
167+ llvm:: LLVMConstPointerCast ( llglobal, llbyte_ptr)
113168 }
169+ RawDylibImportName :: Ordinal ( o) => {
170+ //FIXME: support 32-bit targets
171+ let o = * o as u64 | 0x8000_0000_0000_0000 ;
172+ let llint64 = llvm:: LLVMInt64TypeInContext ( idata_llctx) ;
173+ let llordinal = llvm:: LLVMConstInt ( llint64, o, 0 ) ;
114174
115- let llname = common:: bytes_in_context ( idata_llctx, & buf) ;
116-
117- let global_name = format ! ( "import.{}.fn.{}" , raw_dylib. name, s) ;
118- let global_name = CString :: new ( global_name) . unwrap ( ) ;
119-
120- let llglobal = llvm:: LLVMAddGlobal (
121- idata_llmod,
122- common:: val_ty ( llname) ,
123- global_name. as_ptr ( ) ,
124- ) ;
125-
126- llvm:: LLVMSetInitializer ( llglobal, llname) ;
127- llvm:: LLVMSetGlobalConstant ( & llglobal, 1 ) ;
128- llvm:: LLVMRustSetLinkage ( llglobal, llvm:: Linkage :: PrivateLinkage ) ;
129- llvm:: LLVMSetSection ( llglobal, idata_6. as_ptr ( ) ) ;
175+ llvm:: LLVMConstIntToPtr ( llordinal, llbyte_ptr)
176+ }
130177 }
131- _ => { }
132- }
133- }
178+ } )
179+ . collect :: < Vec < _ > > ( ) ;
180+
181+ lookup_table. push ( llvm:: LLVMConstNull ( llbyte_ptr) ) ;
182+ let lltable =
183+ llvm:: LLVMConstArray ( llbyte_ptr, lookup_table. as_ptr ( ) , lookup_table. len ( ) as u32 ) ;
184+
185+ //import lookup table
186+ let ll_lookup_table = new_global (
187+ & [ "import" , & * raw_dylib. name . as_str ( ) , "desc" ] ,
188+ idata_llmod,
189+ lltable,
190+ llvm:: Linkage :: PrivateLinkage ,
191+ "idata$4" ,
192+ ) ;
193+
194+ //import address table - filled in at runtime
195+ let ll_addr_table = new_global (
196+ & [ "import" , & * raw_dylib. name . as_str ( ) , "ptr" ] ,
197+ idata_llmod,
198+ lltable,
199+ llvm:: Linkage :: PrivateLinkage ,
200+ "idata$3" ,
201+ ) ;
202+
203+ let llzero = llvm:: LLVMConstInt ( llint32, 0 , 0 ) ;
204+ let lldir_entry = llvm:: LLVMConstStructInContext (
205+ idata_llctx,
206+ [
207+ llvm:: LLVMConstPointerCast ( ll_lookup_table, llbyte_ptr) ,
208+ llzero,
209+ llzero,
210+ llvm:: LLVMConstPointerCast ( lldll_name, llbyte_ptr) ,
211+ llvm:: LLVMConstPointerCast ( ll_addr_table, llbyte_ptr) ,
212+ ]
213+ . as_ptr ( ) ,
214+ 5 ,
215+ 0 ,
216+ ) ;
217+
218+ dir_entries. push ( lldir_entry) ;
134219 }
135220 }
221+ unsafe {
222+ dir_entries. push ( llvm:: LLVMConstNull ( lldir_ty) ) ;
223+ let lldir_table =
224+ llvm:: LLVMConstArray ( lldir_ty, dir_entries. as_ptr ( ) , dir_entries. len ( ) as u32 ) ;
225+
226+ let lldir_table = new_global (
227+ & [ ".dllimport" ] ,
228+ idata_llmod,
229+ lldir_table,
230+ llvm:: Linkage :: AppendingLinkage ,
231+ "idata$2" ,
232+ ) ;
233+ llvm:: LLVMSetGlobalConstant ( & lldir_table, 1 ) ;
234+ }
136235}
137236
138237pub struct ValueIter < ' ll > {
0 commit comments