compiler: Write RV64 images through checked byte slices
cb284e737d750af0b52f5fc609cbb25d151286bdc69870b237d800d1373b3e7b
1 parent
f28b0751
compiler/radiance.rad
+21 -10
| 38 | 38 | /// Maximum number of test functions we can discover. |
|
| 39 | 39 | constant MAX_TESTS: u32 = 1024; |
|
| 40 | 40 | /// Maximum number of assembly source paths we can load per package. |
|
| 41 | 41 | constant MAX_ASM_MODULES: u32 = 64; |
|
| 42 | 42 | ||
| 43 | + | /// Byte size of the five u32 fields in a single-file RV64 image header. |
|
| 44 | + | constant IMAGE_HEADER_SIZE: u32 = @sizeOf([u32; 5]); |
|
| 45 | + | ||
| 43 | 46 | /// AST arena size (64 MB) - retains parsed nodes throughout compilation. |
|
| 44 | 47 | constant TEMP_ARENA_SIZE: u32 = 67108864; |
|
| 45 | 48 | /// Per-function lowering and register-allocation arena size (16 MB). |
|
| 46 | 49 | constant FN_ARENA_SIZE: u32 = 16777216; |
|
| 47 | 50 | /// Main arena size (176 MB) - lives throughout compilation. |
| 830 | 833 | ast::Block { statements: stmts, isUnsafe: block.isUnsafe } |
|
| 831 | 834 | )); |
|
| 832 | 835 | } |
|
| 833 | 836 | ||
| 834 | 837 | /// Write a self-contained RV64 image containing text and data sections. |
|
| 835 | - | unsafe fn writeImage( |
|
| 836 | - | code: *[u32], |
|
| 837 | - | roData: *[u8], |
|
| 838 | - | rwData: *[u8], |
|
| 838 | + | fn writeImage( |
|
| 839 | + | code: &[u8], |
|
| 840 | + | roData: &[u8], |
|
| 841 | + | rwData: &[u8], |
|
| 839 | 842 | path: *[u8] |
|
| 840 | 843 | ) -> bool { |
|
| 841 | - | let mut header = rv64::imageHeader(code.len * rv64::INSTR_SIZE as u32, roData.len, rwData.len); |
|
| 842 | - | let headerBytes: *unsafe [u8] = @sliceOf(&header[0] as *unsafe u8, header.len * rv64::WORD_SIZE as u32); |
|
| 843 | - | let codeBytes = @sliceOf(code.ptr as *u8, code.len * rv64::INSTR_SIZE as u32); |
|
| 844 | + | let header = rv64::imageHeader(code.len, roData.len, rwData.len); |
|
| 845 | + | let mut headerBytes = [0 as u8; IMAGE_HEADER_SIZE]; |
|
| 846 | + | assert headerBytes.len == header.len * @sizeOf(u32); |
|
| 847 | + | for word, index in header { |
|
| 848 | + | for byte in 0..@sizeOf(u32) { |
|
| 849 | + | set headerBytes[index * @sizeOf(u32) + byte] = (word >> (byte * 8)) as u8; |
|
| 850 | + | } |
|
| 851 | + | } |
|
| 844 | 852 | ||
| 845 | 853 | let fd = unix::openOpts(path, unix::OpenFlags(*unix::O_WRONLY | *unix::O_CREAT | *unix::O_TRUNC), 420); |
|
| 846 | - | if fd < 0 { return false; } |
|
| 847 | - | let written = unix::writeAll(fd, headerBytes) and unix::writeAll(fd, codeBytes) |
|
| 854 | + | if fd < 0 { |
|
| 855 | + | return false; |
|
| 856 | + | } |
|
| 857 | + | let written = unix::writeAll(fd, &headerBytes[..]) and unix::writeAll(fd, code) |
|
| 848 | 858 | and unix::writeAll(fd, roData) and unix::writeAll(fd, rwData); |
|
| 849 | 859 | let closed = unix::close(fd) == 0; |
|
| 850 | 860 | return written and closed; |
|
| 851 | 861 | } |
|
| 852 | 862 |
| 1349 | 1359 | entryMode: CodegenEntryMode::None |
|
| 1350 | 1360 | if startupPath <> nil |
|
| 1351 | 1361 | else CodegenEntryMode::DefaultEntry, |
|
| 1352 | 1362 | }); |
|
| 1353 | 1363 | ||
| 1364 | + | let codeBytes = @sliceOf(result.code.ptr as *u8, result.code.len * rv64::INSTR_SIZE as u32); |
|
| 1354 | 1365 | if not writeImage( |
|
| 1355 | - | result.code, |
|
| 1366 | + | codeBytes, |
|
| 1356 | 1367 | &RO_DATA_BUF[..result.roDataSize], |
|
| 1357 | 1368 | &RW_DATA_BUF[..result.rwDataSize], |
|
| 1358 | 1369 | outPath |
|
| 1359 | 1370 | ) { |
|
| 1360 | 1371 | throw error(&["fatal:", "failed to write output file"]); |