Introduce arch-specific checker tests.

- The '.cfg' output is now created on target.
- Arch-specific checker tests can be created by inserting a
  suffix. For example:
      /// CHECK-START-ARM64: int Main.foo(int) register (after)
      /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue

Change-Id: I55cdb37f8e806c7ffdde6b676c8f44ac30b59051
diff --git a/disassembler/disassembler_arm64.cc b/disassembler/disassembler_arm64.cc
index 348b2a5..5f88714 100644
--- a/disassembler/disassembler_arm64.cc
+++ b/disassembler/disassembler_arm64.cc
@@ -94,7 +94,7 @@
     int64_t offset = instr->ImmLSUnsigned() << instr->SizeLS();
     std::ostringstream tmp_stream;
     Thread::DumpThreadOffset<8>(tmp_stream, static_cast<uint32_t>(offset));
-    AppendToOutput(" (%s)", tmp_stream.str().c_str());
+    AppendToOutput(" ; %s", tmp_stream.str().c_str());
   }
 }
 
diff --git a/test/526-checker-caller-callee-regs/expected.txt b/test/526-checker-caller-callee-regs/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/526-checker-caller-callee-regs/expected.txt
diff --git a/test/526-checker-caller-callee-regs/info.txt b/test/526-checker-caller-callee-regs/info.txt
new file mode 100644
index 0000000..0e0373a
--- /dev/null
+++ b/test/526-checker-caller-callee-regs/info.txt
@@ -0,0 +1 @@
+Test allocation of caller and callee saved registers.
diff --git a/test/526-checker-caller-callee-regs/src/Main.java b/test/526-checker-caller-callee-regs/src/Main.java
new file mode 100644
index 0000000..a1f3301
--- /dev/null
+++ b/test/526-checker-caller-callee-regs/src/Main.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+
+  public static void assertIntEquals(int expected, int result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  static boolean doThrow = false;
+
+  // This function always returns 1.
+  // We use 'throw' to prevent the function from being inlined.
+  public static int $opt$noinline$function_call(int arg) {
+    if (doThrow) throw new Error();
+    return 1 % arg;
+  }
+
+  //                               | registers available to | regexp
+  //                               | the register allocator |
+  // ------------------------------|------------------------|-----------------
+  // ARM64 callee-saved registers  | [x20-x29]              | x2[0-9]
+  // ARM callee-saved registers    | [r5-r8,r10,r11]        | r([5-8]|10|11)
+
+  /**
+   * Check that a value live across a function call is allocated in a callee
+   * saved register.
+   */
+
+  /// CHECK-START-ARM:   int Main.$opt$LiveInCall(int) register (after)
+  /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue
+  /// CHECK-DAG:   <<Const1:i\d+>>  IntConstant 1
+  /// CHECK:       <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->r([5-8]|10|11)}}
+  /// CHECK:       <<t2:i\d+>>      InvokeStaticOrDirect
+  /// CHECK:                        Sub [<<t1>>,<<t2>>]
+  /// CHECK:                        Return
+
+  /// CHECK-START-ARM64: int Main.$opt$LiveInCall(int) register (after)
+  /// CHECK-DAG:   <<Arg:i\d+>>     ParameterValue
+  /// CHECK-DAG:   <<Const1:i\d+>>  IntConstant 1
+  /// CHECK:       <<t1:i\d+>>      Add [<<Arg>>,<<Const1>>] {{.*->x2[0-9]}}
+  /// CHECK:       <<t2:i\d+>>      InvokeStaticOrDirect
+  /// CHECK:                        Sub [<<t1>>,<<t2>>]
+  /// CHECK:                        Return
+
+  // TODO: Add tests for other architectures.
+
+  public static int $opt$LiveInCall(int arg) {
+    int t1 = arg + 1;
+    int t2 = $opt$noinline$function_call(arg);
+    return t1 - t2;
+  }
+
+  public static void main(String[] args) {
+    int arg = 123;
+    assertIntEquals($opt$LiveInCall(arg), arg);
+  }
+}
diff --git a/test/run-test b/test/run-test
index 3d6f073..84c818b 100755
--- a/test/run-test
+++ b/test/run-test
@@ -626,12 +626,19 @@
   # on a particular DEX output, keep building them with dx for now (b/19467889).
   USE_JACK="false"
 
