"""The Darwin to ELF assembly conversion of the ILP32 guest (tools/android_asm_convert.py): string literals keep every byte. It once took a quoted .ascii operand for a quoted symbol name and dropped its leading "_" (and, after an escaped quote, the "_" of any word after it), which shifted tables such as Opus's pulse cache by a byte: voice chat crashed in decode_pulses on the arm64 and Android builds. Conversions from floating point to an integer in a SIMD register become the vector form, which the x86 emulator's ARM translation has: the scalar form stopped the app with SIGILL in hud_calculate_point once a game was drawn.""" import re import shutil import struct import subprocess import sys from pathlib import Path import pytest from tools.android_asm_convert import Converter ROOT = Path(__file__).resolve().parent.parent def convert(*lines): return Converter(list(lines)).run().splitlines() @pytest.mark.parametrize("directive", [ '.ascii\t"_c[}]L{s{"', '.asciz\t"_transport_error_none"', '.ascii\t"v\\177\\"O7v\\177_\\037\\374"', '.ascii\t"=`\'\\\\_\\026"', '.asciz\t"ltmp0 _x @PAGE ; not a comment"', ]) def test_string_literals_are_kept(directive): op, args = directive.split("\t", 1) assert convert("l_.str:", directive) == [".Ll_.str:", f"\t{op} {args}"] def test_symbols_are_still_renamed(): assert convert("\t.globl\t_table", "_table:", "\tadrp\tx8, _table@PAGE", "\tadd\tx8, x8, _table@PAGEOFF", '\t.long\t"_odd name"') == [ "\t.globl table", "table:", "\tadrp x8, table", "\tadd x8, x8, :lo12:table", '\t.long "odd name"'] def rodata(elf: bytes) -> bytes: """the .rodata section of a 64-bit little-endian ELF object""" shoff, = struct.unpack_from("x = (short)__builtin_rintf(x); result->y = (short)__builtin_rintf(y); }\n" "void store_doubles(double a, double b, long long *result) { result[0] = (long long)a; result[1] = (long long)b; }\n") darwin, converted, obj = tmp_path / "point.darwin.s", tmp_path / "point.s", tmp_path / "point.o" try: subprocess.run([clang, "--target=arm64_32-apple-watchos", "-mcpu=cortex-a53", "-O2", "-mllvm", "-aarch64-neon-syntax=generic", "-S", str(source), "-o", str(darwin)], check=True, capture_output=True) except subprocess.CalledProcessError: pytest.skip("clang has no arm64_32 target") if not SCALAR_FROM_SIMD.search(darwin.read_text()): pytest.skip("this clang converts in general registers") subprocess.run([sys.executable, str(ROOT / "tools" / "android_asm_convert.py"), str(darwin), str(converted)], check=True) text = converted.read_text() assert not SCALAR_FROM_SIMD.search(text) assert re.search(r"fcvtzs v\d+\.2s, v\d+\.2s", text) subprocess.run([clang, "--target=aarch64-linux-gnu", "-c", str(converted), "-o", str(obj)], check=True)