blob: 78b3b7836a702d22a8937530b02addb3e03eee73 [file] [log] [blame]
use std::uint;
pub enum Global {
GType(@mut TypeInfo),
GComp(@mut CompInfo),
GCompDecl(@mut CompInfo),
GEnum(@mut EnumInfo),
GEnumDecl(@mut EnumInfo),
GVar(@mut VarInfo),
GFunc(@mut VarInfo),
GOther
}
pub enum Type {
TVoid,
TInt(IKind),
TFloat(FKind),
TPtr(@Type, bool),
TArray(@Type, uint),
TFunc(@Type, ~[(~str, @Type)], bool),
TNamed(@mut TypeInfo),
TComp(@mut CompInfo),
TEnum(@mut EnumInfo)
}
pub enum IKind {
IBool,
ISChar,
IUChar,
IShort,
IUShort,
IInt,
IUInt,
ILong,
IULong,
ILongLong,
IULongLong
}
pub enum FKind {
FFloat,
FDouble
}
pub struct CompInfo {
cstruct: bool,
name: ~str,
fields: ~[@FieldInfo]
}
pub struct FieldInfo {
name: ~str,
ty: @Type,
bit: Option<uint>
}
pub struct EnumInfo {
name: ~str,
items: ~[@EnumItem],
kind: IKind
}
pub struct EnumItem {
name: ~str,
val: int
}
pub struct TypeInfo {
name: ~str,
ty: @Type
}
pub struct VarInfo {
name: ~str,
ty: @Type,
is_const: bool
}
impl ToStr for Global {
fn to_str(&self) -> ~str {
match *self {
GType(ti) => ti.to_str(),
GComp(ci) => ci.to_str(),
GCompDecl(ci) => ci.to_str(),
GEnum(ei) => ei.to_str(),
GEnumDecl(ei) => ei.to_str(),
GVar(vi) => vi.to_str(),
GFunc(vi) => vi.to_str(),
GOther => ~"*"
}
}
}
impl ToStr for CompInfo {
fn to_str(&self) -> ~str {
self.name.clone()
}
}
impl ToStr for EnumInfo {
fn to_str(&self) -> ~str {
self.name.clone()
}
}
impl ToStr for TypeInfo {
fn to_str(&self) -> ~str {
self.name.clone()
}
}
impl ToStr for VarInfo {
fn to_str(&self) -> ~str {
self.name.clone()
}
}
pub fn mk_compinfo(name: ~str, cstruct: bool, fields: ~[@FieldInfo]) -> @mut CompInfo {
return @mut CompInfo { cstruct: cstruct,
name: name,
fields: fields
};
}
pub fn mk_fieldinfo(name: ~str, ty: @Type, bit: Option<uint>) -> @FieldInfo {
return @FieldInfo { name: name,
ty: ty,
bit: bit
};
}
pub fn mk_enuminfo(name: ~str, kind: IKind, items: ~[@EnumItem]) -> @mut EnumInfo {
return @mut EnumInfo { name: name,
items: items,
kind: kind
};
}
pub fn mk_enumitem(name: ~str, val: int) -> @EnumItem {
return @EnumItem { name: name,
val: val
};
}
pub fn mk_typeinfo(name: ~str, ty: @Type) -> @mut TypeInfo {
return @mut TypeInfo { name: name,
ty: ty
};
}
pub fn mk_varinfo(name: ~str, ty: @Type) -> @mut VarInfo {
return @mut VarInfo { name: name,
ty: ty,
is_const: false
};
}
pub fn global_compinfo(glob: Global) -> @mut CompInfo {
match glob {
GComp(i) => return i,
GCompDecl(i) => return i,
_ => fail!(~"global_compinfo")
}
}
pub fn global_enuminfo(glob: Global) -> @mut EnumInfo {
match glob {
GEnum(i) => return i,
GEnumDecl(i) => return i,
_ => fail!(~"global_enuminfo")
}
}
pub fn global_typeinfo(glob: Global) -> @mut TypeInfo {
match glob {
GType(i) => return i,
_ => fail!(~"global_typeinfo")
}
}
pub fn global_varinfo(glob: Global) -> @mut VarInfo {
match glob {
GVar(i) => i,
GFunc(i) => i,
_ => fail!(~"global_varinfo")
}
}
#[cfg(target_arch="x86_64")]
pub fn type_align(ty: @Type) -> uint {
return match *ty {
TInt(k) => match k {
IBool | ISChar | IUChar => 1,
IShort | IUShort => 2,
IInt | IUInt => 4,
ILong | IULong => 8,
ILongLong | IULongLong => 8
},
TFloat(k) => match k {
FFloat => 4,
FDouble => 8
},
TPtr(*) => 8,
TArray(t, _) => type_align(t),
TNamed(t) => type_align(t.ty),
TComp(ci) => {
let fs = ci.fields.clone();
do fs.iter().fold(0) |a, t| {
uint::max(a, type_align(t.ty))
}
},
TEnum(_) => 4,
TVoid => 0,
TFunc(_, _, _) => 0
};
}
#[cfg(target_arch="x86")]
pub fn type_align(ty: @Type) -> uint {
return match *ty {
TInt(k) => match k {
IBool | ISChar | IUChar => 1,
IShort | IUShort => 2,
IInt | IUInt => 4,
ILong | IULong => 4,
ILongLong | IULongLong => 8
},
TFloat(k) => match k {
FFloat => 4,
FDouble => 8
},
TPtr(*) => 4,
TArray(t, _) => type_align(t),
TNamed(t) => type_align(t.ty),
TComp(ci) => {
let fs = ci.fields.clone();
do fs.iter().fold(0) |a, t| {
uint::max(a, type_align(t.ty))
}
},
TEnum(_) => 4,
TVoid => 0,
TFunc(_, _, _) => 0
};
}
#[cfg(target_arch="x86_64")]
pub fn type_size(ty: @Type) -> uint {
return match *ty {
TInt(k) => match k {
IBool | ISChar | IUChar => 1,
IShort | IUShort => 2,
IInt | IUInt => 4,
ILong | IULong => 8,
ILongLong | IULongLong => 8
},
TFloat(k) => match k {
FFloat => 4,
FDouble => 8
},
TPtr(*) => 8,
TArray(t, s) => type_size(t) * s,
TNamed(t) => type_size(t.ty),
TComp(ci) => if ci.cstruct {
let fs = ci.fields.clone();
let size = do fs.iter().fold(0) |s, t| {
align(s, t.ty) + type_size(t.ty)
};
align(size, ty)
} else {
let fs = ci.fields.clone();
let size = do fs.iter().fold(0) |s, t| {
uint::max(s, type_size(t.ty))
};
align(size, ty)
},
TEnum(_) => 4,
TVoid => 0,
TFunc(_, _, _) => 0
};
}
#[cfg(target_arch="x86")]
pub fn type_size(ty: @Type) -> uint {
return match *ty {
TInt(k) => match k {
IBool | ISChar | IUChar => 1,
IShort | IUShort => 2,
IInt | IUInt => 4,
ILong | IULong => 4,
ILongLong | IULongLong => 8
},
TFloat(k) => match k {
FFloat => 4,
FDouble => 8
},
TPtr(*) => 4,
TArray(t, s) => type_size(t) * s,
TNamed(t) => type_size(t.ty),
TComp(ci) => if ci.cstruct {
let fs = ci.fields.clone();
let size = do fs.iter().fold(0) |s, t| {
align(s, t.ty) + type_size(t.ty)
};
align(size, ty)
} else {
let fs = ci.fields.clone();
let size = do fs.iter().fold(0) |s, t| {
uint::max(s, type_size(t.ty))
};
align(size, ty)
},
TEnum(_) => 4,
TVoid => 0,
TFunc(_, _, _) => 0
};
}
pub fn align(off: uint, ty: @Type) -> uint {
let a = type_align(ty);
if a == 0 {
return 0;
} else {
return (off + a - 1u) / a * a;
}
}