]> git.lizzy.rs Git - rust.git/commitdiff
Implement the __rust_allocate C ABI function.
authorScott Olson <scott@solson.me>
Mon, 21 Mar 2016 00:41:39 +0000 (18:41 -0600)
committerScott Olson <scott@solson.me>
Mon, 21 Mar 2016 00:41:39 +0000 (18:41 -0600)
src/interpreter.rs

index e24489931886039b296db77041814fcfd4910855..e5a593239cf6b3e62fa229ffdadf67ab5daf1b97 100644 (file)
@@ -14,6 +14,7 @@
 use std::ops::Deref;
 use std::rc::Rc;
 use syntax::ast;
+use syntax::attr;
 use syntax::codemap::DUMMY_SP;
 
 use error::{EvalError, EvalResult};
@@ -248,6 +249,9 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>)
                                 }
                             }
 
+                            Abi::C =>
+                                try!(self.call_c_abi(def_id, args, return_ptr.unwrap())),
+
                             Abi::Rust | Abi::RustCall => {
                                 // TODO(tsion): Adjust the first argument when calling a Fn or
                                 // FnMut closure via FnOnce::call_once.
@@ -295,7 +299,7 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>)
                                 TerminatorTarget::Call
                             }
 
-                            abi => panic!("can't handle function with ABI {:?}", abi),
+                            abi => panic!("can't handle function with {:?} ABI", abi),
                         }
                     }
 
@@ -397,6 +401,7 @@ fn call_intrinsic(&mut self, name: &str, substs: &'tcx Substs<'tcx>,
                 try!(self.memory.copy(src, dest, dest_size));
             }
 
+            // TODO(tsion): Mark bytes as undef.
             "uninit" => {}
 
             name => panic!("can't handle intrinsic: {}", name),
@@ -408,6 +413,34 @@ fn call_intrinsic(&mut self, name: &str, substs: &'tcx Substs<'tcx>,
         Ok(TerminatorTarget::Call)
     }
 
+    fn call_c_abi(&mut self, def_id: DefId, args: &[mir::Operand<'tcx>], dest: Pointer)
+        -> EvalResult<TerminatorTarget>
+    {
+        let name = self.tcx.item_name(def_id);
+        let attrs = self.tcx.get_attrs(def_id);
+        let link_name = match attr::first_attr_value_str_by_name(&attrs, "link_name") {
+            Some(ln) => ln.clone(),
+            None => name.as_str(),
+        };
+
+        match &link_name[..] {
+            "__rust_allocate" => {
+                let size_arg  = try!(self.eval_operand(&args[0]));
+                let _align_arg = try!(self.eval_operand(&args[1]));
+                let size = try!(self.memory.read_uint(size_arg, self.memory.pointer_size));
+                let ptr = self.memory.allocate(size as usize);
+                try!(self.memory.write_ptr(dest, ptr));
+            }
+
+            _ => panic!("can't call C ABI function: {}", link_name),
+        }
+
+        // Since we pushed no stack frame, the main loop will act
+        // as if the call just completed and it's returning to the
+        // current frame.
+        Ok(TerminatorTarget::Call)
+    }
+
     fn assign_to_aggregate(&mut self, dest: Pointer, dest_repr: &Repr, variant: usize,
                          operands: &[mir::Operand<'tcx>]) -> EvalResult<()> {
         match *dest_repr {