test/native/build.rad 4.4 KiB raw
1
//! Build a native machine fixture with the reusable RV64 backend.
2
3
use std::sys;
4
use std::sys::unix;
5
use std::lang::il;
6
use std::lang::alloc;
7
use std::lang::gen::data;
8
use std::collections::dict;
9
use std::arch::rv64;
10
use std::arch::rv64::image;
11
12
/// Persistent code generation arena.
13
static MEMORY: [u8; 16777216] = [0; 16777216];
14
/// Function lowering and allocation workspace.
15
static SCRATCH: [u8; 16777216] = [0; 16777216];
16
/// Data symbol lookup workspace.
17
unsafe static ENTRIES: [dict::Entry; data::DATA_SYM_TABLE_SIZE] = undefined;
18
19
/// Compile data accesses and conditional finish writes into a native image.
20
@default unsafe fn main(env: *sys::Env) -> i32 {
21
    assert env.args.len == 2;
22
    let mut arena = alloc::new(&mut MEMORY[..]);
23
    let mut scratch = alloc::new(&mut SCRATCH[..]);
24
    let mut generator = try! rv64::beginProgram(rv64::ProgramOptions {
25
        entryPatch: rv64::EntryPatch::None, debug: false,
26
        placement: image::Placement::Physical {
27
            code: 0x80010000, roData: 0x80018000, rwData: 0x80020000, entry: 0x80010000,
28
        },
29
    }, &mut arena);
30
    let mut args: [il::Val; 0] = [];
31
    let mut entry = [
32
        il::Instr::Copy { dst: il::Reg { n: 0 }, val: il::Val::DataSym("fixture::value") },
33
        il::Instr::Load { typ: il::Type::W64, dst: il::Reg { n: 1 }, src: il::Reg { n: 0 }, offset: 0 },
34
        il::Instr::Br {
35
            op: il::CmpOp::Eq, typ: il::Type::W64, a: il::Val::Reg(il::Reg { n: 1 }), b: il::Val::Imm(42),
36
            thenTarget: 1, thenArgs: &mut args[..], elseTarget: 3, elseArgs: &mut args[..],
37
        },
38
    ];
39
    let mut zero = [
40
        il::Instr::Copy { dst: il::Reg { n: 2 }, val: il::Val::DataSym("fixture::zero") },
41
        il::Instr::Load { typ: il::Type::W64, dst: il::Reg { n: 3 }, src: il::Reg { n: 2 }, offset: 0 },
42
        il::Instr::Br {
43
            op: il::CmpOp::Eq, typ: il::Type::W64, a: il::Val::Reg(il::Reg { n: 3 }), b: il::Val::Imm(0),
44
            thenTarget: 2, thenArgs: &mut args[..], elseTarget: 3, elseArgs: &mut args[..],
45
        },
46
    ];
47
    let mut success = [
48
        il::Instr::Copy { dst: il::Reg { n: 4 }, val: il::Val::Imm(0x10001000) },
49
        il::Instr::Store { typ: il::Type::W32, src: il::Val::Imm(0x5555), dst: il::Reg { n: 4 }, offset: 0 },
50
        il::Instr::Unreachable,
51
    ];
52
    let mut failure = [
53
        il::Instr::Copy { dst: il::Reg { n: 5 }, val: il::Val::Imm(0x10001000) },
54
        il::Instr::Store { typ: il::Type::W32, src: il::Val::Imm(0x13333), dst: il::Reg { n: 5 }, offset: 0 },
55
        il::Instr::Unreachable,
56
    ];
57
    let func = il::Fn {
58
        name: "fixture::entry", params: &[], returnType: il::Type::W64, isExtern: false, isLeaf: true,
59
        blocks: &[
60
            il::Block { label: "entry", params: &[], instrs: &mut entry[..], locs: &[], preds: &[], loopDepth: 0 },
61
            il::Block { label: "zero", params: &[], instrs: &mut zero[..], locs: &[], preds: &[0], loopDepth: 0 },
62
            il::Block { label: "success", params: &[], instrs: &mut success[..], locs: &[], preds: &[1], loopDepth: 0 },
63
            il::Block { label: "failure", params: &[], instrs: &mut failure[..], locs: &[], preds: &[0, 1], loopDepth: 0 },
64
        ],
65
    };
66
    rv64::generateFunction(&mut generator, &func, &mut scratch);
67
    let globals = &[
68
        il::Data {
69
            name: "fixture::value", size: 8, alignment: 8, readOnly: false, isZeroInit: false,
70
            values: &[il::DataValue { item: il::DataItem::Val { typ: il::Type::W64, val: 42 }, count: 1 }],
71
        },
72
        il::Data {
73
            name: "fixture::zero", size: 4096, alignment: 8, readOnly: false, isZeroInit: true, values: &[],
74
        },
75
    ];
76
    unsafe static symbols: [data::DataSym; 2] = undefined;
77
    let mut ro: [u8; 8] = [0; 8];
78
    let mut rw: [u8; 8] = [0; 8];
79
    let result = try! rv64::finishProgram(generator, globals,
80
        rv64::Storage { dataSyms: &mut symbols[..], dataSymEntries: &mut ENTRIES[..] },
81
        &[], &mut ro[..], &mut rw[..]);
82
    let header = try! image::header(result.layout);
83
    let code = @sliceOf(result.code.ptr as *u8, result.code.len * 4);
84
    let fd = unix::openOpts(env.args[1], unix::OpenFlags(*unix::O_WRONLY | *unix::O_CREAT | *unix::O_TRUNC), 420);
85
    assert fd >= 0;
86
    let written = unix::writeAll(fd, &header[..]) and unix::writeAll(fd, code) and unix::writeAll(fd, &ro[..result.roDataSize]) and unix::writeAll(fd, &rw[..result.rwDataSize]);
87
    let closed = unix::close(fd) == 0;
88
    assert written and closed;
89
    return 0;
90
}