Load instruction node. See "include/loader/loader.h".
| 230 | |
| 231 | // Load instruction node. See "include/loader/loader.h". |
| 232 | Expect<void> Loader::loadInstruction(AST::Instruction &Instr) { |
| 233 | // Node: The instruction has checked for the proposals. Need to check their |
| 234 | // immediates. |
| 235 | |
| 236 | auto ReportError = [this](auto E) { |
| 237 | return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Instruction); |
| 238 | }; |
| 239 | |
| 240 | auto readU8 = [this, ReportError](uint8_t &Dst) -> Expect<void> { |
| 241 | EXPECTED_TRY(Dst, FMgr.readByte().map_error(ReportError)); |
| 242 | return {}; |
| 243 | }; |
| 244 | |
| 245 | auto readU32 = [this, ReportError](uint32_t &Dst) -> Expect<void> { |
| 246 | EXPECTED_TRY(Dst, FMgr.readU32().map_error(ReportError)); |
| 247 | return {}; |
| 248 | }; |
| 249 | |
| 250 | auto readU64 = [this, ReportError](uint64_t &Dst) -> Expect<void> { |
| 251 | EXPECTED_TRY(Dst, FMgr.readU64().map_error(ReportError)); |
| 252 | return {}; |
| 253 | }; |
| 254 | |
| 255 | auto readMemImmediate = [this, readU32, readU64, &Instr]() -> Expect<void> { |
| 256 | Instr.getTargetIndex() = 0; |
| 257 | EXPECTED_TRY(readU32(Instr.getMemoryAlign())); |
| 258 | if (Conf.hasProposal(Proposal::MultiMemories) && |
| 259 | Instr.getMemoryAlign() >= 64) { |
| 260 | Instr.getMemoryAlign() -= 64; |
| 261 | EXPECTED_TRY(readU32(Instr.getTargetIndex())); |
| 262 | } |
| 263 | uint32_t MaxAlign = Conf.hasProposal(Proposal::Memory64) ? 64U : 32U; |
| 264 | if (unlikely(Instr.getMemoryAlign() >= MaxAlign)) { |
| 265 | return logLoadError(ErrCode::Value::MalformedMemoryOpFlags, |
| 266 | FMgr.getLastOffset(), ASTNodeAttr::Instruction); |
| 267 | } |
| 268 | if (Conf.hasProposal(Proposal::Memory64)) { |
| 269 | EXPECTED_TRY(readU64(Instr.getMemoryOffset())); |
| 270 | } else { |
| 271 | uint32_t Offset; |
| 272 | EXPECTED_TRY(readU32(Offset)); |
| 273 | Instr.getMemoryOffset() = static_cast<uint64_t>(Offset); |
| 274 | } |
| 275 | return {}; |
| 276 | }; |
| 277 | |
| 278 | auto readCheckZero = [this, readU8](uint32_t &Dst) -> Expect<void> { |
| 279 | uint8_t C = 0; |
| 280 | EXPECTED_TRY(readU8(C)); |
| 281 | if (C != UINT8_C(0)) { |
| 282 | return logLoadError(ErrCode::Value::ExpectedZeroByte, |
| 283 | FMgr.getLastOffset(), ASTNodeAttr::Instruction); |
| 284 | } |
| 285 | Dst = 0; |
| 286 | return {}; |
| 287 | }; |
| 288 | |
| 289 | auto readBlockType = [this, ReportError](BlockType &Dst) -> Expect<void> { |
nothing calls this directly
no test coverage detected