about summary refs log tree commit diff
diff options
context:
space:
mode:
authorValerii Hiora <valerii.hiora@gmail.com>2015-01-09 18:18:23 +0200
committerValerii Hiora <valerii.hiora@gmail.com>2015-01-09 18:38:30 +0200
commitea045d2055638a6cf66e4bd675c6f7deec7a8d8b (patch)
treeeff1efb141d2598c80c4b4e7612685575226ce45
parentac0607acb27ed8ad3852a6e099ff0766b002f40e (diff)
downloadrust-ea045d2055638a6cf66e4bd675c6f7deec7a8d8b.tar.gz
rust-ea045d2055638a6cf66e4bd675c6f7deec7a8d8b.zip
iOS: cabi fixes
Changed alignment according to official Apple docs
-rw-r--r--src/librustc_trans/trans/cabi.rs9
-rw-r--r--src/librustc_trans/trans/cabi_arm.rs85
2 files changed, 75 insertions, 19 deletions
diff --git a/src/librustc_trans/trans/cabi.rs b/src/librustc_trans/trans/cabi.rs
index 8a2a2534cab..f7ffbb95feb 100644
--- a/src/librustc_trans/trans/cabi.rs
+++ b/src/librustc_trans/trans/cabi.rs
@@ -115,8 +115,15 @@ pub fn compute_abi_info(ccx: &CrateContext,
         } else {
             cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def)
         },
-        "arm" => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def),
         "aarch64" => cabi_aarch64::compute_abi_info(ccx, atys, rty, ret_def),
+        "arm" => {
+            let flavor = if ccx.sess().target.target.target_os == "ios" {
+                cabi_arm::Flavor::Ios
+            } else {
+                cabi_arm::Flavor::General
+            };
+            cabi_arm::compute_abi_info(ccx, atys, rty, ret_def, flavor)
+        },
         "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
         a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)
                               []),
diff --git a/src/librustc_trans/trans/cabi_arm.rs b/src/librustc_trans/trans/cabi_arm.rs
index 46440fcf1a1..830771d7397 100644
--- a/src/librustc_trans/trans/cabi_arm.rs
+++ b/src/librustc_trans/trans/cabi_arm.rs
@@ -19,16 +19,23 @@ use trans::type_::Type;
 
 use std::cmp;
 
+pub enum Flavor {
+    General,
+    Ios
+}
+
+type TyAlignFn = fn(ty: Type) -> uint;
+
 fn align_up_to(off: uint, a: uint) -> uint {
     return (off + a - 1u) / a * a;
 }
 
-fn align(off: uint, ty: Type) -> uint {
-    let a = ty_align(ty);
+fn align(off: uint, ty: Type, align_fn: TyAlignFn) -> uint {
+    let a = align_fn(ty);
     return align_up_to(off, a);
 }
 
-fn ty_align(ty: Type) -> uint {
+fn general_ty_align(ty: Type) -> uint {
     match ty.kind() {
         Integer => {
             unsafe {
@@ -43,18 +50,51 @@ fn ty_align(ty: Type) -> uint {
                 1
             } else {
                 let str_tys = ty.field_types();
-                str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
+                str_tys.iter().fold(1, |a, t| cmp::max(a, general_ty_align(*t)))
+            }
+        }
+        Array => {
+            let elt = ty.element_type();
+            general_ty_align(elt)
+        }
+        _ => panic!("ty_align: unhandled type")
+    }
+}
+
+// For more information see:
+// ARMv7
+// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual
+//    /iPhoneOSABIReference/Articles/ARMv7FunctionCallingConventions.html
+// ARMv6
+// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual
+//    /iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
+fn ios_ty_align(ty: Type) -> uint {
+    match ty.kind() {
+        Integer => {
+            unsafe {
+                cmp::min(4, ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8)
+            }
+        }
+        Pointer => 4,
+        Float => 4,
+        Double => 4,
+        Struct => {
+            if ty.is_packed() {
+                1
+            } else {
+                let str_tys = ty.field_types();
+                str_tys.iter().fold(1, |a, t| cmp::max(a, ios_ty_align(*t)))
             }
         }
         Array => {
             let elt = ty.element_type();
-            ty_align(elt)
+            ios_ty_align(elt)
         }
         _ => panic!("ty_align: unhandled type")
     }
 }
 
-fn ty_size(ty: Type) -> uint {
+fn ty_size(ty: Type, align_fn: TyAlignFn) -> uint {
     match ty.kind() {
         Integer => {
             unsafe {
@@ -67,29 +107,32 @@ fn ty_size(ty: Type) -> uint {
         Struct => {
             if ty.is_packed() {
                 let str_tys = ty.field_types();
-                str_tys.iter().fold(0, |s, t| s + ty_size(*t))
+                str_tys.iter().fold(0, |s, t| s + ty_size(*t, align_fn))
             } else {
                 let str_tys = ty.field_types();
-                let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
-                align(size, ty)
+                let size = str_tys.iter()
+                                  .fold(0, |s, t| {
+                                      align(s, *t, align_fn) + ty_size(*t, align_fn)
+                                  });
+                align(size, ty, align_fn)
             }
         }
         Array => {
             let len = ty.array_length();
             let elt = ty.element_type();
-            let eltsz = ty_size(elt);
+            let eltsz = ty_size(elt, align_fn);
             len * eltsz
         }
         _ => panic!("ty_size: unhandled type")
     }
 }
 
-fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
+fn classify_ret_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
     if is_reg_ty(ty) {
         let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
         return ArgType::direct(ty, None, None, attr);
     }
-    let size = ty_size(ty);
+    let size = ty_size(ty, align_fn);
     if size <= 4 {
         let llty = if size <= 1 {
             Type::i8(ccx)
@@ -103,13 +146,13 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
     ArgType::indirect(ty, Some(StructRetAttribute))
 }
 
-fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
+fn classify_arg_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
     if is_reg_ty(ty) {
         let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
         return ArgType::direct(ty, None, None, attr);
     }
-    let align = ty_align(ty);
-    let size = ty_size(ty);
+    let align = align_fn(ty);
+    let size = ty_size(ty, align_fn);
     let llty = if align <= 4 {
         Type::array(&Type::i32(ccx), ((size + 3) / 4) as u64)
     } else {
@@ -131,15 +174,21 @@ fn is_reg_ty(ty: Type) -> bool {
 pub fn compute_abi_info(ccx: &CrateContext,
                         atys: &[Type],
                         rty: Type,
-                        ret_def: bool) -> FnType {
+                        ret_def: bool,
+                        flavor: Flavor) -> FnType {
+    let align_fn = match flavor {
+        Flavor::General => general_ty_align as TyAlignFn,
+        Flavor::Ios => ios_ty_align as TyAlignFn,
+    };
+
     let mut arg_tys = Vec::new();
     for &aty in atys.iter() {
-        let ty = classify_arg_ty(ccx, aty);
+        let ty = classify_arg_ty(ccx, aty, align_fn);
         arg_tys.push(ty);
     }
 
     let ret_ty = if ret_def {
-        classify_ret_ty(ccx, rty)
+        classify_ret_ty(ccx, rty, align_fn)
     } else {
         ArgType::direct(Type::void(ccx), None, None, None)
     };