|
1 | 1 | use std::num::NonZeroU32;
|
2 | 2 |
|
3 | 3 | use super::{
|
4 |
| - asm::MissingMethodPatcher, cilnode::MethodKind, cilroot::BranchCond, Access, Assembly, |
5 |
| - BasicBlock, CILNode, CILRoot, ClassDef, ClassRef, Const, FieldDesc, Int, MethodDef, MethodImpl, |
6 |
| - MethodRef, Type, |
| 4 | + asm::MissingMethodPatcher, |
| 5 | + cilnode::{MethodKind, PtrCastRes}, |
| 6 | + cilroot::BranchCond, |
| 7 | + Access, Assembly, BasicBlock, CILNode, CILRoot, ClassDef, ClassRef, Const, FieldDesc, Int, |
| 8 | + MethodDef, MethodImpl, MethodRef, Type, |
7 | 9 | };
|
8 | 10 |
|
9 | 11 | pub mod atomics;
|
@@ -160,71 +162,165 @@ fn insert_rust_alloc_zeroed(asm: &mut Assembly, patcher: &mut MissingMethodPatch
|
160 | 162 | };
|
161 | 163 | patcher.insert(name, Box::new(generator));
|
162 | 164 | }
|
163 |
| -fn insert_rust_realloc(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { |
| 165 | +fn insert_rust_realloc(asm: &mut Assembly, patcher: &mut MissingMethodPatcher, use_libc: bool) { |
164 | 166 | let name = asm.alloc_string("__rust_realloc");
|
165 |
| - let generator = move |_, asm: &mut Assembly| { |
166 |
| - let ptr = asm.alloc_node(CILNode::LdArg(0)); |
167 |
| - let align = asm.alloc_node(CILNode::LdArg(2)); |
168 |
| - let new_size = asm.alloc_node(CILNode::LdArg(3)); |
169 |
| - let align = asm.alloc_node(CILNode::IntCast { |
170 |
| - input: align, |
171 |
| - target: Int::USize, |
172 |
| - extend: super::cilnode::ExtendKind::ZeroExtend, |
173 |
| - }); |
174 |
| - let new_size = asm.alloc_node(CILNode::IntCast { |
175 |
| - input: new_size, |
176 |
| - target: Int::USize, |
177 |
| - extend: super::cilnode::ExtendKind::ZeroExtend, |
178 |
| - }); |
179 |
| - let void_ptr = asm.nptr(Type::Void); |
180 |
| - let sig = asm.sig( |
181 |
| - [void_ptr, Type::Int(Int::USize), Type::Int(Int::USize)], |
182 |
| - void_ptr, |
183 |
| - ); |
184 |
| - let aligned_realloc = asm.alloc_string("AlignedRealloc"); |
185 |
| - let native_mem = ClassRef::native_mem(asm); |
186 |
| - let call_method = asm.alloc_methodref(MethodRef::new( |
187 |
| - native_mem, |
188 |
| - aligned_realloc, |
189 |
| - sig, |
190 |
| - MethodKind::Static, |
191 |
| - [].into(), |
192 |
| - )); |
193 |
| - let alloc = asm.alloc_node(CILNode::Call(Box::new(( |
194 |
| - call_method, |
195 |
| - Box::new([ptr, new_size, align]), |
196 |
| - )))); |
197 |
| - let ret = asm.alloc_root(CILRoot::Ret(alloc)); |
198 |
| - MethodImpl::MethodBody { |
199 |
| - blocks: vec![BasicBlock::new(vec![ret], 0, None)], |
200 |
| - locals: vec![], |
201 |
| - } |
202 |
| - }; |
203 |
| - patcher.insert(name, Box::new(generator)); |
| 167 | + if use_libc { |
| 168 | + let generator = move |_, asm: &mut Assembly| { |
| 169 | + let ptr = asm.alloc_node(CILNode::LdArg(0)); |
| 170 | + let void_idx = asm.alloc_type(Type::Void); |
| 171 | + let ptr = asm.alloc_node(CILNode::PtrCast( |
| 172 | + ptr, |
| 173 | + Box::new(super::cilnode::PtrCastRes::Ptr(void_idx)), |
| 174 | + )); |
| 175 | + let align = asm.alloc_node(CILNode::LdArg(2)); |
| 176 | + let new_size = asm.alloc_node(CILNode::LdArg(3)); |
| 177 | + let align = asm.alloc_node(CILNode::IntCast { |
| 178 | + input: align, |
| 179 | + target: Int::USize, |
| 180 | + extend: super::cilnode::ExtendKind::ZeroExtend, |
| 181 | + }); |
| 182 | + let new_size = asm.alloc_node(CILNode::IntCast { |
| 183 | + input: new_size, |
| 184 | + target: Int::USize, |
| 185 | + extend: super::cilnode::ExtendKind::ZeroExtend, |
| 186 | + }); |
| 187 | + let void_ptr = asm.nptr(Type::Void); |
| 188 | + let mm_malloc_sig = asm.sig([Type::Int(Int::USize), Type::Int(Int::USize)], void_ptr); |
| 189 | + // 1. call _mm_malloc |
| 190 | + let aligned_realloc = asm.alloc_string("_mm_malloc"); |
| 191 | + let main_module = asm.main_module(); |
| 192 | + let _mm_malloc = asm.alloc_methodref(MethodRef::new( |
| 193 | + *main_module, |
| 194 | + aligned_realloc, |
| 195 | + mm_malloc_sig, |
| 196 | + MethodKind::Static, |
| 197 | + [].into(), |
| 198 | + )); |
| 199 | + let _mm_malloc = asm.alloc_node(CILNode::Call(Box::new(( |
| 200 | + _mm_malloc, |
| 201 | + Box::new([new_size, align]), |
| 202 | + )))); |
| 203 | + let call_mm_malloc = asm.alloc_root(CILRoot::StLoc(0, _mm_malloc)); |
| 204 | + // 2. memcpy the buffer. |
| 205 | + let buff = asm.alloc_node(CILNode::LdLoc(0)); |
| 206 | + let copy = asm.alloc_root(CILRoot::CpBlk(Box::new((buff, ptr, new_size)))); |
| 207 | + // 3. free the old buffer |
| 208 | + let aligned_free = asm.alloc_string("_mm_free"); |
| 209 | + let mm_free_sig = asm.sig([void_ptr], Type::Void); |
| 210 | + let aligned_free = asm.alloc_methodref(MethodRef::new( |
| 211 | + *main_module, |
| 212 | + aligned_free, |
| 213 | + mm_free_sig, |
| 214 | + MethodKind::Static, |
| 215 | + [].into(), |
| 216 | + )); |
| 217 | + let call_aligned_free = |
| 218 | + asm.alloc_root(CILRoot::Call(Box::new((aligned_free, [ptr].into())))); |
| 219 | + let ret = asm.alloc_root(CILRoot::Ret(buff)); |
| 220 | + MethodImpl::MethodBody { |
| 221 | + blocks: vec![BasicBlock::new( |
| 222 | + vec![call_mm_malloc, copy, call_aligned_free, ret], |
| 223 | + 0, |
| 224 | + None, |
| 225 | + )], |
| 226 | + locals: vec![(None, asm.alloc_type(void_ptr))], |
| 227 | + } |
| 228 | + }; |
| 229 | + patcher.insert(name, Box::new(generator)); |
| 230 | + } else { |
| 231 | + let generator = move |_, asm: &mut Assembly| { |
| 232 | + let ptr = asm.alloc_node(CILNode::LdArg(0)); |
| 233 | + let align = asm.alloc_node(CILNode::LdArg(2)); |
| 234 | + let new_size = asm.alloc_node(CILNode::LdArg(3)); |
| 235 | + let align = asm.alloc_node(CILNode::IntCast { |
| 236 | + input: align, |
| 237 | + target: Int::USize, |
| 238 | + extend: super::cilnode::ExtendKind::ZeroExtend, |
| 239 | + }); |
| 240 | + let new_size = asm.alloc_node(CILNode::IntCast { |
| 241 | + input: new_size, |
| 242 | + target: Int::USize, |
| 243 | + extend: super::cilnode::ExtendKind::ZeroExtend, |
| 244 | + }); |
| 245 | + let void_ptr = asm.nptr(Type::Void); |
| 246 | + let sig = asm.sig( |
| 247 | + [void_ptr, Type::Int(Int::USize), Type::Int(Int::USize)], |
| 248 | + void_ptr, |
| 249 | + ); |
| 250 | + let aligned_realloc = asm.alloc_string("AlignedRealloc"); |
| 251 | + let native_mem = ClassRef::native_mem(asm); |
| 252 | + let call_method = asm.alloc_methodref(MethodRef::new( |
| 253 | + native_mem, |
| 254 | + aligned_realloc, |
| 255 | + sig, |
| 256 | + MethodKind::Static, |
| 257 | + [].into(), |
| 258 | + )); |
| 259 | + let alloc = asm.alloc_node(CILNode::Call(Box::new(( |
| 260 | + call_method, |
| 261 | + Box::new([ptr, new_size, align]), |
| 262 | + )))); |
| 263 | + let ret = asm.alloc_root(CILRoot::Ret(alloc)); |
| 264 | + MethodImpl::MethodBody { |
| 265 | + blocks: vec![BasicBlock::new(vec![ret], 0, None)], |
| 266 | + locals: vec![], |
| 267 | + } |
| 268 | + }; |
| 269 | + patcher.insert(name, Box::new(generator)); |
| 270 | + } |
204 | 271 | }
|
205 |
| -fn insert_rust_dealloc(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { |
| 272 | +fn insert_rust_dealloc(asm: &mut Assembly, patcher: &mut MissingMethodPatcher, use_libc: bool) { |
206 | 273 | let name = asm.alloc_string("__rust_dealloc");
|
207 |
| - let generator = move |_, asm: &mut Assembly| { |
208 |
| - let ldarg_0 = asm.alloc_node(CILNode::LdArg(0)); |
209 |
| - let void_ptr = asm.nptr(Type::Void); |
210 |
| - let sig = asm.sig([void_ptr], Type::Void); |
211 |
| - let aligned_realloc = asm.alloc_string("AlignedFree"); |
212 |
| - let native_mem = ClassRef::native_mem(asm); |
213 |
| - let call_method = asm.alloc_methodref(MethodRef::new( |
214 |
| - native_mem, |
215 |
| - aligned_realloc, |
216 |
| - sig, |
217 |
| - MethodKind::Static, |
218 |
| - [].into(), |
219 |
| - )); |
220 |
| - let alloc = asm.alloc_node(CILNode::Call(Box::new((call_method, Box::new([ldarg_0]))))); |
221 |
| - let ret = asm.alloc_root(CILRoot::Ret(alloc)); |
222 |
| - MethodImpl::MethodBody { |
223 |
| - blocks: vec![BasicBlock::new(vec![ret], 0, None)], |
224 |
| - locals: vec![], |
225 |
| - } |
226 |
| - }; |
227 |
| - patcher.insert(name, Box::new(generator)); |
| 274 | + if use_libc { |
| 275 | + let generator = move |_, asm: &mut Assembly| { |
| 276 | + let ldarg_0 = asm.alloc_node(CILNode::LdArg(0)); |
| 277 | + let void_idx = asm.alloc_type(Type::Void); |
| 278 | + let ldarg_0 = asm.alloc_node(CILNode::PtrCast( |
| 279 | + ldarg_0, |
| 280 | + Box::new(PtrCastRes::Ptr(void_idx)), |
| 281 | + )); |
| 282 | + let void_ptr = asm.nptr(Type::Void); |
| 283 | + let sig = asm.sig([void_ptr], Type::Void); |
| 284 | + let mm_free = asm.alloc_string("_mm_free"); |
| 285 | + let main_module = asm.main_module(); |
| 286 | + let call_method = asm.alloc_methodref(MethodRef::new( |
| 287 | + *main_module, |
| 288 | + mm_free, |
| 289 | + sig, |
| 290 | + MethodKind::Static, |
| 291 | + [].into(), |
| 292 | + )); |
| 293 | + let alloc = asm.alloc_node(CILNode::Call(Box::new((call_method, Box::new([ldarg_0]))))); |
| 294 | + let ret = asm.alloc_root(CILRoot::Ret(alloc)); |
| 295 | + MethodImpl::MethodBody { |
| 296 | + blocks: vec![BasicBlock::new(vec![ret], 0, None)], |
| 297 | + locals: vec![], |
| 298 | + } |
| 299 | + }; |
| 300 | + patcher.insert(name, Box::new(generator)); |
| 301 | + } else { |
| 302 | + let generator = move |_, asm: &mut Assembly| { |
| 303 | + let ldarg_0 = asm.alloc_node(CILNode::LdArg(0)); |
| 304 | + let void_ptr = asm.nptr(Type::Void); |
| 305 | + let sig = asm.sig([void_ptr], Type::Void); |
| 306 | + let aligned_realloc = asm.alloc_string("AlignedFree"); |
| 307 | + let native_mem = ClassRef::native_mem(asm); |
| 308 | + let call_method = asm.alloc_methodref(MethodRef::new( |
| 309 | + native_mem, |
| 310 | + aligned_realloc, |
| 311 | + sig, |
| 312 | + MethodKind::Static, |
| 313 | + [].into(), |
| 314 | + )); |
| 315 | + let alloc = asm.alloc_node(CILNode::Call(Box::new((call_method, Box::new([ldarg_0]))))); |
| 316 | + let ret = asm.alloc_root(CILRoot::Ret(alloc)); |
| 317 | + MethodImpl::MethodBody { |
| 318 | + blocks: vec![BasicBlock::new(vec![ret], 0, None)], |
| 319 | + locals: vec![], |
| 320 | + } |
| 321 | + }; |
| 322 | + patcher.insert(name, Box::new(generator)); |
| 323 | + } |
228 | 324 | }
|
229 | 325 | pub fn insert_exeception_stub(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
|
230 | 326 | let rust_exception = asm.alloc_string("RustException");
|
@@ -288,12 +384,11 @@ pub fn insert_exception(asm: &mut Assembly, patcher: &mut MissingMethodPatcher)
|
288 | 384 | ));
|
289 | 385 | insert_catch_unwind(asm, patcher);
|
290 | 386 | }
|
291 |
| -pub fn insert_heap(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { |
| 387 | +pub fn insert_heap(asm: &mut Assembly, patcher: &mut MissingMethodPatcher, use_libc: bool) { |
292 | 388 | insert_rust_alloc(asm, patcher);
|
293 | 389 | insert_rust_alloc_zeroed(asm, patcher);
|
294 |
| - insert_rust_realloc(asm, patcher); |
295 |
| - insert_rust_dealloc(asm, patcher); |
296 |
| - |
| 390 | + insert_rust_realloc(asm, patcher, use_libc); |
| 391 | + insert_rust_dealloc(asm, patcher, use_libc); |
297 | 392 | insert_pause(asm, patcher);
|
298 | 393 | }
|
299 | 394 |
|
|
0 commit comments