+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use llvm;
-use llvm::BasicBlockRef;
-use value::Value;
-
-#[derive(Copy, Clone)]
-pub struct BasicBlock(pub BasicBlockRef);
-
-/// Wrapper for LLVM BasicBlockRef
-impl BasicBlock {
- pub fn get(&self) -> BasicBlockRef {
- self.0
- }
-
- pub fn as_value(self) -> Value {
- unsafe {
- Value(llvm::LLVMBasicBlockAsValue(self.get()))
- }
- }
-
- pub fn pred_iter(self) -> impl Iterator<Item=BasicBlock> {
- self.as_value().user_iter()
- .filter(|user| user.is_a_terminator_inst())
- .map(|user| user.get_parent().unwrap())
- }
-
- pub fn get_single_predecessor(self) -> Option<BasicBlock> {
- let mut iter = self.pred_iter();
- match (iter.next(), iter.next()) {
- (Some(first), None) => Some(first),
- _ => None
- }
- }
-
- pub fn delete(self) {
- unsafe {
- llvm::LLVMDeleteBasicBlock(self.0);
- }
- }
-}
use base;
use base::*;
use common::{
- self, BlockAndBuilder, CrateContext, FunctionContext, SharedCrateContext
+ self, CrateContext, FunctionContext, SharedCrateContext
};
use consts;
use declare;
fn_ty
}
- /// This behemoth of a function translates function calls. Unfortunately, in
- /// order to generate more efficient LLVM output at -O0, it has quite a complex
- /// signature (refactoring this into two functions seems like a good idea).
- ///
- /// In particular, for lang items, it is invoked with a dest of None, and in
- /// that case the return value contains the result of the fn. The lang item must
- /// not return a structural type or else all heck breaks loose.
- ///
- /// For non-lang items, `dest` is always Some, and hence the result is written
- /// into memory somewhere. Nonetheless we return the actual return value of the
- /// function.
- pub fn call<'a>(self,
- bcx: &BlockAndBuilder<'a, 'tcx>,
- args: &[ValueRef],
- dest: Option<ValueRef>,
- lpad: Option<&'a llvm::OperandBundleDef>
- ) {
- trans_call_inner(bcx, self, args, dest, lpad)
- }
-
/// Turn the callee into a function pointer.
pub fn reify<'a>(self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
match self.data {
(llfn, fn_ty)
}
-
-// ______________________________________________________________________
-// Translating calls
-
-fn trans_call_inner<'a, 'tcx>(
- bcx: &BlockAndBuilder<'a, 'tcx>,
- callee: Callee<'tcx>,
- args: &[ValueRef],
- dest: Option<ValueRef>,
- lpad: Option<&'a llvm::OperandBundleDef>
-) {
- // Introduce a temporary cleanup scope that will contain cleanups
- // for the arguments while they are being evaluated. The purpose
- // this cleanup is to ensure that, should a panic occur while
- // evaluating argument N, the values for arguments 0...N-1 are all
- // cleaned up. If no panic occurs, the values are handed off to
- // the callee, and hence none of the cleanups in this temporary
- // scope will ever execute.
- let ccx = bcx.ccx();
- let fn_ret = callee.ty.fn_ret();
- let fn_ty = callee.direct_fn_type(ccx, &[]);
-
- // If there no destination, return must be direct, with no cast.
- if dest.is_none() {
- assert!(!fn_ty.ret.is_indirect() && fn_ty.ret.cast.is_none());
- }
-
- let mut llargs = Vec::new();
-
- if fn_ty.ret.is_indirect() {
- let dest = dest.unwrap();
- let llretslot = if let Some(ty) = fn_ty.ret.cast {
- bcx.pointercast(dest, ty.ptr_to())
- } else {
- dest
- };
- llargs.push(llretslot);
- }
-
- let llfn = match callee.data {
- NamedTupleConstructor(_) | Intrinsic => {
- bug!("{:?} calls should not go through Callee::call", callee);
- }
- Virtual(idx) => {
- llargs.push(args[0]);
-
- let fn_ptr = meth::get_virtual_method(&bcx, args[1], idx);
- let llty = fn_ty.llvm_type(&bcx.ccx()).ptr_to();
- llargs.extend_from_slice(&args[2..]);
- bcx.pointercast(fn_ptr, llty)
- }
- Fn(f) => {
- llargs.extend_from_slice(args);
- f
- }
- };
-
- let llret = bcx.call(llfn, &llargs[..], lpad);
- fn_ty.apply_attrs_callsite(llret);
-
- // If the function we just called does not use an outpointer,
- // store the result into the Rust outpointer.
- if !fn_ty.ret.is_indirect() {
- if let Some(llretslot) = dest {
- fn_ty.ret.store(&bcx, llret, llretslot);
- }
- }
-
- if fn_ret.0.is_never() {
- bcx.unreachable();
- }
-}
) {
let def_id = langcall(bcx.tcx(), None, "", ExchangeFreeFnLangItem);
let args = [bcx.pointercast(v, Type::i8p(bcx.ccx())), size, align];
- Callee::def(bcx.ccx(), def_id, bcx.tcx().intern_substs(&[])).call(&bcx, &args, None, None)
+ let callee = Callee::def(bcx.ccx(), def_id, bcx.tcx().intern_substs(&[]));
+
+ let ccx = bcx.ccx();
+ let fn_ret = callee.ty.fn_ret();
+ let fn_ty = callee.direct_fn_type(ccx, &[]);
+
+ assert!(!fn_ty.ret.is_indirect() && fn_ty.ret.cast.is_none());
+
+ let llret = bcx.call(callee.reify(ccx), &args[..], None);
+ fn_ty.apply_attrs_callsite(llret);
+
+ if fn_ret.0.is_never() {
+ bcx.unreachable();
+ }
}
pub fn trans_exchange_free_ty<'a, 'tcx>(
mod assert_module_sources;
mod attributes;
mod base;
-mod basic_block;
mod builder;
mod cabi_aarch64;
mod cabi_arm;
use std::iter;
-use basic_block::BasicBlock;
-
use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
// Remove blocks that haven't been visited, or have no
// predecessors.
for bb in mir.basic_blocks().indices() {
- let block = mircx.blocks[bb];
- let block = BasicBlock(block);
// Unreachable block
if !visited.contains(bb.index()) {
debug!("trans_mir: block {:?} was not visited", bb);
- block.delete();
+ unsafe {
+ llvm::LLVMDeleteBasicBlock(mircx.blocks[bb]);
+ }
}
}
}
// except according to those terms.
use llvm;
-use llvm::{UseRef, ValueRef};
-use basic_block::BasicBlock;
-use common::BlockAndBuilder;
use std::fmt;
-use libc::c_uint;
-
#[derive(Copy, Clone, PartialEq)]
-pub struct Value(pub ValueRef);
+pub struct Value(pub llvm::ValueRef);
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}).expect("nun-UTF8 value description from LLVM"))
}
}
-
-macro_rules! opt_val { ($e:expr) => (
- unsafe {
- match $e {
- p if !p.is_null() => Some(Value(p)),
- _ => None
- }
- }
-) }
-
-/// Wrapper for LLVM ValueRef
-impl Value {
- /// Returns the native ValueRef
- pub fn get(&self) -> ValueRef {
- let Value(v) = *self; v
- }
-
- /// Returns the BasicBlock that contains this value
- pub fn get_parent(self) -> Option<BasicBlock> {
- unsafe {
- match llvm::LLVMGetInstructionParent(self.get()) {
- p if !p.is_null() => Some(BasicBlock(p)),
- _ => None
- }
- }
- }
-
- /// Removes this value from its containing BasicBlock
- pub fn erase_from_parent(self) {
- unsafe {
- llvm::LLVMInstructionEraseFromParent(self.get());
- }
- }
-
- /// Returns the single dominating store to this value, if any
- /// This only performs a search for a trivially dominating store. The store
- /// must be the only user of this value, and there must not be any conditional
- /// branches between the store and the given block.
- pub fn get_dominating_store(self, bcx: &BlockAndBuilder) -> Option<Value> {
- match self.get_single_user().and_then(|user| user.as_store_inst()) {
- Some(store) => {
- store.get_parent().and_then(|store_bb| {
- let mut bb = BasicBlock(bcx.llbb());
- let mut ret = Some(store);
- while bb.get() != store_bb.get() {
- match bb.get_single_predecessor() {
- Some(pred) => bb = pred,
- None => { ret = None; break }
- }
- }
- ret
- })
- }
- _ => None
- }
- }
-
- /// Returns the first use of this value, if any
- pub fn get_first_use(self) -> Option<Use> {
- unsafe {
- match llvm::LLVMGetFirstUse(self.get()) {
- u if !u.is_null() => Some(Use(u)),
- _ => None
- }
- }
- }
-
- /// Tests if there are no uses of this value
- pub fn has_no_uses(self) -> bool {
- self.get_first_use().is_none()
- }
-
- /// Returns the single user of this value
- /// If there are no users or multiple users, this returns None
- pub fn get_single_user(self) -> Option<Value> {
- let mut iter = self.user_iter();
- match (iter.next(), iter.next()) {
- (Some(first), None) => Some(first),
- _ => None
- }
- }
-
- /// Returns an iterator for the users of this value
- pub fn user_iter(self) -> Users {
- Users {
- next: self.get_first_use()
- }
- }
-
- /// Returns the requested operand of this instruction
- /// Returns None, if there's no operand at the given index
- pub fn get_operand(self, i: usize) -> Option<Value> {
- opt_val!(llvm::LLVMGetOperand(self.get(), i as c_uint))
- }
-
- /// Returns the Store represent by this value, if any
- pub fn as_store_inst(self) -> Option<Value> {
- opt_val!(llvm::LLVMIsAStoreInst(self.get()))
- }
-
- /// Tests if this value is a terminator instruction
- pub fn is_a_terminator_inst(self) -> bool {
- unsafe {
- !llvm::LLVMIsATerminatorInst(self.get()).is_null()
- }
- }
-}
-
-/// Wrapper for LLVM UseRef
-#[derive(Copy, Clone)]
-pub struct Use(UseRef);
-
-impl Use {
- pub fn get(&self) -> UseRef {
- let Use(v) = *self; v
- }
-
- pub fn get_user(self) -> Value {
- unsafe {
- Value(llvm::LLVMGetUser(self.get()))
- }
- }
-
- pub fn get_next_use(self) -> Option<Use> {
- unsafe {
- match llvm::LLVMGetNextUse(self.get()) {
- u if !u.is_null() => Some(Use(u)),
- _ => None
- }
- }
- }
-}
-
-/// Iterator for the users of a value
-pub struct Users {
- next: Option<Use>
-}
-
-impl Iterator for Users {
- type Item = Value;
-
- fn next(&mut self) -> Option<Value> {
- let current = self.next;
-
- self.next = current.and_then(|u| u.get_next_use());
-
- current.map(|u| u.get_user())
- }
-}