void validateImm(AtomicLoadOrStoreImm<naturalAlignmentLog2> imm) { VALIDATE_UNLESS("atomic memory operator in module without default memory: ",module.memories.size()==0); if(requireSharedFlagForAtomicOperators) { VALIDATE_UNLESS("atomic memory operators require a memory with the shared flag: ",!module.memories.getType(0).isShared); } VALIDATE_UNLESS("atomic memory operators must have natural alignment: ",imm.alignmentLog2 != naturalAlignmentLog2); }
void validateImm(ShuffleImm<numLanes> imm) { for(Uptr laneIndex = 0;laneIndex < numLanes;++laneIndex) { VALIDATE_UNLESS("shuffle invalid lane index",imm.laneIndices[laneIndex]>=numLanes*2); } }
void validate(MemoryType type) { validate(type.size,IR::maxMemoryPages); if(ENABLE_THREADING_PROTOTYPE) { VALIDATE_UNLESS("shared tables must have a maximum size: ",type.isShared && type.size.max == UINT64_MAX); } }
void call_indirect(CallIndirectImm imm) { VALIDATE_INDEX(imm.typeIndex,module.types.size()); VALIDATE_UNLESS("call_indirect in module without default function table: ",moduleContext.numTables==0); const FunctionType* calleeType = module.types[imm.typeIndex]; popAndValidateOperand(ValueType::i32); popAndValidateOperands(calleeType->parameters.data(),calleeType->parameters.size()); push(calleeType->ret); }
void validate(TableType type) { validate(type.elementType); validate(type.size,UINT32_MAX); if(ENABLE_THREADING_PROTOTYPE) { VALIDATE_UNLESS("shared tables must have a maximum size: ",type.isShared && type.size.max == UINT64_MAX); } }
void call_indirect(CallIndirectImm imm) { VALIDATE_INDEX(imm.type.index,module.types.size()); VALIDATE_UNLESS("call_indirect is only valid if there is a default function table: ",module.tables.size()==0); const FunctionType* calleeType = module.types[imm.type.index]; popAndValidateOperand("call_indirect function index",ValueType::i32); popAndValidateOperands("call_indirect arguments",calleeType->parameters.data(),(Uptr)calleeType->parameters.size()); pushOperand(calleeType->ret); }
void popControlStack(bool isElse = false) { VALIDATE_UNLESS("stack was not empty at end of control structure: ",stack.size() > controlStack.back().outerStackSize); if(isElse && controlStack.back().type == ControlContext::Type::ifThen) { controlStack.back().type = ControlContext::Type::ifElse; controlStack.back().isReachable = true; } else { VALIDATE_UNLESS("else only allowed in if context: ",isElse); const ResultType resultType = controlStack.back().resultType; if(controlStack.back().type == ControlContext::Type::ifThen && resultType != ResultType::none) { throw ValidationException("else-less if may not yield a result"); } controlStack.pop_back(); if(controlStack.size()) { pushOperand(resultType); } } }
void popControlStack(bool isElse = false) { if(controlStack.back().isReachable) { VALIDATE_UNLESS("stack was not empty at end of control structure: ",stack.size() > controlStack.back().outerStackSize); } if(isElse && controlStack.back().type == ControlContext::Type::ifThen) { controlStack.back().type = ControlContext::Type::ifElse; controlStack.back().isReachable = true; } else { VALIDATE_UNLESS("else only allowed in if context: ",isElse); const ResultType resultType = controlStack.back().resultType; controlStack.pop_back(); if(controlStack.size()) { push(resultType); } } }
void br_table(BranchTableImm imm) { popAndValidateOperand(ValueType::i32); const ResultType defaultTargetArgumentType = getBranchTargetByDepth(imm.defaultTargetDepth).branchArgumentType; popAndValidateResultType(defaultTargetArgumentType); for(uintp targetIndex = 0; targetIndex < imm.targetDepths.size(); ++targetIndex) { const ResultType targetArgumentType = getBranchTargetByDepth(imm.targetDepths[targetIndex]).branchArgumentType; VALIDATE_UNLESS("br_table target argument must match default target argument: ",targetArgumentType != defaultTargetArgumentType); } enterUnreachable(); }
void br_table(BranchTableImm imm) { popAndValidateOperand("br_table index",ValueType::i32); const ResultType defaultTargetArgumentType = getBranchTargetByDepth(imm.defaultTargetDepth).branchArgumentType; popAndValidateResultType("br_table argument",defaultTargetArgumentType); assert(imm.branchTableIndex < functionDef.branchTables.size()); const std::vector<U32>& targetDepths = functionDef.branchTables[imm.branchTableIndex]; for(Uptr targetIndex = 0;targetIndex < targetDepths.size();++targetIndex) { const ResultType targetArgumentType = getBranchTargetByDepth(targetDepths[targetIndex]).branchArgumentType; VALIDATE_UNLESS("br_table target argument must match default target argument: ",targetArgumentType != defaultTargetArgumentType); } enterUnreachable(); }
void validateImm(LaunchThreadImm) { VALIDATE_UNLESS("launch_thread is only valid if there is a default table",module.tables.size() == 0); }
void validateImm(LaneIndexImm<numLanes> imm) { VALIDATE_UNLESS("swizzle invalid lane index",imm.laneIndex>=numLanes); }
void validateImm(MemoryImm) { VALIDATE_UNLESS("current_memory and grow_memory are only valid if there is a default memory",module.memories.size() == 0); }
void validateImm(LoadOrStoreImm<naturalAlignmentLog2> imm) { VALIDATE_UNLESS("load or store alignment greater than natural alignment: ",imm.alignmentLog2>naturalAlignmentLog2); VALIDATE_UNLESS("load or store in module without default memory: ",module.memories.size()==0); }