Skip to content

Commit 997a858

Browse files
committed
Handle symbol and label prefixes in a principled way
1 parent cff0f09 commit 997a858

File tree

2 files changed

+52
-26
lines changed

2 files changed

+52
-26
lines changed

Tools/jit/_optimizers.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ class Optimizer:
7070

7171
path: pathlib.Path
7272
_: dataclasses.KW_ONLY
73-
# prefix used to mangle symbols on some platforms:
74-
prefix: str = ""
73+
# Prefixes used to mangle local labels and symbols:
74+
label_prefix: str
75+
symbol_prefix: str
7576
# The first block in the linked list:
7677
_root: _Block = dataclasses.field(init=False, default_factory=_Block)
7778
_labels: dict[str, _Block] = dataclasses.field(init=False, default_factory=dict)
@@ -130,8 +131,12 @@ def __post_init__(self) -> None:
130131
block.fallthrough = False
131132

132133
def _preprocess(self, text: str) -> str:
133-
# Override this method to do preprocessing of the textual assembly:
134-
return text
134+
# Override this method to do preprocessing of the textual assembly.
135+
# In all cases, replace references to the _JIT_CONTINUE symbol with
136+
# references to a local _JIT_CONTINUE label (which we will add later):
137+
continue_symbol = rf"\b{re.escape(self.symbol_prefix)}_JIT_CONTINUE\b"
138+
continue_label = f"{self.label_prefix}_JIT_CONTINUE"
139+
return re.sub(continue_symbol, continue_label, text)
135140

136141
@classmethod
137142
def _invert_branch(cls, line: str, target: str) -> str | None:
@@ -198,7 +203,7 @@ def _insert_continue_label(self) -> None:
198203
# jmp FOO
199204
# _JIT_CONTINUE:
200205
# This lets the assembler encode _JIT_CONTINUE jumps at build time!
201-
continuation = self._lookup_label(f"{self.prefix}_JIT_CONTINUE")
206+
continuation = self._lookup_label(f"{self.label_prefix}_JIT_CONTINUE")
202207
assert continuation.label
203208
continuation.noninstructions.append(f"{continuation.label}:")
204209
end.link, continuation.link = continuation, end.link

