compiler: Write binary package files in checked code
859cfb8c8328f524709d9d4ac198fff5f72061292a25e32f75a59f62dda138d6
1 parent
b74f809e
compiler/radiance.rad
+16 -11
| 1296 | 1296 | } |
|
| 1297 | 1297 | } |
|
| 1298 | 1298 | return PackageExports { count, entry: entryName }; |
|
| 1299 | 1299 | } |
|
| 1300 | 1300 | ||
| 1301 | + | /// Write encoded binary RIL bytes into an existing directory. |
|
| 1302 | + | fn writePackage(bytes: &[u8], directory: *[u8], name: *[u8]) throws (Error) { |
|
| 1303 | + | let mut path = [0 as u8; MAX_PATH_LEN]; |
|
| 1304 | + | let mut pos: u32 = 0; |
|
| 1305 | + | for part in &[directory, "/", name, ".ril"] { |
|
| 1306 | + | set pos += try mem::copy(&mut path[pos..MAX_PATH_LEN - 1], part) catch { |
|
| 1307 | + | throw error(&["binary RIL output path is too long"]); |
|
| 1308 | + | }; |
|
| 1309 | + | } |
|
| 1310 | + | set path[pos] = 0; |
|
| 1311 | + | if not unix::writeFile(&path[..pos], bytes) { |
|
| 1312 | + | throw error(&["cannot write binary RIL package", name]); |
|
| 1313 | + | } |
|
| 1314 | + | } |
|
| 1315 | + | ||
| 1301 | 1316 | /// Emit one binary RIL file per package into an existing directory. |
|
| 1302 | 1317 | unsafe fn emitPackages 'arena ( |
|
| 1303 | 1318 | ctx: &CompileContext, |
|
| 1304 | 1319 | res: *unsafe mut resolver::Resolver 'arena, |
|
| 1305 | 1320 | directory: *[u8] |
| 1334 | 1349 | throw error(&["cannot collect binary RIL package", pkg.name]); |
|
| 1335 | 1350 | }; |
|
| 1336 | 1351 | let length = try program::encode(&mut FN_ARENA[..], &image) catch { |
|
| 1337 | 1352 | throw error(&["binary RIL output capacity exceeded", pkg.name]); |
|
| 1338 | 1353 | }; |
|
| 1339 | - | let mut path: [u8; MAX_PATH_LEN] = undefined; |
|
| 1340 | - | let mut pos: u32 = 0; |
|
| 1341 | - | for part in &[directory, "/", pkg.name, ".ril"] { |
|
| 1342 | - | set pos += try mem::copy(&mut path[pos..MAX_PATH_LEN - 1], part) catch { |
|
| 1343 | - | throw error(&["binary RIL output path is too long"]); |
|
| 1344 | - | }; |
|
| 1345 | - | } |
|
| 1346 | - | set path[pos] = 0; |
|
| 1347 | - | if not unix::writeFile(&path[..pos], &FN_ARENA[..length]) { |
|
| 1348 | - | throw error(&["cannot write binary RIL package", pkg.name]); |
|
| 1349 | - | } |
|
| 1354 | + | try writePackage(&FN_ARENA[..length], directory, pkg.name); |
|
| 1350 | 1355 | } |
|
| 1351 | 1356 | } |
|
| 1352 | 1357 | } |
|
| 1353 | 1358 | ||
| 1354 | 1359 | /// Match a qualified definition to its package name. |
test/command
+30 -0
| 93 | 93 | printf '%s\n' '/// Package fixture value.' 'constant value: u32 = 0;' > "$work/$name.rad" |
|
| 94 | 94 | arguments="$arguments -pkg $name -mod $work/$name.rad" |
|
| 95 | 95 | done |
|
| 96 | 96 | accept "$arguments -pkg p -mod $work/p.rad -entry p -o $work/multiple.rv64" |
|
| 97 | 97 | timeout 10 "${RAD_EMULATOR:-emulator}" -run "$work/multiple.rv64" |
|
| 98 | + | ||
| 99 | + | # Binary package output preserves bytes across destinations and replacements. |
|
| 100 | + | mkdir "$work/packages" |
|
| 101 | + | accept "$arguments -pkg p -mod $work/p.rad -entry p -ril $work/packages" |
|
| 102 | + | for name in a b c p; do |
|
| 103 | + | test -s "$work/packages/$name.ril" |
|
| 104 | + | done |
|
| 105 | + | cp "$work/packages/p.ril" "$work/expected.ril" |
|
| 106 | + | printf '%s\n' 'stale output bytes' >> "$work/packages/p.ril" |
|
| 107 | + | accept "-pkg p -mod $work/p.rad -ril $work/packages" |
|
| 108 | + | cmp "$work/expected.ril" "$work/packages/p.ril" |
|
| 109 | + | ||
| 110 | + | # MAX_PATH_LEN includes the terminating zero byte. |
|
| 111 | + | for length in 249 250 255 256; do |
|
| 112 | + | leaf=$(awk -v n="$((length - ${#work} - 1))" 'BEGIN { for (i = 0; i < n; i++) printf "x" }') |
|
| 113 | + | directory="$work/$leaf" |
|
| 114 | + | if [ "$length" -eq 249 ]; then |
|
| 115 | + | mkdir "$directory" |
|
| 116 | + | accept "-pkg p -mod $work/p.rad -ril $directory" |
|
| 117 | + | cmp "$work/expected.ril" "$directory/p.ril" |
|
| 118 | + | reject "-pkg package -mod $work/p.rad -ril $directory" 'binary RIL output path is too long' |
|
| 119 | + | else |
|
| 120 | + | reject "-pkg p -mod $work/p.rad -ril $directory" 'binary RIL output path is too long' |
|
| 121 | + | fi |
|
| 122 | + | done |
|
| 123 | + | reject "-pkg p -mod $work/p.rad -ril $work/missing" 'cannot write binary RIL package p' |
|
| 124 | + | mkdir -p "$work/blocked/p.ril" |
|
| 125 | + | reject "-pkg p -mod $work/p.rad -ril $work/blocked" 'cannot write binary RIL package p' |
|
| 126 | + | reject "-pkg p -mod $work/p.rad -mod absent.ras -ril $work/packages" 'binary RIL output requires Radiance source modules' |
|
| 127 | + | reject "-pkg p -mod $work/p.rad -start absent.ras -ril $work/packages" 'binary RIL output requires Radiance source modules' |
|
| 98 | 128 | echo "command tests: $checks passed" |