Add a Rust string ostream for LLVM
This commit is contained in:
parent
77b3a7ba8b
commit
225353d8bb
4 changed files with 67 additions and 24 deletions
|
@ -21,11 +21,10 @@ use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel};
|
||||||
|
|
||||||
use std::c_str::ToCStr;
|
use std::c_str::ToCStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::string;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use libc::{c_uint, c_void, free};
|
use libc::c_uint;
|
||||||
|
|
||||||
#[deriving(Clone, PartialEq, Show)]
|
#[deriving(Clone, PartialEq, Show)]
|
||||||
pub struct Type {
|
pub struct Type {
|
||||||
|
@ -339,12 +338,9 @@ impl TypeNames {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_to_string(&self, ty: Type) -> String {
|
pub fn type_to_string(&self, ty: Type) -> String {
|
||||||
unsafe {
|
llvm::build_string(|s| unsafe {
|
||||||
let s = llvm::LLVMTypeToString(ty.to_ref());
|
llvm::LLVMWriteTypeToString(ty.to_ref(), s);
|
||||||
let ret = string::raw::from_buf(s as *const u8);
|
}).expect("non-UTF8 type description from LLVM")
|
||||||
free(s as *mut c_void);
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn types_to_str(&self, tys: &[Type]) -> String {
|
pub fn types_to_str(&self, tys: &[Type]) -> String {
|
||||||
|
@ -353,11 +349,8 @@ impl TypeNames {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn val_to_string(&self, val: ValueRef) -> String {
|
pub fn val_to_string(&self, val: ValueRef) -> String {
|
||||||
unsafe {
|
llvm::build_string(|s| unsafe {
|
||||||
let s = llvm::LLVMValueToString(val);
|
llvm::LLVMWriteValueToString(val, s);
|
||||||
let ret = string::raw::from_buf(s as *const u8);
|
}).expect("nun-UTF8 value description from LLVM")
|
||||||
free(s as *mut c_void);
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
use std::c_str::ToCStr;
|
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_uint, c_ushort, uint64_t, c_int, size_t, c_char};
|
||||||
use libc::{c_longlong, c_ulonglong};
|
use libc::{c_longlong, c_ulonglong};
|
||||||
use debuginfo::{DIBuilderRef, DIDescriptor,
|
use debuginfo::{DIBuilderRef, DIDescriptor,
|
||||||
|
@ -1839,8 +1841,8 @@ extern {
|
||||||
-> ValueRef;
|
-> ValueRef;
|
||||||
|
|
||||||
pub fn LLVMDICompositeTypeSetTypeArray(CompositeType: ValueRef, TypeArray: ValueRef);
|
pub fn LLVMDICompositeTypeSetTypeArray(CompositeType: ValueRef, TypeArray: ValueRef);
|
||||||
pub fn LLVMTypeToString(Type: TypeRef) -> *const c_char;
|
pub fn LLVMWriteTypeToString(Type: TypeRef, s: RustStringRef);
|
||||||
pub fn LLVMValueToString(value_ref: ValueRef) -> *const c_char;
|
pub fn LLVMWriteValueToString(value_ref: ValueRef, s: RustStringRef);
|
||||||
|
|
||||||
pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
|
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
|
// FIXME #15460 - create a public function that actually calls our
|
||||||
// static LLVM symbols. Otherwise the linker will just throw llvm
|
// static LLVM symbols. Otherwise the linker will just throw llvm
|
||||||
// away. We're just calling lots of stuff until we transitively get
|
// away. We're just calling lots of stuff until we transitively get
|
||||||
|
|
|
@ -645,22 +645,18 @@ extern "C" void LLVMDICompositeTypeSetTypeArray(
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" char *LLVMTypeToString(LLVMTypeRef Type) {
|
extern "C" void LLVMWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
|
||||||
std::string s;
|
raw_rust_string_ostream os(str);
|
||||||
llvm::raw_string_ostream os(s);
|
|
||||||
unwrap<llvm::Type>(Type)->print(os);
|
unwrap<llvm::Type>(Type)->print(os);
|
||||||
return strdup(os.str().data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" char *LLVMValueToString(LLVMValueRef Value) {
|
extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) {
|
||||||
std::string s;
|
raw_rust_string_ostream os(str);
|
||||||
llvm::raw_string_ostream os(s);
|
|
||||||
os << "(";
|
os << "(";
|
||||||
unwrap<llvm::Value>(Value)->getType()->print(os);
|
unwrap<llvm::Value>(Value)->getType()->print(os);
|
||||||
os << ":";
|
os << ":";
|
||||||
unwrap<llvm::Value>(Value)->print(os);
|
unwrap<llvm::Value>(Value)->print(os);
|
||||||
os << ")";
|
os << ")";
|
||||||
return strdup(os.str().data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LLVM_VERSION_MINOR >= 5
|
#if LLVM_VERSION_MINOR >= 5
|
||||||
|
|
|
@ -69,3 +69,31 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void LLVMRustSetLastError(const char*);
|
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue