[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