-  if [ "$runtime" = "art" -a "$image_suffix" = "-optimizing" -a "$target_mode" = "no" -a "$debuggable" = "no" ]; then
+  if [ "$runtime" = "art" -a "$image_suffix" = "-optimizing" -a "$debuggable" = "no" ]; then
     # In no-prebuild mode, the compiler is only invoked if both dex2oat and
     # patchoat are available. Disable Checker otherwise (b/22552692).
     if [ "$prebuild_mode" = "yes" ] || [ "$have_patchoat" = "yes" -a "$have_dex2oat" = "yes" ]; then
       run_checker="yes"
-      run_args="${run_args} -Xcompiler-option --dump-cfg=$tmp_dir/$cfg_output \
+      if [ "$target_mode" = "no" ]; then
+        cfg_output_dir="$tmp_dir"
+        checker_arch_option=
+      else
+        cfg_output_dir="$DEX_LOCATION"
+        checker_arch_option="--arch=${target_arch_name^^}"
+      fi
+      run_args="${run_args} -Xcompiler-option --dump-cfg=$cfg_output_dir/$cfg_output \
                             -Xcompiler-option -j1"
     fi
   fi
@@ -647,6 +654,12 @@
   build_file_size_limit=5120
   run_file_size_limit=5120
 fi
+if [ "$run_checker" = "yes" -a "$target_mode" = "yes" ]; then
+  # We will need to `adb pull` the .cfg output from the target onto the host to
+  # run checker on it. This file can be big.
+  build_file_size_limit=16384
+  run_file_size_limit=16384
+fi
 if [ ${USE_JACK} = "false" ]; then
   # Set ulimit if we build with dx only, Jack can generate big temp files.
   if ! ulimit -S "$build_file_size_limit"; then
@@ -671,7 +684,10 @@
 
         if [ "$run_exit" = "0" ]; then
             if [ "$run_checker" = "yes" ]; then
-                "$checker" "$cfg_output" "$tmp_dir" 2>&1
+                if [ "$target_mode" = "yes" ]; then
+                  adb pull $cfg_output_dir/$cfg_output &> /dev/null
+                fi
+                "$checker" $checker_arch_option "$cfg_output" "$tmp_dir" 2>&1
                 checker_exit="$?"
                 if [ "$checker_exit" = "0" ]; then
                     good="yes"
@@ -693,7 +709,10 @@
         echo "${test_dir}: running..." 1>&2
         "./${run}" $run_args "$@" >"$output" 2>&1
         if [ "$run_checker" = "yes" ]; then
-          "$checker" -q "$cfg_output" "$tmp_dir" >> "$output" 2>&1
+          if [ "$target_mode" = "yes" ]; then
+            adb pull $cfg_output_dir/$cfg_output &> /dev/null
+          fi
+          "$checker" -q $checker_arch_option "$cfg_output" "$tmp_dir" >> "$output" 2>&1
         fi
         sed -e 's/[[:cntrl:]]$//g' < "$output" >"${td_expected}"
         good="yes"
@@ -731,7 +750,10 @@
             echo "run exit status: $run_exit" 1>&2
             good_run="no"
         elif [ "$run_checker" = "yes" ]; then
-            "$checker" -q "$cfg_output" "$tmp_dir" >> "$output" 2>&1
+            if [ "$target_mode" = "yes" ]; then
+              adb pull $cfg_output_dir/$cfg_output &> /dev/null
+            fi
+            "$checker" -q $checker_arch_option "$cfg_output" "$tmp_dir" >> "$output" 2>&1
             checker_exit="$?"
             if [ "$checker_exit" != "0" ]; then
                 echo "checker exit status: $checker_exit" 1>&2
diff --git a/tools/checker/README b/tools/checker/README
index 858a773..259691e 100644
--- a/tools/checker/README
+++ b/tools/checker/README
@@ -52,3 +52,11 @@
   The engine will attempt to match the check lines against the output of the
   group named on the first line. Together they verify that the CFG after
   constant folding returns an integer constant with value either 11 or 22.
