(index<- )        ./librustc/middle/trans/cabi_mips.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Wed Apr  9 17:27:02 2014
   1  // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  #![allow(non_uppercase_pattern_statics)]
  12  
  13  use libc::c_uint;
  14  use std::cmp;
  15  use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
  16  use lib::llvm::StructRetAttribute;
  17  use middle::trans::context::CrateContext;
  18  use middle::trans::cabi::*;
  19  use middle::trans::type_::Type;
  20  
  21  fn align_up_to(off: uint, a: uint) -> uint {
  22      return (off + a - 1u) / a * a;
  23  }
  24  
  25  fn align(off: uint, tyType) -> uint {
  26      let a = ty_align(ty);
  27      return align_up_to(off, a);
  28  }
  29  
  30  fn ty_align(tyType) -> uint {
  31      match ty.kind() {
  32          Integer => {
  33              unsafe {
  34                  ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
  35              }
  36          }
  37          Pointer => 4,
  38          Float => 4,
  39          Double => 8,
  40          Struct => {
  41            if ty.is_packed() {
  42              1
  43            } else {
  44              let str_tys = ty.field_types();
  45              str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
  46            }
  47          }
  48          Array => {
  49              let elt = ty.element_type();
  50              ty_align(elt)
  51          }
  52          _ => fail!("ty_size: unhandled type")
  53      }
  54  }
  55  
  56  fn ty_size(tyType) -> uint {
  57      match ty.kind() {
  58          Integer => {
  59              unsafe {
  60                  ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
  61              }
  62          }
  63          Pointer => 4,
  64          Float => 4,
  65          Double => 8,
  66          Struct => {
  67              if ty.is_packed() {
  68                  let str_tys = ty.field_types();
  69                  str_tys.iter().fold(0, |s, t| s + ty_size(*t))
  70              } else {
  71                  let str_tys = ty.field_types();
  72                  let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
  73                  align(size, ty)
  74              }
  75          }
  76          Array => {
  77              let len = ty.array_length();
  78              let elt = ty.element_type();
  79              let eltsz = ty_size(elt);
  80              len * eltsz
  81          }
  82          _ => fail!("ty_size: unhandled type")
  83      }
  84  }
  85  
  86  fn classify_ret_ty(tyType) -> ArgType {
  87      if is_reg_ty(ty) {
  88          ArgType::direct(ty, None, None, None)
  89      } else {
  90          ArgType::indirect(ty, Some(StructRetAttribute))
  91      }
  92  }
  93  
  94  fn classify_arg_ty(ccx: &CrateContext, tyType, offset: &mut uint) -> ArgType {
  95      let orig_offset = *offset;
  96      let size = ty_size(ty) * 8;
  97      let mut align = ty_align(ty);
  98  
  99      align = cmp::min(cmp::max(align, 4), 8);
 100      *offset = align_up_to(*offset, align);
 101      *offset += align_up_to(size, align * 8) / 8;
 102  
 103      if is_reg_ty(ty) {
 104          ArgType::direct(ty, None, None, None)
 105      } else {
 106          ArgType::direct(
 107              ty,
 108              Some(struct_ty(ccx, ty)),
 109              padding_ty(ccx, align, orig_offset),
 110              None
 111          )
 112      }
 113  }
 114  
 115  fn is_reg_ty(tyType) -> bool {
 116      return match ty.kind() {
 117          Integer
 118          | Pointer
 119          | Float
 120          | Double => true,
 121          _ => false
 122      };
 123  }
 124  
 125  fn padding_ty(ccx: &CrateContext, align: uint, offset: uint) -> Option<Type> {
 126      if ((align - 1 ) & offset) > 0 {
 127          Some(Type::i32(ccx))
 128      } else {
 129          None
 130      }
 131  }
 132  
 133  fn coerce_to_int(ccx: &CrateContext, size: uint) -> Vec<Type> {
 134      let int_ty = Type::i32(ccx);
 135      let mut args = Vec::new();
 136  
 137      let mut n = size / 32;
 138      while n > 0 {
 139          args.push(int_ty);
 140          n -= 1;
 141      }
 142  
 143      let r = size % 32;
 144      if r > 0 {
 145          unsafe {
 146              args.push(Type::from_ref(llvm::LLVMIntTypeInContext(ccx.llcx, r as c_uint)));
 147          }
 148      }
 149  
 150      args
 151  }
 152  
 153  fn struct_ty(ccx: &CrateContext, tyType) -> Type {
 154      let size = ty_size(ty) * 8;
 155      Type::struct_(ccx, coerce_to_int(ccx, size).as_slice(), false)
 156  }
 157  
 158  pub fn compute_abi_info(ccx: &CrateContext,
 159                          atys: &[Type],
 160                          rtyType,
 161                          ret_def: bool) -> FnType {
 162      let ret_ty = if ret_def {
 163          classify_ret_ty(rty)
 164      } else {
 165          ArgType::direct(Type::void(ccx), None, None, None)
 166      };
 167  
 168      let sret = ret_ty.is_indirect();
 169      let mut arg_tys = Vec::new();
 170      let mut offset = if sret { 4 } else { 0 };
 171  
 172      for aty in atys.iter() {
 173          let ty = classify_arg_ty(ccx, *aty, &mut offset);
 174          arg_tys.push(ty);
 175      };
 176  
 177      return FnType {
 178          arg_tys: arg_tys,
 179          ret_ty: ret_ty,
 180      };
 181  }


librustc/middle/trans/cabi_mips.rs:20:1-20:1 -fn- definition:
fn align_up_to(off: uint, a: uint) -> uint {
    return (off + a - 1u) / a * a;
}
references:- 3
26:     let a = ty_align(ty);
27:     return align_up_to(off, a);
28: }
--
99:     align = cmp::min(cmp::max(align, 4), 8);
100:     *offset = align_up_to(*offset, align);
101:     *offset += align_up_to(size, align * 8) / 8;


librustc/middle/trans/cabi_mips.rs:24:1-24:1 -fn- definition:
fn align(off: uint, ty: Type) -> uint {
    let a = ty_align(ty);
    return align_up_to(off, a);
references:- 2
71:                 let str_tys = ty.field_types();
72:                 let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
73:                 align(size, ty)
74:             }


librustc/middle/trans/cabi_mips.rs:29:1-29:1 -fn- definition:
fn ty_align(ty: Type) -> uint {
    match ty.kind() {
        Integer => {
references:- 4
25: fn align(off: uint, ty: Type) -> uint {
26:     let a = ty_align(ty);
27:     return align_up_to(off, a);
--
44:             let str_tys = ty.field_types();
45:             str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
46:           }
--
49:             let elt = ty.element_type();
50:             ty_align(elt)
51:         }
--
96:     let size = ty_size(ty) * 8;
97:     let mut align = ty_align(ty);


librustc/middle/trans/cabi_mips.rs:55:1-55:1 -fn- definition:
fn ty_size(ty: Type) -> uint {
    match ty.kind() {
        Integer => {
references:- 5
153: fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
154:     let size = ty_size(ty) * 8;
155:     Type::struct_(ccx, coerce_to_int(ccx, size).as_slice(), false)


librustc/middle/trans/cabi_mips.rs:114:1-114:1 -fn- definition:
fn is_reg_ty(ty: Type) -> bool {
    return match ty.kind() {
        Integer
references:- 2
103:     if is_reg_ty(ty) {
104:         ArgType::direct(ty, None, None, None)