compiler: Check decoder block table filling
97e4033fb9fbcf135549bd0f53266be824c7d7f89eee6cf992b7a1370629a6ea
1 parent
62f24fee
lib/std/lang/il/binary/decodeTests.rad
+5 -0
| 57 | 57 | for param, j in original.params { |
|
| 58 | 58 | assert restored.params[j].value.n == param.value.n; |
|
| 59 | 59 | assert restored.params[j].type == param.type; |
|
| 60 | 60 | } |
|
| 61 | 61 | assert restored.blocks.len == original.blocks.len; |
|
| 62 | + | let mut isLeaf = true; |
|
| 62 | 63 | for block, j in original.blocks { |
|
| 64 | + | for instr in block.instrs { |
|
| 65 | + | if il::isCall(instr) { set isLeaf = false; } |
|
| 66 | + | } |
|
| 63 | 67 | let rebuilt = &restored.blocks[j]; |
|
| 64 | 68 | try testing::expectBytesEq(rebuilt.label, block.label); |
|
| 65 | 69 | assert rebuilt.loopDepth == block.loopDepth; |
|
| 66 | 70 | assert rebuilt.params.len == block.params.len; |
|
| 67 | 71 | for param, k in block.params { |
| 69 | 73 | assert rebuilt.params[k].type == param.type; |
|
| 70 | 74 | } |
|
| 71 | 75 | assert rebuilt.preds.len == block.preds.len; |
|
| 72 | 76 | for pred, k in block.preds { assert rebuilt.preds[k] == pred; } |
|
| 73 | 77 | } |
|
| 78 | + | assert restored.isLeaf == isLeaf; |
|
| 74 | 79 | } |
|
| 75 | 80 | let mut encoded: [u8; 2048] = [0; 2048]; |
|
| 76 | 81 | let repeated = try program::encode(&mut encoded[..], &decoded) catch { |
|
| 77 | 82 | throw testing::TestError::Failed; |
|
| 78 | 83 | }; |
lib/std/lang/il/binary/program.rad
+26 -10
| 248 | 248 | for j in 0..count { |
|
| 249 | 249 | let label = try reader::bytes(input); |
|
| 250 | 250 | let blockParams = try readParams(input); |
|
| 251 | 251 | let loopDepth = try reader::integer(input, 4) as u32; |
|
| 252 | 252 | let predCount = try reader::count(input, 4); |
|
| 253 | - | let preds = try reader::storage(input, @sizeOf(u32), @alignOf(u32), predCount) as *mut [u32]; |
|
| 254 | - | for k in 0..predCount { |
|
| 255 | - | set preds[k] = try reader::target(input); |
|
| 256 | - | } |
|
| 253 | + | let predStorage = try reader::storage(input, @sizeOf(u32), @alignOf(u32), predCount) as *mut [u32]; |
|
| 254 | + | let preds = try fillPredecessors(input, predStorage); |
|
| 257 | 255 | let instrCount = try reader::count(input, 1); |
|
| 258 | 256 | let instrs = try reader::storage(input, @sizeOf(il::Instr), @alignOf(il::Instr), instrCount) |
|
| 259 | 257 | as *mut [il::Instr]; |
|
| 260 | - | for k in 0..instrCount { |
|
| 261 | - | let instr = try reader::instr(input); |
|
| 262 | - | if il::isCall(instr) { |
|
| 263 | - | set isLeaf = false; |
|
| 264 | - | } |
|
| 265 | - | set instrs[k] = instr; |
|
| 258 | + | if try fillInstructions(input, &mut instrs[..]) { |
|
| 259 | + | set isLeaf = false; |
|
| 266 | 260 | } |
|
| 267 | 261 | set blocks[j] = il::Block { |
|
| 268 | 262 | label, params: blockParams, instrs: (&mut instrs[..]) as *unsafe mut [il::Instr], locs: &[], preds: (&preds[..]) as *unsafe [u32], loopDepth, |
|
| 269 | 263 | }; |
|
| 270 | 264 | } |
| 273 | 267 | set fns[i] = &func[0]; |
|
| 274 | 268 | } |
|
| 275 | 269 | return (&fns[..]) as *unsafe [*unsafe il::Fn]; |
|
| 276 | 270 | } |
|
| 277 | 271 | ||
| 272 | + | /// Fill owned predecessor storage with checked block indices. |
|
| 273 | + | fn fillPredecessors 'input (input: &mut reader::Reader 'input, preds: *mut [u32]) -> *[u32] throws (binary::Error) { |
|
| 274 | + | for i in 0..preds.len { |
|
| 275 | + | set preds[i] = try reader::target(input); |
|
| 276 | + | } |
|
| 277 | + | return preds; |
|
| 278 | + | } |
|
| 279 | + | ||
| 280 | + | /// Fill an instruction table and report whether it contains a call. |
|
| 281 | + | fn fillInstructions 'input (input: &mut reader::Reader 'input, instrs: &mut [il::Instr]) -> bool throws (binary::Error) { |
|
| 282 | + | let mut hasCall = false; |
|
| 283 | + | for i in 0..instrs.len { |
|
| 284 | + | unsafe { |
|
| 285 | + | set instrs[i] = try reader::instr(input); |
|
| 286 | + | } |
|
| 287 | + | if il::isCall(instrs[i]) { |
|
| 288 | + | set hasCall = true; |
|
| 289 | + | } |
|
| 290 | + | } |
|
| 291 | + | return hasCall; |
|
| 292 | + | } |
|
| 293 | + | ||
| 278 | 294 | /// Read the package tables. The input must contain exactly one package. |
|
| 279 | 295 | unsafe fn readPackage 'input (input: &mut reader::Reader 'input, limits: binary::Limits) |
|
| 280 | 296 | -> binary::Package throws (binary::Error) |
|
| 281 | 297 | { |
|
| 282 | 298 | let magic = try reader::integer(input, 4) as u32; |