+
+A group of check lines can be made architecture-specific by inserting '-<arch>'
+after the 'CHECK-START' keyword. The previous example can be updated to run for
+arm64 only with:
+
+  // CHECK-START-ARM64: int MyClass.MyMethod() constant_folding (after)
+  // CHECK:         <<ID:i\d+>>  IntConstant {{11|22}}
+  // CHECK:                      Return [<<ID>>]
diff --git a/tools/checker/checker.py b/tools/checker/checker.py
index 4e516de..bc5e17d 100755
--- a/tools/checker/checker.py
+++ b/tools/checker/checker.py
@@ -17,6 +17,7 @@
 import argparse
 import os
 
+from common.archs                     import archs_list
 from common.logger                    import Logger
 from file_format.c1visualizer.parser  import ParseC1visualizerStream
 from file_format.checker.parser       import ParseCheckerStream
@@ -34,6 +35,8 @@
                       help="print a list of all passes found in the tested file")
   parser.add_argument("--dump-pass", dest="dump_pass", metavar="PASS",
                       help="print a compiler pass dump")
+  parser.add_argument("--arch", dest="arch", choices=archs_list,
+                      help="Run the tests for the specified target architecture.")
   parser.add_argument("-q", "--quiet", action="store_true",
                       help="print only errors")
   return parser.parse_args()
@@ -80,13 +83,13 @@
     Logger.fail("Source path \"" + path + "\" not found")
 
 
-def RunTests(checkPrefix, checkPath, outputFilename):
+def RunTests(checkPrefix, checkPath, outputFilename, targetArch):
   c1File = ParseC1visualizerStream(os.path.basename(outputFilename), open(outputFilename, "r"))
   for checkFilename in FindCheckerFiles(checkPath):
     checkerFile = ParseCheckerStream(os.path.basename(checkFilename),
                                      checkPrefix,
                                      open(checkFilename, "r"))
-    MatchFiles(checkerFile, c1File)
+    MatchFiles(checkerFile, c1File, targetArch)
 
 
 if __name__ == "__main__":
@@ -100,4 +103,4 @@
   elif args.dump_pass:
     DumpPass(args.tested_file, args.dump_pass)
   else:
-    RunTests(args.check_prefix, args.source_path, args.tested_file)
+    RunTests(args.check_prefix, args.source_path, args.tested_file, args.arch)
diff --git a/tools/checker/common/archs.py b/tools/checker/common/archs.py
new file mode 100644
index 0000000..84bded9
--- /dev/null
+++ b/tools/checker/common/archs.py
@@ -0,0 +1,15 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+archs_list = ['ARM', 'ARM64', 'MIPS64', 'X86', 'X86_64']
diff --git a/tools/checker/file_format/c1visualizer/parser.py b/tools/checker/file_format/c1visualizer/parser.py
index 335a195..bdcde9d 100644
--- a/tools/checker/file_format/c1visualizer/parser.py
+++ b/tools/checker/file_format/c1visualizer/parser.py
@@ -27,10 +27,12 @@
 
 def __parseC1Line(line, lineNo, state, fileName):
   """ This function is invoked on each line of the output file and returns
-      a pair which instructs the parser how the line should be handled. If the
+      a triplet which instructs the parser how the line should be handled. If the
       line is to be included in the current group, it is returned in the first
       value. If the line starts a new output group, the name of the group is
-      returned in the second value.
+      returned in the second value. The third value is only here to make the
+      function prototype compatible with `SplitStream` and is always set to
+      `None` here.
   """
   if state.currentState == C1ParserState.StartingCfgBlock:
     # Previous line started a new 'cfg' block which means that this one must
@@ -39,16 +41,16 @@
       # Extract the pass name, prepend it with the name of the method and
       # return as the beginning of a new group.
       state.currentState = C1ParserState.InsideCfgBlock
-      return (None, state.lastMethodName + " " + line.split("\"")[1])
+      return (None, state.lastMethodName + " " + line.split("\"")[1], None)
     else:
       Logger.fail("Expected output group name", fileName, lineNo)
 
   elif state.currentState == C1ParserState.InsideCfgBlock:
     if line == "end_cfg":
       state.currentState = C1ParserState.OutsideBlock
