@@ -76,63 +76,162 @@ pub fn write_compressed_metadata<'tcx>(
76
76
}
77
77
}
78
78
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
+
79
100
pub fn write_idata_sections < ' tcx > (
80
101
_tcx : TyCtxt < ' tcx > ,
81
102
raw_dylibs : & [ RawDylibImports ] ,
82
103
llvm_module : & mut ModuleLlvm ,
83
104
) {
84
105
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
+ } ;
85
123
86
- let idata_7 = SmallCStr :: new ( ".idata$7" ) ;
87
- let idata_6 = SmallCStr :: new ( ".idata$6" ) ;
124
+ let mut dir_entries = vec ! [ ] ;
88
125
89
126
for raw_dylib in raw_dylibs {
90
127
debug ! ( "creating raw dylib idata secions - {:?}" , raw_dylib) ;
91
128
92
129
let name = CString :: new ( & * raw_dylib. name . as_str ( ) ) . unwrap ( ) ;
93
130
let llname = common:: bytes_in_context ( idata_llctx, name. as_bytes ( ) ) ;
94
131
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
+ ) ;
104
139
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)
113
168
}
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 ) ;
114
174
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
+ }
130
177
}
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) ;
134
219
}
135
220
}
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
+ }
136
235
}
137
236
138
237
pub struct ValueIter < ' ll > {
0 commit comments