An IEC61131-3 industrial PLC language compiler based on LLVM
Through the IEC61131-3 industrial PLC language compiler based on LLVM, the front-end separation design is adopted, which solves the problems of complex expansion and maintenance of traditional compilers and the difficulty of integrating with debugging tools, and realizes the decoupling and modularization of the compiler, improving the Development efficiency and performance.
Patent Information
- Application Number
- CN202411255465.1
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Filing Date
- 2024-09-09
- Publication Date
- 2025-01-14
- Estimated Expiration
- 2044-09-09
AI Technical Summary
Traditional compilers are designed for specific languages and architectures, and are complex to scale and maintain, difficult to share optimization technologies, and are difficult to efficiently integrate with debugging tools, and difficult to support efficient JIT compilation, affecting speed and the performance of generated code.
Using the IEC61131-3 industrial PLC language compiler based on LLVM, adopts the front-end separation design, the front-end uses ieclang, and the back-end uses LLVM, that is, the underlying virtual machine. C language code is generated through lexical analysis, syntax analysis, and semantic analysis, and is compiled by LLVM. The machine is optimized to target machine code to realize compiler decoupling and modularization.
It improves the portability and development efficiency of the compiler, allows different teams to develop front-end and back-end in parallel, and speeds up development speed and production efficiency.
Smart Images

