Initial Type Refactoring done
This commit is contained in:
parent
befbd3a680
commit
57a75374d6
20 changed files with 429 additions and 478 deletions
|
@ -31,7 +31,7 @@ fn align(off: uint, ty: Type) -> uint {
|
|||
return align_up_to(off, a);
|
||||
}
|
||||
|
||||
fn ty_align(ty: TypeRef) -> uint {
|
||||
fn ty_align(ty: Type) -> uint {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
Integer => {
|
||||
|
@ -41,7 +41,7 @@ fn ty_align(ty: TypeRef) -> uint {
|
|||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||
if ty.is_packed() {
|
||||
1
|
||||
} else {
|
||||
let str_tys = struct_tys(ty);
|
||||
|
@ -71,32 +71,31 @@ fn ty_size(ty: TypeRef) -> uint {
|
|||
let str_tys = struct_tys(ty);
|
||||
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
|
||||
} else {
|
||||
let str_tys = struct_tys(ty);
|
||||
let str_tys = ty.field_types();
|
||||
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
|
||||
align(size, ty)
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
let eltsz = ty_size(elt);
|
||||
len * eltsz
|
||||
let len = ty.array_length();
|
||||
let elt = ty.element_type();
|
||||
let eltsz = ty_size(elt);
|
||||
len * eltsz
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ret_ty(ty: TypeRef) -> (LLVMType, Option<Attribute>) {
|
||||
fn classify_ret_ty(ty: Type) -> (LLVMType, Option<Attribute>) {
|
||||
return if is_reg_ty(ty) {
|
||||
(LLVMType { cast: false, ty: ty }, None)
|
||||
} else {
|
||||
(LLVMType { cast: false, ty: T_ptr(ty) }, Some(StructRetAttribute))
|
||||
(LLVMType { cast: false, ty: ty.ptr_to() }, Some(StructRetAttribute))
|
||||
};
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ty: TypeRef,
|
||||
offset: &mut uint) -> (LLVMType, Option<Attribute>) {
|
||||
fn classify_arg_ty(ty: Type, offset: &mut uint) -> (LLVMType, Option<Attribute>) {
|
||||
let orig_offset = *offset;
|
||||
let size = ty_size(ty) * 8;
|
||||
let mut align = ty_align(ty);
|
||||
|
@ -123,7 +122,7 @@ fn classify_arg_ty(ty: TypeRef,
|
|||
|
||||
fn is_reg_ty(ty: TypeRef) -> bool {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
return match ty.kind() {
|
||||
Integer
|
||||
| Pointer
|
||||
| Float
|
||||
|
@ -133,16 +132,16 @@ fn is_reg_ty(ty: TypeRef) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn padding_ty(align: uint, offset: uint) -> Option<TypeRef> {
|
||||
fn padding_ty(align: uint, offset: uint) -> Option<Type> {
|
||||
if ((align - 1 ) & offset) > 0 {
|
||||
return Some(T_i32());
|
||||
return Some(Type::i32());
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
fn coerce_to_int(size: uint) -> ~[TypeRef] {
|
||||
let int_ty = T_i32();
|
||||
fn coerce_to_int(size: uint) -> ~[Type] {
|
||||
let int_ty = Type::i32();
|
||||
let mut args = ~[];
|
||||
|
||||
let mut n = size / 32;
|
||||
|
@ -154,16 +153,16 @@ fn coerce_to_int(size: uint) -> ~[TypeRef] {
|
|||
let r = size % 32;
|
||||
if r > 0 {
|
||||
unsafe {
|
||||
args.push(llvm::LLVMIntTypeInContext(task_llcx(), r as c_uint))
|
||||
Type::from_ref(args.push(llvm::LLVMIntTypeInContext(task_llcx(), r as c_uint)))
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
fn struct_ty(ty: TypeRef,
|
||||
padding: Option<TypeRef>,
|
||||
coerce: bool) -> TypeRef {
|
||||
fn struct_ty(ty: Type,
|
||||
padding: Option<Type>,
|
||||
coerce: bool) -> Type {
|
||||
let size = ty_size(ty) * 8;
|
||||
let mut fields = padding.map_default(~[], |p| ~[*p]);
|
||||
|
||||
|
@ -173,20 +172,20 @@ fn struct_ty(ty: TypeRef,
|
|||
fields.push(ty);
|
||||
}
|
||||
|
||||
return T_struct(fields, false);
|
||||
return Type::struct_(fields, false);
|
||||
}
|
||||
|
||||
enum MIPS_ABIInfo { MIPS_ABIInfo }
|
||||
|
||||
impl ABIInfo for MIPS_ABIInfo {
|
||||
fn compute_info(&self,
|
||||
atys: &[TypeRef],
|
||||
rty: TypeRef,
|
||||
atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
let mut (ret_ty, ret_attr) = if ret_def {
|
||||
classify_ret_ty(rty)
|
||||
} else {
|
||||
(LLVMType { cast: false, ty: T_void() }, None)
|
||||
(LLVMType { cast: false, ty: Type::void() }, None)
|
||||
};
|
||||
|
||||
let sret = ret_attr.is_some();
|
||||
|
@ -203,7 +202,7 @@ impl ABIInfo for MIPS_ABIInfo {
|
|||
if sret {
|
||||
arg_tys = vec::append(~[ret_ty], arg_tys);
|
||||
attrs = vec::append(~[ret_attr], attrs);
|
||||
ret_ty = LLVMType { cast: false, ty: T_void() };
|
||||
ret_ty = LLVMType { cast: false, ty: Type::void() };
|
||||
}
|
||||
|
||||
return FnType {
|
||||
|
|
|
@ -23,8 +23,8 @@ struct X86_ABIInfo {
|
|||
|
||||
impl ABIInfo for X86_ABIInfo {
|
||||
fn compute_info(&self,
|
||||
atys: &[TypeRef],
|
||||
rty: TypeRef,
|
||||
atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
let mut arg_tys = do atys.map |a| {
|
||||
LLVMType { cast: false, ty: *a }
|
||||
|
@ -41,7 +41,7 @@ impl ABIInfo for X86_ABIInfo {
|
|||
// http://www.angelcode.com/dev/callconv/callconv.html
|
||||
// Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
|
||||
let sret = {
|
||||
let returning_a_struct = unsafe { LLVMGetTypeKind(rty) == Struct && ret_def };
|
||||
let returning_a_struct = unsafe { rty.kind() == Struct && ret_def };
|
||||
let big_struct = match self.ccx.sess.targ_cfg.os {
|
||||
os_win32 | os_macos => llsize_of_alloc(self.ccx, rty) > 8,
|
||||
_ => true
|
||||
|
@ -52,13 +52,13 @@ impl ABIInfo for X86_ABIInfo {
|
|||
if sret {
|
||||
let ret_ptr_ty = LLVMType {
|
||||
cast: false,
|
||||
ty: T_ptr(ret_ty.ty)
|
||||
ty: ret_ty.ty.ptr_to()
|
||||
};
|
||||
arg_tys = ~[ret_ptr_ty] + arg_tys;
|
||||
attrs = ~[Some(StructRetAttribute)] + attrs;
|
||||
ret_ty = LLVMType {
|
||||
cast: false,
|
||||
ty: T_void(),
|
||||
ty: Type::void(),
|
||||
};
|
||||
} else if !ret_def {
|
||||
ret_ty = LLVMType {
|
||||
|
|
|
@ -26,66 +26,81 @@ use core::uint;
|
|||
use core::vec;
|
||||
|
||||
#[deriving(Eq)]
|
||||
enum x86_64_reg_class {
|
||||
no_class,
|
||||
integer_class,
|
||||
sse_fs_class,
|
||||
sse_fv_class,
|
||||
sse_ds_class,
|
||||
sse_dv_class,
|
||||
sse_int_class,
|
||||
sseup_class,
|
||||
x87_class,
|
||||
x87up_class,
|
||||
complex_x87_class,
|
||||
memory_class
|
||||
enum RegClass {
|
||||
NoClass,
|
||||
Integer,
|
||||
SSEFs,
|
||||
SSEFv,
|
||||
SSEDs,
|
||||
SSEDv,
|
||||
SSEInt,
|
||||
SSEUp,
|
||||
X87,
|
||||
X87Up,
|
||||
ComplexX87,
|
||||
Memory
|
||||
}
|
||||
|
||||
fn is_sse(c: x86_64_reg_class) -> bool {
|
||||
return match c {
|
||||
sse_fs_class | sse_fv_class |
|
||||
sse_ds_class | sse_dv_class => true,
|
||||
_ => false
|
||||
};
|
||||
impl Type {
|
||||
fn is_reg_ty(&self) -> bool {
|
||||
match ty.kind() {
|
||||
Integer | Pointer | Float | Double => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_ymm(cls: &[x86_64_reg_class]) -> bool {
|
||||
let len = cls.len();
|
||||
return (len > 2u &&
|
||||
is_sse(cls[0]) &&
|
||||
cls[1] == sseup_class &&
|
||||
cls[2] == sseup_class) ||
|
||||
(len > 3u &&
|
||||
is_sse(cls[1]) &&
|
||||
cls[2] == sseup_class &&
|
||||
cls[3] == sseup_class);
|
||||
impl RegClass {
|
||||
fn is_sse(&self) -> bool {
|
||||
match *self {
|
||||
SSEFs | SSEFv | SSEDs | SSEDv => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
||||
fn align(off: uint, ty: TypeRef) -> uint {
|
||||
impl<'self> ClassList for &'self [RegClass] {
|
||||
fn is_pass_byval(&self) -> bool {
|
||||
if self.len() == 0 { return false; }
|
||||
|
||||
let class = self[0];
|
||||
class == Memory
|
||||
|| class == X87
|
||||
|| class == ComplexX87
|
||||
}
|
||||
|
||||
fn is_ret_bysret(&self) -> bool {
|
||||
if self.len() == 0 { return false; }
|
||||
|
||||
self[0] == Memory
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ty(ty: Type) -> ~[RegClass] {
|
||||
fn align(off: uint, ty: Type) -> uint {
|
||||
let a = ty_align(ty);
|
||||
return (off + a - 1u) / a * a;
|
||||
}
|
||||
|
||||
fn ty_align(ty: TypeRef) -> uint {
|
||||
fn ty_align(ty: Type) -> uint {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
|
||||
((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
|
||||
}
|
||||
Pointer => 8,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||
if ty.is_packed() {
|
||||
1
|
||||
} else {
|
||||
let str_tys = struct_tys(ty);
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
let elt = ty.element_type();
|
||||
ty_align(elt)
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
|
@ -95,7 +110,7 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
|||
|
||||
fn ty_size(ty: TypeRef) -> uint {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
|
||||
}
|
||||
|
@ -103,35 +118,35 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
|||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||
let str_tys = struct_tys(ty);
|
||||
if ty.is_packed() {
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
|
||||
} else {
|
||||
let str_tys = struct_tys(ty);
|
||||
let str_tys = ty.field_types();
|
||||
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
|
||||
align(size, ty)
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
let eltsz = ty_size(elt);
|
||||
len * eltsz
|
||||
let len = ty.array_length();
|
||||
let elt = ty.element_type();
|
||||
let eltsz = ty_size(elt);
|
||||
len * eltsz
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn all_mem(cls: &mut [x86_64_reg_class]) {
|
||||
fn all_mem(cls: &mut [RegClass]) {
|
||||
for uint::range(0, cls.len()) |i| {
|
||||
cls[i] = memory_class;
|
||||
}
|
||||
}
|
||||
|
||||
fn unify(cls: &mut [x86_64_reg_class],
|
||||
fn unify(cls: &mut [RegClass],
|
||||
i: uint,
|
||||
newv: x86_64_reg_class) {
|
||||
newv: RegClass) {
|
||||
if cls[i] == newv {
|
||||
return;
|
||||
} else if cls[i] == no_class {
|
||||
|
@ -154,8 +169,8 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
|||
}
|
||||
}
|
||||
|
||||
fn classify_struct(tys: &[TypeRef],
|
||||
cls: &mut [x86_64_reg_class], i: uint,
|
||||
fn classify_struct(tys: &[Type],
|
||||
cls: &mut [RegClass], i: uint,
|
||||
off: uint) {
|
||||
let mut field_off = off;
|
||||
for tys.each |ty| {
|
||||
|
@ -165,8 +180,8 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
|||
}
|
||||
}
|
||||
|
||||
fn classify(ty: TypeRef,
|
||||
cls: &mut [x86_64_reg_class], ix: uint,
|
||||
fn classify(ty: Type,
|
||||
cls: &mut [RegClass], ix: uint,
|
||||
off: uint) {
|
||||
unsafe {
|
||||
let t_align = ty_align(ty);
|
||||
|
@ -183,28 +198,28 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
|||
return;
|
||||
}
|
||||
|
||||
match llvm::LLVMGetTypeKind(ty) as int {
|
||||
8 /* integer */ |
|
||||
12 /* pointer */ => {
|
||||
match ty.kind() {
|
||||
Integer |
|
||||
Pointer => {
|
||||
unify(cls, ix + off / 8u, integer_class);
|
||||
}
|
||||
2 /* float */ => {
|
||||
Float => {
|
||||
if off % 8u == 4u {
|
||||
unify(cls, ix + off / 8u, sse_fv_class);
|
||||
} else {
|
||||
unify(cls, ix + off / 8u, sse_fs_class);
|
||||
}
|
||||
}
|
||||
3 /* double */ => {
|
||||
Double => {
|
||||
unify(cls, ix + off / 8u, sse_ds_class);
|
||||
}
|
||||
10 /* struct */ => {
|
||||
classify_struct(struct_tys(ty), cls, ix, off);
|
||||
Struct => {
|
||||
classify_struct(ty.field_types(), cls, ix, off);
|
||||
}
|
||||
11 /* array */ => {
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
Array => {
|
||||
let len = ty.array_length();
|
||||
let elt = ty.element_type();
|
||||
let eltsz = ty_size(elt);
|
||||
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
||||
let mut i = 0u;
|
||||
while i < len {
|
||||
classify(elt, cls, ix, off + i * eltsz);
|
||||
|
@ -216,15 +231,15 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
|||
}
|
||||
}
|
||||
|
||||
fn fixup(ty: TypeRef, cls: &mut [x86_64_reg_class]) {
|
||||
fn fixup(ty: Type, cls: &mut [RegClass]) {
|
||||
unsafe {
|
||||
let mut i = 0u;
|
||||
let llty = llvm::LLVMGetTypeKind(ty) as int;
|
||||
let ty_kind = ty.kind();
|
||||
let e = cls.len();
|
||||
if cls.len() > 2u &&
|
||||
(llty == 10 /* struct */ ||
|
||||
llty == 11 /* array */) {
|
||||
if is_sse(cls[i]) {
|
||||
(ty_kind == Struct ||
|
||||
ty_kind == Array) {
|
||||
if cls[i].is_sse() {
|
||||
i += 1u;
|
||||
while i < e {
|
||||
if cls[i] != sseup_class {
|
||||
|
@ -251,7 +266,7 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
|||
}
|
||||
if cls[i] == sseup_class {
|
||||
cls[i] = sse_int_class;
|
||||
} else if is_sse(cls[i]) {
|
||||
} else if cls[i].is_sse() {
|
||||
i += 1;
|
||||
while i != e && cls[i] == sseup_class { i += 1u; }
|
||||
} else if cls[i] == x87_class {
|
||||
|
@ -277,8 +292,8 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
|||
return cls;
|
||||
}
|
||||
|
||||
fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef {
|
||||
fn llvec_len(cls: &[x86_64_reg_class]) -> uint {
|
||||
fn llreg_ty(cls: &[RegClass]) -> Type {
|
||||
fn llvec_len(cls: &[RegClass]) -> uint {
|
||||
let mut len = 1u;
|
||||
for cls.each |c| {
|
||||
if *c != sseup_class {
|
||||
|
@ -296,96 +311,68 @@ fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef {
|
|||
while i < e {
|
||||
match cls[i] {
|
||||
integer_class => {
|
||||
tys.push(T_i64());
|
||||
tys.push(Type::i64());
|
||||
}
|
||||
sse_fv_class => {
|
||||
let vec_len = llvec_len(vec::tailn(cls, i + 1u)) * 2u;
|
||||
let vec_ty = llvm::LLVMVectorType(T_f32(),
|
||||
vec_len as c_uint);
|
||||
let vec_ty = Type::vector(Type::f32(), vec_len);
|
||||
tys.push(vec_ty);
|
||||
i += vec_len;
|
||||
loop;
|
||||
}
|
||||
sse_fs_class => {
|
||||
tys.push(T_f32());
|
||||
tys.push(Type::f32());
|
||||
}
|
||||
sse_ds_class => {
|
||||
tys.push(T_f64());
|
||||
tys.push(Type::f64());
|
||||
}
|
||||
_ => fail!("llregtype: unhandled class")
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
return T_struct(tys, false);
|
||||
return Type::struct_(tys, false);
|
||||
}
|
||||
}
|
||||
|
||||
fn x86_64_tys(atys: &[TypeRef],
|
||||
rty: TypeRef,
|
||||
fn x86_64_tys(atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
fn is_reg_ty(ty: TypeRef) -> bool {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) as int {
|
||||
8 /* integer */ |
|
||||
12 /* pointer */ |
|
||||
2 /* float */ |
|
||||
3 /* double */ => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn is_pass_byval(cls: &[x86_64_reg_class]) -> bool {
|
||||
return cls.len() > 0 &&
|
||||
(cls[0] == memory_class ||
|
||||
cls[0] == x87_class ||
|
||||
cls[0] == complex_x87_class);
|
||||
}
|
||||
|
||||
fn is_ret_bysret(cls: &[x86_64_reg_class]) -> bool {
|
||||
return cls.len() > 0 && cls[0] == memory_class;
|
||||
}
|
||||
|
||||
fn x86_64_ty(ty: TypeRef,
|
||||
is_mem_cls: &fn(cls: &[x86_64_reg_class]) -> bool,
|
||||
fn x86_64_ty(ty: Type,
|
||||
is_mem_cls: &fn(cls: &[RegClass]) -> bool,
|
||||
attr: Attribute) -> (LLVMType, Option<Attribute>) {
|
||||
let mut cast = false;
|
||||
let mut ty_attr = option::None;
|
||||
let mut llty = ty;
|
||||
if !is_reg_ty(ty) {
|
||||
let (cast, attr, ty) = if !ty.is_reg_ty() {
|
||||
let cls = classify_ty(ty);
|
||||
if is_mem_cls(cls) {
|
||||
llty = T_ptr(ty);
|
||||
ty_attr = option::Some(attr);
|
||||
(false, option::Some(attr), ty.ptr_to())
|
||||
} else {
|
||||
cast = true;
|
||||
llty = llreg_ty(cls);
|
||||
(true, option::None, llreg_ty(cls))
|
||||
}
|
||||
}
|
||||
return (LLVMType { cast: cast, ty: llty }, ty_attr);
|
||||
};
|
||||
return (LLVMType { cast: cast, ty: ty }, attr);
|
||||
}
|
||||
|
||||
let mut arg_tys = ~[];
|
||||
let mut attrs = ~[];
|
||||
for atys.each |t| {
|
||||
let (ty, attr) = x86_64_ty(*t, is_pass_byval, ByValAttribute);
|
||||
let (ty, attr) = x86_64_ty(*t, |cls| cls.is_pass_byval(), ByValAttribute);
|
||||
arg_tys.push(ty);
|
||||
attrs.push(attr);
|
||||
}
|
||||
let mut (ret_ty, ret_attr) = x86_64_ty(rty, is_ret_bysret,
|
||||
let mut (ret_ty, ret_attr) = x86_64_ty(rty, |cls| cls.is_ret_bysret(),
|
||||
StructRetAttribute);
|
||||
let sret = ret_attr.is_some();
|
||||
if sret {
|
||||
arg_tys = vec::append(~[ret_ty], arg_tys);
|
||||
ret_ty = LLVMType {
|
||||
cast: false,
|
||||
ty: T_void()
|
||||
ty: Type::void()
|
||||
};
|
||||
attrs = vec::append(~[ret_attr], attrs);
|
||||
} else if !ret_def {
|
||||
ret_ty = LLVMType {
|
||||
cast: false,
|
||||
ty: T_void()
|
||||
ty: Type::void()
|
||||
};
|
||||
}
|
||||
return FnType {
|
||||
|
@ -400,8 +387,8 @@ enum X86_64_ABIInfo { X86_64_ABIInfo }
|
|||
|
||||
impl ABIInfo for X86_64_ABIInfo {
|
||||
fn compute_info(&self,
|
||||
atys: &[TypeRef],
|
||||
rty: TypeRef,
|
||||
atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
return x86_64_tys(atys, rty, ret_def);
|
||||
}
|
||||
|
|
|
@ -326,7 +326,7 @@ pub fn trans_fn_ref_with_vtables(
|
|||
let ref_ty = common::node_id_type(bcx, ref_id);
|
||||
|
||||
val = PointerCast(
|
||||
bcx, val, T_ptr(type_of::type_of_fn_from_ty(ccx, ref_ty)));
|
||||
bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
|
||||
}
|
||||
return FnData {llfn: val};
|
||||
}
|
||||
|
@ -516,7 +516,7 @@ pub fn trans_call_inner(in_cx: block,
|
|||
let mut bcx = callee.bcx;
|
||||
let ccx = cx.ccx();
|
||||
let ret_flag = if ret_in_loop {
|
||||
let flag = alloca(bcx, T_bool());
|
||||
let flag = alloca(bcx, Type::bool());
|
||||
Store(bcx, C_bool(false), flag);
|
||||
Some(flag)
|
||||
} else {
|
||||
|
@ -526,13 +526,13 @@ pub fn trans_call_inner(in_cx: block,
|
|||
let (llfn, llenv) = unsafe {
|
||||
match callee.data {
|
||||
Fn(d) => {
|
||||
(d.llfn, llvm::LLVMGetUndef(T_opaque_box_ptr(ccx)))
|
||||
(d.llfn, llvm::LLVMGetUndef(Type::opaque_box(ccx).ptr_to()))
|
||||
}
|
||||
Method(d) => {
|
||||
// Weird but true: we pass self in the *environment* slot!
|
||||
let llself = PointerCast(bcx,
|
||||
d.llself,
|
||||
T_opaque_box_ptr(ccx));
|
||||
Type::opaque_box(ccx).ptr_to());
|
||||
(d.llfn, llself)
|
||||
}
|
||||
Closure(d) => {
|
||||
|
@ -653,7 +653,7 @@ pub fn trans_ret_slot(bcx: block, fn_ty: ty::t, dest: expr::Dest)
|
|||
expr::Ignore => {
|
||||
if ty::type_is_nil(retty) {
|
||||
unsafe {
|
||||
llvm::LLVMGetUndef(T_ptr(T_nil()))
|
||||
llvm::LLVMGetUndef(Type::nil().ptr_to())
|
||||
}
|
||||
} else {
|
||||
alloc_ty(bcx, retty)
|
||||
|
@ -838,7 +838,7 @@ pub fn trans_arg_expr(bcx: block,
|
|||
// this could happen due to e.g. subtyping
|
||||
let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, &formal_arg_ty);
|
||||
let llformal_arg_ty = match self_mode {
|
||||
ty::ByRef => T_ptr(llformal_arg_ty),
|
||||
ty::ByRef => llformal_arg_ty.ptr_to(),
|
||||
ty::ByCopy => llformal_arg_ty,
|
||||
};
|
||||
debug!("casting actual type (%s) to match formal (%s)",
|
||||
|
|
|
@ -72,7 +72,7 @@ use syntax::parse::token::special_idents;
|
|||
// closure".
|
||||
//
|
||||
// Typically an opaque closure suffices because we only manipulate it
|
||||
// by ptr. The routine common::T_opaque_box_ptr() returns an
|
||||
// by ptr. The routine Type::opaque_box().ptr_to() returns an
|
||||
// appropriate type for such an opaque closure; it allows access to
|
||||
// the box fields, but not the closure_data itself.
|
||||
//
|
||||
|
@ -168,7 +168,7 @@ pub fn allocate_cbox(bcx: block, sigil: ast::Sigil, cdata_ty: ty::t)
|
|||
let _icx = bcx.insn_ctxt("closure::nuke_ref_count");
|
||||
// Initialize ref count to arbitrary value for debugging:
|
||||
let ccx = bcx.ccx();
|
||||
let llbox = PointerCast(bcx, llbox, T_opaque_box_ptr(ccx));
|
||||
let llbox = PointerCast(bcx, llbox, Type::opaque_box(ccx).ptr_to());
|
||||
let ref_cnt = GEPi(bcx, llbox, [0u, abi::box_field_refcnt]);
|
||||
let rc = C_int(ccx, 0x12345678);
|
||||
Store(bcx, rc, ref_cnt);
|
||||
|
@ -302,7 +302,7 @@ pub fn build_closure(bcx0: block,
|
|||
Some(retptr) => retptr,
|
||||
}
|
||||
};
|
||||
let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil()));
|
||||
let ret_casted = PointerCast(bcx, ret_true, Type::nil().ptr_to());
|
||||
let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(),
|
||||
mode: ByRef(ZeroMem)};
|
||||
env_vals.push(EnvValue {action: EnvRef,
|
||||
|
@ -509,22 +509,22 @@ pub fn make_opaque_cbox_take_glue(
|
|||
// ~fn requires a deep copy.
|
||||
let ccx = bcx.ccx();
|
||||
let tcx = ccx.tcx;
|
||||
let llopaquecboxty = T_opaque_box_ptr(ccx);
|
||||
let llopaquecboxty = Type::opaque_box(ccx).ptr_to();
|
||||
let cbox_in = Load(bcx, cboxptr);
|
||||
do with_cond(bcx, IsNotNull(bcx, cbox_in)) |bcx| {
|
||||
// Load the size from the type descr found in the cbox
|
||||
let cbox_in = PointerCast(bcx, cbox_in, llopaquecboxty);
|
||||
let tydescptr = GEPi(bcx, cbox_in, [0u, abi::box_field_tydesc]);
|
||||
let tydesc = Load(bcx, tydescptr);
|
||||
let tydesc = PointerCast(bcx, tydesc, T_ptr(ccx.tydesc_type));
|
||||
let tydesc = PointerCast(bcx, tydesc, ccx.tydesc_type.ptr_to());
|
||||
let sz = Load(bcx, GEPi(bcx, tydesc, [0u, abi::tydesc_field_size]));
|
||||
|
||||
// Adjust sz to account for the rust_opaque_box header fields
|
||||
let sz = Add(bcx, sz, machine::llsize_of(ccx, T_box_header(ccx)));
|
||||
let sz = Add(bcx, sz, machine::llsize_of(ccx, Type::box_header(ccx)));
|
||||
|
||||
// Allocate memory, update original ptr, and copy existing data
|
||||
let opaque_tydesc = PointerCast(bcx, tydesc, T_ptr(T_i8()));
|
||||
let rval = alloca(bcx, T_ptr(T_i8()));
|
||||
let opaque_tydesc = PointerCast(bcx, tydesc, Type::i8p());
|
||||
let rval = alloca(bcx, Type::i8p());
|
||||
let bcx = callee::trans_lang_call(
|
||||
bcx,
|
||||
bcx.tcx().lang_items.exchange_malloc_fn(),
|
||||
|
@ -585,7 +585,7 @@ pub fn make_opaque_cbox_free_glue(
|
|||
let ccx = bcx.ccx();
|
||||
do with_cond(bcx, IsNotNull(bcx, cbox)) |bcx| {
|
||||
// Load the type descr found in the cbox
|
||||
let lltydescty = T_ptr(ccx.tydesc_type);
|
||||
let lltydescty = ccx.tydesc_type.ptr_to();
|
||||
let cbox = Load(bcx, cbox);
|
||||
let tydescptr = GEPi(bcx, cbox, [0u, abi::box_field_tydesc]);
|
||||
let tydesc = Load(bcx, tydescptr);
|
||||
|
|
|
@ -53,9 +53,7 @@ pub use middle::trans::context::CrateContext;
|
|||
pub type namegen = @fn(s: &str) -> ident;
|
||||
pub fn new_namegen() -> namegen {
|
||||
let f: @fn(s: &str) -> ident = |prefix| {
|
||||
token::str_to_ident(fmt!("%s_%u",
|
||||
prefix,
|
||||
token::gensym(prefix)))
|
||||
token::str_to_ident(fmt!("%s_%u", prefix, token::gensym(prefix)))
|
||||
};
|
||||
f
|
||||
}
|
||||
|
@ -1030,27 +1028,29 @@ pub fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
|
|||
|
||||
|
||||
// LLVM constant constructors.
|
||||
pub fn C_null(t: TypeRef) -> ValueRef {
|
||||
pub fn C_null(t: Type) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstNull(t);
|
||||
llvm::LLVMConstNull(t.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_undef(t: TypeRef) -> ValueRef {
|
||||
pub fn C_undef(t: Type) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMGetUndef(t);
|
||||
llvm::LLVMGetUndef(t.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_integral(t: TypeRef, u: u64, sign_extend: Bool) -> ValueRef {
|
||||
pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstInt(t, u, sign_extend);
|
||||
llvm::LLVMConstInt(t.to_ref(), u, sign_extend as Bool)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_floating(s: &str, t: TypeRef) -> ValueRef {
|
||||
pub fn C_floating(s: &str, t: Type) -> ValueRef {
|
||||
unsafe {
|
||||
return str::as_c_str(s, |buf| llvm::LLVMConstRealOfString(t, buf));
|
||||
do s.as_c_str |buf| {
|
||||
llvm::LLVMConstRealOfString(t.to_ref(), buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1058,32 +1058,32 @@ pub fn C_nil() -> ValueRef {
|
|||
return C_struct([]);
|
||||
}
|
||||
|
||||
pub fn C_bool(b: bool) -> ValueRef {
|
||||
C_integral(T_bool(), if b { 1u64 } else { 0u64 }, False)
|
||||
pub fn C_bool(val: bool) -> ValueRef {
|
||||
C_integral(Type::bool(), val as u64, false)
|
||||
}
|
||||
|
||||
pub fn C_i1(b: bool) -> ValueRef {
|
||||
return C_integral(T_i1(), if b { 1 } else { 0 }, False);
|
||||
pub fn C_i1(val: bool) -> ValueRef {
|
||||
C_integral(Type::i1(), val as u64, false)
|
||||
}
|
||||
|
||||
pub fn C_i32(i: i32) -> ValueRef {
|
||||
return C_integral(T_i32(), i as u64, True);
|
||||
return C_integral(Type::i32(), i as u64, true);
|
||||
}
|
||||
|
||||
pub fn C_i64(i: i64) -> ValueRef {
|
||||
return C_integral(T_i64(), i as u64, True);
|
||||
return C_integral(Type::i64(), i as u64, true);
|
||||
}
|
||||
|
||||
pub fn C_int(cx: &CrateContext, i: int) -> ValueRef {
|
||||
return C_integral(cx.int_type, i as u64, True);
|
||||
return C_integral(cx.int_type, i as u64, true);
|
||||
}
|
||||
|
||||
pub fn C_uint(cx: &CrateContext, i: uint) -> ValueRef {
|
||||
return C_integral(cx.int_type, i as u64, False);
|
||||
return C_integral(cx.int_type, i as u64, false);
|
||||
}
|
||||
|
||||
pub fn C_u8(i: uint) -> ValueRef {
|
||||
return C_integral(T_i8(), i as u64, False);
|
||||
return C_integral(Type::i8(), i as u64, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1091,18 +1091,19 @@ pub fn C_u8(i: uint) -> ValueRef {
|
|||
// our boxed-and-length-annotated strings.
|
||||
pub fn C_cstr(cx: &mut CrateContext, s: @str) -> ValueRef {
|
||||
unsafe {
|
||||
match cx.const_cstr_cache.find(&s) {
|
||||
match cx.const_cstr_cache.find_equiv(&s) {
|
||||
Some(&llval) => return llval,
|
||||
None => ()
|
||||
}
|
||||
|
||||
let sc = do str::as_c_str(s) |buf| {
|
||||
llvm::LLVMConstStringInContext(cx.llcx, buf, s.len() as c_uint,
|
||||
False)
|
||||
let sc = do s.as_c_str |buf| {
|
||||
llvm::LLVMConstStringInContext(cx.llcx, buf, s.len() as c_uint, False)
|
||||
};
|
||||
|
||||
let gsym = token::gensym("str");
|
||||
let g = fmt!("str%u", gsym).as_c_str |buf| {
|
||||
llvm::LLVMAddGlobal(cx.llmod, val_ty(sc).to_ref(), buf)
|
||||
};
|
||||
let g =
|
||||
str::as_c_str(fmt!("str%u", (cx.names)("str").name),
|
||||
|buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf));
|
||||
llvm::LLVMSetInitializer(g, sc);
|
||||
llvm::LLVMSetGlobalConstant(g, True);
|
||||
lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
|
||||
|
@ -1118,7 +1119,7 @@ pub fn C_cstr(cx: &mut CrateContext, s: @str) -> ValueRef {
|
|||
pub fn C_estr_slice(cx: &mut CrateContext, s: @str) -> ValueRef {
|
||||
unsafe {
|
||||
let len = s.len();
|
||||
let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), T_ptr(T_i8()));
|
||||
let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p().to_ref());
|
||||
C_struct([cs, C_uint(cx, len + 1u /* +1 for null */)])
|
||||
}
|
||||
}
|
||||
|
@ -1126,10 +1127,9 @@ pub fn C_estr_slice(cx: &mut CrateContext, s: @str) -> ValueRef {
|
|||
// Returns a Plain Old LLVM String:
|
||||
pub fn C_postr(s: &str) -> ValueRef {
|
||||
unsafe {
|
||||
return do str::as_c_str(s) |buf| {
|
||||
llvm::LLVMConstStringInContext(base::task_llcx(),
|
||||
buf, s.len() as c_uint, False)
|
||||
};
|
||||
do s.as_c_str |buf| {
|
||||
llvm::LLVMConstStringInContext(base::task_llcx(), buf, s.len() as c_uint, False)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1138,17 +1138,14 @@ pub fn C_zero_byte_arr(size: uint) -> ValueRef {
|
|||
let mut i = 0u;
|
||||
let mut elts: ~[ValueRef] = ~[];
|
||||
while i < size { elts.push(C_u8(0u)); i += 1u; }
|
||||
return llvm::LLVMConstArray(T_i8(),
|
||||
vec::raw::to_ptr(elts),
|
||||
elts.len() as c_uint);
|
||||
return llvm::LLVMConstArray(Type::i8(), vec::raw::to_ptr(elts), elts.len() as c_uint);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
|
||||
unsafe {
|
||||
do vec::as_imm_buf(elts) |ptr, len| {
|
||||
llvm::LLVMConstStructInContext(base::task_llcx(),
|
||||
ptr, len as c_uint, False)
|
||||
llvm::LLVMConstStructInContext(base::task_llcx(), ptr, len as c_uint, False)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1156,8 +1153,7 @@ pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
|
|||
pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef {
|
||||
unsafe {
|
||||
do vec::as_imm_buf(elts) |ptr, len| {
|
||||
llvm::LLVMConstStructInContext(base::task_llcx(),
|
||||
ptr, len as c_uint, True)
|
||||
llvm::LLVMConstStructInContext(base::task_llcx(), ptr, len as c_uint, True)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1172,38 +1168,35 @@ pub fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef {
|
|||
|
||||
pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts),
|
||||
elts.len() as c_uint);
|
||||
return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts), elts.len() as c_uint);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_bytes(bytes: &[u8]) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstStringInContext(base::task_llcx(),
|
||||
cast::transmute(vec::raw::to_ptr(bytes)),
|
||||
bytes.len() as c_uint, True);
|
||||
let ptr = cast::transmute(vec::raw::to_ptr(bytes));
|
||||
return llvm::LLVMConstStringInContext(base::task_llcx(), ptr, bytes.len() as c_uint, True);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstStringInContext(base::task_llcx(),
|
||||
cast::transmute(vec::raw::to_ptr(bytes)),
|
||||
bytes.len() as c_uint, False);
|
||||
let ptr = cast::transmute(vec::raw::to_ptr(bytes));
|
||||
return llvm::LLVMConstStringInContext(base::task_llcx(), ptr, bytes.len() as c_uint,False);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_shape(ccx: &CrateContext, bytes: ~[u8]) -> ValueRef {
|
||||
unsafe {
|
||||
let llshape = C_bytes_plus_null(bytes);
|
||||
let name = fmt!("shape%u", (ccx.names)("shape").name);
|
||||
let llglobal = str::as_c_str(name, |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf)
|
||||
});
|
||||
llvm::LLVMSetInitializer(llglobal, llshape);
|
||||
let name = fmt!("shape%u", token::gensym("shape"));
|
||||
let llglobal = do name.as_c_str |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape).to_ref(), buf)
|
||||
};
|
||||
llvm::LLVMSetInitializer(llglobal, llshape.to_ref());
|
||||
llvm::LLVMSetGlobalConstant(llglobal, True);
|
||||
lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
|
||||
return llvm::LLVMConstPointerCast(llglobal, T_ptr(T_i8()));
|
||||
return llvm::LLVMConstPointerCast(llglobal, Type::i8p().to_ref());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1478,7 +1471,7 @@ pub fn filename_and_line_num_from_span(bcx: block,
|
|||
span: span) -> (ValueRef, ValueRef) {
|
||||
let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo);
|
||||
let filename_cstr = C_cstr(bcx.ccx(), loc.file.name);
|
||||
let filename = build::PointerCast(bcx, filename_cstr, T_ptr(T_i8()));
|
||||
let filename = build::PointerCast(bcx, filename_cstr, Type::i8p());
|
||||
let line = C_int(bcx.ccx(), loc.line as int);
|
||||
(filename, line)
|
||||
}
|
||||
|
|
|
@ -151,7 +151,11 @@ impl CrateContext {
|
|||
let tydesc_type = Type::tydesc(targ_cfg.arch);
|
||||
let opaque_vec_type = Type::opaque_vec(targ_cfg.arch);
|
||||
|
||||
let str_slice_ty = Type::named_struct("str_slice");
|
||||
str_slice_ty.set_struct_body([Type::i8p(), int_type]);
|
||||
|
||||
tn.associate_type("tydesc", &tydesc_type);
|
||||
tn.associate_type("str_slice", &str_slice_ty);
|
||||
|
||||
let crate_map = decl_crate_map(sess, link_meta, llmod);
|
||||
let dbg_cx = if sess.opts.debuginfo {
|
||||
|
@ -233,6 +237,7 @@ impl CrateContext {
|
|||
((end.nsec as int) - (start.nsec as int)) / 1000000;
|
||||
self.stats.fn_times.push((name, elapsed));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
|
|
|
@ -204,10 +204,10 @@ pub fn trans_log(log_ex: @ast::expr,
|
|||
let global;
|
||||
unsafe {
|
||||
global = str::as_c_str(s, |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, T_i32(), buf)
|
||||
llvm::LLVMAddGlobal(ccx.llmod, Type::i32(), buf)
|
||||
});
|
||||
llvm::LLVMSetGlobalConstant(global, False);
|
||||
llvm::LLVMSetInitializer(global, C_null(T_i32()));
|
||||
llvm::LLVMSetInitializer(global, C_null(Type::i32()));
|
||||
lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage);
|
||||
}
|
||||
ccx.module_data.insert(modname, global);
|
||||
|
@ -307,7 +307,7 @@ pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block {
|
|||
Store(bcx, C_bool(false), bcx.fcx.llretptr.get());
|
||||
expr::SaveIn(match e {
|
||||
Some(x) => PointerCast(bcx, retptr,
|
||||
T_ptr(type_of(bcx.ccx(), expr_ty(bcx, x)))),
|
||||
type_of(bcx.ccx(), expr_ty(bcx, x)).ptr_to()),
|
||||
None => retptr
|
||||
})
|
||||
}
|
||||
|
@ -381,8 +381,8 @@ fn trans_fail_value(bcx: block,
|
|||
(C_cstr(bcx.ccx(), @"<runtime>"), 0)
|
||||
}
|
||||
};
|
||||
let V_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8()));
|
||||
let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8()));
|
||||
let V_str = PointerCast(bcx, V_fail_str, Type::i8p());
|
||||
let V_filename = PointerCast(bcx, V_filename, Type::i8p());
|
||||
let args = ~[V_str, V_filename, C_int(ccx, V_line)];
|
||||
let bcx = callee::trans_lang_call(
|
||||
bcx, bcx.tcx().lang_items.fail_fn(), args, expr::Ignore);
|
||||
|
|
|
@ -474,7 +474,7 @@ impl Datum {
|
|||
ByRef(_) => self.val,
|
||||
ByValue => {
|
||||
if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
|
||||
C_null(T_ptr(type_of::type_of(bcx.ccx(), self.ty)))
|
||||
C_null(type_of::type_of(bcx.ccx(), self.ty).ptr_to())
|
||||
} else {
|
||||
let slot = alloc_ty(bcx, self.ty);
|
||||
Store(bcx, self.val, slot);
|
||||
|
|
|
@ -122,7 +122,7 @@ lvalues are *never* stored by value.
|
|||
use core::prelude::*;
|
||||
|
||||
use back::abi;
|
||||
use lib::llvm::{ValueRef, TypeRef, llvm};
|
||||
use lib::llvm::{ValueRef, llvm};
|
||||
use lib;
|
||||
use metadata::csearch;
|
||||
use middle::trans::_match;
|
||||
|
@ -794,7 +794,7 @@ fn trans_def_datum_unadjusted(bcx: block,
|
|||
ty: ty::mk_mach_uint(ast::ty_u8),
|
||||
mutbl: ast::m_imm
|
||||
}); // *u8
|
||||
(rust_ty, PointerCast(bcx, fn_data.llfn, T_ptr(T_i8())))
|
||||
(rust_ty, PointerCast(bcx, fn_data.llfn, Type::i8p()))
|
||||
} else {
|
||||
let fn_ty = expr_ty(bcx, ref_expr);
|
||||
(fn_ty, fn_data.llfn)
|
||||
|
@ -924,7 +924,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||
ix_val, unscaled_len)
|
||||
};
|
||||
let elt = InBoundsGEP(bcx, base, [ix_val]);
|
||||
let elt = PointerCast(bcx, elt, T_ptr(vt.llunit_ty));
|
||||
let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to());
|
||||
return DatumBlock {
|
||||
bcx: bcx,
|
||||
datum: Datum {val: elt,
|
||||
|
@ -963,7 +963,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||
// which may not be equal to the enum's type for
|
||||
// non-C-like enums.
|
||||
let val = base::get_item_val(bcx.ccx(), did.node);
|
||||
let pty = T_ptr(type_of(bcx.ccx(), const_ty));
|
||||
let pty = type_of(bcx.ccx(), const_ty).ptr_to();
|
||||
PointerCast(bcx, val, pty)
|
||||
} else {
|
||||
{
|
||||
|
@ -1054,7 +1054,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
|
|||
// This cast should not be necessary. We should cast self *once*,
|
||||
// but right now this conflicts with default methods.
|
||||
let real_self_ty = monomorphize_type(bcx, self_info.t);
|
||||
let llselfty = T_ptr(type_of::type_of(bcx.ccx(), real_self_ty));
|
||||
let llselfty = type_of::type_of(bcx.ccx(), real_self_ty).ptr_to();
|
||||
|
||||
let casted_val = PointerCast(bcx, self_info.v, llselfty);
|
||||
Datum {
|
||||
|
@ -1438,7 +1438,7 @@ fn trans_eager_binop(bcx: block,
|
|||
}
|
||||
let cmpr = base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op);
|
||||
bcx = cmpr.bcx;
|
||||
ZExt(bcx, cmpr.val, T_i8())
|
||||
ZExt(bcx, cmpr.val, Type::i8())
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -1491,7 +1491,7 @@ fn trans_lazy_binop(bcx: block,
|
|||
}
|
||||
|
||||
Br(past_rhs, join.llbb);
|
||||
let phi = Phi(join, T_bool(), [lhs, rhs], [past_lhs.llbb,
|
||||
let phi = Phi(join, Type::bool(), [lhs, rhs], [past_lhs.llbb,
|
||||
past_rhs.llbb]);
|
||||
|
||||
return immediate_rvalue_bcx(join, phi, binop_ty);
|
||||
|
@ -1548,7 +1548,7 @@ fn trans_overloaded_op(bcx: block,
|
|||
DoAutorefArg)
|
||||
}
|
||||
|
||||
fn int_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef,
|
||||
fn int_cast(bcx: block, lldsttype: Type, llsrctype: Type,
|
||||
llsrc: ValueRef, signed: bool) -> ValueRef {
|
||||
let _icx = bcx.insn_ctxt("int_cast");
|
||||
unsafe {
|
||||
|
@ -1566,7 +1566,7 @@ fn int_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef,
|
|||
}
|
||||
}
|
||||
|
||||
fn float_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef,
|
||||
fn float_cast(bcx: block, lldsttype: Type, llsrctype: Type,
|
||||
llsrc: ValueRef) -> ValueRef {
|
||||
let _icx = bcx.insn_ctxt("float_cast");
|
||||
let srcsz = lib::llvm::float_width(llsrctype);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use core::prelude::*;
|
||||
|
||||
use back::{link, abi};
|
||||
use lib::llvm::{TypeRef, ValueRef};
|
||||
use lib::llvm::{ValueRef};
|
||||
use lib;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::cabi;
|
||||
|
@ -72,10 +72,10 @@ struct ShimTypes {
|
|||
|
||||
/// Type of the struct we will use to shuttle values back and forth.
|
||||
/// This is always derived from the llsig.
|
||||
bundle_ty: TypeRef,
|
||||
bundle_ty: Type,
|
||||
|
||||
/// Type of the shim function itself.
|
||||
shim_fn_ty: TypeRef,
|
||||
shim_fn_ty: Type,
|
||||
|
||||
/// Adapter object for handling native ABI rules (trust me, you
|
||||
/// don't want to know).
|
||||
|
@ -83,8 +83,8 @@ struct ShimTypes {
|
|||
}
|
||||
|
||||
struct LlvmSignature {
|
||||
llarg_tys: ~[TypeRef],
|
||||
llret_ty: TypeRef,
|
||||
llarg_tys: ~[Type],
|
||||
llret_ty: Type,
|
||||
sret: bool,
|
||||
}
|
||||
|
||||
|
@ -113,20 +113,16 @@ fn shim_types(ccx: @mut CrateContext, id: ast::node_id) -> ShimTypes {
|
|||
_ => ccx.sess.bug("c_arg_and_ret_lltys called on non-function type")
|
||||
};
|
||||
let llsig = foreign_signature(ccx, &fn_sig);
|
||||
let bundle_ty = T_struct(vec::append_one(copy llsig.llarg_tys,
|
||||
T_ptr(llsig.llret_ty)),
|
||||
false);
|
||||
let bundle_ty = Type::struct_(llsig.llarg_tys + [llsig.llret_ty.ptr_to()], false);
|
||||
let ret_def = !ty::type_is_bot(fn_sig.output) &&
|
||||
!ty::type_is_nil(fn_sig.output);
|
||||
let fn_ty = abi_info(ccx).compute_info(llsig.llarg_tys,
|
||||
llsig.llret_ty,
|
||||
ret_def);
|
||||
let fn_ty = abi_info(ccx).compute_info(llsig.llarg_tys, llsig.llret_ty, ret_def);
|
||||
ShimTypes {
|
||||
fn_sig: fn_sig,
|
||||
llsig: llsig,
|
||||
ret_def: ret_def,
|
||||
bundle_ty: bundle_ty,
|
||||
shim_fn_ty: T_fn([T_ptr(bundle_ty)], T_void()),
|
||||
shim_fn_ty: Type::func([bundle_ty.ptr_to()], Type::void()),
|
||||
fn_ty: fn_ty
|
||||
}
|
||||
}
|
||||
|
@ -210,8 +206,8 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
|||
arg_builder(bcx, tys, llwrapfn, llargbundle);
|
||||
|
||||
// Create call itself.
|
||||
let llshimfnptr = PointerCast(bcx, llshimfn, T_ptr(T_i8()));
|
||||
let llrawargbundle = PointerCast(bcx, llargbundle, T_ptr(T_i8()));
|
||||
let llshimfnptr = PointerCast(bcx, llshimfn, Type::i8p());
|
||||
let llrawargbundle = PointerCast(bcx, llargbundle, Type::i8p());
|
||||
Call(bcx, shim_upcall, [llrawargbundle, llshimfnptr]);
|
||||
ret_builder(bcx, tys, llargbundle);
|
||||
|
||||
|
@ -239,7 +235,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
|||
// XXX: This is ugly.
|
||||
let llretptr = BitCast(return_context,
|
||||
fcx.llretptr.get(),
|
||||
T_ptr(llfunctionreturntype));
|
||||
llfunctionreturntype.ptr_to());
|
||||
Ret(return_context, Load(return_context, llretptr));
|
||||
}
|
||||
}
|
||||
|
@ -688,9 +684,9 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let static_ti = get_tydesc(ccx, tp_ty);
|
||||
glue::lazily_emit_all_tydesc_glue(ccx, static_ti);
|
||||
|
||||
// FIXME (#3727): change this to T_ptr(ccx.tydesc_ty) when the
|
||||
// FIXME (#3727): change this to ccx.tydesc_ty.ptr_to() when the
|
||||
// core::sys copy of the get_tydesc interface dies off.
|
||||
let td = PointerCast(bcx, static_ti.tydesc, T_ptr(T_nil()));
|
||||
let td = PointerCast(bcx, static_ti.tydesc, Type::nil().ptr_to());
|
||||
Store(bcx, td, fcx.llretptr.get());
|
||||
}
|
||||
"init" => {
|
||||
|
@ -734,7 +730,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
// code bloat when `transmute` is used on large structural
|
||||
// types.
|
||||
let lldestptr = fcx.llretptr.get();
|
||||
let lldestptr = PointerCast(bcx, lldestptr, T_ptr(T_i8()));
|
||||
let lldestptr = PointerCast(bcx, lldestptr, Type::i8p());
|
||||
|
||||
let llsrcval = get_param(decl, first_real_arg);
|
||||
let llsrcptr = if ty::type_is_immediate(in_type) {
|
||||
|
@ -744,7 +740,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
} else {
|
||||
llsrcval
|
||||
};
|
||||
let llsrcptr = PointerCast(bcx, llsrcptr, T_ptr(T_i8()));
|
||||
let llsrcptr = PointerCast(bcx, llsrcptr, Type::i8p());
|
||||
|
||||
let llsize = llsize_of(ccx, llintype);
|
||||
call_memcpy(bcx, lldestptr, llsrcptr, llsize, 1);
|
||||
|
@ -761,12 +757,9 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let visitor = get_param(decl, first_real_arg + 1u);
|
||||
//let llvisitorptr = alloca(bcx, val_ty(visitor));
|
||||
//Store(bcx, visitor, llvisitorptr);
|
||||
let td = PointerCast(bcx, td, T_ptr(ccx.tydesc_type));
|
||||
glue::call_tydesc_glue_full(bcx,
|
||||
visitor,
|
||||
td,
|
||||
abi::tydesc_field_visit_glue,
|
||||
None);
|
||||
let td = PointerCast(bcx, td, ccx.tydesc_type.ptr_to());
|
||||
glue::call_tydesc_glue_full(bcx, visitor, td,
|
||||
abi::tydesc_field_visit_glue, None);
|
||||
}
|
||||
"frame_address" => {
|
||||
let frameaddress = ccx.intrinsics.get_copy(& &"llvm.frameaddress");
|
||||
|
@ -801,8 +794,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let llfty = type_of_fn(bcx.ccx(), [], ty::mk_nil());
|
||||
let morestack_addr = decl_cdecl_fn(
|
||||
bcx.ccx().llmod, "__morestack", llfty);
|
||||
let morestack_addr = PointerCast(bcx, morestack_addr,
|
||||
T_ptr(T_nil()));
|
||||
let morestack_addr = PointerCast(bcx, morestack_addr, Type::nil().ptr_to());
|
||||
Store(bcx, morestack_addr, fcx.llretptr.get());
|
||||
}
|
||||
"memcpy32" => {
|
||||
|
@ -811,8 +803,8 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p());
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
let llfn = bcx.ccx().intrinsics.get_copy(& &"llvm.memcpy.p0i8.p0i8.i32");
|
||||
|
@ -824,8 +816,8 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p());
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
let llfn = bcx.ccx().intrinsics.get_copy(& &"llvm.memcpy.p0i8.p0i8.i64");
|
||||
|
@ -837,8 +829,8 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p());
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
let llfn = bcx.ccx().intrinsics.get_copy(& &"llvm.memmove.p0i8.p0i8.i32");
|
||||
|
@ -850,8 +842,8 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p());
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
let llfn = bcx.ccx().intrinsics.get_copy(& &"llvm.memmove.p0i8.p0i8.i64");
|
||||
|
@ -863,7 +855,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let val = get_param(decl, first_real_arg + 1);
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
|
@ -876,7 +868,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let val = get_param(decl, first_real_arg + 1);
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
|
@ -1231,7 +1223,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
|||
llargvals.push(llretptr);
|
||||
}
|
||||
|
||||
let llenvptr = C_null(T_opaque_box_ptr(bcx.ccx()));
|
||||
let llenvptr = C_null(Type::opaque_box(bcx.ccx()).ptr_to());
|
||||
llargvals.push(llenvptr);
|
||||
while i < n {
|
||||
// Get a pointer to the argument:
|
||||
|
|
|
@ -18,7 +18,7 @@ use back::abi;
|
|||
use back::link::*;
|
||||
use driver::session;
|
||||
use lib;
|
||||
use lib::llvm::{llvm, ValueRef, TypeRef, True};
|
||||
use lib::llvm::{llvm, ValueRef, Type, True};
|
||||
use middle::trans::adt;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::callee;
|
||||
|
@ -44,19 +44,17 @@ use syntax::ast;
|
|||
|
||||
pub fn trans_free(cx: block, v: ValueRef) -> block {
|
||||
let _icx = cx.insn_ctxt("trans_free");
|
||||
callee::trans_lang_call(
|
||||
cx,
|
||||
callee::trans_lang_call(cx,
|
||||
cx.tcx().lang_items.free_fn(),
|
||||
[PointerCast(cx, v, T_ptr(T_i8()))],
|
||||
[PointerCast(cx, v, Type::i8p())],
|
||||
expr::Ignore)
|
||||
}
|
||||
|
||||
pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
|
||||
let _icx = cx.insn_ctxt("trans_exchange_free");
|
||||
callee::trans_lang_call(
|
||||
cx,
|
||||
callee::trans_lang_call(cx,
|
||||
cx.tcx().lang_items.exchange_free_fn(),
|
||||
[PointerCast(cx, v, T_ptr(T_i8()))],
|
||||
[PointerCast(cx, v, Type::i8p())],
|
||||
expr::Ignore)
|
||||
}
|
||||
|
||||
|
@ -78,14 +76,10 @@ pub fn drop_ty(cx: block, v: ValueRef, t: ty::t) -> block {
|
|||
return cx;
|
||||
}
|
||||
|
||||
pub fn drop_ty_root(bcx: block,
|
||||
v: ValueRef,
|
||||
rooted: bool,
|
||||
t: ty::t)
|
||||
-> block {
|
||||
pub fn drop_ty_root(bcx: block, v: ValueRef, rooted: bool, t: ty::t) -> block {
|
||||
if rooted {
|
||||
// NB: v is a raw ptr to an addrspace'd ptr to the value.
|
||||
let v = PointerCast(bcx, Load(bcx, v), T_ptr(type_of(bcx.ccx(), t)));
|
||||
let v = PointerCast(bcx, Load(bcx, v), type_of(bcx.ccx(), t).ptr_to());
|
||||
drop_ty(bcx, v, t)
|
||||
} else {
|
||||
drop_ty(bcx, v, t)
|
||||
|
@ -95,14 +89,14 @@ pub fn drop_ty_root(bcx: block,
|
|||
pub fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
|
||||
let _icx = bcx.insn_ctxt("drop_ty_immediate");
|
||||
match ty::get(t).sty {
|
||||
ty::ty_uniq(_) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) |
|
||||
ty::ty_estr(ty::vstore_uniq) => {
|
||||
ty::ty_uniq(_)
|
||||
| ty::ty_evec(_, ty::vstore_uniq)
|
||||
| ty::ty_estr(ty::vstore_uniq) => {
|
||||
free_ty_immediate(bcx, v, t)
|
||||
}
|
||||
ty::ty_box(_) | ty::ty_opaque_box |
|
||||
ty::ty_evec(_, ty::vstore_box) |
|
||||
ty::ty_estr(ty::vstore_box) => {
|
||||
ty::ty_box(_) | ty::ty_opaque_box
|
||||
| ty::ty_evec(_, ty::vstore_box)
|
||||
| ty::ty_estr(ty::vstore_box) => {
|
||||
decr_refcnt_maybe_free(bcx, v, None, t)
|
||||
}
|
||||
_ => bcx.tcx().sess.bug("drop_ty_immediate: non-box ty")
|
||||
|
@ -340,7 +334,7 @@ pub fn call_tydesc_glue_full(bcx: block,
|
|||
}
|
||||
};
|
||||
|
||||
let llrawptr = PointerCast(bcx, v, T_ptr(T_i8()));
|
||||
let llrawptr = PointerCast(bcx, v, Type::i8p());
|
||||
|
||||
let llfn = {
|
||||
match static_glue_fn {
|
||||
|
@ -353,8 +347,8 @@ pub fn call_tydesc_glue_full(bcx: block,
|
|||
}
|
||||
};
|
||||
|
||||
Call(bcx, llfn, [C_null(T_ptr(T_nil())),
|
||||
C_null(T_ptr(T_ptr(bcx.ccx().tydesc_type))),
|
||||
Call(bcx, llfn, [C_null(Type::nil().ptr_to()),
|
||||
C_null(bcx.ccx().tydesc_type.ptr_to().ptr_to()),
|
||||
llrawptr]);
|
||||
}
|
||||
|
||||
|
@ -372,7 +366,7 @@ pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
|
|||
let bcx = do with_scope(bcx, None, "visitor cleanup") |bcx| {
|
||||
let mut bcx = bcx;
|
||||
let (visitor_trait, object_ty) = ty::visitor_object_ty(bcx.tcx());
|
||||
let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), object_ty)));
|
||||
let v = PointerCast(bcx, v, type_of::type_of(bcx.ccx(), object_ty).ptr_to());
|
||||
bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id);
|
||||
// The visitor is a boxed object and needs to be dropped
|
||||
add_clean(bcx, v, object_ty);
|
||||
|
@ -390,7 +384,7 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
|
|||
let v = Load(bcx, v);
|
||||
let body = GEPi(bcx, v, [0u, abi::box_field_body]);
|
||||
// Cast away the addrspace of the box pointer.
|
||||
let body = PointerCast(bcx, body, T_ptr(type_of(ccx, body_mt.ty)));
|
||||
let body = PointerCast(bcx, body, type_of(ccx, body_mt.ty).ptr_to());
|
||||
let bcx = drop_ty(bcx, body, body_mt.ty);
|
||||
trans_free(bcx, v)
|
||||
}
|
||||
|
@ -517,9 +511,8 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
|
|||
let llvtable = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable]));
|
||||
|
||||
// Cast the vtable to a pointer to a pointer to a tydesc.
|
||||
let llvtable = PointerCast(bcx,
|
||||
llvtable,
|
||||
T_ptr(T_ptr(ccx.tydesc_type)));
|
||||
let llvtable = PointerCast(bcx, llvtable,
|
||||
ccx.tydesc_type.ptr_to().ptr_to());
|
||||
let lltydesc = Load(bcx, llvtable);
|
||||
call_tydesc_glue_full(bcx,
|
||||
lluniquevalue,
|
||||
|
@ -680,7 +673,7 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
|
|||
|
||||
pub type glue_helper = @fn(block, ValueRef, ty::t);
|
||||
|
||||
pub fn declare_generic_glue(ccx: @mut CrateContext, t: ty::t, llfnty: TypeRef,
|
||||
pub fn declare_generic_glue(ccx: @mut CrateContext, t: ty::t, llfnty: Type,
|
||||
name: ~str) -> ValueRef {
|
||||
let _icx = ccx.insn_ctxt("declare_generic_glue");
|
||||
let name = name;
|
||||
|
@ -711,7 +704,7 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext,
|
|||
let rawptr0_arg = fcx.arg_pos(1u);
|
||||
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
|
||||
let llty = type_of(ccx, t);
|
||||
let llrawptr0 = PointerCast(bcx, llrawptr0, T_ptr(llty));
|
||||
let llrawptr0 = PointerCast(bcx, llrawptr0, llty.ptr_to());
|
||||
helper(bcx, llrawptr0, t);
|
||||
finish_fn(fcx, lltop);
|
||||
return llfn;
|
||||
|
@ -739,7 +732,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
|
|||
//let _icx = ccx.insn_ctxt("emit_tydescs");
|
||||
// As of this point, allow no more tydescs to be created.
|
||||
ccx.finished_tydescs = true;
|
||||
let glue_fn_ty = T_ptr(T_generic_glue_fn(ccx));
|
||||
let glue_fn_ty = T_generic_glue_fn(ccx).ptr_to();
|
||||
let tyds = &mut ccx.tydescs;
|
||||
for tyds.each_value |&val| {
|
||||
let ti = val;
|
||||
|
@ -789,8 +782,8 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
|
|||
}
|
||||
};
|
||||
|
||||
let shape = C_null(T_ptr(T_i8()));
|
||||
let shape_tables = C_null(T_ptr(T_i8()));
|
||||
let shape = C_null(Type::i8p());
|
||||
let shape_tables = C_null(Type::i8p());
|
||||
|
||||
let tydesc =
|
||||
C_named_struct(ccx.tydesc_type,
|
||||
|
@ -811,7 +804,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
|
|||
|
||||
// Index tydesc by addrspace.
|
||||
if ti.addrspace > gc_box_addrspace {
|
||||
let llty = T_ptr(ccx.tydesc_type);
|
||||
let llty = ccx.tydesc_type.ptr_to();
|
||||
let addrspace_name = fmt!("_gc_addrspace_metadata_%u",
|
||||
ti.addrspace as uint);
|
||||
let addrspace_gvar = str::as_c_str(addrspace_name, |buf| {
|
||||
|
|
|
@ -22,17 +22,17 @@ use util::ppaux::ty_to_str;
|
|||
// compute sizeof / alignof
|
||||
|
||||
// Returns the number of bytes clobbered by a Store to this type.
|
||||
pub fn llsize_of_store(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llsize_of_store(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
return llvm::LLVMStoreSizeOfType(cx.td.lltd, t) as uint;
|
||||
return llvm::LLVMStoreSizeOfType(cx.td.lltd, ty.to_ref()) as uint;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the number of bytes between successive elements of type T in an
|
||||
// array of T. This is the "ABI" size. It includes any ABI-mandated padding.
|
||||
pub fn llsize_of_alloc(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llsize_of_alloc(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
return llvm::LLVMABISizeOfType(cx.td.lltd, t) as uint;
|
||||
return llvm::LLVMABISizeOfType(cx.td.lltd, ty.to_ref()) as uint;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,9 +44,9 @@ pub fn llsize_of_alloc(cx: &CrateContext, t: TypeRef) -> uint {
|
|||
// that LLVM *does* distinguish between e.g. a 1-bit value and an 8-bit value
|
||||
// at the codegen level! In general you should prefer `llbitsize_of_real`
|
||||
// below.
|
||||
pub fn llsize_of_real(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llsize_of_real(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
let nbits = llvm::LLVMSizeOfTypeInBits(cx.td.lltd, t) as uint;
|
||||
let nbits = llvm::LLVMSizeOfTypeInBits(cx.td.lltd, ty.to_ref()) as uint;
|
||||
if nbits & 7u != 0u {
|
||||
// Not an even number of bytes, spills into "next" byte.
|
||||
1u + (nbits >> 3)
|
||||
|
@ -57,14 +57,14 @@ pub fn llsize_of_real(cx: &CrateContext, t: TypeRef) -> uint {
|
|||
}
|
||||
|
||||
/// Returns the "real" size of the type in bits.
|
||||
pub fn llbitsize_of_real(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llbitsize_of_real(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
llvm::LLVMSizeOfTypeInBits(cx.td.lltd, t) as uint
|
||||
llvm::LLVMSizeOfTypeInBits(cx.td.lltd, ty.to_ref()) as uint
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the size of the type as an LLVM constant integer value.
|
||||
pub fn llsize_of(cx: &CrateContext, t: TypeRef) -> ValueRef {
|
||||
pub fn llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
|
||||
// Once upon a time, this called LLVMSizeOf, which does a
|
||||
// getelementptr(1) on a null pointer and casts to an int, in
|
||||
// order to obtain the type size as a value without requiring the
|
||||
|
@ -72,17 +72,17 @@ pub fn llsize_of(cx: &CrateContext, t: TypeRef) -> ValueRef {
|
|||
// there's no need for that contrivance. The instruction
|
||||
// selection DAG generator would flatten that GEP(1) node into a
|
||||
// constant of the type's alloc size, so let's save it some work.
|
||||
return C_uint(cx, llsize_of_alloc(cx, t));
|
||||
return C_uint(cx, llsize_of_alloc(cx, ty));
|
||||
}
|
||||
|
||||
// Returns the "default" size of t (see above), or 1 if the size would
|
||||
// be zero. This is important for things like vectors that expect
|
||||
// space to be consumed.
|
||||
pub fn nonzero_llsize_of(cx: &CrateContext, t: TypeRef) -> ValueRef {
|
||||
if llbitsize_of_real(cx, t) == 0 {
|
||||
unsafe { llvm::LLVMConstInt(cx.int_type, 1, False) }
|
||||
pub fn nonzero_llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
|
||||
if llbitsize_of_real(cx, ty) == 0 {
|
||||
unsafe { llvm::LLVMConstInt(cx.int_type.to_ref(), 1, False) }
|
||||
} else {
|
||||
llsize_of(cx, t)
|
||||
llsize_of(cx, ty)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,28 +90,28 @@ pub fn nonzero_llsize_of(cx: &CrateContext, t: TypeRef) -> ValueRef {
|
|||
// The preferred alignment may be larger than the alignment used when
|
||||
// packing the type into structs. This will be used for things like
|
||||
// allocations inside a stack frame, which LLVM has a free hand in.
|
||||
pub fn llalign_of_pref(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llalign_of_pref(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
return llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, t) as uint;
|
||||
return llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, ty.to_ref()) as uint;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the minimum alignment of a type required by the platform.
|
||||
// This is the alignment that will be used for struct fields, arrays,
|
||||
// and similar ABI-mandated things.
|
||||
pub fn llalign_of_min(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llalign_of_min(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
return llvm::LLVMABIAlignmentOfType(cx.td.lltd, t) as uint;
|
||||
return llvm::LLVMABIAlignmentOfType(cx.td.lltd, ty.to_ref()) as uint;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the "default" alignment of t, which is calculated by casting
|
||||
// null to a record containing a single-bit followed by a t value, then
|
||||
// doing gep(0,1) to get at the trailing (and presumably padded) t cell.
|
||||
pub fn llalign_of(cx: &CrateContext, t: TypeRef) -> ValueRef {
|
||||
pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstIntCast(
|
||||
llvm::LLVMAlignOf(t), cx.int_type, False);
|
||||
llvm::LLVMAlignOf(ty.to_ref()), cx.int_type.to_ref(), False);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ pub fn static_size_of_enum(cx: &mut CrateContext, t: ty::t) -> uint {
|
|||
cx.tcx.sess.str_of(variant.name),
|
||||
cx.tn.type_to_str(T_struct(lltypes, false)));
|
||||
|
||||
let this_size = llsize_of_real(cx, T_struct(lltypes, false));
|
||||
let this_size = llsize_of_real(cx, Type::struct_(lltypes, false));
|
||||
if max_size < this_size {
|
||||
max_size = this_size;
|
||||
}
|
||||
|
|
|
@ -363,7 +363,7 @@ pub fn trans_static_method_callee(bcx: block,
|
|||
Some(callee_origins));
|
||||
|
||||
let callee_ty = node_id_type(bcx, callee_id);
|
||||
let llty = T_ptr(type_of_fn_from_ty(ccx, callee_ty));
|
||||
let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
|
||||
FnData {llfn: PointerCast(bcx, lval, llty)}
|
||||
}
|
||||
_ => {
|
||||
|
@ -463,7 +463,7 @@ pub fn trans_monomorphized_callee(bcx: block,
|
|||
|
||||
// create a llvalue that represents the fn ptr
|
||||
let fn_ty = node_id_type(bcx, callee_id);
|
||||
let llfn_ty = T_ptr(type_of_fn_from_ty(ccx, fn_ty));
|
||||
let llfn_ty = type_of_fn_from_ty(ccx, fn_ty).to_ptr();
|
||||
let llfn_val = PointerCast(bcx, callee.llfn, llfn_ty);
|
||||
|
||||
// combine the self environment with the rest
|
||||
|
@ -628,7 +628,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
|
|||
PointerCast(bcx,
|
||||
GEPi(bcx, llpair,
|
||||
[0u, abi::trt_field_vtable]),
|
||||
T_ptr(T_ptr(T_vtable()))));
|
||||
Type::vtable().ptr_to().ptr_to()));
|
||||
|
||||
// Load the box from the @Trait pair and GEP over the box header if
|
||||
// necessary:
|
||||
|
@ -705,7 +705,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
|
|||
// Plus one in order to skip past the type descriptor.
|
||||
let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1]));
|
||||
|
||||
let mptr = PointerCast(bcx, mptr, T_ptr(llcallee_ty));
|
||||
let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to());
|
||||
|
||||
return Callee {
|
||||
bcx: bcx,
|
||||
|
@ -814,7 +814,7 @@ pub fn make_impl_vtable(bcx: block,
|
|||
if im.generics.has_type_params() || ty::type_has_self(fty) {
|
||||
debug!("(making impl vtable) method has self or type params: %s",
|
||||
tcx.sess.str_of(im.ident));
|
||||
C_null(T_ptr(T_nil()))
|
||||
C_null(Type::nil().ptr_to())
|
||||
} else {
|
||||
debug!("(making impl vtable) adding method to vtable: %s",
|
||||
tcx.sess.str_of(im.ident));
|
||||
|
@ -857,7 +857,7 @@ pub fn trans_trait_cast(bcx: block,
|
|||
// have no type descriptor field.)
|
||||
llboxdest = PointerCast(bcx,
|
||||
llboxdest,
|
||||
T_ptr(type_of(bcx.ccx(), v_ty)));
|
||||
type_of(bcx.ccx(), v_ty).ptr_to());
|
||||
bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
|
||||
|
||||
// Store the vtable into the pair or triple.
|
||||
|
@ -866,7 +866,7 @@ pub fn trans_trait_cast(bcx: block,
|
|||
let vtable = get_vtable(bcx, v_ty, orig);
|
||||
Store(bcx, vtable, PointerCast(bcx,
|
||||
GEPi(bcx, lldest, [0u, abi::trt_field_vtable]),
|
||||
T_ptr(val_ty(vtable))));
|
||||
val_ty(vtable).ptr_to()));
|
||||
|
||||
bcx
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use back::link::mangle_internal_name_by_path_and_seq;
|
||||
use lib::llvm::{TypeRef, ValueRef, llvm};
|
||||
use lib::llvm::{Type, ValueRef, llvm};
|
||||
use middle::trans::adt;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
|
@ -37,7 +37,7 @@ pub struct Reflector {
|
|||
visitor_val: ValueRef,
|
||||
visitor_methods: @~[@ty::Method],
|
||||
final_bcx: block,
|
||||
tydesc_ty: TypeRef,
|
||||
tydesc_ty: Type,
|
||||
bcx: block
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ impl Reflector {
|
|||
let str_ty = ty::mk_estr(bcx.tcx(), str_vstore);
|
||||
let scratch = scratch_datum(bcx, str_ty, false);
|
||||
let len = C_uint(bcx.ccx(), s.len() + 1);
|
||||
let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), T_ptr(T_i8()));
|
||||
let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), Type::i8p());
|
||||
Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ]));
|
||||
Store(bcx, len, GEPi(bcx, scratch.val, [ 0, 1 ]));
|
||||
scratch.val
|
||||
|
@ -76,7 +76,7 @@ impl Reflector {
|
|||
let bcx = self.bcx;
|
||||
let static_ti = get_tydesc(bcx.ccx(), t);
|
||||
glue::lazily_emit_all_tydesc_glue(bcx.ccx(), static_ti);
|
||||
PointerCast(bcx, static_ti.tydesc, T_ptr(self.tydesc_ty))
|
||||
PointerCast(bcx, static_ti.tydesc, self.tydesc_ty.ptr_to())
|
||||
}
|
||||
|
||||
pub fn c_mt(&mut self, mt: &ty::mt) -> ~[ValueRef] {
|
||||
|
@ -271,7 +271,7 @@ impl Reflector {
|
|||
let ccx = bcx.ccx();
|
||||
let repr = adt::represent_type(bcx.ccx(), t);
|
||||
let variants = ty::substd_enum_variants(ccx.tcx, did, substs);
|
||||
let llptrty = T_ptr(type_of(ccx, t));
|
||||
let llptrty = type_of(ccx, t).ptr_to();
|
||||
let (_, opaquety) =
|
||||
ccx.tcx.intrinsic_defs.find_copy(&ccx.sess.ident_of("Opaque"))
|
||||
.expect("Failed to resolve intrinsic::Opaque");
|
||||
|
|
|
@ -48,23 +48,22 @@ pub fn mk_global(ccx: &CrateContext,
|
|||
|
||||
pub fn mk_ctxt(llmod: ModuleRef) -> Ctxt {
|
||||
unsafe {
|
||||
let llshapetablesty = trans::common::T_named_struct("shapes");
|
||||
let _llshapetables = str::as_c_str("shapes", |buf| {
|
||||
let llshapetablesty = Type::named_struct("shapes");
|
||||
do "shapes".as_c_str |buf| {
|
||||
llvm::LLVMAddGlobal(llmod, llshapetablesty, buf)
|
||||
});
|
||||
};
|
||||
|
||||
return Ctxt {
|
||||
Ctxt {
|
||||
next_tag_id: 0u16,
|
||||
pad: 0u16,
|
||||
pad2: 0u32
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Although these two functions are never called, they are here
|
||||
for a VERY GOOD REASON. See #3670
|
||||
*/
|
||||
pub fn add_u16(dest: &mut ~[u8], val: u16) {
|
||||
*dest += [(val & 0xffu16) as u8, (val >> 8u16) as u8];
|
||||
}
|
||||
|
@ -73,3 +72,4 @@ pub fn add_substr(dest: &mut ~[u8], src: ~[u8]) {
|
|||
add_u16(&mut *dest, src.len() as u16);
|
||||
*dest += src;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
use back::abi;
|
||||
use lib;
|
||||
use lib::llvm::{llvm, ValueRef, TypeRef};
|
||||
use lib::llvm::{llvm, ValueRef};
|
||||
use middle::trans::base;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
|
@ -73,7 +73,7 @@ pub fn get_dataptr(bcx: block, vptr: ValueRef) -> ValueRef {
|
|||
pub fn pointer_add(bcx: block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
|
||||
let _icx = bcx.insn_ctxt("tvec::pointer_add");
|
||||
let old_ty = val_ty(ptr);
|
||||
let bptr = PointerCast(bcx, ptr, T_ptr(T_i8()));
|
||||
let bptr = PointerCast(bcx, ptr, Type::i8p());
|
||||
return PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ pub fn make_drop_glue_unboxed(bcx: block, vptr: ValueRef, vec_ty: ty::t) ->
|
|||
pub struct VecTypes {
|
||||
vec_ty: ty::t,
|
||||
unit_ty: ty::t,
|
||||
llunit_ty: TypeRef,
|
||||
llunit_ty: Type,
|
||||
llunit_size: ValueRef
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,7 @@ pub fn trans_slice_vstore(bcx: block,
|
|||
let fixed_ty = ty::mk_evec(bcx.tcx(),
|
||||
ty::mt {ty: vt.unit_ty, mutbl: ast::m_mutbl},
|
||||
ty::vstore_fixed(count));
|
||||
let llfixed_ty = T_ptr(type_of::type_of(bcx.ccx(), fixed_ty));
|
||||
let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty).ptr_to();
|
||||
let llfixed_casted = BitCast(bcx, llfixed, llfixed_ty);
|
||||
add_clean(bcx, llfixed_casted, fixed_ty);
|
||||
|
||||
|
@ -271,13 +271,10 @@ pub fn trans_lit_str(bcx: block,
|
|||
let bytes = str_lit.len() + 1; // count null-terminator too
|
||||
let llbytes = C_uint(bcx.ccx(), bytes);
|
||||
let llcstr = C_cstr(bcx.ccx(), str_lit);
|
||||
let llcstr = llvm::LLVMConstPointerCast(llcstr,
|
||||
T_ptr(T_i8()));
|
||||
Store(bcx,
|
||||
llcstr,
|
||||
let llcstr = llvm::LLVMConstPointerCast(llcstr, Type::i8p().to_ref());
|
||||
Store(bcx, llcstr,
|
||||
GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
|
||||
Store(bcx,
|
||||
llbytes,
|
||||
Store(bcx, llbytes,
|
||||
GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
|
||||
bcx
|
||||
}
|
||||
|
@ -286,9 +283,7 @@ pub fn trans_lit_str(bcx: block,
|
|||
}
|
||||
|
||||
|
||||
pub fn trans_uniq_or_managed_vstore(bcx: block,
|
||||
heap: heap,
|
||||
vstore_expr: @ast::expr,
|
||||
pub fn trans_uniq_or_managed_vstore(bcx: block, heap: heap, vstore_expr: @ast::expr,
|
||||
content_expr: @ast::expr) -> DatumBlock {
|
||||
//!
|
||||
//
|
||||
|
@ -307,7 +302,7 @@ pub fn trans_uniq_or_managed_vstore(bcx: block,
|
|||
node: ast::lit_str(s), _
|
||||
}) => {
|
||||
let llptrval = C_cstr(bcx.ccx(), s);
|
||||
let llptrval = PointerCast(bcx, llptrval, T_ptr(T_i8()));
|
||||
let llptrval = PointerCast(bcx, llptrval, Type::i8p());
|
||||
let llsizeval = C_uint(bcx.ccx(), s.len());
|
||||
let typ = ty::mk_estr(bcx.tcx(), ty::vstore_uniq);
|
||||
let lldestval = scratch_datum(bcx, typ, false);
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
use core::prelude::*;
|
||||
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::{TypeRef};
|
||||
use middle::trans::adt;
|
||||
use middle::trans::base;
|
||||
use middle::trans::common::*;
|
||||
|
@ -25,46 +24,50 @@ pub fn arg_is_indirect(_: &CrateContext, arg_ty: &ty::t) -> bool {
|
|||
!ty::type_is_immediate(*arg_ty)
|
||||
}
|
||||
|
||||
pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: &ty::t) -> TypeRef {
|
||||
pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: &ty::t) -> Type {
|
||||
let llty = type_of(ccx, *arg_ty);
|
||||
if arg_is_indirect(ccx, arg_ty) {T_ptr(llty)} else {llty}
|
||||
if arg_is_indirect(ccx, arg_ty) {
|
||||
llty.ptr_to()
|
||||
} else {
|
||||
llty
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_of_explicit_args(ccx: &mut CrateContext,
|
||||
inputs: &[ty::t]) -> ~[TypeRef] {
|
||||
inputs: &[ty::t]) -> ~[Type] {
|
||||
inputs.map(|arg_ty| type_of_explicit_arg(ccx, arg_ty))
|
||||
}
|
||||
|
||||
pub fn type_of_fn(cx: &mut CrateContext, inputs: &[ty::t], output: ty::t)
|
||||
-> TypeRef {
|
||||
-> Type {
|
||||
unsafe {
|
||||
let mut atys: ~[TypeRef] = ~[];
|
||||
let mut atys: ~[Type] = ~[];
|
||||
|
||||
// Arg 0: Output pointer.
|
||||
// (if the output type is non-immediate)
|
||||
let output_is_immediate = ty::type_is_immediate(output);
|
||||
let lloutputtype = type_of(cx, output);
|
||||
if !output_is_immediate {
|
||||
atys.push(T_ptr(lloutputtype));
|
||||
atys.push(lloutputtype.ptr_to());
|
||||
}
|
||||
|
||||
// Arg 1: Environment
|
||||
atys.push(T_opaque_box_ptr(cx));
|
||||
atys.push(Type::opaque_box(cx).ptr_to());
|
||||
|
||||
// ... then explicit args.
|
||||
atys.push_all(type_of_explicit_args(cx, inputs));
|
||||
|
||||
// Use the output as the actual return value if it's immediate.
|
||||
if output_is_immediate && !ty::type_is_nil(output) {
|
||||
T_fn(atys, lloutputtype)
|
||||
Type::func(atys, lloutputtype)
|
||||
} else {
|
||||
T_fn(atys, llvm::LLVMVoidTypeInContext(cx.llcx))
|
||||
Type::func(atys, Type::void())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Given a function type and a count of ty params, construct an llvm type
|
||||
pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> TypeRef {
|
||||
pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> Type {
|
||||
match ty::get(fty).sty {
|
||||
ty::ty_closure(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output),
|
||||
ty::ty_bare_fn(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output),
|
||||
|
@ -74,7 +77,7 @@ pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> TypeRef {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||
assert!(!ty::type_needs_infer(t));
|
||||
|
||||
let t_norm = ty::normalize_ty(cx.tcx, t);
|
||||
|
@ -84,11 +87,11 @@ pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
|||
match ty::get(t).sty {
|
||||
ty::ty_box(mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
T_ptr(T_box(cx, ty))
|
||||
Type::box(cx, ty).ptr_to()
|
||||
}
|
||||
ty::ty_uniq(mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
T_ptr(T_unique(cx, ty))
|
||||
Type::unique(cx, ty).ptr_to()
|
||||
}
|
||||
_ => {
|
||||
cx.sess.bug("non-box in type_of_non_gc_box");
|
||||
|
@ -109,18 +112,18 @@ pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
|||
// recursive types. For example, `static_size_of_enum()` relies on this
|
||||
// behavior.
|
||||
|
||||
pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
match cx.llsizingtypes.find(&t) {
|
||||
Some(t) => return *t,
|
||||
pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||
match cx.llsizingtypes.find_copy(&t) {
|
||||
Some(t) => return t,
|
||||
None => ()
|
||||
}
|
||||
|
||||
let llsizingty = match ty::get(t).sty {
|
||||
ty::ty_nil | ty::ty_bot => T_nil(),
|
||||
ty::ty_bool => T_bool(),
|
||||
ty::ty_int(t) => T_int_ty(cx, t),
|
||||
ty::ty_uint(t) => T_uint_ty(cx, t),
|
||||
ty::ty_float(t) => T_float_ty(cx, t),
|
||||
ty::ty_nil | ty::ty_bot => Type::nil(),
|
||||
ty::ty_bool => Type::bool(),
|
||||
ty::ty_int(t) => Type::int_from_ty(cx, t),
|
||||
ty::ty_uint(t) => Type::uint_from_ty(cx, t),
|
||||
ty::ty_float(t) => Type::float_from_ty(cx, t),
|
||||
|
||||
ty::ty_estr(ty::vstore_uniq) |
|
||||
ty::ty_estr(ty::vstore_box) |
|
||||
|
@ -132,48 +135,46 @@ pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
|||
ty::ty_ptr(*) |
|
||||
ty::ty_rptr(*) |
|
||||
ty::ty_type |
|
||||
ty::ty_opaque_closure_ptr(*) => T_ptr(T_i8()),
|
||||
ty::ty_opaque_closure_ptr(*) => Type::i8p(),
|
||||
|
||||
ty::ty_estr(ty::vstore_slice(*)) |
|
||||
ty::ty_evec(_, ty::vstore_slice(*)) => {
|
||||
T_struct([T_ptr(T_i8()), T_ptr(T_i8())], false)
|
||||
Type::struct_([Type::i8p(), Type::i8p()], false)
|
||||
}
|
||||
|
||||
ty::ty_bare_fn(*) => T_ptr(T_i8()),
|
||||
ty::ty_closure(*) => T_struct([T_ptr(T_i8()), T_ptr(T_i8())], false),
|
||||
ty::ty_trait(_, _, store, _) => T_opaque_trait(cx, store),
|
||||
ty::ty_bare_fn(*) => Type::i8p(),
|
||||
ty::ty_closure(*) => Type::struct_([Type::i8p(), Type::i8p()], false),
|
||||
ty::ty_trait(_, _, store, _) => Type::opaque_trait(cx, store),
|
||||
|
||||
ty::ty_estr(ty::vstore_fixed(size)) => T_array(T_i8(), size),
|
||||
ty::ty_estr(ty::vstore_fixed(size)) => Type::array(Type::i8(), size),
|
||||
ty::ty_evec(mt, ty::vstore_fixed(size)) => {
|
||||
T_array(sizing_type_of(cx, mt.ty), size)
|
||||
Type::array(sizing_type_of(cx, mt.ty), size)
|
||||
}
|
||||
|
||||
ty::ty_unboxed_vec(mt) => {
|
||||
let sz_ty = sizing_type_of(cx, mt.ty);
|
||||
T_vec(cx, sz_ty)
|
||||
Type::vec(cx.sess.targ_cfg.arch, sz_ty)
|
||||
}
|
||||
|
||||
ty::ty_tup(*) | ty::ty_enum(*) => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
T_struct(adt::sizing_fields_of(cx, repr), false)
|
||||
Type::struct_(adt::sizing_fields_of(cx, repr), false)
|
||||
}
|
||||
|
||||
ty::ty_struct(did, _) => {
|
||||
if ty::type_is_simd(cx.tcx, t) {
|
||||
let et = ty::simd_type(cx.tcx, t);
|
||||
let n = ty::simd_size(cx.tcx, t);
|
||||
T_vector(type_of(cx, et), n)
|
||||
Type::vector(type_of(cx, et), n)
|
||||
} else {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
let packed = ty::lookup_packed(cx.tcx, did);
|
||||
T_struct(adt::sizing_fields_of(cx, repr), packed)
|
||||
Type::struct_(adt::sizing_fields_of(cx, repr), packed)
|
||||
}
|
||||
}
|
||||
|
||||
ty::ty_self(_) | ty::ty_infer(*) | ty::ty_param(*) | ty::ty_err(*) => {
|
||||
cx.tcx.sess.bug(
|
||||
fmt!("fictitious type %? in sizing_type_of()",
|
||||
ty::get(t).sty))
|
||||
cx.tcx.sess.bug(fmt!("fictitious type %? in sizing_type_of()", ty::get(t).sty))
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -182,7 +183,7 @@ pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
|||
}
|
||||
|
||||
// NB: If you update this, be sure to update `sizing_type_of()` as well.
|
||||
pub fn type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||
debug!("type_of %?: %?", t, ty::get(t));
|
||||
|
||||
// Check the cache.
|
||||
|
@ -205,13 +206,13 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
|||
}
|
||||
|
||||
let llty = match ty::get(t).sty {
|
||||
ty::ty_nil | ty::ty_bot => T_nil(),
|
||||
ty::ty_bool => T_bool(),
|
||||
ty::ty_int(t) => T_int_ty(cx, t),
|
||||
ty::ty_uint(t) => T_uint_ty(cx, t),
|
||||
ty::ty_float(t) => T_float_ty(cx, t),
|
||||
ty::ty_nil | ty::ty_bot => Type::nil(),
|
||||
ty::ty_bool => Type::bool(),
|
||||
ty::ty_int(t) => Type::int_from_ty(cx, t),
|
||||
ty::ty_uint(t) => Type::uint_from_ty(cx, t),
|
||||
ty::ty_float(t) => Type::float_from_ty(cx, t),
|
||||
ty::ty_estr(ty::vstore_uniq) => {
|
||||
T_unique_ptr(T_unique(cx, T_vec(cx, T_i8())))
|
||||
Type::unique(cx, Type::vec(cx.sess.targ_cfg.arch, Type::i8())).ptr_to()
|
||||
}
|
||||
ty::ty_enum(did, ref substs) => {
|
||||
// Only create the named struct, but don't fill it in. We
|
||||
|
@ -219,84 +220,79 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
|||
// avoids creating more than one copy of the enum when one
|
||||
// of the enum's variants refers to the enum itself.
|
||||
|
||||
common::T_named_struct(llvm_type_name(cx,
|
||||
an_enum,
|
||||
did,
|
||||
substs.tps))
|
||||
Type::named_struct(llvm_type_name(cx, an_enum, did, substs.tps))
|
||||
}
|
||||
ty::ty_estr(ty::vstore_box) => {
|
||||
T_box_ptr(T_box(cx, T_vec(cx, T_i8())))
|
||||
Type::box(cx, Type::vec(cx, Type::i8())).ptr_to()
|
||||
}
|
||||
ty::ty_evec(ref mt, ty::vstore_box) => {
|
||||
let e_ty = type_of(cx, mt.ty);
|
||||
let v_ty = T_vec(cx, e_ty);
|
||||
T_box_ptr(T_box(cx, v_ty))
|
||||
let v_ty = Type::vec(cx.sess.targ_cfg.arch, e_ty);
|
||||
Type::box(cx, v_ty).ptr_to()
|
||||
}
|
||||
ty::ty_box(ref mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
T_box_ptr(T_box(cx, ty))
|
||||
Type::box(cx, ty).ptr_to()
|
||||
}
|
||||
ty::ty_opaque_box => T_box_ptr(T_box(cx, T_i8())),
|
||||
ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
|
||||
ty::ty_uniq(ref mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
T_unique_ptr(T_unique(cx, ty))
|
||||
Type::unique(cx, ty).ptr_to()
|
||||
}
|
||||
ty::ty_evec(ref mt, ty::vstore_uniq) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
let ty = T_vec(cx, ty);
|
||||
T_unique_ptr(T_unique(cx, ty))
|
||||
let ty = Type::vec(cx, ty);
|
||||
Type::unique(cx, ty).ptr_to()
|
||||
}
|
||||
ty::ty_unboxed_vec(ref mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
T_vec(cx, ty)
|
||||
Type::vec(cx.sess.targ_cfg.arch, ty)
|
||||
}
|
||||
ty::ty_ptr(ref mt) => T_ptr(type_of(cx, mt.ty)),
|
||||
ty::ty_rptr(_, ref mt) => T_ptr(type_of(cx, mt.ty)),
|
||||
ty::ty_ptr(ref mt) => type_of(cx, mt.ty).ptr_to(),
|
||||
ty::ty_rptr(_, ref mt) => type_of(cx, mt.ty).ptr_to(),
|
||||
|
||||
ty::ty_evec(ref mt, ty::vstore_slice(_)) => {
|
||||
let p_ty = T_ptr(type_of(cx, mt.ty));
|
||||
let u_ty = T_uint_ty(cx, ast::ty_u);
|
||||
T_struct([p_ty, u_ty], false)
|
||||
let p_ty = type_of(cx, mt.ty).ptr_to();
|
||||
let u_ty = Type::uint_from_ty(cx, ast::ty_u);
|
||||
Type::struct_([p_ty, u_ty], false)
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_slice(_)) => {
|
||||
T_struct([T_ptr(T_i8()), T_uint_ty(cx, ast::ty_u)], false)
|
||||
// This means we get a nicer name in the output
|
||||
cx.tn.find_type("str_slice").get()
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_fixed(n)) => {
|
||||
T_array(T_i8(), n + 1u /* +1 for trailing null */)
|
||||
Type::array(Type::i8(), n + 1u /* +1 for trailing null */)
|
||||
}
|
||||
|
||||
ty::ty_evec(ref mt, ty::vstore_fixed(n)) => {
|
||||
T_array(type_of(cx, mt.ty), n)
|
||||
Type::array(type_of(cx, mt.ty), n)
|
||||
}
|
||||
|
||||
ty::ty_bare_fn(_) => T_ptr(type_of_fn_from_ty(cx, t)),
|
||||
ty::ty_bare_fn(_) => type_of_fn_from_ty(cx, t).ptr_to(),
|
||||
ty::ty_closure(_) => {
|
||||
let ty = type_of_fn_from_ty(cx, t);
|
||||
T_fn_pair(cx, ty)
|
||||
Type::func_pair(cx, ty)
|
||||
}
|
||||
ty::ty_trait(_, _, store, _) => T_opaque_trait(cx, store),
|
||||
ty::ty_type => T_ptr(cx.tydesc_type),
|
||||
ty::ty_trait(_, _, store, _) => Type::opaque_trait(cx, store),
|
||||
ty::ty_type => cx.tydesc_type.to_ptr(),
|
||||
ty::ty_tup(*) => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
T_struct(adt::fields_of(cx, repr), false)
|
||||
Type::struct_(adt::fields_of(cx, repr), false)
|
||||
}
|
||||
ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx),
|
||||
ty::ty_opaque_closure_ptr(_) => Type::opaque_box(cx).ptr_to(),
|
||||
ty::ty_struct(did, ref substs) => {
|
||||
if ty::type_is_simd(cx.tcx, t) {
|
||||
let et = ty::simd_type(cx.tcx, t);
|
||||
let n = ty::simd_size(cx.tcx, t);
|
||||
T_vector(type_of(cx, et), n)
|
||||
} else {
|
||||
// Only create the named struct, but don't fill it in. We fill it
|
||||
// in *after* placing it into the type cache. This prevents
|
||||
// infinite recursion with recursive struct types.
|
||||
T_named_struct(llvm_type_name(cx,
|
||||
a_struct,
|
||||
did,
|
||||
substs.tps))
|
||||
}
|
||||
if ty::type_is_simd(cx.tcx, t) {
|
||||
let et = ty::simd_type(cx.tcx, t);
|
||||
let n = ty::simd_size(cx.tcx, t);
|
||||
Type::vector(type_of(cx, et), n)
|
||||
} else {
|
||||
// Only create the named struct, but don't fill it in. We fill it
|
||||
// in *after* placing it into the type cache. This prevents
|
||||
// infinite recursion with recursive struct types.
|
||||
Type::named_struct(llvm_type_name(cx, a_struct, did, substs.tps))
|
||||
}
|
||||
}
|
||||
ty::ty_self(*) => cx.tcx.sess.unimpl("type_of: ty_self"),
|
||||
ty::ty_infer(*) => cx.tcx.sess.bug("type_of with ty_infer"),
|
||||
|
@ -336,33 +332,32 @@ pub fn llvm_type_name(cx: &CrateContext,
|
|||
did: ast::def_id,
|
||||
tps: &[ty::t]) -> ~str {
|
||||
let name = match what {
|
||||
a_struct => { "~struct" }
|
||||
an_enum => { "~enum" }
|
||||
a_struct => { "struct" }
|
||||
an_enum => { "enum" }
|
||||
};
|
||||
return fmt!(
|
||||
"%s %s[#%d]",
|
||||
name,
|
||||
ppaux::parameterized(
|
||||
cx.tcx,
|
||||
ty::item_path_str(cx.tcx, did),
|
||||
None,
|
||||
tps),
|
||||
did.crate
|
||||
);
|
||||
let tstr = ppaux::parameterized(cx.tcx, ty::item_path_str(cx.tcx, did), None, tps);
|
||||
if did.crate == 0 {
|
||||
fmt!("%s.%s", name, tstr)
|
||||
} else {
|
||||
fmt!("%s.%s[#%d]", name, tstr, did.crate)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_of_dtor(ccx: &mut CrateContext, self_ty: ty::t) -> TypeRef {
|
||||
T_fn([T_ptr(type_of(ccx, self_ty))] /* self */, T_void())
|
||||
pub fn type_of_dtor(ccx: &mut CrateContext, self_ty: ty::t) -> Type {
|
||||
let self_ty = type_of(ccx, self_ty).ptr_to();
|
||||
Type::func([self_ty], Type::viod())
|
||||
}
|
||||
|
||||
pub fn type_of_rooted(ccx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
/*
|
||||
pub fn type_of_rooted(ccx: &mut CrateContext, t: ty::t) -> Type {
|
||||
let addrspace = base::get_tydesc(ccx, t).addrspace;
|
||||
debug!("type_of_rooted %s in addrspace %u",
|
||||
ppaux::ty_to_str(ccx.tcx, t), addrspace as uint);
|
||||
return T_root(type_of(ccx, t), addrspace);
|
||||
}
|
||||
|
||||
pub fn type_of_glue_fn(ccx: &CrateContext) -> TypeRef {
|
||||
pub fn type_of_glue_fn(ccx: &CrateContext) -> Type {
|
||||
let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
|
||||
return T_fn([T_ptr(T_nil()), tydescpp, T_ptr(T_i8())], T_void());
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -67,17 +67,12 @@ pub fn return_to_mut(mut bcx: block,
|
|||
bcx.val_to_str(frozen_val_ref),
|
||||
bcx.val_to_str(bits_val_ref));
|
||||
|
||||
let box_ptr =
|
||||
Load(bcx, PointerCast(bcx,
|
||||
frozen_val_ref,
|
||||
T_ptr(T_ptr(T_i8()))));
|
||||
let box_ptr = Load(bcx, PointerCast(bcx, frozen_val_ref, Type::i8p().ptr_to()));
|
||||
|
||||
let bits_val =
|
||||
Load(bcx, bits_val_ref);
|
||||
let bits_val = Load(bcx, bits_val_ref);
|
||||
|
||||
if bcx.tcx().sess.debug_borrows() {
|
||||
bcx = callee::trans_lang_call(
|
||||
bcx,
|
||||
bcx = callee::trans_lang_call( bcx,
|
||||
bcx.tcx().lang_items.unrecord_borrow_fn(),
|
||||
[
|
||||
box_ptr,
|
||||
|
@ -146,10 +141,7 @@ fn root(datum: &Datum,
|
|||
DynaMut => bcx.tcx().lang_items.borrow_as_mut_fn(),
|
||||
};
|
||||
|
||||
let box_ptr = Load(bcx,
|
||||
PointerCast(bcx,
|
||||
scratch.val,
|
||||
T_ptr(T_ptr(T_i8()))));
|
||||
let box_ptr = Load(bcx, PointerCast(bcx, scratch.val, Type::i8p().ptr_to()));
|
||||
|
||||
bcx = callee::trans_lang_call(
|
||||
bcx,
|
||||
|
@ -194,6 +186,6 @@ fn perform_write_guard(datum: &Datum,
|
|||
callee::trans_lang_call(
|
||||
bcx,
|
||||
bcx.tcx().lang_items.check_not_borrowed_fn(),
|
||||
[PointerCast(bcx, llval, T_ptr(T_i8())), filename, line],
|
||||
[PointerCast(bcx, llval, Type::i8p()), filename, line],
|
||||
expr::Ignore)
|
||||
}
|
||||
|
|
|
@ -457,9 +457,9 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
|
|||
}
|
||||
ty_estr(vs) => fmt!("%s%s", vstore_to_str(cx, vs), "str"),
|
||||
ty_opaque_box => ~"@?",
|
||||
ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"closure&",
|
||||
ty_opaque_closure_ptr(ast::ManagedSigil) => ~"closure@",
|
||||
ty_opaque_closure_ptr(ast::OwnedSigil) => ~"closure~",
|
||||
ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"&closure",
|
||||
ty_opaque_closure_ptr(ast::ManagedSigil) => ~"@closure",
|
||||
ty_opaque_closure_ptr(ast::OwnedSigil) => ~"~closure",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,17 +469,17 @@ pub fn parameterized(cx: ctxt,
|
|||
tps: &[ty::t]) -> ~str {
|
||||
|
||||
let r_str = match self_r {
|
||||
None => ~"",
|
||||
Some(r) => {
|
||||
fmt!("/%s", region_to_str(cx, r))
|
||||
}
|
||||
None => ~"",
|
||||
Some(r) => {
|
||||
region_to_str(cx, r)
|
||||
}
|
||||
};
|
||||
|
||||
if tps.len() > 0u {
|
||||
let strs = vec::map(tps, |t| ty_to_str(cx, *t));
|
||||
fmt!("%s%s<%s>", base, r_str, strs.connect(","))
|
||||
fmt!("%s%s<%s>", r_str, base, strs.connect(","))
|
||||
} else {
|
||||
fmt!("%s%s", base, r_str)
|
||||
fmt!("%s%s", r_str, base)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue