-
Notifications
You must be signed in to change notification settings - Fork 0
Intermediate Representation to Portable C Decompiler
The primary file, "decompiler.py" that parses tokens from the input function in order to translate to C code.
End of C -> IR -> C pipeline; can see full process here: https://github.com/dubya62/optimizer.
️# IR to C Decompiler - Documentation
The IR to C Decompiler is a Python-based tool that converts an internal intermediate representation (IR) of C-like code into valid C source code. It handles various IR constructs such as type declarations, function definitions, struct/union/enum handling, casting, and complex assignment expressions.
The core class responsible for translating IR tokens into C code. The translation happens primarily inside the method generate_c_code. Modules and Functions get_type(toks: list[Token]) Purpose: Converts type-related tokens like #TYPE, #STRUCT, #UNION, or #ENUM into valid C syntax. handle_multiple_set(tokens) Purpose: Normalizes chained assignments (x = y = z) into sequential assignments.
generate_c_code(tokens, libraries) The main method for decompilation. Processing steps include: Include Headers – Adds necessary includes. Normalize Chained Assignments – Converts multiple assignment patterns. Type Casts and References – Rewrites cast, ref, and access appropriately. Handle Structs, Unions, Enums – Converts to proper C declarations. Function Definitions – Parses function signatures and bodies. Comma-Separated Assignment Fixes – Resolves complex multi-variable assignments. Type Inference and Substitution – Detects untyped vars and replaces consistently. Formatting – Adds newlines and generates final C code string.
Uses a custom Token class with markers like: #FUNC, #TYPE, #STRUCT, #UNION, #ENUM, #FUNCCALL "ref", "access" which can be found in the lexer.py and normalizer.py
from ir_to_c_decompiler import IRToCDecompiler
tokens = [...] # List of Token instances
libraries = ["stdio.h", "stdlib.h"]
decompiler = IRToCDecompiler()
c_code = decompiler.generate_c_code(tokens, libraries)
print(c_code)
where test tokens may look like this:
TEST_TOKENS = ['#3', '=', '0', ';',
'@1', ':',
'#5', '=', '#3', '<', '10', ';',
'if', '#5', '{',
'#7', '=', '"Hello, World!\\n"', ';',
'#4', 'call', '#7', ';',
'#3', ';',
'#3', '=', '#3', '+', '1', ';',
'goto', '@3', ';', '}',
'else', '{',
# '#3', '=', '#3', '+', '1', ';',
'}',
'@0', ':',
'#6', '=', '0', ';',
'#8', 'access', '0', '=', '#6', ';',
'return', ';']
`