[llvm] [WebAssembly] Unify type checking in AsmTypeCheck (PR #110094)
Derek Schuff via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 26 09:52:32 PDT 2024
================
@@ -77,34 +71,119 @@ bool WebAssemblyAsmTypeCheck::typeError(SMLoc ErrorLoc, const Twine &Msg) {
return Parser.Error(ErrorLoc, Msg);
}
-bool WebAssemblyAsmTypeCheck::popType(SMLoc ErrorLoc,
- std::optional<wasm::ValType> EVT) {
- if (Stack.empty()) {
- return typeError(ErrorLoc,
- EVT ? StringRef("empty stack while popping ") +
- WebAssembly::typeToString(*EVT)
- : StringRef("empty stack while popping value"));
+bool WebAssemblyAsmTypeCheck::match(StackType TypeA, StackType TypeB) {
+ if (TypeA == TypeB)
+ return false;
+ if (std::get_if<Any>(&TypeA) || std::get_if<Any>(&TypeB))
+ return false;
+
+ if (std::get_if<Ref>(&TypeB))
+ std::swap(TypeA, TypeB);
+ assert(std::get_if<wasm::ValType>(&TypeB));
+ if (std::get_if<Ref>(&TypeA) &&
+ WebAssembly::isRefType(std::get<wasm::ValType>(TypeB)))
+ return false;
+ return true;
+}
+
+std::string WebAssemblyAsmTypeCheck::getTypesString(ArrayRef<StackType> Types,
+ size_t StartPos) {
+ SmallVector<std::string, 4> Reverse;
+ for (auto I = Types.size(); I > StartPos; I--) {
+ if (std::get_if<Any>(&Types[I - 1]))
+ Reverse.push_back("any");
+ else if (std::get_if<Ref>(&Types[I - 1]))
+ Reverse.push_back("ref");
+ else
+ Reverse.push_back(
+ WebAssembly::typeToString(std::get<wasm::ValType>(Types[I - 1])));
}
- auto PVT = Stack.pop_back_val();
- if (EVT && *EVT != PVT) {
- return typeError(ErrorLoc,
- StringRef("popped ") + WebAssembly::typeToString(PVT) +
- ", expected " + WebAssembly::typeToString(*EVT));
+
+ std::stringstream SS;
+ SS << "[";
+ bool First = true;
+ for (auto It = Reverse.rbegin(); It != Reverse.rend(); ++It) {
+ if (!First)
+ SS << ", ";
+ SS << *It;
+ First = false;
}
- return false;
+ SS << "]";
+ return SS.str();
}
-bool WebAssemblyAsmTypeCheck::popRefType(SMLoc ErrorLoc) {
- if (Stack.empty()) {
- return typeError(ErrorLoc, StringRef("empty stack while popping reftype"));
- }
- auto PVT = Stack.pop_back_val();
- if (!WebAssembly::isRefType(PVT)) {
- return typeError(ErrorLoc, StringRef("popped ") +
- WebAssembly::typeToString(PVT) +
- ", expected reftype");
+SmallVector<WebAssemblyAsmTypeCheck::StackType, 4>
+WebAssemblyAsmTypeCheck::valTypeToStackType(ArrayRef<wasm::ValType> ValTypes) {
+ SmallVector<StackType, 4> Types(ValTypes.size());
+ std::transform(ValTypes.begin(), ValTypes.end(), Types.begin(),
+ [](wasm::ValType Val) -> StackType { return Val; });
+ return Types;
+}
+
+bool WebAssemblyAsmTypeCheck::checkTypes(SMLoc ErrorLoc,
+ ArrayRef<wasm::ValType> ValTypes,
+ bool ExactMatch) {
+ return checkTypes(ErrorLoc, valTypeToStackType(ValTypes), ExactMatch);
+}
+
+bool WebAssemblyAsmTypeCheck::checkTypes(SMLoc ErrorLoc,
+ ArrayRef<StackType> Types,
+ bool ExactMatch) {
+ auto StackI = Stack.size();
+ auto TypeI = Types.size();
+ bool Error = false;
+ for (; StackI > 0 && TypeI > 0; StackI--, TypeI--) {
+ if (match(Stack[StackI - 1], Types[TypeI - 1])) {
+ Error = true;
+ break;
+ }
}
- return false;
+ if (TypeI > 0 || (ExactMatch && StackI > 0))
+ Error = true;
+
+ if (!Error)
+ return false;
+
+ auto StackStartPos =
+ ExactMatch ? 0 : std::max(0, (int)Stack.size() - (int)Types.size());
+ return typeError(ErrorLoc, "type mismatch, expected " +
+ getTypesString(Types, 0) + " but got " +
+ getTypesString(Stack, StackStartPos));
+}
+
+bool WebAssemblyAsmTypeCheck::checkAndPopTypes(SMLoc ErrorLoc,
+ ArrayRef<wasm::ValType> ValTypes,
+ bool ExactMatch) {
+ SmallVector<StackType, 4> Types(ValTypes.size());
+ std::transform(ValTypes.begin(), ValTypes.end(), Types.begin(),
----------------
dschuff wrote:
can this be replaced with `valTypeToStackType`?
https://github.com/llvm/llvm-project/pull/110094
More information about the llvm-commits
mailing list