test_ir.rs 13.9 KB
Newer Older
1 2 3 4
extern crate mu;

use self::mu::ast::types::*;
use self::mu::ast::ir::*;
5
use self::mu::ast::inst::*;
6
use self::mu::ast::ptr::*;
qinsoon's avatar
qinsoon committed
7
use self::mu::ast::op::*;
8 9
use self::mu::vm::context::*;

10
use std::cell::RefCell;
11
use std::collections::HashMap;
12

13 14 15 16 17 18
#[test]
#[allow(unused_variables)]
fn test_factorial() {
    let vm = factorial();
}

qinsoon's avatar
qinsoon committed
19 20 21 22 23 24
#[test]
#[allow(unused_variables)]
fn test_sum() {
    let vm = sum();
}

qinsoon's avatar
qinsoon committed
25 26 27 28 29 30
#[test]
#[allow(unused_variables)]
fn test_global_access() {
    let vm = global_access();
}

qinsoon's avatar
qinsoon committed
31
pub fn sum() -> VMContext {
32
    let vm = VMContext::new();
33

qinsoon's avatar
qinsoon committed
34 35 36
    // .typedef @int_64 = int<64>
    let type_def_int64 = vm.declare_type("int_64", P(MuType::int(64)));
    let type_def_int1  = vm.declare_type("int_1", P(MuType::int(1)));
37

qinsoon's avatar
qinsoon committed
38 39 40 41
    // .const @int_64_0 <@int_64> = 0
    // .const @int_64_1 <@int_64> = 1
    let const_def_int64_0 = vm.declare_const("int64_0", type_def_int64.clone(), Constant::Int(0));
    let const_def_int64_1 = vm.declare_const("int64_1", type_def_int64.clone(), Constant::Int(1));
42

qinsoon's avatar
qinsoon committed
43 44
    // .funcsig @sum_sig = (@int_64) -> (@int_64)
    let sum_sig = vm.declare_func_sig("sum_sig", vec![type_def_int64.clone()], vec![type_def_int64.clone()]);
45

46 47 48 49 50 51
    // .funcdecl @sum <@sum_sig>
    let func = MuFunction::new("sum", sum_sig.clone());
    vm.declare_func(func);

    // .funcdef @sum VERSION @sum_v1 <@sum_sig> 
    let mut func_ver = MuFunctionVersion::new("sum", "sum_v1", sum_sig.clone());
52

qinsoon's avatar
qinsoon committed
53 54
    // %entry(<@int_64> %n):
    let mut blk_entry = Block::new("entry");
55 56 57
    let blk_entry_n = func_ver.new_ssa("blk_entry_n", type_def_int64.clone());
    let const_def_int64_0_local = func_ver.new_constant(const_def_int64_0.clone()); // FIXME: why we need a local version?
    let const_def_int64_1_local = func_ver.new_constant(const_def_int64_1.clone());
58

qinsoon's avatar
qinsoon committed
59
    // BRANCH %head
60
    let blk_entry_term = func_ver.new_inst(Instruction {
qinsoon's avatar
qinsoon committed
61 62 63 64 65 66 67
        value: None,
        ops: RefCell::new(vec![blk_entry_n.clone(), const_def_int64_0_local.clone(), const_def_int64_0_local.clone()]),
        v: Instruction_::Branch1(Destination{
            target: "head",
            args: vec![DestArg::Normal(0), DestArg::Normal(1), DestArg::Normal(2)]
        })
    });
68

qinsoon's avatar
qinsoon committed
69
    let blk_entry_content = BlockContent {
70
        args: vec![blk_entry_n.clone_value()],
qinsoon's avatar
qinsoon committed
71 72 73 74
        body: vec![blk_entry_term],
        keepalives: None
    };
    blk_entry.content = Some(blk_entry_content);
75

qinsoon's avatar
qinsoon committed
76 77
    // %head(<@int_64> %n, <@int_64> %s, <@int_64> %i):
    let mut blk_head = Block::new("head");
78 79 80
    let blk_head_n = func_ver.new_ssa("blk_head_n", type_def_int64.clone());
    let blk_head_s = func_ver.new_ssa("blk_head_s", type_def_int64.clone());
    let blk_head_i = func_ver.new_ssa("blk_head_i", type_def_int64.clone());
81

qinsoon's avatar
qinsoon committed
82
    // %s2 = ADD %s %i
83 84
    let blk_head_s2 = func_ver.new_ssa("blk_head_s2", type_def_int64.clone());
    let blk_head_inst0 = func_ver.new_inst(Instruction {
qinsoon's avatar
qinsoon committed
85
        value: Some(vec![blk_head_s2.clone_value()]),
qinsoon's avatar
qinsoon committed
86 87 88
        ops: RefCell::new(vec![blk_head_s.clone(), blk_head_i.clone()]),
        v: Instruction_::BinOp(BinOp::Add, 0, 1)
    });
89

qinsoon's avatar
qinsoon committed
90
    // %i2 = ADD %i 1
91 92
    let blk_head_i2 = func_ver.new_ssa("blk_head_i2", type_def_int64.clone());
    let blk_head_inst1 = func_ver.new_inst(Instruction {
qinsoon's avatar
qinsoon committed
93
        value: Some(vec![blk_head_i2.clone_value()]),
qinsoon's avatar
qinsoon committed
94 95 96
        ops: RefCell::new(vec![blk_head_i.clone(), const_def_int64_1_local.clone()]),
        v: Instruction_::BinOp(BinOp::Add, 0, 1)
    });
97

qinsoon's avatar
qinsoon committed
98
    // %cond = UGT %i %n
99 100
    let blk_head_cond = func_ver.new_ssa("blk_head_cond", type_def_int1.clone());
    let blk_head_inst2 = func_ver.new_inst(Instruction {
qinsoon's avatar
qinsoon committed
101
        value: Some(vec![blk_head_cond.clone_value()]),
qinsoon's avatar
qinsoon committed
102 103 104 105 106
        ops: RefCell::new(vec![blk_head_i.clone(), blk_head_n.clone()]),
        v: Instruction_::CmpOp(CmpOp::UGT, 0, 1)
    });

    // BRANCH2 %cond %ret(%s2) %head(%n %s2 %i2)
107
    let blk_head_term = func_ver.new_inst(Instruction{
qinsoon's avatar
qinsoon committed
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
        value: None,
        ops: RefCell::new(vec![blk_head_cond.clone(), blk_head_n.clone(), blk_head_s2.clone(), blk_head_i2.clone()]),
        v: Instruction_::Branch2 {
            cond: 0,
            true_dest: Destination {
                target: "ret",
                args: vec![DestArg::Normal(2)]
            },
            false_dest: Destination {
                target: "head",
                args: vec![DestArg::Normal(1), DestArg::Normal(2), DestArg::Normal(3)]
            },
            true_prob: 0.6f32
        }
    });

    let blk_head_content = BlockContent {
125
        args: vec![blk_head_n.clone_value(), blk_head_s.clone_value(), blk_head_i.clone_value()],
qinsoon's avatar
qinsoon committed
126 127 128 129
        body: vec![blk_head_inst0, blk_head_inst1, blk_head_inst2, blk_head_term],
        keepalives: None
    };
    blk_head.content = Some(blk_head_content);
130

qinsoon's avatar
qinsoon committed
131 132
    // %ret(<@int_64> %s):
    let mut blk_ret = Block::new("ret");
133
    let blk_ret_s = func_ver.new_ssa("blk_ret_s", type_def_int64.clone());
134

qinsoon's avatar
qinsoon committed
135
    // RET %s
136
    let blk_ret_term = func_ver.new_inst(Instruction{
qinsoon's avatar
qinsoon committed
137 138 139 140
        value: None,
        ops: RefCell::new(vec![blk_ret_s.clone()]),
        v: Instruction_::Return(vec![0])
    });
141

qinsoon's avatar
qinsoon committed
142
    let blk_ret_content = BlockContent {
143
        args: vec![blk_ret_s.clone_value()],
qinsoon's avatar
qinsoon committed
144 145 146 147 148 149
        body: vec![blk_ret_term],
        keepalives: None
    };
    blk_ret.content = Some(blk_ret_content);

    // wrap into a function
150
    func_ver.define(FunctionContent{
151
            entry: "entry",
qinsoon's avatar
qinsoon committed
152 153 154 155 156 157 158 159
            blocks: {
                let mut blocks = HashMap::new();
                blocks.insert("entry", blk_entry);
                blocks.insert("head", blk_head);
                blocks.insert("ret", blk_ret);
                blocks
            }
    });
160

161
    vm.define_func_version(func_ver);
162

qinsoon's avatar
qinsoon committed
163 164 165
    vm
}

