[FRONTEND] Fix ExternLibrary(format=) bug; type annotate build_extern.py (#883)
Ran mypy over `build_extern.py`, cleaned up type annotations. Found a fixed a bug where `ExternLibrary(format=)` was being ignored.
This commit is contained in:
committed by
GitHub
parent
0d7e753227
commit
0e4691e6dd
@@ -1,10 +1,24 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import subprocess
|
import subprocess
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
|
||||||
class Symbol:
|
class Symbol:
|
||||||
def __init__(self, name: str, op_name: str, ret_type: str, arg_names: list, arg_types: list) -> None:
|
_name: str
|
||||||
|
_op_name: str
|
||||||
|
_ret_type: str
|
||||||
|
_arg_names: List[str]
|
||||||
|
_arg_types: List[str]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: str,
|
||||||
|
op_name: str,
|
||||||
|
ret_type: str,
|
||||||
|
arg_names: List[str],
|
||||||
|
arg_types: List[str],
|
||||||
|
) -> None:
|
||||||
'''
|
'''
|
||||||
A symbol is a function declaration.
|
A symbol is a function declaration.
|
||||||
|
|
||||||
@@ -17,31 +31,31 @@ class Symbol:
|
|||||||
self._name = name
|
self._name = name
|
||||||
self._op_name = op_name
|
self._op_name = op_name
|
||||||
self._ret_type = ret_type
|
self._ret_type = ret_type
|
||||||
self._arg_names = arg_names
|
self._arg_names = list(arg_names)
|
||||||
self._arg_types = arg_types
|
self._arg_types = list(arg_types)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self) -> str:
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def op_name(self):
|
def op_name(self) -> str:
|
||||||
return self._op_name
|
return self._op_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ret_type(self):
|
def ret_type(self) -> str:
|
||||||
return self._ret_type
|
return self._ret_type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def arg_names(self):
|
def arg_names(self) -> List[str]:
|
||||||
return self._arg_names
|
return self._arg_names
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def arg_types(self):
|
def arg_types(self) -> List[str]:
|
||||||
return self._arg_types
|
return self._arg_types
|
||||||
|
|
||||||
|
|
||||||
def convert_type(type_str):
|
def convert_type(type_str) -> Optional[str]:
|
||||||
if type_str == "i32":
|
if type_str == "i32":
|
||||||
return "int32"
|
return "int32"
|
||||||
elif type_str == "u32":
|
elif type_str == "u32":
|
||||||
@@ -59,7 +73,7 @@ def convert_type(type_str):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def to_unsigned(type_str):
|
def to_unsigned(type_str) -> str:
|
||||||
if type_str == "int32":
|
if type_str == "int32":
|
||||||
return "uint32"
|
return "uint32"
|
||||||
elif type_str == "int64":
|
elif type_str == "int64":
|
||||||
@@ -69,7 +83,19 @@ def to_unsigned(type_str):
|
|||||||
|
|
||||||
|
|
||||||
class ExternLibrary(ABC):
|
class ExternLibrary(ABC):
|
||||||
def __init__(self, name: str, path: str, format: bool = True, grouping: bool = True) -> None:
|
_name: str
|
||||||
|
_path: str
|
||||||
|
_symbols: Dict[str, Symbol]
|
||||||
|
_format: bool
|
||||||
|
_grouping: bool
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: str,
|
||||||
|
path: str,
|
||||||
|
format: bool = True,
|
||||||
|
grouping: bool = True,
|
||||||
|
) -> None:
|
||||||
'''
|
'''
|
||||||
Abstract class for extern library.
|
Abstract class for extern library.
|
||||||
|
|
||||||
@@ -80,34 +106,34 @@ class ExternLibrary(ABC):
|
|||||||
self._name = name
|
self._name = name
|
||||||
self._path = path
|
self._path = path
|
||||||
self._symbols = {}
|
self._symbols = {}
|
||||||
self._format = True
|
self._format = format
|
||||||
self._grouping = grouping
|
self._grouping = grouping
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self) -> str:
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self) -> str:
|
||||||
return self._path
|
return self._path
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def symbols(self):
|
def symbols(self) -> Dict[str, Symbol]:
|
||||||
return self._symbols
|
return self._symbols
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def grouping(self):
|
def grouping(self) -> bool:
|
||||||
return self._grouping
|
return self._grouping
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def parse_symbols(self, input_file):
|
def parse_symbols(self, input_file) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def _output_stubs(self) -> str:
|
def _output_stubs(self) -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def generate_stub_file(self, output_dir):
|
def generate_stub_file(self, output_dir) -> None:
|
||||||
file_str = self._output_stubs()
|
file_str = self._output_stubs()
|
||||||
if file_str is None or len(file_str) == 0:
|
if file_str is None or len(file_str) == 0:
|
||||||
raise Exception("file_str is empty")
|
raise Exception("file_str is empty")
|
||||||
@@ -123,6 +149,8 @@ class ExternLibrary(ABC):
|
|||||||
|
|
||||||
|
|
||||||
class Libdevice(ExternLibrary):
|
class Libdevice(ExternLibrary):
|
||||||
|
_symbol_groups: Dict[str, List[Symbol]]
|
||||||
|
|
||||||
def __init__(self, path) -> None:
|
def __init__(self, path) -> None:
|
||||||
'''
|
'''
|
||||||
Constructor for Libdevice.
|
Constructor for Libdevice.
|
||||||
@@ -132,7 +160,7 @@ class Libdevice(ExternLibrary):
|
|||||||
super().__init__("libdevice", path)
|
super().__init__("libdevice", path)
|
||||||
self._symbol_groups = {}
|
self._symbol_groups = {}
|
||||||
|
|
||||||
def _extract_symbol(self, line):
|
def _extract_symbol(self, line) -> Optional[Symbol]:
|
||||||
# Extract symbols from line in the following format:
|
# Extract symbols from line in the following format:
|
||||||
# "define [internal] <ret_type> @<name>(<arg_types>,)"
|
# "define [internal] <ret_type> @<name>(<arg_types>,)"
|
||||||
entries = line.split("@")
|
entries = line.split("@")
|
||||||
@@ -174,7 +202,7 @@ class Libdevice(ExternLibrary):
|
|||||||
arg_types[i] = to_unsigned(arg_type)
|
arg_types[i] = to_unsigned(arg_type)
|
||||||
return Symbol(func_name, op_name, ret_type, arg_names, arg_types)
|
return Symbol(func_name, op_name, ret_type, arg_names, arg_types)
|
||||||
|
|
||||||
def _group_symbols(self):
|
def _group_symbols(self) -> None:
|
||||||
symbol_set = {}
|
symbol_set = {}
|
||||||
for symbol in self._symbols.values():
|
for symbol in self._symbols.values():
|
||||||
op_name = symbol.op_name
|
op_name = symbol.op_name
|
||||||
@@ -244,7 +272,7 @@ class Libdevice(ExternLibrary):
|
|||||||
else:
|
else:
|
||||||
self._symbol_groups[op_name] = [symbol]
|
self._symbol_groups[op_name] = [symbol]
|
||||||
|
|
||||||
def parse_symbols(self, input_file):
|
def parse_symbols(self, input_file) -> None:
|
||||||
if len(self.symbols) > 0:
|
if len(self.symbols) > 0:
|
||||||
return
|
return
|
||||||
output = subprocess.check_output(["grep", "define", input_file]).decode().splitlines()
|
output = subprocess.check_output(["grep", "define", input_file]).decode().splitlines()
|
||||||
@@ -256,7 +284,7 @@ class Libdevice(ExternLibrary):
|
|||||||
|
|
||||||
self._group_symbols()
|
self._group_symbols()
|
||||||
|
|
||||||
def _output_stubs(self):
|
def _output_stubs(self) -> str:
|
||||||
# Generate python functions in the following format:
|
# Generate python functions in the following format:
|
||||||
# @extern.extern
|
# @extern.extern
|
||||||
# def <op_name>(<args>, _builder=None):
|
# def <op_name>(<args>, _builder=None):
|
||||||
@@ -297,7 +325,10 @@ class Libdevice(ExternLibrary):
|
|||||||
|
|
||||||
|
|
||||||
class LLVMDisassembler:
|
class LLVMDisassembler:
|
||||||
def __init__(self, path):
|
_path: str
|
||||||
|
_ll_file: str
|
||||||
|
|
||||||
|
def __init__(self, path) -> None:
|
||||||
'''
|
'''
|
||||||
Invoke llvm-dis to disassemble the given file.
|
Invoke llvm-dis to disassemble the given file.
|
||||||
|
|
||||||
@@ -306,23 +337,28 @@ class LLVMDisassembler:
|
|||||||
self._path = path
|
self._path = path
|
||||||
self._ll_file = "/tmp/extern_lib.ll"
|
self._ll_file = "/tmp/extern_lib.ll"
|
||||||
|
|
||||||
def disasm(self, lib_path):
|
def disasm(self, lib_path: str) -> None:
|
||||||
subprocess.Popen([self._path, lib_path, "-o", self.ll_file],
|
subprocess.Popen([self._path, lib_path, "-o", self.ll_file],
|
||||||
stdout=subprocess.PIPE).communicate()
|
stdout=subprocess.PIPE).communicate()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ll_file(self):
|
def ll_file(self) -> str:
|
||||||
return self._ll_file
|
return self._ll_file
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self) -> str:
|
||||||
return self._path
|
return self._path
|
||||||
|
|
||||||
|
|
||||||
extern_libs = ["libdevice"]
|
extern_libs = ["libdevice"]
|
||||||
|
|
||||||
|
|
||||||
def build(llvm_dis_path, lib_path, lib_name, output_dir):
|
def build(
|
||||||
|
llvm_dis_path: str,
|
||||||
|
lib_path: str,
|
||||||
|
lib_name: str,
|
||||||
|
output_dir: str,
|
||||||
|
) -> None:
|
||||||
'''
|
'''
|
||||||
Interface function to build the library file.
|
Interface function to build the library file.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user