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 {
}
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 {
}
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")
}
}
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,
-> 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;
}
}
+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
#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
#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();
+ }
+};