#[macro_use]
use corollary_support::*;
use analysis::sem_rep::*;
use syntax::ast::*;
use analysis::trav_monad::*;
use syntax::constants::*;
use data::ident::Ident;
use analysis::ast_analysis::*;
use analysis::def_table::*;
pub struct MachineDesc {
iSize: fn(IntType) -> isize,
fSize: fn(FloatType) -> isize,
builtinSize: fn(BuiltinType) -> isize,
ptrSize: isize,
voidSize: isize,
iAlign: fn(IntType) -> isize,
fAlign: fn(FloatType) -> isize,
builtinAlign: fn(BuiltinType) -> isize,
ptrAlign: isize,
voidAlign: isize,
}
fn iSize(a: MachineDesc) -> fn(IntType) -> isize {
a.iSize
}
fn fSize(a: MachineDesc) -> fn(FloatType) -> isize {
a.fSize
}
fn builtinSize(a: MachineDesc) -> fn(BuiltinType) -> isize {
a.builtinSize
}
fn ptrSize(a: MachineDesc) -> isize {
a.ptrSize
}
fn voidSize(a: MachineDesc) -> isize {
a.voidSize
}
fn iAlign(a: MachineDesc) -> fn(IntType) -> isize {
a.iAlign
}
fn fAlign(a: MachineDesc) -> fn(FloatType) -> isize {
a.fAlign
}
fn builtinAlign(a: MachineDesc) -> fn(BuiltinType) -> isize {
a.builtinAlign
}
fn ptrAlign(a: MachineDesc) -> isize {
a.ptrAlign
}
fn voidAlign(a: MachineDesc) -> isize {
a.voidAlign
}
pub fn intExpr(n: n, i: isize) -> m<CExpr> {
__op_bind(genName,
|name| CConst(CIntConst((cisize(i)), (mkNodeInfo((posOf(n)), name)))))
}
pub fn sizeofType(_0: MachineDesc, _1: n, _2: Type) -> m<isize> {
match (_0, _1, _2) {
(md, _, DirectType(TyVoid, _, _)) => voidSize(md),
(md, _, DirectType(TyIntegral(it), _, _)) => iSize(md, it),
(md, _, DirectType(TyFloating(ft), _, _)) => fSize(md, ft),
(md, _, DirectType(TyComplex(ft), _, _)) => (2 * fSize(md, ft)),
(md, _, DirectType(TyComp(ctr), _, _)) => compSize(md, ctr),
(md, _, DirectType(TyEnum(_), _, _)) => iSize(md, TyInt),
(md, _, DirectType(TyBuiltin(b), _, _)) => builtinSize(md, b),
(md, _, PtrType(_, _, _)) => ptrSize(md),
(md, _, ArrayType(_, UnknownArraySize(_), _, _)) => ptrSize(md),
(md, n, ArrayType(bt, ArraySize(_, sz), _, _)) => {
{
let sz_q = constEval(md, Map::empty, sz);
match sz_q {
CConst(CIntConst(i, _)) => {
{
let s = sizeofType(md, n, bt);
(getCisize(i) * s)
}
}
_ => ptrSize(md),
}
}
}
(md, n, TypeDefType(TypeDefRef(_, t, _), _, _)) => sizeofType(md, n, t),
(md, _, FunctionType(_, _)) => ptrSize(md),
}
}
pub fn alignofType(_0: MachineDesc, _1: n, _2: Type) -> m<isize> {
match (_0, _1, _2) {
(md, _, DirectType(TyVoid, _, _)) => voidAlign(md),
(md, _, DirectType(TyIntegral(it), _, _)) => iAlign(md, it),
(md, _, DirectType(TyFloating(ft), _, _)) => fAlign(md, ft),
(md, _, DirectType(TyComplex(ft), _, _)) => fAlign(md, ft),
(md, _, DirectType(TyEnum(_), _, _)) => iAlign(md, TyInt),
(md, _, DirectType(TyBuiltin(b), _, _)) => builtinAlign(md, b),
(md, _, PtrType(_, _, _)) => ptrAlign(md),
(md, _, ArrayType(_, UnknownArraySize(_), _, _)) => ptrAlign(md),
(md, n, ArrayType(bt, ArraySize(_, _), _, _)) => alignofType(md, n, bt),
(md, n, TypeDefType(TypeDefRef(_, t, _), _, _)) => alignofType(md, n, t),
(_, n, t) => {
astError((nodeInfo(n)),
__op_addadd("can\'t find alignment of type: ".to_string(),
(render(pretty))(t)))
}
}
}
pub fn compSize(md: MachineDesc, ctr: CompTypeRef) -> m<isize> {
{
let dt = getDefTable;
match lookupTag((sueRef(ctr)), dt) {
Some(Left(_)) => {
astError((nodeInfo(ctr)),
"composite declared but not defined".to_string())
}
Some(Right(CompDef(CompType(_, tag, ms, _, ni)))) => {
{
let ts = __map!(declType, ms);
let sizes = mapM((sizeofType(md, ni)), ts);
match tag {
StructTag => sum(sizes),
UnionTag => maximum(sizes),
}
}
}
Some(Right(EnumDef(_))) => iSize(md, TyInt),
None => astError((nodeInfo(ctr)), "unknown composite".to_string()),
}
}
}
pub fn intOp(_0: CBinaryOp, _1: isize, _2: isize) -> isize {
match (_0, _1, _2) {
(CAddOp, i1, i2) => (i1 + i2),
(CSubOp, i1, i2) => (i1 - i2),
(CMulOp, i1, i2) => (i1 * i2),
(CDivOp, i1, i2) => div(i1, i2),
(CRmdOp, i1, i2) => __mod(i1, i2),
(CShlOp, i1, i2) => shiftL(i1, fromInteger(i2)),
(CShrOp, i1, i2) => shiftR(i1, fromInteger(i2)),
(CLeOp, i1, i2) => toInteger(fromEnum((i1 < i2))),
(CGrOp, i1, i2) => toInteger(fromEnum((i1 > i2))),
(CLeqOp, i1, i2) => toInteger(fromEnum((i1 <= i2))),
(CGeqOp, i1, i2) => toInteger(fromEnum((i1 >= i2))),
(CEqOp, i1, i2) => toInteger(fromEnum((i1 == i2))),
(CNeqOp, i1, i2) => toInteger(fromEnum(__op_assign_div(i1, i2))),
(CAndOp, i1, i2) => __op_dotted_and(i1, i2),
(CXorOp, i1, i2) => xor(i1, i2),
(COrOp, i1, i2) => __op_dotted_or(i1, i2),
(CLndOp, i1, i2) => {
toInteger(fromEnum(((__op_assign_div(i1, 0)) && (__op_assign_div(i2, 0)))))
}
(CLorOp, i1, i2) => {
toInteger(fromEnum(((__op_assign_div(i1, 0)) || (__op_assign_div(i2, 0)))))
}
}
}
pub fn intUnOp(_0: CUnaryOp, _1: isize) -> Option<isize> {
match (_0, _1) {
(CPlusOp, i) => Some(i),
(CMinOp, i) => Some(-(i)),
(CCompOp, i) => Some(complement(i)),
(CNegOp, i) => Some(toInteger(fromEnum((i == 0)))),
(_, _) => None,
}
}
pub fn withWordBytes(bytes: isize, n: isize) -> isize {
rem(n, (shiftL(1, (shiftL(bytes, 3)))))
}
pub fn boolValue(_0: CExpr) -> Option<bool> {
match (_0) {
CConst(CIntConst(i, _)) => Some(__op_assign_div(getCInteger(i), 0)),
CConst(CCharConst(c, _)) => Some(__op_assign_div(getCCharAsInt(c), 0)),
CConst(CStrConst(_, _)) => Some(true),
_ => None,
}
}
pub fn intValue(_0: CExpr) -> Option<isize> {
match (_0) {
CConst(CIntConst(i, _)) => Some(getCInteger(i)),
CConst(CCharConst(c, _)) => Some(getCCharAsInt(c)),
_ => None,
}
}
pub fn constEval(_0: MachineDesc, _1: Map::Map<Ident, CExpr>, _2: CExpr) -> m<CExpr> {
match (_0, _1, _2) {
(md, env, CCond(e1, me2, e3, ni)) => {
{
let e1_q = constEval(md, env, e1);
let me2_q = maybe((None), (|e| liftM(Some, constEval(md, env, e))), me2);
let e3_q = constEval(md, env, e3);
match boolValue(e1_q) {
Some(true) => fromMaybe(e1_q, me2_q),
Some(false) => e3_q,
None => CCond(e1_q, me2_q, e3_q, ni),
}
}
}
(md, env, e, __OP__, CBinary(op, e1, e2, ni)) => {
{
let e1_q = constEval(md, env, e1);
let e2_q = constEval(md, env, e2);
let t = tExpr(vec![], RValue, e);
let bytes = liftM(fromIntegral, sizeofType(md, e, t));
match (intValue(e1_q), intValue(e2_q)) {
(Some(i1), Some(i2)) => {
intExpr(ni, (withWordBytes(bytes, (intOp(op, i1, i2)))))
}
(_, _) => CBinary(op, e1_q, e2_q, ni),
}
}
}
(md, env, CUnary(op, e, ni)) => {
{
let e_q = constEval(md, env, e);
let t = tExpr(vec![], RValue, e);
let bytes = liftM(fromIntegral, sizeofType(md, e, t));
match intValue(e_q) {
Some(i) => {
match intUnOp(op, i) {
Some(i_q) => intExpr(ni, (withWordBytes(bytes, i_q))),
None => {
astError(ni,
"invalid unary operator applied to constant".to_string())
}
}
}
None => CUnary(op, e_q, ni),
}
}
}
(md, env, CCast(d, e, ni)) => {
{
let e_q = constEval(md, env, e);
let t = analyseTypeDecl(d);
let bytes = liftM(fromIntegral, sizeofType(md, d, t));
match intValue(e_q) {
Some(i) => intExpr(ni, (withWordBytes(bytes, i))),
None => CCast(d, e_q, ni),
}
}
}
(md, _, CSizeofExpr(e, ni)) => {
{
let t = tExpr(vec![], RValue, e);
let sz = sizeofType(md, e, t);
intExpr(ni, sz)
}
}
(md, _, CSizeofType(d, ni)) => {
{
let t = analyseTypeDecl(d);
let sz = sizeofType(md, d, t);
intExpr(ni, sz)
}
}
(md, _, CAlignofExpr(e, ni)) => {
{
let t = tExpr(vec![], RValue, e);
let sz = alignofType(md, e, t);
intExpr(ni, sz)
}
}
(md, _, CAlignofType(d, ni)) => {
{
let t = analyseTypeDecl(d);
let sz = alignofType(md, d, t);
intExpr(ni, sz)
}
}
(_, env, e, __OP__, CVar(i, _)) => {
Error
}
(md, env, e, __OP__, CVar(i, _)) => {
{
let t = tExpr(vec![], RValue, e);
match derefTypeDef(t) {
DirectType(TyEnum(etr), _, _) => {
{
let dt = getDefTable;
match lookupTag((sueRef(etr)), dt) {
Some(Right(EnumDef(EnumType(_, es, _, _)))) => {
{
let env_q = foldM(enumConst, env, es);
fromMaybe(e, Map::lookup(i, env_q))
}
}
_ => e,
}
}
}
_ => e,
}
}
}
(_, _, e) => e,
}
}