]> git.lizzy.rs Git - rust.git/commitdiff
Add a Rust string ostream for LLVM
authorKeegan McAllister <kmcallister@mozilla.com>
Wed, 10 Sep 2014 06:12:09 +0000 (23:12 -0700)
committerKeegan McAllister <kmcallister@mozilla.com>
Fri, 12 Sep 2014 18:46:38 +0000 (11:46 -0700)
src/librustc/middle/trans/type_.rs
src/librustc_llvm/lib.rs
src/rustllvm/RustWrapper.cpp
src/rustllvm/rustllvm.h

index 3df1ce32fc7d751fcba880fcfd77e235b07f8d1f..a6a30d6ba85ecb6d68dfe63c47b1814b6e59a472 100644 (file)
 
 use std::c_str::ToCStr;
 use std::mem;
-use std::string;
 use std::cell::RefCell;
 use std::collections::HashMap;
 
-use libc::{c_uint, c_void, free};
+use libc::c_uint;
 
 #[deriving(Clone, PartialEq, Show)]
 pub struct Type {
@@ -339,12 +338,9 @@ pub fn find_type(&self, s: &str) -> Option<Type> {
     }
 
     pub fn type_to_string(&self, ty: Type) -> String {
-        unsafe {
-            let s = llvm::LLVMTypeToString(ty.to_ref());
-            let ret = string::raw::from_buf(s as *const u8);
-            free(s as *mut c_void);
-            ret
-        }
+        llvm::build_string(|s| unsafe {
+                llvm::LLVMWriteTypeToString(ty.to_ref(), s);
+            }).expect("non-UTF8 type description from LLVM")
     }
 
     pub fn types_to_str(&self, tys: &[Type]) -> String {
@@ -353,11 +349,8 @@ pub fn types_to_str(&self, tys: &[Type]) -> String {
     }
 
     pub fn val_to_string(&self, val: ValueRef) -> String {
-        unsafe {
-            let s = llvm::LLVMValueToString(val);
-            let ret = string::raw::from_buf(s as *const u8);
-            free(s as *mut c_void);
-            ret
-        }
+        llvm::build_string(|s| unsafe {
+                llvm::LLVMWriteValueToString(val, s);
+            }).expect("nun-UTF8 value description from LLVM")
     }
 }
index ceb29ddcf8fe5e0ab2f094b88fdcbf94df034c1b..354448085b950fae809fc74acce5d109e2273857 100644 (file)
@@ -28,6 +28,8 @@
 extern crate libc;
 
 use std::c_str::ToCStr;
+use std::cell::RefCell;
+use std::{raw, mem};
 use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
 use libc::{c_longlong, c_ulonglong};
 use debuginfo::{DIBuilderRef, DIDescriptor,
@@ -1839,8 +1841,8 @@ pub fn LLVMDIBuilderCreateNameSpace(Builder: DIBuilderRef,
                                         -> ValueRef;
 
     pub fn LLVMDICompositeTypeSetTypeArray(CompositeType: ValueRef, TypeArray: ValueRef);
-    pub fn LLVMTypeToString(Type: TypeRef) -> *const c_char;
-    pub fn LLVMValueToString(value_ref: ValueRef) -> *const c_char;
+    pub fn LLVMWriteTypeToString(Type: TypeRef, s: RustStringRef);
+    pub fn LLVMWriteValueToString(value_ref: ValueRef, s: RustStringRef);
 
     pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
 
@@ -2046,6 +2048,30 @@ pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
     }
 }
 
+pub enum RustString_opaque {}
+pub type RustStringRef = *mut RustString_opaque;
+type RustStringRepr = *mut RefCell<Vec<u8>>;
+
+/// Appending to a Rust string -- used by raw_rust_string_ostream.
+#[no_mangle]
+pub unsafe extern "C" fn rust_llvm_string_write_impl(sr: RustStringRef,
+                                                     ptr: *const c_char,
+                                                     size: size_t) {
+    let slice: &[u8] = mem::transmute(raw::Slice {
+        data: ptr as *const u8,
+        len: size as uint,
+    });
+
+    let sr: RustStringRepr = mem::transmute(sr);
+    (*sr).borrow_mut().push_all(slice);
+}
+
+pub fn build_string(f: |RustStringRef|) -> Option<String> {
+    let mut buf = RefCell::new(Vec::new());
+    f(&mut buf as RustStringRepr as RustStringRef);
+    String::from_utf8(buf.unwrap()).ok()
+}
+
 // FIXME #15460 - create a public function that actually calls our
 // static LLVM symbols. Otherwise the linker will just throw llvm
 // away.  We're just calling lots of stuff until we transitively get
index cdd36d7f458a41db6bf7bdabe51b0dde94d2b8e9..5893b582cd84b139df1b27f72252cadb6cadaba6 100644 (file)
@@ -645,22 +645,18 @@ extern "C" void LLVMDICompositeTypeSetTypeArray(
 #endif
 }
 
-extern "C" char *LLVMTypeToString(LLVMTypeRef Type) {
-    std::string s;
-    llvm::raw_string_ostream os(s);
+extern "C" void LLVMWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
+    raw_rust_string_ostream os(str);
     unwrap<llvm::Type>(Type)->print(os);
-    return strdup(os.str().data());
 }
 
-extern "C" char *LLVMValueToString(LLVMValueRef Value) {
-    std::string s;
-    llvm::raw_string_ostream os(s);
+extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) {
+    raw_rust_string_ostream os(str);
     os << "(";
     unwrap<llvm::Value>(Value)->getType()->print(os);
     os << ":";
     unwrap<llvm::Value>(Value)->print(os);
     os << ")";
-    return strdup(os.str().data());
 }
 
 #if LLVM_VERSION_MINOR >= 5
index 5722eea48d7d83e56c9f27fcc888c0707ba70152..92f94b0e8e552675e4bd1cab10fb61a8941f1bc3 100644 (file)
 #endif
 
 void LLVMRustSetLastError(const char*);
+
+typedef struct OpaqueRustString *RustStringRef;
+
+extern "C" void
+rust_llvm_string_write_impl(RustStringRef str, const char *ptr, size_t size);
+
+class raw_rust_string_ostream : public llvm::raw_ostream  {
+    RustStringRef str;
+    uint64_t pos;
+
+    void write_impl(const char *ptr, size_t size) override {
+        rust_llvm_string_write_impl(str, ptr, size);
+        pos += size;
+    }
+
+    uint64_t current_pos() const override {
+        return pos;
+    }
+
+public:
+    explicit raw_rust_string_ostream(RustStringRef str)
+        : str(str), pos(0) { }
+
+    ~raw_rust_string_ostream() {
+        // LLVM requires this.
+        flush();
+    }
+};