[llvm] [lit] Use text mode when piping output (PR #217434)

Abhina Sree via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 19 11:59:52 PDT 2026


https://github.com/abhina-sree created https://github.com/llvm/llvm-project/pull/217434

On z/OS, we rely on autoconversion to read files correctly, and this requires files to be opened as text. 

The following change https://github.com/llvm/llvm-project/pull/208024 changed the streams to be read and piped as binary resulting in some test regressions due to unreadable output. This patch restores the functionality of opening and reading as a text stream.

>From 50f624bb4ff7a90c7313ffd48ecf052e3dc42ee6 Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Wed, 19 Aug 2026 14:55:57 -0400
Subject: [PATCH] when piping output, use a text stream to enable
 autoconversion on z/OS

---
 llvm/utils/lit/lit/ShellEnvironment.py     |  6 +-----
 llvm/utils/lit/lit/TestRunner.py           |  2 +-
 llvm/utils/lit/lit/builtin_commands/cat.py | 18 +++++++++++++++---
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/llvm/utils/lit/lit/ShellEnvironment.py b/llvm/utils/lit/lit/ShellEnvironment.py
index e2cf602de96ff..3cf41c4ab2c6b 100644
--- a/llvm/utils/lit/lit/ShellEnvironment.py
+++ b/llvm/utils/lit/lit/ShellEnvironment.py
@@ -228,11 +228,7 @@ def as_binary_reader(stream: None | int | io.TextIOBase | BinaryIO) -> BinaryIO:
         # No real input to read.
         return io.BytesIO(b"")
     if isinstance(stream, io.TextIOBase):
-        buffer = getattr(stream, "buffer", None)
-        if buffer is not None:
-            return buffer
-        data = stream.read()
-        return io.BytesIO(data.encode() if isinstance(data, str) else data)
+        return stream
     # Already a binary reader.
     assert hasattr(stream, "read"), f"expected a binary reader, got {type(stream)!r}"
     return stream
diff --git a/llvm/utils/lit/lit/TestRunner.py b/llvm/utils/lit/lit/TestRunner.py
index 30a39745d01b9..ed9ba8bc58de5 100644
--- a/llvm/utils/lit/lit/TestRunner.py
+++ b/llvm/utils/lit/lit/TestRunner.py
@@ -403,7 +403,7 @@ def _make_out_sink(stdout: int | TextIO, is_last: bool) -> IO[bytes] | None:
         last stage or a non-pipe target, which don't need this sink.
     """
     if stdout == subprocess.PIPE and not is_last:
-        return tempfile.SpooledTemporaryFile(max_size=1 << 20)
+        return tempfile.SpooledTemporaryFile(max_size=1 << 20, mode='w+')
     return None
 
 
diff --git a/llvm/utils/lit/lit/builtin_commands/cat.py b/llvm/utils/lit/lit/builtin_commands/cat.py
index bfd6e86f46bdb..f6fcdb30b78ba 100644
--- a/llvm/utils/lit/lit/builtin_commands/cat.py
+++ b/llvm/utils/lit/lit/builtin_commands/cat.py
@@ -90,9 +90,21 @@ def run(argv, stdin, stdout, stderr, cwd):
 
         if show_nonprinting:
             contents = convertToCaretAndMNotation(contents)
-        elif is_text:
-            contents = contents.encode()
-        stdout.write(contents)
+        # Determine if stdout expects text or binary
+        is_text_output = False
+        if hasattr(stdout, 'mode'):
+            mode = getattr(stdout, 'mode', 'b')
+            is_text_output = 'b' not in mode
+
+        if is_text_output:
+            if isinstance(contents, bytes):
+                contents = contents.decode()
+            stdout.write(contents)
+        else:
+            if isinstance(contents, str):
+                contents = contents.encode()
+            stdout.write(contents)
+
     return 0
 
 



More information about the llvm-commits mailing list