Skip to content

Instantly share code, notes, and snippets.

@sueszli
Last active February 9, 2026 16:20
Show Gist options
  • Select an option

  • Save sueszli/c33b2ef81278ab8791c97d7f91826789 to your computer and use it in GitHub Desktop.

Select an option

Save sueszli/c33b2ef81278ab8791c97d7f91826789 to your computer and use it in GitHub Desktop.
visibility of `unnamed_addr` and `visibility_` when using `mlir-opt`.
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "polars",
# ]
# ///
import itertools
import re
import subprocess
import polars as pl
def run_mlir_opt(mlir_input: str) -> str:
# Runs mlir-opt and returns generic output
process = subprocess.run(
["mlir-opt", "--mlir-print-op-generic"],
input=mlir_input,
capture_output=True,
text=True,
check=True
)
return process.stdout
def extract_attr(output: str, attr_name: str) -> str:
# Extracts the value of an attribute from generic MLIR output
if output.startswith("ERROR:"):
return "ERR"
match = re.search(f"{attr_name} = (\\d+) : i64", output)
return match.group(1) if match else "-"
# Templates
generic_template = '''"builtin.module"() ({{
"llvm.func"() ({{
"llvm.return"() : () -> ()
}}) {{
sym_name = "f",
function_type = !llvm.func<void ()>,
linkage = #llvm.linkage<external>,
CConv = #llvm.cconv<ccc>{extra_attrs}
}} : () -> ()
}}) : () -> ()
'''
# Custom format uses keywords, not i64 attributes:
# visibility_: 0=default (no keyword), 1=hidden, 2=protected
# unnamed_addr: 0=default (no keyword), 1=local_unnamed_addr, 2=unnamed_addr
VIS_KEYWORDS = {None: "", 0: "", 1: "hidden ", 2: "protected "}
UNNAMED_KEYWORDS = {None: "", 0: "", 1: "local_unnamed_addr ", 2: "unnamed_addr "}
custom_template = '''llvm.func {vis}{unnamed}@f() {{
llvm.return
}}
'''
results = []
for fmt in ["generic", "custom"]:
for vis, unnamed in itertools.product([None, 0, 1], repeat=2):
# Build input based on format
if fmt == "generic":
attrs = []
if vis is not None:
attrs.append(f"visibility_ = {vis} : i64")
if unnamed is not None:
attrs.append(f"unnamed_addr = {unnamed} : i64")
extra = (", " + ", ".join(attrs)) if attrs else ""
mlir_input = generic_template.format(extra_attrs=extra)
else:
vis_kw = VIS_KEYWORDS[vis]
unnamed_kw = UNNAMED_KEYWORDS[unnamed]
mlir_input = custom_template.format(vis=vis_kw, unnamed=unnamed_kw)
output = run_mlir_opt(mlir_input)
results.append({
"format": fmt,
"in_vis": str(vis) if vis is not None else "-",
"in_unnamed": str(unnamed) if unnamed is not None else "-",
"out_vis": extract_attr(output, "visibility_"),
"out_unnamed": extract_attr(output, "unnamed_addr"),
})
df = pl.DataFrame(results)
with pl.Config(tbl_hide_column_data_types=True, tbl_rows=-1):
print(df)
$ uv run experiment.py
shape: (18, 5)
┌─────────┬────────┬────────────┬─────────┬─────────────┐
│ format ┆ in_vis ┆ in_unnamed ┆ out_vis ┆ out_unnamed │
╞═════════╪════════╪════════════╪═════════╪═════════════╡
│ generic ┆ - ┆ - ┆ 0 ┆ - │
│ generic ┆ - ┆ 0 ┆ 0 ┆ 0 │
│ generic ┆ - ┆ 1 ┆ 0 ┆ 1 │
│ generic ┆ 0 ┆ - ┆ 0 ┆ - │
│ generic ┆ 0 ┆ 0 ┆ 0 ┆ 0 │
│ generic ┆ 0 ┆ 1 ┆ 0 ┆ 1 │
│ generic ┆ 1 ┆ - ┆ 1 ┆ - │
│ generic ┆ 1 ┆ 0 ┆ 1 ┆ 0 │
│ generic ┆ 1 ┆ 1 ┆ 1 ┆ 1 │
│ custom ┆ - ┆ - ┆ 0 ┆ 0 │
│ custom ┆ - ┆ 0 ┆ 0 ┆ 0 │
│ custom ┆ - ┆ 1 ┆ 0 ┆ 1 │
│ custom ┆ 0 ┆ - ┆ 0 ┆ 0 │
│ custom ┆ 0 ┆ 0 ┆ 0 ┆ 0 │
│ custom ┆ 0 ┆ 1 ┆ 0 ┆ 1 │
│ custom ┆ 1 ┆ - ┆ 1 ┆ 0 │
│ custom ┆ 1 ┆ 0 ┆ 1 ┆ 0 │
│ custom ┆ 1 ┆ 1 ┆ 1 ┆ 1 │
└─────────┴────────┴────────────┴─────────┴─────────────┘
Conclusions:
- both the generic and custom format behave the same (but place the `visibility_` and `unnamed_addr` attributes differently.
- `visibility_`: always defaults to 0.
- `unnamed_addr`: always defaults to 0 in custom format. only printed if explicitly set in generic format.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment