# Copyright 2021 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Converts ST generated .icf linker files into basic .ld linker files"""

from typing import Dict, Optional, Tuple

import pathlib


def parse_icf(icf_file: str) -> Tuple[Dict, Dict]:
    """Parse ICF linker file.

    ST only provides .icf linker files for many products, so there is a need
    to generate basic GCC compatible .ld files for all products.
    This parses the basic features from the .icf format well enough to work
    for the ST's .icf files that exist in `cmsis_device`

    Args:
        icf_file: .icf linker file read into a string

    Returns:
        (regions, blocks) where
            `regions` is a map from region_name -> (start_hex, end_hex)
            `blocks` is a map from block_name -> {feature_1: val_1,...}

    Raises:
        IndexError if .icf is malformed (at least compared to how ST makes them)
    """
    symbols = {}
    regions = {}  # region: (start_addr, end_addr)
    blocks = {}
    for line in icf_file.split('\n'):
        line = line.strip()
        if line == '' or line.startswith('/*') or line.startswith('//'):
            continue
        tokens = line.split()
        if len(tokens) < 2:
            continue
        if tokens[0] == 'define':
            if tokens[1] == 'symbol':
                symbols[tokens[2]] = tokens[4].strip(';')
            elif tokens[1] == 'region':
                regions[tokens[2].split('_')[0]] = (tokens[5],
                                                    tokens[7].strip('];'))
            elif tokens[1] == 'block':
                blocks[tokens[2]] = {
                    tokens[4]: tokens[6].strip(','),
                    tokens[7]: tokens[9]
                }
    parsed_regions = {
        region: (symbols[start] if start in symbols else start,
                 symbols[end] if end in symbols else end)
        for region, (start, end) in regions.items()
    }

    parsed_blocks = {
        name:
        {k: symbols[v] if v in symbols else v
         for k, v in fields.items()}
        for name, fields in blocks.items()
    }

    return (parsed_regions, parsed_blocks)


def icf_regions_to_ld_regions(icf_regions: Dict) -> Dict:
    """Converts .icf regions to .ld regions

    The .icf format specifies the beginning and end of each region, while
    .ld expects the beginning and a length string.

    Args:
        icf_regions: icf_regions parsed with `parse_icf()`

    Returns:
        A map from `region_name` -> (start_hex, length_str)
    """
    ld_regions = {}
    for region, (start, end) in icf_regions.items():
        start_dec = int(start, 16)
        end_dec = int(end, 16)
        length = end_dec - start_dec + 1
        length_str = str(length)
        if length % 1024 == 0:
            length_str = f'{int(length/1024)}K'

        # Some icf scripts incorrectly have an exclusive region end.
        # This corrects for that.
        elif (length - 1) % 1024 == 0:
            length_str = f'{int((length-1)/1024)}K'

        # ST's gcc linker scripts generally use FLASH instead of ROM
        if region == 'ROM':
            region = 'FLASH'

        ld_regions[region] = (start, length_str)

    return ld_regions


def create_ld(ld_regions: Dict, blocks: Dict) -> str:
    """Create .ld file from template.

    This creates a barebones .ld file that *should* work for most single core
    stm32 families. It only contains regions for RAM and FLASH.

    This template can be bypassed in GN if a more sophisticated linker file
    is required.

    Args:
        ld_regions: generated by `icf_regions_to_ld_regions()`
        blocks: generated by `parse_icf`

    Returns:
        a string linker file with the RAM/FLASH specified by the given reginos.

    Raises:
        KeyError if ld_regions does not contain 'RAM' and 'FLASH'
    """
    return f"""\
ENTRY(Reset_Handler)
_estack = ORIGIN(RAM) + LENGTH(RAM);

_Min_Heap_Size = {blocks['HEAP']['size']};
_Min_Stack_Size = {blocks['CSTACK']['size']};

MEMORY
{{
  RAM (xrw) : ORIGIN = {ld_regions['RAM'][0]}, LENGTH = {ld_regions['RAM'][1]}
  FLASH (rx) : ORIGIN = {ld_regions['FLASH'][0]}, LENGTH = {ld_regions['FLASH'][1]}
}}

SECTIONS
{{

  /* The ARMv8-M architecture requires this is at least aligned to 128 bytes,
   * and aligned to a power of two that is greater than 4 times the number of
   * supported exceptions. 512 has been selected as it accommodates most vector
   * tables.
   */
  .isr_vector :
  {{
    . = ALIGN(512);
    KEEP(*(.isr_vector))
    . = ALIGN(4);
  }} >FLASH

  .text :
  {{
    . = ALIGN(4);
    *(.text)
    *(.text*)
    *(.glue_7)
    *(.glue_7t)
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;
  }} >FLASH

  .rodata :
  {{
    . = ALIGN(4);
    *(.rodata)
    *(.rodata*)
    . = ALIGN(4);
  }} >FLASH

  .ARM.extab   : {{
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  }} >FLASH

  .ARM : {{
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  }} >FLASH

  .preinit_array     :
  {{
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  }} >FLASH

  .init_array :
  {{
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  }} >FLASH

  .fini_array :
  {{
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  }} >FLASH

  _sidata = LOADADDR(.data);
  .data :
  {{
    . = ALIGN(4);
    _sdata = .;
    *(.data)
    *(.data*)
    . = ALIGN(4);
    _edata = .;
  }} >RAM AT> FLASH

  . = ALIGN(4);
  .bss :
  {{
    _sbss = .;
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;
    __bss_end__ = _ebss;
  }} >RAM

  /* The ARMv7-M architecture may require 8-byte alignment of the stack pointer
   * rather than 4 in some contexts and implementations, so this region is
   * 8-byte aligned (see ARMv7-M Architecture Reference Manual DDI0403E
   * section B1.5.7).
   */
  ._user_heap_stack :
  {{
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  }} >RAM

  /DISCARD/ :
  {{
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }}

  .ARM.attributes 0 : {{ *(.ARM.attributes) }}
}}
    """


def icf_to_ld(icf_path: pathlib.Path, ld_path: Optional[pathlib.Path]):
    """Convert icf file into an ld file.

    Note: This only works for ST generated .icf files.

    Args:
        icf_path: path to .icf file to convert
        ld_path: path to write generated .ld file or None.
                 If None, the .ld file is written to stdout.
    """
    with open(icf_path, 'rb') as icf_file:
        icf_str = icf_file.read().decode('utf-8', errors='ignore')

    icf_regions, blocks = parse_icf(icf_str)
    ld_regions = icf_regions_to_ld_regions(icf_regions)
    ld_str = create_ld(ld_regions, blocks)

    if ld_path:
        with open(ld_path, 'w') as ld_file:
            ld_file.write(ld_str)
    else:
        print(ld_str)