Tools/jit/_targets.py

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class _Target(typing.Generic[_S, _R]):
4444
_: dataclasses.KW_ONLY
4545
args: typing.Sequence[str] = ()
4646
optimizer: type[_optimizers.Optimizer] = _optimizers.Optimizer
47-
prefix: str = ""
47+
label_prefix: typing.ClassVar[str]
48+
symbol_prefix: typing.ClassVar[str]
4849
stable: bool = False
4950
debug: bool = False
5051
verbose: bool = False
@@ -164,7 +165,9 @@ async def _compile(
164165
*shlex.split(self.cflags),
165166
]
166167
await _llvm.run("clang", args_s, echo=self.verbose)
167-
self.optimizer(s, prefix=self.prefix).run()
168+
self.optimizer(
169+
s, label_prefix=self.label_prefix, symbol_prefix=self.symbol_prefix
170+
).run()
168171
args_o = [f"--target={self.triple}", "-c", "-o", f"{o}", f"{s}"]
169172
await _llvm.run("clang", args_o, echo=self.verbose)
170173
return await self._parse(o)
@@ -266,7 +269,7 @@ def _handle_section(
266269
symbol = wrapped_symbol["Symbol"]
267270
offset = base + symbol["Value"]
268271
name = symbol["Name"]
269-
name = name.removeprefix(self.prefix)
272+
name = name.removeprefix(self.symbol_prefix)
270273
if name not in group.symbols:
271274
group.symbols[name] = value, offset
272275
for wrapped_relocation in section["Relocations"]:
@@ -277,9 +280,9 @@ def _handle_section(
277280
def _unwrap_dllimport(self, name: str) -> tuple[_stencils.HoleValue, str | None]:
278281
if name.startswith("__imp_"):
279282
name = name.removeprefix("__imp_")
280-
name = name.removeprefix(self.prefix)
283+
name = name.removeprefix(self.symbol_prefix)
281284
return _stencils.HoleValue.GOT, name
282-
name = name.removeprefix(self.prefix)
285+
name = name.removeprefix(self.symbol_prefix)
283286
return _stencils.symbol_to_value(name)
284287

285288
def _handle_relocation(
@@ -327,9 +330,24 @@ def _handle_relocation(
327330
return _stencils.Hole(offset, kind, value, symbol, addend)
328331

329332

333+
class _COFF32(_COFF):
334+
# These mangle like Mach-O and other "older" formats:
335+
label_prefix: str = "L"
336+
symbol_prefix: str = "_"
337+
338+
339+
class _COFF64(_COFF):
340+
# These mangle like ELF and other "newer" formats:
341+
label_prefix: str = ".L"
342+
symbol_prefix: str = ""
343+
344+
330345
class _ELF(
331346
_Target[_schema.ELFSection, _schema.ELFRelocation]
332347
): # pylint: disable = too-few-public-methods
348+
label_prefix = ".L"
349+
symbol_prefix = ""
350+
333351
def _handle_section(
334352
self, section: _schema.ELFSection, group: _stencils.StencilGroup
335353
) -> None:
@@ -366,7 +384,7 @@ def _handle_section(
366384
symbol = wrapped_symbol["Symbol"]
367385
offset = len(stencil.body) + symbol["Value"]
368386
name = symbol["Name"]["Name"]
369-
name = name.removeprefix(self.prefix)
387+
name = name.removeprefix(self.symbol_prefix)
370388
group.symbols[name] = value, offset
371389
stencil.body.extend(section["SectionData"]["Bytes"])
372390
assert not section["Relocations"]
@@ -401,7 +419,7 @@ def _handle_relocation(
401419
},
402420
}:
403421
offset += base
404-
s = s.removeprefix(self.prefix)
422+
s = s.removeprefix(self.symbol_prefix)
405423
value, symbol = _stencils.HoleValue.GOT, s
406424
case {
407425
"Addend": addend,
@@ -410,7 +428,7 @@ def _handle_relocation(
410428
"Type": {"Name": kind},
411429
}:
412430
offset += base
413-
s = s.removeprefix(self.prefix)
431+
s = s.removeprefix(self.symbol_prefix)
414432
value, symbol = _stencils.symbol_to_value(s)
415433
case _:
416434
raise NotImplementedError(relocation)
@@ -420,14 +438,17 @@ def _handle_relocation(
420438
class _MachO(
421439
_Target[_schema.MachOSection, _schema.MachORelocation]
422440
): # pylint: disable = too-few-public-methods
441+
label_prefix = "L"
442+
symbol_prefix = "_"
443+
423444
def _handle_section(
424445
self, section: _schema.MachOSection, group: _stencils.StencilGroup
425446
) -> None:
426447
assert section["Address"] >= len(group.code.body)
427448
assert "SectionData" in section
428449
flags = {flag["Name"] for flag in section["Attributes"]["Flags"]}
429450
name = section["Name"]["Value"]
430-
name = name.removeprefix(self.prefix)
451+
name = name.removeprefix(self.symbol_prefix)
431452
if "Debug" in flags:
432453
return
433454
if "PureInstructions" in flags:
@@ -451,7 +472,7 @@ def _handle_section(
451472
symbol = wrapped_symbol["Symbol"]
452473
offset = symbol["Value"] - start_address
453474
name = symbol["Name"]["Name"]
454-
name = name.removeprefix(self.prefix)
475+
name = name.removeprefix(self.symbol_prefix)
455476
group.symbols[name] = value, offset
456477
assert "Relocations" in section
457478
for wrapped_relocation in section["Relocations"]:
@@ -476,7 +497,7 @@ def _handle_relocation(
476497
},
477498
}:
478499
offset += base
479-
s = s.removeprefix(self.prefix)
500+
s = s.removeprefix(self.symbol_prefix)
480501
value, symbol = _stencils.HoleValue.GOT, s
481502
addend = 0
482503
case {
@@ -485,7 +506,7 @@ def _handle_relocation(
485506
"Type": {"Name": "X86_64_RELOC_GOT" | "X86_64_RELOC_GOT_LOAD" as kind},
486507
}:
487508
offset += base
488-
s = s.removeprefix(self.prefix)
509+
s = s.removeprefix(self.symbol_prefix)
489510
value, symbol = _stencils.HoleValue.GOT, s
490511
addend = (
491512
int.from_bytes(raw[offset : offset + 4], "little", signed=True) - 4
@@ -500,7 +521,7 @@ def _handle_relocation(
500521
"Type": {"Name": "X86_64_RELOC_BRANCH" | "X86_64_RELOC_SIGNED" as kind},
501522
}:
502523
offset += base
503-
s = s.removeprefix(self.prefix)
524+
s = s.removeprefix(self.symbol_prefix)
504525
value, symbol = _stencils.symbol_to_value(s)
505526
addend = (
506527
int.from_bytes(raw[offset : offset + 4], "little", signed=True) - 4
@@ -515,27 +536,27 @@ def _handle_relocation(
515536
"Type": {"Name": kind},
516537
}:
517538
offset += base
518-
s = s.removeprefix(self.prefix)
539+
s = s.removeprefix(self.symbol_prefix)
519540
value, symbol = _stencils.symbol_to_value(s)
520541
addend = 0
521542
case _:
522543
raise NotImplementedError(relocation)
523544
return _stencils.Hole(offset, kind, value, symbol, addend)
524545

525546

526-
def get_target(host: str) -> _COFF | _ELF | _MachO:
547+
def get_target(host: str) -> _COFF32 | _COFF64 | _ELF | _MachO:
527548
"""Build a _Target for the given host "triple" and options."""
528549
optimizer: type[_optimizers.Optimizer]
529-
target: _COFF | _ELF | _MachO
550+
target: _COFF32 | _COFF64 | _ELF | _MachO
530551
if re.fullmatch(r"aarch64-apple-darwin.*", host):
531552
condition = "defined(__aarch64__) && defined(__APPLE__)"
532553
optimizer = _optimizers.OptimizerAArch64
533-
target = _MachO(host, condition, optimizer=optimizer, prefix="_")
554+
target = _MachO(host, condition, optimizer=optimizer)
534555
elif re.fullmatch(r"aarch64-pc-windows-msvc", host):
535556
args = ["-fms-runtime-lib=dll", "-fplt"]
536557
condition = "defined(_M_ARM64)"
537558
optimizer = _optimizers.OptimizerAArch64
538-
target = _COFF(host, condition, args=args, optimizer=optimizer)
559+
target = _COFF64(host, condition, args=args, optimizer=optimizer)
539560
elif re.fullmatch(r"aarch64-.*-linux-gnu", host):
540561
# -mno-outline-atomics: Keep intrinsics from being emitted.
541562
args = ["-fpic", "-mno-outline-atomics"]
@@ -547,16 +568,16 @@ def get_target(host: str) -> _COFF | _ELF | _MachO:
547568
args = ["-DPy_NO_ENABLE_SHARED", "-Wno-ignored-attributes"]
548569
optimizer = _optimizers.OptimizerX86
549570
condition = "defined(_M_IX86)"
550-
target = _COFF(host, condition, args=args, optimizer=optimizer, prefix="_")
571+
target = _COFF32(host, condition, args=args, optimizer=optimizer)
551572
elif re.fullmatch(r"x86_64-apple-darwin.*", host):
552573
condition = "defined(__x86_64__) && defined(__APPLE__)"
553574
optimizer = _optimizers.OptimizerX86
554-
target = _MachO(host, condition, optimizer=optimizer, prefix="_")
575+
target = _MachO(host, condition, optimizer=optimizer)
555576
elif re.fullmatch(r"x86_64-pc-windows-msvc", host):
556577
args = ["-fms-runtime-lib=dll"]
557578
condition = "defined(_M_X64)"
558579
optimizer = _optimizers.OptimizerX86
559-
target = _COFF(host, condition, args=args, optimizer=optimizer)
580+
target = _COFF64(host, condition, args=args, optimizer=optimizer)
560581
elif re.fullmatch(r"x86_64-.*-linux-gnu", host):
561582
args = ["-fno-pic", "-mcmodel=medium", "-mlarge-data-threshold=0"]
562583
condition = "defined(__x86_64__) && defined(__linux__)"

0 commit comments

Comments
 (0)