Figure CN118778940B_ABST
Abstract
Description
Technical Field
[0001] The present invention relates to the technical field of compilation principles, and in particular to an IEC61131-3 industrial PLC language compiler based on LLVM. Background Art
[0002] Traditional compilers are usually designed for specific languages and architectures, making expansion and maintenance complex and inflexible. Different programming languages often have their own compilers, making it difficult to share optimization technologies. In addition, developing and debugging modern software requires a complex tool chain, including debuggers, static analysis tools, and dynamic analysis tools. Therefore, traditional compilers are often difficult to efficiently integrate with these tools. Traditional compiler frameworks do not easily support efficient JIT compilation, and speed and the performance of generated code have always been key issues in the design. Summary of the invention
[0003] Purpose of the invention: The purpose of the present invention is to provide an IEC61131-3 industrial PLC language compiler based on LLVM to solve the problems existing in the background technology.
[0004] Technical solution: The IEC61131-3 industrial PLC language compiler based on LLVM described in the present invention adopts a front-end and back-end separation design, that is, the front-end is ieclang and the back-end is LLVM, i.e., the underlying virtual machine (Low Level Virtual Machine), and includes the following steps:
[0005] (1) Take the IEC61131-3 source code as input and decompose it into token streams by applying the lexical analyzer flex;
[0006] (2) The token stream token is passed through the syntax analysis bison to build an abstract syntax tree AST;
[0007] (3) Fill the global symbol table and transmit it to the next stage together with the abstract syntax tree;
[0008] (4) Perform semantic analysis, including type checking, and generate an abstract syntax tree with additional semantic information;
[0009] (5) Parse the abstract syntax tree with additional semantic information, generate C language code and transmit it to the next stage C language compiler or LLVM compiler; the ieclang front-end work is completed;
[0010] (6) The GCC language compiler compiles the C language code after receiving it and outputs the corresponding executable file;
[0011] (7) After receiving the C language code, the LLVM compiler compiles it and outputs X86 and PowerPC target codes.
[0012] Furthermore, in step (1), applying a lexical analyzer includes the following steps:
[0013] Identify various tokens in the input text by defining regular expressions, including: keywords, identifiers, operators, and other symbols;
[0014] Read the lexical rule file, i.e., the .ll file, and generate the corresponding C language code file, i.e., lex.yy.c;
[0015] Reads a C language code file, breaks it into tokens, and performs corresponding actions for each token, including calling a specific function or returning a token type.
[0016] Furthermore, in step (2), applying a syntax analyzer includes the following steps:
[0017] By defining a context-free grammar, the input token stream is parsed to ensure that it conforms to specific grammatical rules;
[0018] Read the grammar rule file .yy file and generate the corresponding C language code file;
[0019] It receives the token stream provided by the lexical analyzer and builds a parse tree or abstract syntax tree according to the defined grammar rules.
[0020] Furthermore, in step (3), filling the global symbol table includes the following steps:
[0021] Fill function table: a symbol table containing all globally declared functions POU;
[0022] Fill the function block type table: Contains the symbol table of all globally declared function block POUs;
[0023] Filling the program type table: a symbol table containing all globally declared program POUs;
[0024] Fill the total type table: a symbol table containing definitions of all user-declared data types;
[0025] Populate the enumeration value table: A symbol table containing all identifiers declared for an enumeration type.
[0026] Furthermore, in step (4), applying a semantic analyzer includes:
[0027] Type checking, scope checking, consistency checking, symbol table management, constant expression evaluation, control flow checking, data flow analysis, function call checking, context condition checking.
[0028] Furthermore, in step (5), the AST is converted into C language code, including: recursively traversing the AST to generate corresponding C language code.
[0029] Furthermore, in step (7), the C language code is input into the LLVM compiler for processing, including: converting the C language code into an intermediate representation of LLVM; performing various optimizations on the intermediate representation; and converting the optimized intermediate representation into target machine code.
[0030] Beneficial effects: Compared with the prior art, the present invention has the following significant advantages: the separation design of the front-end and the back-end realizes compiler decoupling and improves compiler portability; the compiler is modularized, which is conducive to parallel development and allows different teams to develop the front-end and the back-end at the same time, thereby speeding up development and improving overall production efficiency. BRIEF DESCRIPTION OF THE DRAWINGS
[0031] Figure 1 is a flowchart of the compiler of the present invention. DETAILED DESCRIPTION
[0032] The technical solution of the present invention is further described below in conjunction with the accompanying drawings.
[0033] like Figure 1 As shown, an embodiment of the present invention provides an IEC61131-3 industrial PLC language compiler based on LLVM, using ieclang as the front end, including the following steps:
[0034] (1): Take the IEC61131-3 source code as input and decompose it into token streams (tokens) through lexical analysis (flex); including:
[0035] Read Input: Read characters from a source code file or input stream.
[0036] Skip whitespace and comments: Skip whitespace characters (such as space, tab, and newline) and comments, which are usually insignificant in the markup stream.
[0037] Identify tokens: Identify different types of tokens such as keywords, identifiers, literals, operators, etc. through pattern matching.
[0038] Generate Tags: Generates a structure containing the tag type and value for each identified tag
[0039] Handling errors: If an unrecognizable character sequence is encountered, report a lexical error and decide whether to continue parsing or terminate.
[0040] Output token stream: Output the generated token stream to the parser for further processing.
[0041] Step 2: The token stream is parsed by bison to build an abstract syntax tree (AST); including:
[0042] Read Token Stream: Receives a stream of tokens from the lexer.
[0043] Select the analysis method: Select an appropriate syntax analysis method, such as recursive descent analysis, LR analysis, LL analysis, etc.
[0044] Build an Abstract Syntax Tree (AST): Recursively combine token streams into grammatical structures according to the grammar rules.
[0045] Handle syntax errors: If a syntax error is encountered, report the error message and terminate the process.
[0046] Output parsing results: Output the constructed parse tree or abstract syntax tree.
[0047] Step 3: Fill the global symbol table and transmit it to the next stage together with the abstract syntax tree; filling the global symbol table includes:
[0048] Fill function table: Contains the symbol table of all globally declared functions POU
[0049] Fill the function block type table: Contains the symbol table of all globally declared function blocks POU
[0050] Filling the Program Type Table: A symbol table containing all globally declared program POUs.
[0051] Populate the total type table: A symbol table containing definitions of all user-declared (non-elementary) data types.
[0052] Populate the enumeration value table: A symbol table containing all identifiers (values) declared for an enumeration type.
[0053] Step 4: Perform semantic analysis, including type checking, generate an abstract syntax tree with additional semantic information and transfer it to the next stage; including:
[0054] Implement array range checking in the array range checking class.
[0055] Check the elements in the CASE statement in the CASE element check class.
[0056] In the constant folding class, constant folding is performed: the abstract syntax tree (AST) of the program is traversed, constant expressions are evaluated, and their results are substituted into the corresponding positions.
[0057] Ensure consistency between external variable declarations and global variable declarations in external check classes. This is done by looking up the declaration and type of the variable and comparing them. If inconsistencies are found, an error is logged.
[0058] Coordinate the entire declaration checking process in the declaration checking class. Recursively process configuration and resource declarations, and use external checking classes for specific variable checking when needed.
[0059] Inserts an enumeration value into the symbol table in a populated enumeration value class. Avoids duplicate definitions by checking if the enumeration value already exists and reports an error if a duplicate is found.
[0060] The entire enumeration declaration checking process is coordinated in the Enumeration Declaration Checking class. The corresponding symbol tables are populated and checked by accessing library, data type, function, function block, program, configuration and resource declarations.
[0061] Implement the functionality of analyzing each expression / field / etc. possible data type in the Fill Alternative Data Type class and annotate the abstract syntax tree.
[0062] The analysis of instruction control flow is implemented in the instruction control flow analysis class, which effectively handles the control flow in functions, function blocks and programs, and constructs an instruction link relationship diagram that reflects the actual control flow.
[0063] The assignment check class checks whether the assignment operation is legal. It ensures that the lvalue meets certain conditions: control variables, output variables, constants, and expressions cannot be assigned.
[0064] Identifies forward dependencies of a given symbol in the Find Forward Dependencies class. It checks whether a particular identifier (like a function or a variable) has been declared.
[0065] Remove the forward dependencies from the library in the Remove Forward Dependencies class and create a new library tree without forward dependencies.
[0066] The number of Program Organization Units (POUs) in the library is counted in the Organization Unit Count class. It is implemented as a singleton pattern to ensure that only one instance exists during the entire program run.
[0067] Implement the function of reducing all possible data types used in each expression / field, etc. to a single data type in the candidate data type reduction class and annotate the abstract syntax tree
[0068] In the print data type class, each object in the abstract syntax tree that may have a data type will correctly fill in the variable "datatype" function. If the analyzed IEC 61131-3 source code contains semantic data type incompatibility errors, error information will be printed.
[0069] Step 5: Parse the abstract syntax tree with additional semantic information, generate C language code and transmit it to the next stage. At this point, the ieclang front-end work is completed; including:
[0070] Traversing AST nodes: Traverse each node in the AST and generate corresponding C language code according to the node type. The following are the specific steps for processing different types of nodes:
[0071] Process variable declarations: allocate memory space for variable declarations and add them to the symbol table.
[0072] Process constants and variable references: For constants, directly generate the corresponding C language constant value. For variable references, get the address of the variable from the symbol table and generate a load instruction.
[0073] Processing arithmetic operations: Generate corresponding C language instructions based on the operators in the AST nodes.
[0074] Processing control flow: When processing conditional statements (such as if-else) and loops (such as for, while), generate corresponding basic blocks and jump instructions.
[0075] Processing function definitions and calls: Generates entry and return instructions for function definitions, as well as function call instructions.
[0076] Using the LLVM compiler as the backend, the following steps are included:
[0077] Step 6: After receiving the C language code, a C language compiler such as GCC compiles it and outputs the corresponding executable file; including:
[0078] Preprocessing: Process preprocessing instructions and generate preprocessed source code files.
[0079] Compile: Convert the preprocessed source code into assembly code files.
[0080] Assembly: Convert assembly code into object files.
[0081] Link: Link the target file and library file together to generate an executable file.
[0082] Step 7: After receiving the C language code, the LLVM compiler compiles it and outputs target codes such as X86 and PowerPC. Including:
[0083] Convert C code to LLVM intermediate representation.
[0084] Optimize the LLVM intermediate representation. Use LLVM's opt tool to perform various code optimizations: execute Mem2Reg, Constant Folding, Dead Code Elimination, Inlining, Loop Unrolling and other optimization passes to optimize the intermediate representation. After each pass optimizes the intermediate representation, it will pass the intermediate representation to the next optimization pass.
[0085] Convert optimized LLVM intermediate representation into target machine code. Including instruction selection, register allocation and code generation:
[0086] Instruction selection: Mapping the high-level operations in the intermediate representation onto the instruction set of the target architecture. This process selects the instructions that are most suitable for the target architecture to implement the desired operations in the generated target code.
[0087] Register allocation: Mapping virtual registers to physical registers of the target architecture. This includes global register allocation and local register allocation. Global register allocation considers the register requirements of the entire function or module, while local register allocation is done within the scope of a basic block or smaller code unit.
[0088] Instruction Scheduling: Reordering instruction sequences to maximize the use of the processor's pipeline and other parallel execution resources. Instruction scheduling can be divided into static scheduling and dynamic scheduling. Static scheduling is done during compilation, while dynamic scheduling is usually performed by the processor hardware.
[0089] Generate target code: Generate target machine code or assembly code based on the selected, allocated and scheduled instruction sequence. This step takes into account the characteristics and limitations of the target architecture to ensure that the generated code runs correctly in the target environment.
Claims
1. An IEC61131-3 industrial PLC language compiler based on LLVM, characterized in that: The design of separating the front-end and back-end is adopted, that is, the front-end is ieclang and the back-end is LLVM, including the following steps: (1) Take the IEC61131-3 source code as input and decompose it into a token stream token by applying the lexical analyzer flex; applying the lexical analyzer includes the following steps: Identify various tokens in the input text by defining regular expressions, including: keywords, identifiers, operators, and other symbols; Read the lexical rule file, i.e., the .ll file, and generate the corresponding C language code file, i.e., lex.yy.c; Reads a C language code file, breaks it into tokens, and performs corresponding actions for each token including: calling a specific function or returning a token type; (2) The token stream token is passed through the syntax analysis bison to build an abstract syntax tree AST; the syntax analyzer is applied, including the following steps: By defining a context-free grammar, the input token stream is parsed to ensure that it conforms to specific grammatical rules; Read the grammar rule file .yy file and generate the corresponding C language code file; Receive the token stream provided by the lexical analyzer and build a parse tree or abstract syntax tree according to the defined grammar rules; (3) Fill the global symbol table and transmit it to the next stage together with the abstract syntax tree; Filling the global symbol table includes the following steps: Fill function table: a symbol table containing all globally declared functions POU; Fill the function block type table: Contains the symbol table of all globally declared function block POUs; Filling the program type table: a symbol table containing all globally declared program POUs; Fill the total type table: a symbol table containing definitions of all user-declared data types; Fill the enumeration value table: a symbol table containing all identifiers declared for the enumeration type; (4) Perform semantic analysis, including type checking, generate an abstract syntax tree with additional semantic information and transmit it to the next stage; including: Implement array range checking in the array range checking class; Check the elements in the CASE statement in the CASE element check class; Perform constant folding in the constant folding class: traverse the abstract syntax tree AST of the program, evaluate the constant expression, and replace its result into the corresponding position; Ensure consistency between external variable declarations and global variable declarations in the external check class by looking up the variable declarations and types and comparing them; if inconsistencies are found, an error is logged; Coordinate the entire declaration checking process in the declaration checking class; recursively process configuration and resource declarations and use external checking classes for specific variable checking when needed; Insert enumeration values into the symbol table in the populated enumeration value class; avoid duplicate definitions by checking whether the enumeration value already exists and report an error if a duplication is found; Coordinates the entire enumeration declaration checking process in the enumeration declaration checking class; populates and checks the corresponding symbol tables by accessing libraries, data types, functions, function blocks, procedures, configurations, and resource declarations; Implement the function of analyzing the data type of each expression / field in the fill candidate data type class and annotate the abstract syntax tree; The analysis of instruction control flow is implemented in the instruction control flow analysis class, which effectively processes the control flow in functions, function blocks and programs, and constructs an instruction link relationship diagram that reflects the actual control flow; Check whether the assignment operation is legal in the assignment check class; ensure that the lvalue meets specific conditions: control variables, output variables, constants, and expressions cannot be assigned; Identifies forward dependencies of a given symbol in the Find Forward Dependencies class; it checks whether a particular identifier has been declared; Remove the forward dependencies in the library in the Remove Forward Dependencies class and create a new library tree without forward dependencies; The number of program organization units POUs in the library is counted in the Organization Unit Count class; it is implemented as a singleton pattern to ensure that only one instance exists during the entire program run; Implement the function of reducing all data types used by each expression / field to a single data type in the reduction candidate data type class and annotate the abstract syntax tree; In the Print Data Type class, each object with a data type in the abstract syntax tree will correctly fill in the variable "datatype". If the analyzed IEC 61131-3 source code contains semantic data type incompatibility errors, an error message will be printed; (5) Parse the abstract syntax tree with additional semantic information, generate C language code and transmit it to the next stage; at this point, the ieclang front-end work is completed; including: Traverse AST nodes: traverse each node in the AST and generate corresponding C language code according to the node type; the following are the specific steps for processing different types of nodes: Process variable declarations: allocate memory space for variable declarations and add them to the symbol table; Process constants and variable references: For constants, directly generate the corresponding C language constant value; for variable references, get the address of the variable from the symbol table and generate a load instruction; Processing arithmetic operations: Generate corresponding C language instructions based on the operators in the AST nodes; Processing control flow: When processing conditional statements and loop statements, generate corresponding basic blocks and jump instructions; Processing function definitions and calls: generating entry and return instructions for function definitions, as well as function call instructions; Using the LLVM compiler as the backend, the following steps are included: (6) After receiving the C language code, the C language compiler compiles it and outputs the corresponding executable file; including: Preprocessing: Process preprocessing instructions and generate preprocessed source code files; Compile: convert the preprocessed source code into assembly code file; Assembly: Convert assembly code into object file; Link: Link the target file and library file together to generate an executable file; (7) After receiving the C language code, the LLVM compiler compiles it and outputs X86 and PowerPC target codes; including: Convert C language code to LLVM intermediate representation; Optimize the LLVM intermediate representation; use LLVM's opt tool to perform various code optimizations: execute Mem2Reg, Constant Folding, Dead Code Elimination, Inlining, Loop Unrolling optimization passes, optimize the intermediate representation, and pass the intermediate representation to the next optimization pass after each pass optimizes the intermediate representation; convert the optimized LLVM intermediate representation into target machine code; including instruction selection, register allocation, and code generation: Instruction selection: Mapping the high-level operations in the intermediate representation onto the target architecture’s instruction set; this process selects the instructions that are most appropriate for the target architecture to implement the desired operations in the generated target code; Register allocation: Mapping virtual registers to physical registers of the target architecture; including global register allocation and local register allocation; global register allocation considers the register requirements of the entire function or module, while local register allocation is completed within the scope of the basic block or the smallest code unit; Instruction scheduling: reordering instruction sequences to maximize the use of the processor's pipeline and other parallel execution resources; instruction scheduling can be divided into static scheduling and dynamic scheduling. Static scheduling is completed during compilation, while dynamic scheduling is performed by the processor hardware. Generate target code: Generate target machine code or assembly code based on the selected, allocated and scheduled instruction sequence; taking into account the characteristics and limitations of the target architecture to ensure that the generated code runs correctly in the target environment.
Citation Information
Patent Citations
Method for transforming switch special language into C language
CN102222004A
Security redundancy compiling operation method, computer equipment and readable storage medium
CN114780382A
Code processing method and device, electronic equipment and storage medium
CN117971231A