[Lldb-commits] [lldb] [lldb][bytecode] Add swift output to Python->bytecode compiler (PR #185773)
Dave Lee via lldb-commits
lldb-commits at lists.llvm.org
Wed Mar 11 14:52:50 PDT 2026
https://github.com/kastiglione updated https://github.com/llvm/llvm-project/pull/185773
>From b3827a73789e2ca83853affc072170421e77b163 Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Tue, 10 Mar 2026 16:11:02 -0700
Subject: [PATCH 1/4] [lldb][bytecode] Add swift output to Python->bytecode
compiler
---
lldb/examples/python/formatter_bytecode.py | 85 +++++++++++++++++--
...atter.txt => RigidArrayLLDBFormatterC.txt} | 2 +-
.../RigidArrayLLDBFormatterSwift.txt | 38 +++++++++
.../Python/python-bytecode.test | 6 +-
4 files changed, 123 insertions(+), 8 deletions(-)
rename lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/{RigidArrayLLDBFormatter.txt => RigidArrayLLDBFormatterC.txt} (95%)
create mode 100644 lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterSwift.txt
diff --git a/lldb/examples/python/formatter_bytecode.py b/lldb/examples/python/formatter_bytecode.py
index dfa6fda0f6402..2cd62480584b0 100644
--- a/lldb/examples/python/formatter_bytecode.py
+++ b/lldb/examples/python/formatter_bytecode.py
@@ -226,6 +226,12 @@ def write_binary(self, output: BinaryIO) -> None:
output.write(_to_uleb(len(bin)))
output.write(self._to_binary())
+ def write_source(self, output: TextIO, language: str) -> None:
+ if language == "c":
+ self.write_c(output)
+ elif language == "swift":
+ self.write_swift(output)
+
class _CBuilder:
"""Helper class for emitting binary data as a C-string literal."""
@@ -248,7 +254,7 @@ def add_bytes(self, x: bytes, comment: str) -> None:
def add_string(self, string: str, comment: str) -> None:
self.entries.append((f'"{string}"', comment))
- def write_source(self, output: TextIO) -> None:
+ def write_c(self, output: TextIO) -> None:
self.validate()
size = len(self._to_binary())
@@ -281,13 +287,82 @@ def write_source(self, output: TextIO) -> None:
"__attribute__((used, section(FORMATTER_SECTION)))",
file=output,
)
- print(f"unsigned char _{var_name}_synthetic[] =", file=output)
+ print(f"unsigned char _{var_name}_formatter[] =", file=output)
indent = " "
for string, comment in b.entries:
print(f"{indent}// {comment}", file=output)
print(f"{indent}{string}", file=output)
print(";", file=output)
+ class _SwiftBuilder:
+ """Helper class for emitting binary data as a Swift tuple literal."""
+
+ entries: list[Tuple[bytes, str]]
+
+ def __init__(self) -> None:
+ self.entries = []
+
+ def add_byte(self, x: int, comment: str) -> None:
+ self.add_bytes(_to_byte(x), comment)
+
+ def add_uleb(self, x: int, comment: str) -> None:
+ self.add_bytes(_to_uleb(x), comment)
+
+ def add_bytes(self, x: bytes, comment: str) -> None:
+ self.entries.append((x, comment))
+
+ def add_string(self, string: str, comment: str) -> None:
+ self.add_bytes(string.encode(), comment)
+
+ @property
+ def type_decl(self):
+ total_bytes = sum((len(bs) for bs, _ in self.entries))
+ element_list = ", ".join(["UInt8"] * total_bytes)
+ return f"({element_list})"
+
+ def write_swift(self, output: TextIO) -> None:
+ self.validate()
+
+ size = len(self._to_binary())
+
+ builder = self._SwiftBuilder()
+ builder.add_byte(BINARY_VERSION, "version")
+ builder.add_uleb(size, "remaining record size")
+ builder.add_uleb(len(self.type_name), "type name size")
+ builder.add_string(self.type_name, f'type name: "{self.type_name}"')
+ builder.add_byte(self.flags, "flags")
+ for sig, bc in self.signatures:
+ builder.add_byte(SIGNATURES[sig], f"sig_{sig}")
+ builder.add_uleb(len(bc), "program size")
+ builder.add_bytes(bc, "program")
+
+ darwin = ("macOS", "iOS", "watchOS", "tvOS", "visionOS")
+ darwin_list = " || ".join(f"os({_os})" for _os in darwin)
+ print(
+ textwrap.dedent(
+ f"""
+ @used
+ #if {darwin_list}
+ @section("__TEXT,__lldbsummaries")
+ #else
+ @section(".lldbsummaries")
+ #endif
+ """
+ ),
+ file=output,
+ )
+ var_name = re.sub(r"\W", "_", self.type_name)
+ print(
+ f"static let _{var_name}_formatter: {builder.type_decl} = (",
+ file=output,
+ )
+ indent = " "
+ for bs, comment in builder.entries:
+ print(f"{indent}// {comment}", file=output)
+ byte_list = ", ".join(f"0x{b:02x}" for b in bs)
+ print(f"{indent}{byte_list},", file=output)
+ print(")", file=output)
+
def assemble_file(type_name: str, input: TextIO) -> BytecodeSection:
input_tokens = _tokenize(input.read())
@@ -1110,7 +1185,7 @@ def _main():
parser.add_argument(
"-f",
"--format",
- choices=("binary", "c"),
+ choices=("binary", "c", "swift"),
default="binary",
help="output file format",
)
@@ -1133,9 +1208,9 @@ def _main():
if args.format == "binary":
with open(args.output, "wb") as output:
section.write_binary(output)
- else: # args.format == "c"
+ else:
with open(args.output, "w") as output:
- section.write_source(output)
+ section.write_source(output, language=args.format)
elif args.assemble:
if not args.type_name:
parser.error("--type-name is required with --assemble")
diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatter.txt b/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterC.txt
similarity index 95%
rename from lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatter.txt
rename to lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterC.txt
index a8daf9e20b85c..dd322077720d7 100644
--- a/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatter.txt
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterC.txt
@@ -6,7 +6,7 @@
#endif
__attribute__((used, section(FORMATTER_SECTION)))
-unsigned char _RigidArray_synthetic[] =
+unsigned char _RigidArray_formatter[] =
// version
"\x01"
// remaining record size
diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterSwift.txt b/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterSwift.txt
new file mode 100644
index 0000000000000..daf14d35a2d32
--- /dev/null
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterSwift.txt
@@ -0,0 +1,38 @@
+
+ at used
+#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
+ at section("__TEXT,__lldbsummaries")
+#else
+ at section(".lldbsummaries")
+#endif
+
+static let _RigidArray_formatter: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) = (
+ // version
+ 0x01,
+ // remaining record size
+ 0x47,
+ // type name size
+ 0x0a,
+ // type name: "RigidArray"
+ 0x52, 0x69, 0x67, 0x69, 0x64, 0x41, 0x72, 0x72, 0x61, 0x79,
+ // flags
+ 0x00,
+ // sig_update
+ 0x05,
+ // program size
+ 0x27,
+ // program
+ 0x21, 0x00, 0x03, 0x22, 0x08, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x23, 0x12, 0x60, 0x23, 0x18, 0x60, 0x21, 0x00, 0x03, 0x22, 0x06, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x23, 0x12, 0x60, 0x23, 0x18, 0x60, 0x23, 0x21, 0x60,
+ // sig_get_num_children
+ 0x02,
+ // program size
+ 0x04,
+ // program
+ 0x21, 0x02, 0x03, 0x13,
+ // sig_get_child_at_index
+ 0x04,
+ // program size
+ 0x0a,
+ // program
+ 0x21, 0x01, 0x03, 0x21, 0x04, 0x03, 0x23, 0x11, 0x60, 0x13,
+)
diff --git a/lldb/test/Shell/ScriptInterpreter/Python/python-bytecode.test b/lldb/test/Shell/ScriptInterpreter/Python/python-bytecode.test
index 4ed865021e947..82b5ac19bd6db 100644
--- a/lldb/test/Shell/ScriptInterpreter/Python/python-bytecode.test
+++ b/lldb/test/Shell/ScriptInterpreter/Python/python-bytecode.test
@@ -1,6 +1,8 @@
# RUN: mkdir -p %t
-# RUN: %python %S/../../../../examples/python/formatter_bytecode.py --compile %s --format c --type-name RigidArray --output %t/output.txt
-# RUN: diff -u --strip-trailing-cr %S/Inputs/FormatterBytecode/RigidArrayLLDBFormatter.txt %t/output.txt
+# RUN: %python %S/../../../../examples/python/formatter_bytecode.py --compile %s --format c --type-name RigidArray --output %t/c-output.txt
+# RUN: %python %S/../../../../examples/python/formatter_bytecode.py --compile %s --format swift --type-name RigidArray --output %t/swift-output.txt
+# RUN: diff -u --strip-trailing-cr %S/Inputs/FormatterBytecode/RigidArrayLLDBFormatterC.txt %t/c-output.txt
+# RUN: diff -u --strip-trailing-cr %S/Inputs/FormatterBytecode/RigidArrayLLDBFormatterSwift.txt %t/swift-output.txt
import lldb
>From f9e797c679ffc2d7b9572c22472ed42ca360dd90 Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Tue, 10 Mar 2026 16:56:12 -0700
Subject: [PATCH 2/4] Fix tests, and --assemble
---
lldb/examples/python/formatter_bytecode.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/lldb/examples/python/formatter_bytecode.py b/lldb/examples/python/formatter_bytecode.py
index 2cd62480584b0..10c29c0813a79 100644
--- a/lldb/examples/python/formatter_bytecode.py
+++ b/lldb/examples/python/formatter_bytecode.py
@@ -1221,9 +1221,9 @@ def _main():
if args.format == "binary":
with open(args.output, "wb") as output:
section.write_binary(output)
- else: # args.format == "c"
+ else:
with open(args.output, "w") as output:
- section.write_source(output)
+ section.write_source(output, language=args.format)
elif args.disassemble:
if args.output:
with (
@@ -1317,11 +1317,11 @@ def test_write_source(self):
],
)
out = io.StringIO()
- section.write_source(out)
+ section.write_source(out, language="c")
src = out.getvalue()
self.assertIn("__attribute__((used, section(FORMATTER_SECTION)))", src)
- self.assertIn("unsigned char _Account_synthetic[] =", src)
+ self.assertIn("unsigned char _Account_formatter[] =", src)
self.assertIn('"\\x01"', src) # version
self.assertIn('"\\x15"', src) # record size (21)
self.assertIn('"\\x07"', src) # type name size (7)
@@ -1340,7 +1340,7 @@ def test_write_source(self):
# Non-identifier characters in the type name are replaced with '_'.
out2 = io.StringIO()
- BytecodeSection("std::vector<int>", 0, []).write_source(out2)
- self.assertIn("_std__vector_int__synthetic[] =", out2.getvalue())
+ BytecodeSection("std::vector<int>", 0, []).write_source(out2, language="c")
+ self.assertIn("_std__vector_int__formatter[] =", out2.getvalue())
unittest.main(argv=[__file__])
>From 446cc5c44119ae3ddd83f7c2f9ea20f8fe793efc Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Wed, 11 Mar 2026 14:20:23 -0700
Subject: [PATCH 3/4] Minor tweaks
---
lldb/examples/python/formatter_bytecode.py | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/lldb/examples/python/formatter_bytecode.py b/lldb/examples/python/formatter_bytecode.py
index 10c29c0813a79..a49eec2448ce6 100644
--- a/lldb/examples/python/formatter_bytecode.py
+++ b/lldb/examples/python/formatter_bytecode.py
@@ -336,13 +336,11 @@ def write_swift(self, output: TextIO) -> None:
builder.add_uleb(len(bc), "program size")
builder.add_bytes(bc, "program")
- darwin = ("macOS", "iOS", "watchOS", "tvOS", "visionOS")
- darwin_list = " || ".join(f"os({_os})" for _os in darwin)
print(
textwrap.dedent(
- f"""
+ """
@used
- #if {darwin_list}
+ #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
@section("__TEXT,__lldbsummaries")
#else
@section(".lldbsummaries")
@@ -353,7 +351,7 @@ def write_swift(self, output: TextIO) -> None:
)
var_name = re.sub(r"\W", "_", self.type_name)
print(
- f"static let _{var_name}_formatter: {builder.type_decl} = (",
+ f"let _{var_name}_formatter: {builder.type_decl} = (",
file=output,
)
indent = " "
>From 10ad3f03f1d02012f7c9c18d982ac59ffcd67ce1 Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Wed, 11 Mar 2026 14:27:13 -0700
Subject: [PATCH 4/4] Fix section names, and formatting
---
lldb/examples/python/formatter_bytecode.py | 9 ++++-----
.../FormatterBytecode/RigidArrayLLDBFormatterSwift.txt | 10 ++++------
2 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/lldb/examples/python/formatter_bytecode.py b/lldb/examples/python/formatter_bytecode.py
index a49eec2448ce6..e142c1dbaf536 100644
--- a/lldb/examples/python/formatter_bytecode.py
+++ b/lldb/examples/python/formatter_bytecode.py
@@ -338,14 +338,13 @@ def write_swift(self, output: TextIO) -> None:
print(
textwrap.dedent(
- """
- @used
+ """\
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
- @section("__TEXT,__lldbsummaries")
+ @section("__DATA_CONST,__lldbformatters")
#else
- @section(".lldbsummaries")
+ @section(".lldbformatters")
#endif
- """
+ @used"""
),
file=output,
)
diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterSwift.txt b/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterSwift.txt
index daf14d35a2d32..42b5dff8614e6 100644
--- a/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterSwift.txt
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/RigidArrayLLDBFormatterSwift.txt
@@ -1,12 +1,10 @@
-
- at used
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
- at section("__TEXT,__lldbsummaries")
+ at section("__DATA_CONST,__lldbformatters")
#else
- at section(".lldbsummaries")
+ at section(".lldbformatters")
#endif
-
-static let _RigidArray_formatter: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) = (
+ at used
+let _RigidArray_formatter: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) = (
// version
0x01,
// remaining record size
More information about the lldb-commits
mailing list