166 167
#[allow(unused_variables)]
pub fn factorial() -> VMContext {
168
    let vm = VMContext::new();
169

170 171 172 173 174 175 176
    // .typedef @int_64 = int<64>
    // .typedef @int_1 = int<1>
    // .typedef @float = float
    // .typedef @double = double
    // .typedef @void = void
    // .typedef @int_8 = int<8>
    // .typedef @int_32 = int<32>
qinsoon's avatar
qinsoon committed
177 178 179 180 181 182 183
    let type_def_int64 = vm.declare_type("int_64", P(MuType::int(64)));
    let type_def_int1  = vm.declare_type("int_1", P(MuType::int(1)));
    let type_def_float = vm.declare_type("float", P(MuType::float()));
    let type_def_double = vm.declare_type("double", P(MuType::double()));
    let type_def_void  = vm.declare_type("void", P(MuType::void()));
    let type_def_int8  = vm.declare_type("int8", P(MuType::int(8)));
    let type_def_int32 = vm.declare_type("int32", P(MuType::int(32)));
184

185
    // .const @int_64_1 <@int_64> = 1
186
    let const_def_int64_1 = vm.declare_const("int64_1", type_def_int64.clone(), Constant::Int(1));
187

188 189
    // .funcsig @fac_sig = (@int_64) -> (@int_64)
    let fac_sig = vm.declare_func_sig("fac_sig", vec![type_def_int64.clone()], vec![type_def_int64.clone()]);
190
    let type_def_funcref_fac = vm.declare_type("fac_sig", P(MuType::funcref(fac_sig.clone())));
191

192 193 194 195
    // .funcdecl @fac <@fac_sig>
    let func = MuFunction::new("fac", fac_sig.clone());
    vm.declare_func(func);

196
    // .funcdef @fac VERSION @fac_v1 <@fac_sig>
197
    let const_func_fac = vm.declare_const("fac", type_def_funcref_fac, Constant::FuncRef("fac"));
198
    let mut func_ver = MuFunctionVersion::new("fac", "fac_v1", fac_sig.clone());
199

200 201
    // %blk_0(<@int_64> %n_3):
    let mut blk_0 = Block::new("blk_0");
202 203
    let blk_0_n_3 = func_ver.new_ssa("blk_0_n_3", type_def_int64.clone());
    let const_def_int64_1_local = func_ver.new_constant(const_def_int64_1.clone());
204

205
    //   %v48 = EQ <@int_64> %n_3 @int_64_1
206 207
    let blk_0_v48 = func_ver.new_ssa("blk_0_v48", type_def_int64.clone());
    let blk_0_inst0 = func_ver.new_inst(Instruction {
qinsoon's avatar
qinsoon committed
208
            value: Some(vec![blk_0_v48.clone_value()]),
209 210
            ops: RefCell::new(vec![blk_0_n_3.clone(), const_def_int64_1_local.clone()]),
            v: Instruction_::CmpOp(CmpOp::EQ, 0, 1)
211 212
    });

213
    //   BRANCH2 %v48 %blk_2(@int_64_1) %blk_1(%n_3)
214
    let blk_0_term = func_ver.new_inst(Instruction{
215 216 217 218 219 220 221 222 223 224 225
        value: None,
        ops: RefCell::new(vec![blk_0_v48.clone(), const_def_int64_1_local.clone(), blk_0_n_3.clone()]),
        v: Instruction_::Branch2 {
            cond: 0,
            true_dest: Destination {
                target: "blk_2",
                args: vec![DestArg::Normal(1)]
            },
            false_dest: Destination {
                target: "blk_1",
                args: vec![DestArg::Normal(2)]
226
            },
227
            true_prob: 0.3f32
228
        }
qinsoon's avatar
qinsoon committed
229
    });
230

231
    let blk_0_content = BlockContent {
232
        args: vec![blk_0_n_3.clone_value()],
233
        body: vec![blk_0_inst0, blk_0_term],
234
        keepalives: None
235
    };
236
    blk_0.content = Some(blk_0_content);
237 238 239

    // %blk_2(<@int_64> %v53):
    let mut blk_2 = Block::new("blk_2");
240
    let blk_2_v53 = func_ver.new_ssa("blk_2_v53", type_def_int64.clone());
241

242
    //   RET %v53
243
    let blk_2_term = func_ver.new_inst(Instruction{
244 245 246 247
        value: None,
        ops: RefCell::new(vec![blk_2_v53.clone()]),
        v: Instruction_::Return(vec![0])
    });
248

249
    let blk_2_content = BlockContent {
250
        args: vec![blk_2_v53.clone_value()],
251
        body: vec![blk_2_term],
252 253
        keepalives: None
    };
254
    blk_2.content = Some(blk_2_content);
255

256 257
    // %blk_1(<@int_64> %n_3):
    let mut blk_1 = Block::new("blk_1");
258
    let blk_1_n_3 = func_ver.new_ssa("blk_1_n_3", type_def_int64.clone());
259

260
    //   %v50 = SUB <@int_64> %n_3 @int_64_1
261 262
    let blk_1_v50 = func_ver.new_ssa("blk_1_v50", type_def_int64.clone());
    let blk_1_inst0 = func_ver.new_inst(Instruction{
qinsoon's avatar
qinsoon committed
263
        value: Some(vec![blk_1_v50.clone_value()]),
264 265 266
        ops: RefCell::new(vec![blk_1_n_3.clone(), const_def_int64_1_local.clone()]),
        v: Instruction_::BinOp(BinOp::Sub, 0, 1)
    });
267

268
    //   %v51 = CALL <@fac_sig> @fac (%v50)
269 270 271
    let blk_1_v51 = func_ver.new_ssa("blk_1_v51", type_def_int64.clone());
    let blk_1_fac = func_ver.new_constant(const_func_fac.clone());
    let blk_1_inst1 = func_ver.new_inst(Instruction{
qinsoon's avatar
qinsoon committed
272 273
        value: Some(vec![blk_1_v51.clone_value()]),
        ops: RefCell::new(vec![blk_1_fac, blk_1_v50.clone()]),
274 275 276 277 278 279 280 281
        v: Instruction_::ExprCall {
            data: CallData {
                func: 0,
                args: vec![1],
                convention: CallConvention::Mu
            },
            is_abort: true
        }
qinsoon's avatar
qinsoon committed
282
    });
283

284
    //   %v52 = MUL <@int_64> %n_3 %v51
285 286
    let blk_1_v52 = func_ver.new_ssa("blk_1_v52", type_def_int64.clone());
    let blk_1_inst2 = func_ver.new_inst(Instruction{
qinsoon's avatar
qinsoon committed
287
        value: Some(vec![blk_1_v52.clone_value()]),
288 289
        ops: RefCell::new(vec![blk_1_n_3.clone(), blk_1_v51.clone()]),
        v: Instruction_::BinOp(BinOp::Mul, 0, 1)
qinsoon's avatar
qinsoon committed
290
    });
291

292
    // BRANCH blk_2 (%blk_1_v52)
293
    let blk_1_term = func_ver.new_inst(Instruction{
294 295 296 297 298 299 300
        value: None,
        ops: RefCell::new(vec![blk_1_v52.clone()]),
        v: Instruction_::Branch1(Destination {
                target: "blk_2",
                args: vec![DestArg::Normal(0)]
           })
    });
301

302
    let blk_1_content = BlockContent {
303
        args: vec![blk_1_n_3.clone_value()],
304
        body: vec![blk_1_inst0, blk_1_inst1, blk_1_inst2, blk_1_term],
305 306
        keepalives: None
    };
307
    blk_1.content = Some(blk_1_content);
308

309
    // wrap into a function
310
    func_ver.define(FunctionContent{
311
            entry: "blk_0",
312 313 314 315 316 317 318 319
            blocks: {
                let mut blocks = HashMap::new();
                blocks.insert("blk_0", blk_0);
                blocks.insert("blk_1", blk_1);
                blocks.insert("blk_2", blk_2);
                blocks
            }
    });
320

321
    vm.define_func_version(func_ver);
322

323
    vm
324
}
qinsoon's avatar
qinsoon committed
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356