-      return (None, None)
+      return (None, None, None)
     else:
-      return (line, None)
+      return (line, None, None)
 
   elif state.currentState == C1ParserState.InsideCompilationBlock:
     # Search for the method's name. Format: method "<name>"
@@ -59,7 +61,7 @@
       state.lastMethodName = methodName
     elif line == "end_compilation":
       state.currentState = C1ParserState.OutsideBlock
-    return (None, None)
+    return (None, None, None)
 
   else:
     assert state.currentState == C1ParserState.OutsideBlock
@@ -69,10 +71,10 @@
       if state.lastMethodName is None:
         Logger.fail("Expected method header", fileName, lineNo)
       state.currentState = C1ParserState.StartingCfgBlock
-      return (None, None)
+      return (None, None, None)
     elif line == "begin_compilation":
       state.currentState = C1ParserState.InsideCompilationBlock
-      return (None, None)
+      return (None, None, None)
     else:
       Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
 
@@ -82,6 +84,7 @@
   fnProcessLine = lambda line, lineNo: __parseC1Line(line, lineNo, state, fileName)
   fnLineOutsideChunk = lambda line, lineNo: \
       Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
-  for passName, passLines, startLineNo in SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
+  for passName, passLines, startLineNo, testArch in \
+      SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
     C1visualizerPass(c1File, passName, passLines, startLineNo + 1)
   return c1File
diff --git a/tools/checker/file_format/checker/parser.py b/tools/checker/file_format/checker/parser.py
index f354395..001f72a 100644
--- a/tools/checker/file_format/checker/parser.py
+++ b/tools/checker/file_format/checker/parser.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from common.archs               import archs_list
 from common.logger              import Logger
 from file_format.common         import SplitStream
 from file_format.checker.struct import CheckerFile, TestCase, TestAssertion, RegexExpression
@@ -21,17 +22,18 @@
 def __isCheckerLine(line):
   return line.startswith("///") or line.startswith("##")
 
-def __extractLine(prefix, line):
+def __extractLine(prefix, line, arch = None):
   """ Attempts to parse a check line. The regex searches for a comment symbol
       followed by the CHECK keyword, given attribute and a colon at the very
       beginning of the line. Whitespaces are ignored.
   """
   rIgnoreWhitespace = r"\s*"
   rCommentSymbols = [r"///", r"##"]
+  arch_specifier = r"-%s" % arch if arch is not None else r""
   regexPrefix = rIgnoreWhitespace + \
                 r"(" + r"|".join(rCommentSymbols) + r")" + \
                 rIgnoreWhitespace + \
-                prefix + r":"
+                prefix + arch_specifier + r":"
 
   # The 'match' function succeeds only if the pattern is matched at the
   # beginning of the line.
@@ -42,39 +44,42 @@
     return None
 
 def __processLine(line, lineNo, prefix, fileName):
-  """ This function is invoked on each line of the check file and returns a pair
+  """ This function is invoked on each line of the check file and returns a triplet
       which instructs the parser how the line should be handled. If the line is
       to be included in the current check group, it is returned in the first
       value. If the line starts a new check group, the name of the group is
