use middle::trans::tvec;
use middle::trans::type_of;
use middle::trans::type_of::*;
+ use middle::trans::value::Value;
use middle::ty;
use util::common::indenter;
use util::ppaux::{Repr, ty_to_str};
use middle::trans::type_::Type;
+use std::c_str::ToCStr;
use std::hash;
use std::hashmap::HashMap;
use std::io;
}
pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
- let llfn: ValueRef = do name.as_c_str |buf| {
+ let llfn: ValueRef = do name.to_c_str().with_ref |buf| {
unsafe {
llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref())
}
None => ()
}
unsafe {
- let c = do name.as_c_str |buf| {
+ let c = do name.to_c_str().with_ref |buf| {
llvm::LLVMAddGlobal(llmod, ty.to_ref(), buf)
};
externs.insert(name, c);
// Structural comparison: a rather involved form of glue.
pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
if cx.sess.opts.save_temps {
- do s.as_c_str |buf| {
+ do s.to_c_str().with_ref |buf| {
unsafe {
llvm::LLVMSetValueName(v, buf)
}
opt_node_info: Option<NodeInfo>)
-> @mut Block {
unsafe {
- let llbb = do name.as_c_str |buf| {
+ let llbb = do name.to_c_str().with_ref |buf| {
llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf)
};
let bcx = @mut Block::new(llbb,
pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
unsafe {
let cx = task_llcx();
- do "static_allocas".as_c_str | buf| {
+ do "static_allocas".to_c_str().with_ref | buf| {
llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
}
}
pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
unsafe {
let cx = task_llcx();
- do "return".as_c_str |buf| {
+ do "return".to_c_str().with_ref |buf| {
llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
}
}
// Builds the return block for a function.
pub fn build_return_block(fcx: &FunctionContext, ret_cx: @mut Block) {
// Return the value if this function immediate; otherwise, return void.
- if fcx.llretptr.is_some() && fcx.has_immediate_return_value {
- Ret(ret_cx, Load(ret_cx, fcx.llretptr.unwrap()))
- } else {
- RetVoid(ret_cx)
+ if fcx.llretptr.is_none() || !fcx.has_immediate_return_value {
+ return RetVoid(ret_cx);
}
+
+ let retptr = Value(fcx.llretptr.unwrap());
+ let retval = match retptr.get_dominating_store(ret_cx) {
+ // If there's only a single store to the ret slot, we can directly return
+ // the value that was stored and omit the store and the alloca
+ Some(s) => {
+ let retval = *s.get_operand(0).unwrap();
+ s.erase_from_parent();
+
+ if retptr.has_no_uses() {
+ retptr.erase_from_parent();
+ }
+
+ retval
+ }
+ // Otherwise, load the return value from the ret slot
+ None => Load(ret_cx, fcx.llretptr.unwrap())
+ };
+
+
+ Ret(ret_cx, retval);
}
pub enum self_arg { impl_self(ty::t, ty::SelfMode), no_self, }
};
decl_cdecl_fn(ccx.llmod, main_name, llfty)
};
- let llbb = do "top".as_c_str |buf| {
+ let llbb = do "top".to_c_str().with_ref |buf| {
unsafe {
llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
}
llvm::LLVMPositionBuilderAtEnd(bld, llbb);
let crate_map = ccx.crate_map;
- let opaque_crate_map = do "crate_map".as_c_str |buf| {
+ let opaque_crate_map = do "crate_map".to_c_str().with_ref |buf| {
llvm::LLVMBuildPointerCast(bld, crate_map, Type::i8p().to_ref(), buf)
};
};
let args = {
- let opaque_rust_main = do "rust_main".as_c_str |buf| {
+ let opaque_rust_main = do "rust_main".to_c_str().with_ref |buf| {
llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p().to_ref(), buf)
};
(rust_main, args)
};
- let result = llvm::LLVMBuildCall(bld,
- start_fn,
- &args[0],
- args.len() as c_uint,
- noname());
+ let result = do args.as_imm_buf |buf, len| {
+ llvm::LLVMBuildCall(bld, start_fn, buf, len as c_uint, noname())
+ };
+
llvm::LLVMBuildRet(bld, result);
}
}
unsafe {
let llty = llvm::LLVMTypeOf(v);
- let g = do sym.as_c_str |buf| {
+ let g = do sym.to_c_str().with_ref |buf| {
llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
};
match (attr::first_attr_value_str_by_name(i.attrs, "link_section")) {
Some(sect) => unsafe {
- do sect.as_c_str |buf| {
+ do sect.to_c_str().with_ref |buf| {
llvm::LLVMSetSection(v, buf);
}
},
}
ast::foreign_item_static(*) => {
let ident = token::ident_to_str(&ni.ident);
- let g = do ident.as_c_str |buf| {
+ let g = do ident.to_c_str().with_ref |buf| {
unsafe {
let ty = type_of(ccx, ty);
llvm::LLVMAddGlobal(ccx.llmod, ty.to_ref(), buf)
let s = mangle_exported_name(ccx, p, ty::mk_int()).to_managed();
let disr_val = vi[i].disr_val;
note_unique_llvm_symbol(ccx, s);
- let discrim_gvar = do s.as_c_str |buf| {
+ let discrim_gvar = do s.to_c_str().with_ref |buf| {
unsafe {
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
}
}
let gc_metadata_name = ~"_gc_module_metadata_" + llmod_id;
- let gc_metadata = do gc_metadata_name.as_c_str |buf| {
+ let gc_metadata = do gc_metadata_name.to_c_str().with_ref |buf| {
unsafe {
llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
}
pub fn create_module_map(ccx: &mut CrateContext) -> ValueRef {
let elttype = Type::struct_([ccx.int_type, ccx.int_type], false);
let maptype = Type::array(&elttype, (ccx.module_data.len() + 1) as u64);
- let map = do "_rust_mod_map".as_c_str |buf| {
+ let map = do "_rust_mod_map".to_c_str().with_ref |buf| {
unsafe {
llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
}
let sym_name = ~"_rust_crate_map_" + mapname;
let arrtype = Type::array(&int_type, n_subcrates as u64);
let maptype = Type::struct_([Type::i32(), Type::i8p(), int_type, arrtype], false);
- let map = do sym_name.as_c_str |buf| {
+ let map = do sym_name.to_c_str().with_ref |buf| {
unsafe {
llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
}
cdata.name,
cstore::get_crate_vers(cstore, i),
cstore::get_crate_hash(cstore, i));
- let cr = do nm.as_c_str |buf| {
+ let cr = do nm.to_c_str().with_ref |buf| {
unsafe {
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
}
let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
let llmeta = C_bytes(encoder::encode_metadata(encode_parms, crate));
let llconst = C_struct([llmeta]);
- let mut llglobal = do "rust_metadata".as_c_str |buf| {
+ let mut llglobal = do "rust_metadata".to_c_str().with_ref |buf| {
unsafe {
llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst).to_ref(), buf)
}
};
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
- do cx.sess.targ_cfg.target_strs.meta_sect_name.as_c_str |buf| {
+ do cx.sess.targ_cfg.target_strs.meta_sect_name.to_c_str().with_ref |buf| {
llvm::LLVMSetSection(llglobal, buf)
};
lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
let t_ptr_i8 = Type::i8p();
llglobal = llvm::LLVMConstBitCast(llglobal, t_ptr_i8.to_ref());
- let llvm_used = do "llvm.used".as_c_str |buf| {
+ let llvm_used = do "llvm.used".to_c_str().with_ref |buf| {
llvm::LLVMAddGlobal(cx.llmod, Type::array(&t_ptr_i8, 1).to_ref(), buf)
};
lib::llvm::SetLinkage(llvm_used, lib::llvm::AppendingLinkage);
internal: bool)
-> ValueRef {
unsafe {
- let llglobal = do name.as_c_str |buf| {
+ let llglobal = do name.to_c_str().with_ref |buf| {
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval).to_ref(), buf)
};
llvm::LLVMSetInitializer(llglobal, llval);