compiler/
kernel/
lib/
scripts/
seed/
sublime/
test/
acceptance/
boot/
bootstrap/
cycles/
dispatch/
loader/
mmio/
modules/
native/
build.rad
4.4 KiB
packages/
pages/
runtime/
scheduling/
shared/
slots/
smp/
sync/
termination/
tests/
trap/
run
2.7 KiB
runner.rad
10.3 KiB
vim/
.gitignore
336 B
.gitsigners
112 B
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
10.2 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.5 KiB
std.lib.test
551 B
test/native/build.rad
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(&mut 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 | } |