#[allow(unused_variables)]
pub fn global_access() -> VMContext {
    let vm = VMContext::new();
    
    // .typedef @int64 = int<64>
    // .typedef @iref_int64 = iref<int<64>>
    let type_def_int64 = vm.declare_type("int64", P(MuType::int(64)));
    let type_def_iref_int64 = vm.declare_type("iref_int64", P(MuType::iref(type_def_int64.clone())));
    
    // .const @int_64_0 <@int_64> = 0
    // .const @int_64_1 <@int_64> = 1
    let const_def_int64_0 = vm.declare_const("int64_0", type_def_int64.clone(), Constant::Int(0));
    let const_def_int64_1 = vm.declare_const("int64_1", type_def_int64.clone(), Constant::Int(1));
    
    // .global @a <@int_64>
    let global_a = vm.declare_global("a", type_def_int64.clone());
    
    // .funcsig @global_access_sig = () -> ()
    let func_sig = vm.declare_func_sig("global_access_sig", vec![], vec![]);

    // .funcdecl @global_access <@global_access_sig>
    let func = MuFunction::new("global_access", func_sig.clone());
    vm.declare_func(func);
    
    // .funcdef @global_access VERSION @v1 <@global_access_sig>
    let mut func_ver = MuFunctionVersion::new("global_access", "v1", func_sig.clone());
    
    // %blk_0():
    let mut blk_0 = Block::new("blk_0");
    
    // %x = LOAD <@int_64> @a
357
    let blk_0_x = func_ver.new_ssa("blk_0_x", type_def_int64.clone()).clone_value();
qinsoon's avatar
qinsoon committed
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
    let blk_0_a = func_ver.new_global(global_a.clone());
    let blk_0_inst0 = func_ver.new_inst(Instruction{
        value: Some(vec![blk_0_x]),
        ops: RefCell::new(vec![blk_0_a.clone()]),
        v: Instruction_::Load{
            is_ptr: false,
            order: MemoryOrder::SeqCst,
            mem_loc: 0
        }
    });
    
    // STORE <@int_64> @a @int_64_1
    let blk_0_const_int64_1 = func_ver.new_constant(const_def_int64_1.clone());
    let blk_0_inst1 = func_ver.new_inst(Instruction{
        value: None,
        ops: RefCell::new(vec![blk_0_a.clone(), blk_0_const_int64_1.clone()]),
        v: Instruction_::Store{
            is_ptr: false,
            order: MemoryOrder::SeqCst,
            mem_loc: 0,
            value: 1
        }
    });
    
    let blk_0_term = func_ver.new_inst(Instruction{
        value: None,
        ops: RefCell::new(vec![]),
        v: Instruction_::Return(vec![])
    });
    
    let blk_0_content = BlockContent {
        args: vec![],
        body: vec![blk_0_inst0, blk_0_inst1, blk_0_term],
        keepalives: None
    };
    blk_0.content = Some(blk_0_content);
    
    func_ver.define(FunctionContent{
        entry: "blk_0",
        blocks: {
            let mut ret = HashMap::new();
            ret.insert("blk_0", blk_0);
            ret
        }
    });
    
    vm.define_func_version(func_ver);
    
    vm
}