-      returned in the second value.
+      returned in the second value. The third value indicates whether the line
+      contained an architecture-specific suffix.
   """
   if not __isCheckerLine(line):
-    return None, None
+    return None, None, None
 
   # Lines beginning with 'CHECK-START' start a new test case.
-  startLine = __extractLine(prefix + "-START", line)
-  if startLine is not None:
-    return None, startLine
+  # We currently only consider the architecture suffix in "CHECK-START" lines.
+  for arch in [None] + archs_list:
+    startLine = __extractLine(prefix + "-START", line, arch)
+    if startLine is not None:
+      return None, startLine, arch
 
   # Lines starting only with 'CHECK' are matched in order.
   plainLine = __extractLine(prefix, line)
   if plainLine is not None:
-    return (plainLine, TestAssertion.Variant.InOrder, lineNo), None
+    return (plainLine, TestAssertion.Variant.InOrder, lineNo), None, None
 
   # 'CHECK-NEXT' lines are in-order but must match the very next line.
   nextLine = __extractLine(prefix + "-NEXT", line)
   if nextLine is not None:
-    return (nextLine, TestAssertion.Variant.NextLine, lineNo), None
+    return (nextLine, TestAssertion.Variant.NextLine, lineNo), None, None
 
   # 'CHECK-DAG' lines are no-order assertions.
   dagLine = __extractLine(prefix + "-DAG", line)
   if dagLine is not None:
-    return (dagLine, TestAssertion.Variant.DAG, lineNo), None
+    return (dagLine, TestAssertion.Variant.DAG, lineNo), None, None
 
   # 'CHECK-NOT' lines are no-order negative assertions.
   notLine = __extractLine(prefix + "-NOT", line)
   if notLine is not None:
-    return (notLine, TestAssertion.Variant.Not, lineNo), None
+    return (notLine, TestAssertion.Variant.Not, lineNo), None, None
 
   Logger.fail("Checker assertion could not be parsed: '" + line + "'", fileName, lineNo)
 
@@ -146,8 +151,9 @@
   fnProcessLine = lambda line, lineNo: __processLine(line, lineNo, prefix, fileName)
   fnLineOutsideChunk = lambda line, lineNo: \
       Logger.fail("Checker line not inside a group", fileName, lineNo)
-  for caseName, caseLines, startLineNo in SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
-    testCase = TestCase(checkerFile, caseName, startLineNo)
+  for caseName, caseLines, startLineNo, testArch in \
+      SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
+    testCase = TestCase(checkerFile, caseName, startLineNo, testArch)
     for caseLine in caseLines:
       ParseCheckerAssertion(testCase, caseLine[0], caseLine[1], caseLine[2])
   return checkerFile
diff --git a/tools/checker/file_format/checker/struct.py b/tools/checker/file_format/checker/struct.py
index 6a54142..2b2e442 100644
--- a/tools/checker/file_format/checker/struct.py
+++ b/tools/checker/file_format/checker/struct.py
@@ -26,6 +26,9 @@
   def addTestCase(self, new_test_case):
     self.testCases.append(new_test_case)
 
+  def testCasesForArch(self, targetArch):
+    return [t for t in self.testCases if t.testArch == targetArch]
+
   def __eq__(self, other):
     return isinstance(other, self.__class__) \
        and self.testCases == other.testCases
@@ -33,13 +36,14 @@
 
 class TestCase(PrintableMixin):
 
-  def __init__(self, parent, name, startLineNo):
+  def __init__(self, parent, name, startLineNo, testArch = None):
     assert isinstance(parent, CheckerFile)
 
     self.parent = parent
     self.name = name
     self.assertions = []
     self.startLineNo = startLineNo
+    self.testArch = testArch
 
     if not self.name:
       Logger.fail("Test case does not have a name", self.fileName, self.startLineNo)
diff --git a/tools/checker/file_format/checker/test.py b/tools/checker/file_format/checker/test.py
index ff24cc1..36ed4b1 100644
--- a/tools/checker/file_format/checker/test.py
+++ b/tools/checker/file_format/checker/test.py
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from common.archs               import archs_list
 from common.testing             import ToUnicode
 from file_format.checker.parser import ParseCheckerStream
 from file_format.checker.struct import CheckerFile, TestCase, TestAssertion, RegexExpression
@@ -280,3 +281,51 @@
           /// CHECK-START: Example Group
           /// CHECK-NEXT: bar
         """)
