# Copyright 2022 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import json
from os import path
import platform
import re
import subprocess
import sys

REPO_DIR = path.join(path.dirname(__file__), '..', '..')


def llvm_readobj():
    binary_name = {
        'Darwin': 'llvm-readobj',
        'Linux': 'llvm-readobj',
        'Windows': 'llvm-readobj.exe',
    }[platform.system()]
    return path.realpath(
        path.join(REPO_DIR, 'third_party', 'emscripten-releases', 'install',
                  'bin', binary_name))


def wasm_as():
    binary_name = {
        'Darwin': 'wasm-as',
        'Linux': 'wasm-as',
        'Windows': 'wasm-as.exe',
    }[platform.system()]
    return path.realpath(
        path.join(REPO_DIR, 'third_party', 'emscripten-releases', 'install',
                  'bin', binary_name))


def script_main(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('input')
    parser.add_argument('output')
    options = parser.parse_args(args)

    sourcemap = f'{options.output}.map'
    subprocess.check_call([
        wasm_as(), options.input, '-g', '-sm', sourcemap, '-o', options.output
    ])

    wasm_obj_headers = subprocess.check_output([
        llvm_readobj(),
        '-e',
        # TODO(crbug.com/1328729): use JSON output as soon as that's supported for wasm
        # '--elf-output-style=JSON',
        options.output
    ])
    (size, offset) = re.search(
        rb'Section {[^}]*Type: CODE[^}]*Size: (\d*)[^}]*Offset: (\d*)[^}]*}',
        wasm_obj_headers).groups()

    # readobj reports as offset the location of the first byte of the header.
    # Our offsets are relative to the first byte of the section though, so
    # calculate the offset manually. The header is composed of one byte for the
    # section id, and an leb128 value for the length.
    size = int(size)
    leb_len = 0
    while size > 0:
        size >>= 7
        leb_len += 1
    offset = int(offset) + 1 + leb_len

    node = path.realpath(path.join(REPO_DIR, 'third_party', 'node', 'node.py'))
    sourcemap2json = path.realpath(
        path.join(REPO_DIR, 'scripts', 'build', 'wasm_sourcemap.mjs'))
    sourcemap_contents = subprocess.check_output([
        sys.executable, node, '--output', sourcemap2json, sourcemap,
        '%s' % (offset)
    ])

    json_file = f'{options.output}.map.json'
    with open(json_file, 'wb') as output:
        output.write(sourcemap_contents)

    return 0


if __name__ == '__main__':
    sys.exit(script_main(sys.argv[1:]))
