dd4112bf79
LLVM doesn't really like types with a bit-width that isn't a multiple of 8 and disable various optimizations if it encounters such types used with loads/stores. OTOH, booleans must be represented as i1 when used as SSA values. To get the best results, we must use i1 for SSA values, and i8 when storing the value to memory. By using range asserts on loads, LLVM can eliminate the required zero-extend and truncate operations. Fixes #15203
89 lines
2.8 KiB
Rust
89 lines
2.8 KiB
Rust
// 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 syntax::abi::{OsWin32, OsMacos, OsiOS};
|
|
use lib::llvm::*;
|
|
use super::cabi::*;
|
|
use super::common::*;
|
|
use super::machine::*;
|
|
use middle::trans::type_::Type;
|
|
|
|
pub fn compute_abi_info(ccx: &CrateContext,
|
|
atys: &[Type],
|
|
rty: Type,
|
|
ret_def: bool) -> FnType {
|
|
let mut arg_tys = Vec::new();
|
|
|
|
let ret_ty;
|
|
if !ret_def {
|
|
ret_ty = ArgType::direct(Type::void(ccx), None, None, None);
|
|
} else if rty.kind() == Struct {
|
|
// Returning a structure. Most often, this will use
|
|
// a hidden first argument. On some platforms, though,
|
|
// small structs are returned as integers.
|
|
//
|
|
// Some links:
|
|
// http://www.angelcode.com/dev/callconv/callconv.html
|
|
// Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
|
|
|
|
enum Strategy { RetValue(Type), RetPointer }
|
|
let strategy = match ccx.sess().targ_cfg.os {
|
|
OsWin32 | OsMacos | OsiOS => {
|
|
match llsize_of_alloc(ccx, rty) {
|
|
1 => RetValue(Type::i8(ccx)),
|
|
2 => RetValue(Type::i16(ccx)),
|
|
4 => RetValue(Type::i32(ccx)),
|
|
8 => RetValue(Type::i64(ccx)),
|
|
_ => RetPointer
|
|
}
|
|
}
|
|
_ => {
|
|
RetPointer
|
|
}
|
|
};
|
|
|
|
match strategy {
|
|
RetValue(t) => {
|
|
ret_ty = ArgType::direct(rty, Some(t), None, None);
|
|
}
|
|
RetPointer => {
|
|
ret_ty = ArgType::indirect(rty, Some(StructRetAttribute));
|
|
}
|
|
}
|
|
} else {
|
|
let attr = if rty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
|
|
ret_ty = ArgType::direct(rty, None, None, attr);
|
|
}
|
|
|
|
for &t in atys.iter() {
|
|
let ty = match t.kind() {
|
|
Struct => {
|
|
let size = llsize_of_alloc(ccx, t);
|
|
if size == 0 {
|
|
ArgType::ignore(t)
|
|
} else {
|
|
ArgType::indirect(t, Some(ByValAttribute))
|
|
}
|
|
}
|
|
_ => {
|
|
let attr = if t == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
|
|
ArgType::direct(t, None, None, attr)
|
|
}
|
|
};
|
|
arg_tys.push(ty);
|
|
}
|
|
|
|
return FnType {
|
|
arg_tys: arg_tys,
|
|
ret_ty: ret_ty,
|
|
};
|
|
}
|