+
+
+class CheckerParser_ArchTests(unittest.TestCase):
+
+  noarch_block = """
+                  /// CHECK-START: Group
+                  /// CHECK:       foo
+                  /// CHECK-NEXT:  bar
+                  /// CHECK-NOT:   baz
+                  /// CHECK-DAG:   yoyo
+                """
+
+  arch_block = """
+                  /// CHECK-START-{test_arch}: Group
+                  /// CHECK:       foo
+                  /// CHECK-NEXT:  bar
+                  /// CHECK-NOT:   baz
+                  /// CHECK-DAG:   yoyo
+                """
+
+  def test_NonArchTests(self):
+    for arch in [None] + archs_list:
+      checkerFile = ParseCheckerStream("<test-file>",
+                                       "CHECK",
+                                       io.StringIO(ToUnicode(self.noarch_block)))
+      self.assertEqual(len(checkerFile.testCases), 1)
+      self.assertEqual(len(checkerFile.testCases[0].assertions), 4)
+
+  def test_IgnoreNonTargetArch(self):
+    for targetArch in archs_list:
+      for testArch in [a for a in archs_list if a != targetArch]:
+        checkerText = self.arch_block.format(test_arch = testArch)
+        checkerFile = ParseCheckerStream("<test-file>",
+                                         "CHECK",
+                                         io.StringIO(ToUnicode(checkerText)))
+        self.assertEqual(len(checkerFile.testCases), 1)
+        self.assertEqual(len(checkerFile.testCasesForArch(testArch)), 1)
+        self.assertEqual(len(checkerFile.testCasesForArch(targetArch)), 0)
+
+  def test_Arch(self):
+    for arch in archs_list:
+      checkerText = self.arch_block.format(test_arch = arch)
+      checkerFile = ParseCheckerStream("<test-file>",
+                                       "CHECK",
+                                       io.StringIO(ToUnicode(checkerText)))
+      self.assertEqual(len(checkerFile.testCases), 1)
+      self.assertEqual(len(checkerFile.testCasesForArch(arch)), 1)
+      self.assertEqual(len(checkerFile.testCases[0].assertions), 4)
diff --git a/tools/checker/file_format/common.py b/tools/checker/file_format/common.py
index f91fdeb..4931550 100644
--- a/tools/checker/file_format/common.py
+++ b/tools/checker/file_format/common.py
@@ -18,8 +18,9 @@
 
   Arguments:
    - fnProcessLine: Called on each line with the text and line number. Must
-     return a pair, name of the chunk started on this line and data extracted
-     from this line (or None in both cases).
+     return a triplet, composed of the name of the chunk started on this line,
+     the data extracted, and the name of the architecture this test applies to
+     (or None to indicate that all architectures should run this test).
    - fnLineOutsideChunk: Called on attempt to attach data prior to creating
      a chunk.
   """
@@ -36,9 +37,11 @@
     # Let the child class process the line and return information about it.
     # The _processLine method can modify the content of the line (or delete it
     # entirely) and specify whether it starts a new group.
-    processedLine, newChunkName = fnProcessLine(line, lineNo)
+    processedLine, newChunkName, testArch = fnProcessLine(line, lineNo)
+    # Currently, only a full chunk can be specified as architecture-specific.
+    assert testArch is None or newChunkName is not None
     if newChunkName is not None:
-      currentChunk = (newChunkName, [], lineNo)
+      currentChunk = (newChunkName, [], lineNo, testArch)
       allChunks.append(currentChunk)
     if processedLine is not None:
       if currentChunk is not None:
diff --git a/tools/checker/match/file.py b/tools/checker/match/file.py
index b22211a..42ca7df 100644
--- a/tools/checker/match/file.py
+++ b/tools/checker/match/file.py
@@ -150,8 +150,10 @@
     matchFrom = match.scope.end + 1
     variables = match.variables
 
-def MatchFiles(checkerFile, c1File):
+def MatchFiles(checkerFile, c1File, targetArch):
   for testCase in checkerFile.testCases:
+    if testCase.testArch not in [None, targetArch]:
+      continue
     # TODO: Currently does not handle multiple occurrences of the same group
     # name, e.g. when a pass is run multiple times. It will always try to
     # match a check group against the first output group of the same name.
diff --git a/tools/checker/run_unit_tests.py b/tools/checker/run_unit_tests.py
index 01708db..2f5b1fe 100755
--- a/tools/checker/run_unit_tests.py
+++ b/tools/checker/run_unit_tests.py
@@ -18,7 +18,8 @@
 from file_format.c1visualizer.test import C1visualizerParser_Test
 from file_format.checker.test      import CheckerParser_PrefixTest, \
                                           CheckerParser_RegexExpressionTest, \
-                                          CheckerParser_FileLayoutTest
+                                          CheckerParser_FileLayoutTest, \
+                                          CheckerParser_ArchTests
 from match.test                    import MatchLines_Test, \
                                           MatchFiles_Test