├── .gitignore ├── ANTLR ├── .gitignore ├── Expression │ ├── Expression.g4 │ ├── Expression.interp │ ├── Expression.tokens │ ├── ExpressionBaseListener.cpp │ ├── ExpressionBaseListener.h │ ├── ExpressionBaseVisitor.cpp │ ├── ExpressionBaseVisitor.h │ ├── ExpressionLexer.cpp │ ├── ExpressionLexer.h │ ├── ExpressionLexer.interp │ ├── ExpressionLexer.tokens │ ├── ExpressionListener.cpp │ ├── ExpressionListener.h │ ├── ExpressionParser.cpp │ ├── ExpressionParser.h │ ├── ExpressionVisitor.cpp │ ├── ExpressionVisitor.h │ ├── expr.txt │ └── main.cpp ├── Frontend │ ├── NodeLang.g4 │ ├── NodeLang.interp │ ├── NodeLang.tokens │ ├── NodeLangBaseListener.cpp │ ├── NodeLangBaseListener.h │ ├── NodeLangBaseVisitor.cpp │ ├── NodeLangBaseVisitor.h │ ├── NodeLangLexer.cpp │ ├── NodeLangLexer.h │ ├── NodeLangLexer.interp │ ├── NodeLangLexer.tokens │ ├── NodeLangListener.cpp │ ├── NodeLangListener.h │ ├── NodeLangParser.cpp │ ├── NodeLangParser.h │ ├── NodeLangVisitor.cpp │ ├── NodeLangVisitor.h │ ├── app.nl │ ├── main.cpp │ ├── nodelang.ll │ ├── nodelang.opt.ll │ ├── nodelang.opt.s │ └── test.nl └── README.md ├── Flex_Bison ├── 0.lex ├── 0.sh ├── 1.lex ├── 1.sh ├── 10.lex ├── 10.sh ├── 10.txt ├── 10.y ├── 11.lex ├── 11.sh ├── 11.txt ├── 11.y ├── 12.lex ├── 12.sh ├── 12.txt ├── 12.y ├── 2.sh ├── 2.y ├── 3.lex ├── 3.sh ├── 3.y ├── 4.lex ├── 4.sh ├── 4.y ├── 5.lex ├── 5.sh ├── 5.y ├── 6.lex ├── 6.sh ├── 6.y ├── 7.lex ├── 7.sh ├── 7.y ├── 8.lex ├── 8.sh ├── 8.y ├── 9.lex ├── 9.sh ├── 9.txt ├── 9.y ├── FrontEnd.lex ├── FrontEnd.sh ├── FrontEnd.y ├── README.md ├── app.lang ├── lang.ll ├── lang.opt.ll └── lang.opt.s ├── Full_Pipeline ├── README.md ├── app.c ├── app.lang ├── app.nl ├── app2.c ├── compile_sim.sh ├── graphic.c ├── graphic.lang └── graphic.nl ├── LICENSE ├── LLVM_BackEnd ├── README.md ├── TableGen │ ├── test.td │ └── test_i.td ├── app.c ├── app.ll ├── app.o ├── app.s ├── graphic.c ├── graphic.ll ├── graphic.o ├── graphic.s ├── test.c ├── test.ll ├── test.o └── test.s ├── LLVM_IRGen ├── 0_IR_reader.cpp ├── 1_ir_gen.cpp ├── 2_ir_gen+ee.cpp ├── 3_hello_ir_gen.cpp ├── 4_ext_funcs.cpp ├── 5.s ├── 5_asm_ext_func.cpp ├── 5_asm_ir_func.cpp ├── 6.s ├── 6_asm_BB.cpp ├── 7_0.s ├── 7_1.s ├── 7_2.s ├── 7_cpu.cpp ├── 8_0.s ├── 8_cpu.cpp ├── 9_0.txt ├── 9_1.txt ├── 9_2.txt ├── 9_expr.cpp ├── 9_funcs.cpp ├── README.md ├── expr.s ├── expression_check.txt └── hello.c ├── LLVM_Pass ├── Legacy │ ├── ModPass_dump.cpp │ ├── Pass_cfg.cpp │ ├── Pass_change.cpp │ ├── Pass_dump.cpp │ ├── Pass_opt.cpp │ ├── Pass_start.cpp │ ├── Pass_uses.cpp │ └── README.md ├── Pass1_reg.cpp ├── Pass2_names.cpp ├── Pass3_dump.cpp ├── Pass4_uses.cpp ├── Pass5_change.cpp ├── Pass6_cfg.cpp ├── Pass7_opt.cpp ├── Pass_trace.cpp ├── README.md ├── c_examples │ ├── calc.c │ ├── exp1.c │ ├── exp2.c │ ├── fact.c │ ├── hello.c │ └── test.c ├── log.c └── trace.sh ├── README.md ├── SDL ├── IRGen │ ├── app.s │ ├── app2isa.txt │ ├── app_asm_IRgen_1.cpp │ ├── app_asm_IRgen_2.cpp │ ├── app_ir_gen.cpp │ ├── app_pre.s │ └── app_pre2.s ├── README.md ├── app.c ├── app2.c ├── sim.c ├── sim.h └── start.c └── Sim ├── README.md ├── bin.cpp ├── binElf.cpp ├── cpu.cpp ├── elfio ├── elf_types.hpp ├── elfio.hpp ├── elfio_array.hpp ├── elfio_dump.hpp ├── elfio_dynamic.hpp ├── elfio_header.hpp ├── elfio_modinfo.hpp ├── elfio_note.hpp ├── elfio_relocation.hpp ├── elfio_section.hpp ├── elfio_segment.hpp ├── elfio_strings.hpp ├── elfio_symbols.hpp ├── elfio_utils.hpp ├── elfio_version.hpp └── elfio_versym.hpp ├── examples ├── app.sim ├── app2.o ├── app2.s ├── clang.o ├── clang.s ├── graphic.o ├── graphic.s ├── graphic.sim ├── lang.o ├── lang.s ├── nodelang.o └── nodelang.s ├── extIR.cpp ├── fullIR.cpp ├── include ├── ISA.h ├── bin.h ├── cpu.h ├── extIR.h ├── fullIR.h ├── instr.h └── sim.h ├── instr.cpp ├── loop.sh └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.ll 2 | *.o 3 | *.so 4 | *.out 5 | *.bc 6 | .vscode 7 | -------------------------------------------------------------------------------- /ANTLR/.gitignore: -------------------------------------------------------------------------------- 1 | *.antlr -------------------------------------------------------------------------------- /ANTLR/Expression/Expression.g4: -------------------------------------------------------------------------------- 1 | grammar Expression; 2 | 3 | // Parser rule 4 | expr: 5 | '-' expr 6 | | expr ( '*' | '/') expr 7 | | expr ( '+' | '-') expr 8 | | '{' expr '}' 9 | | INT; 10 | 11 | // Lexer rules 12 | INT: [0-9]+; 13 | WS: [ \t\r\n]+ -> skip; -------------------------------------------------------------------------------- /ANTLR/Expression/Expression.interp: -------------------------------------------------------------------------------- 1 | token literal names: 2 | null 3 | '-' 4 | '*' 5 | '/' 6 | '+' 7 | '{' 8 | '}' 9 | null 10 | null 11 | 12 | token symbolic names: 13 | null 14 | null 15 | null 16 | null 17 | null 18 | null 19 | null 20 | INT 21 | WS 22 | 23 | rule names: 24 | expr 25 | 26 | 27 | atn: 28 | [3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 10, 26, 4, 2, 9, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 5, 2, 13, 10, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 7, 2, 21, 10, 2, 12, 2, 14, 2, 24, 11, 2, 3, 2, 2, 3, 2, 3, 2, 2, 4, 3, 2, 4, 5, 4, 2, 3, 3, 6, 6, 2, 28, 2, 12, 3, 2, 2, 2, 4, 5, 8, 2, 1, 2, 5, 6, 7, 3, 2, 2, 6, 13, 5, 2, 2, 7, 7, 8, 7, 7, 2, 2, 8, 9, 5, 2, 2, 2, 9, 10, 7, 8, 2, 2, 10, 13, 3, 2, 2, 2, 11, 13, 7, 9, 2, 2, 12, 4, 3, 2, 2, 2, 12, 7, 3, 2, 2, 2, 12, 11, 3, 2, 2, 2, 13, 22, 3, 2, 2, 2, 14, 15, 12, 6, 2, 2, 15, 16, 9, 2, 2, 2, 16, 21, 5, 2, 2, 7, 17, 18, 12, 5, 2, 2, 18, 19, 9, 3, 2, 2, 19, 21, 5, 2, 2, 6, 20, 14, 3, 2, 2, 2, 20, 17, 3, 2, 2, 2, 21, 24, 3, 2, 2, 2, 22, 20, 3, 2, 2, 2, 22, 23, 3, 2, 2, 2, 23, 3, 3, 2, 2, 2, 24, 22, 3, 2, 2, 2, 5, 12, 20, 22] -------------------------------------------------------------------------------- /ANTLR/Expression/Expression.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | T__1=2 3 | T__2=3 4 | T__3=4 5 | T__4=5 6 | T__5=6 7 | INT=7 8 | WS=8 9 | '-'=1 10 | '*'=2 11 | '/'=3 12 | '+'=4 13 | '{'=5 14 | '}'=6 15 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionBaseListener.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Generated from Expression.g4 by ANTLR 4.9.2 3 | 4 | 5 | #include "ExpressionBaseListener.h" 6 | 7 | 8 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionBaseListener.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from Expression.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | #include "ExpressionListener.h" 9 | 10 | 11 | /** 12 | * This class provides an empty implementation of ExpressionListener, 13 | * which can be extended to create a listener which only needs to handle a subset 14 | * of the available methods. 15 | */ 16 | class ExpressionBaseListener : public ExpressionListener { 17 | public: 18 | 19 | virtual void enterExpr(ExpressionParser::ExprContext * /*ctx*/) override { } 20 | virtual void exitExpr(ExpressionParser::ExprContext * /*ctx*/) override { } 21 | 22 | 23 | virtual void enterEveryRule(antlr4::ParserRuleContext * /*ctx*/) override { } 24 | virtual void exitEveryRule(antlr4::ParserRuleContext * /*ctx*/) override { } 25 | virtual void visitTerminal(antlr4::tree::TerminalNode * /*node*/) override { } 26 | virtual void visitErrorNode(antlr4::tree::ErrorNode * /*node*/) override { } 27 | 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionBaseVisitor.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Generated from Expression.g4 by ANTLR 4.9.2 3 | 4 | 5 | #include "ExpressionBaseVisitor.h" 6 | 7 | 8 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionBaseVisitor.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from Expression.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | #include "ExpressionVisitor.h" 9 | 10 | 11 | /** 12 | * This class provides an empty implementation of ExpressionVisitor, which can be 13 | * extended to create a visitor which only needs to handle a subset of the available methods. 14 | */ 15 | class ExpressionBaseVisitor : public ExpressionVisitor { 16 | public: 17 | 18 | virtual antlrcpp::Any visitExpr(ExpressionParser::ExprContext *ctx) override { 19 | return visitChildren(ctx); 20 | } 21 | 22 | 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionLexer.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from Expression.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | 9 | 10 | 11 | 12 | class ExpressionLexer : public antlr4::Lexer { 13 | public: 14 | enum { 15 | T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6, INT = 7, 16 | WS = 8 17 | }; 18 | 19 | explicit ExpressionLexer(antlr4::CharStream *input); 20 | ~ExpressionLexer(); 21 | 22 | virtual std::string getGrammarFileName() const override; 23 | virtual const std::vector& getRuleNames() const override; 24 | 25 | virtual const std::vector& getChannelNames() const override; 26 | virtual const std::vector& getModeNames() const override; 27 | virtual const std::vector& getTokenNames() const override; // deprecated, use vocabulary instead 28 | virtual antlr4::dfa::Vocabulary& getVocabulary() const override; 29 | 30 | virtual const std::vector getSerializedATN() const override; 31 | virtual const antlr4::atn::ATN& getATN() const override; 32 | 33 | private: 34 | static std::vector _decisionToDFA; 35 | static antlr4::atn::PredictionContextCache _sharedContextCache; 36 | static std::vector _ruleNames; 37 | static std::vector _tokenNames; 38 | static std::vector _channelNames; 39 | static std::vector _modeNames; 40 | 41 | static std::vector _literalNames; 42 | static std::vector _symbolicNames; 43 | static antlr4::dfa::Vocabulary _vocabulary; 44 | static antlr4::atn::ATN _atn; 45 | static std::vector _serializedATN; 46 | 47 | 48 | // Individual action functions triggered by action() above. 49 | 50 | // Individual semantic predicate functions triggered by sempred() above. 51 | 52 | struct Initializer { 53 | Initializer(); 54 | }; 55 | static Initializer _init; 56 | }; 57 | 58 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionLexer.interp: -------------------------------------------------------------------------------- 1 | token literal names: 2 | null 3 | '-' 4 | '*' 5 | '/' 6 | '+' 7 | '{' 8 | '}' 9 | null 10 | null 11 | 12 | token symbolic names: 13 | null 14 | null 15 | null 16 | null 17 | null 18 | null 19 | null 20 | INT 21 | WS 22 | 23 | rule names: 24 | T__0 25 | T__1 26 | T__2 27 | T__3 28 | T__4 29 | T__5 30 | INT 31 | WS 32 | 33 | channel names: 34 | DEFAULT_TOKEN_CHANNEL 35 | HIDDEN 36 | 37 | mode names: 38 | DEFAULT_MODE 39 | 40 | atn: 41 | [3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 10, 43, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 6, 8, 33, 10, 8, 13, 8, 14, 8, 34, 3, 9, 6, 9, 38, 10, 9, 13, 9, 14, 9, 39, 3, 9, 3, 9, 2, 2, 10, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 3, 2, 4, 3, 2, 50, 59, 5, 2, 11, 12, 15, 15, 34, 34, 2, 44, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 3, 19, 3, 2, 2, 2, 5, 21, 3, 2, 2, 2, 7, 23, 3, 2, 2, 2, 9, 25, 3, 2, 2, 2, 11, 27, 3, 2, 2, 2, 13, 29, 3, 2, 2, 2, 15, 32, 3, 2, 2, 2, 17, 37, 3, 2, 2, 2, 19, 20, 7, 47, 2, 2, 20, 4, 3, 2, 2, 2, 21, 22, 7, 44, 2, 2, 22, 6, 3, 2, 2, 2, 23, 24, 7, 49, 2, 2, 24, 8, 3, 2, 2, 2, 25, 26, 7, 45, 2, 2, 26, 10, 3, 2, 2, 2, 27, 28, 7, 125, 2, 2, 28, 12, 3, 2, 2, 2, 29, 30, 7, 127, 2, 2, 30, 14, 3, 2, 2, 2, 31, 33, 9, 2, 2, 2, 32, 31, 3, 2, 2, 2, 33, 34, 3, 2, 2, 2, 34, 32, 3, 2, 2, 2, 34, 35, 3, 2, 2, 2, 35, 16, 3, 2, 2, 2, 36, 38, 9, 3, 2, 2, 37, 36, 3, 2, 2, 2, 38, 39, 3, 2, 2, 2, 39, 37, 3, 2, 2, 2, 39, 40, 3, 2, 2, 2, 40, 41, 3, 2, 2, 2, 41, 42, 8, 9, 2, 2, 42, 18, 3, 2, 2, 2, 5, 2, 34, 39, 3, 8, 2, 2] -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionLexer.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | T__1=2 3 | T__2=3 4 | T__3=4 5 | T__4=5 6 | T__5=6 7 | INT=7 8 | WS=8 9 | '-'=1 10 | '*'=2 11 | '/'=3 12 | '+'=4 13 | '{'=5 14 | '}'=6 15 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionListener.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Generated from Expression.g4 by ANTLR 4.9.2 3 | 4 | 5 | #include "ExpressionListener.h" 6 | 7 | 8 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionListener.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from Expression.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | #include "ExpressionParser.h" 9 | 10 | 11 | /** 12 | * This interface defines an abstract listener for a parse tree produced by ExpressionParser. 13 | */ 14 | class ExpressionListener : public antlr4::tree::ParseTreeListener { 15 | public: 16 | 17 | virtual void enterExpr(ExpressionParser::ExprContext *ctx) = 0; 18 | virtual void exitExpr(ExpressionParser::ExprContext *ctx) = 0; 19 | 20 | 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionParser.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from Expression.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | 9 | 10 | 11 | 12 | class ExpressionParser : public antlr4::Parser { 13 | public: 14 | enum { 15 | T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6, INT = 7, 16 | WS = 8 17 | }; 18 | 19 | enum { 20 | RuleExpr = 0 21 | }; 22 | 23 | explicit ExpressionParser(antlr4::TokenStream *input); 24 | ~ExpressionParser(); 25 | 26 | virtual std::string getGrammarFileName() const override; 27 | virtual const antlr4::atn::ATN& getATN() const override { return _atn; }; 28 | virtual const std::vector& getTokenNames() const override { return _tokenNames; }; // deprecated: use vocabulary instead. 29 | virtual const std::vector& getRuleNames() const override; 30 | virtual antlr4::dfa::Vocabulary& getVocabulary() const override; 31 | 32 | 33 | class ExprContext; 34 | 35 | class ExprContext : public antlr4::ParserRuleContext { 36 | public: 37 | ExprContext(antlr4::ParserRuleContext *parent, size_t invokingState); 38 | virtual size_t getRuleIndex() const override; 39 | std::vector expr(); 40 | ExprContext* expr(size_t i); 41 | antlr4::tree::TerminalNode *INT(); 42 | 43 | virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override; 44 | virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override; 45 | 46 | virtual antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor *visitor) override; 47 | 48 | }; 49 | 50 | ExprContext* expr(); 51 | ExprContext* expr(int precedence); 52 | 53 | virtual bool sempred(antlr4::RuleContext *_localctx, size_t ruleIndex, size_t predicateIndex) override; 54 | bool exprSempred(ExprContext *_localctx, size_t predicateIndex); 55 | 56 | private: 57 | static std::vector _decisionToDFA; 58 | static antlr4::atn::PredictionContextCache _sharedContextCache; 59 | static std::vector _ruleNames; 60 | static std::vector _tokenNames; 61 | 62 | static std::vector _literalNames; 63 | static std::vector _symbolicNames; 64 | static antlr4::dfa::Vocabulary _vocabulary; 65 | static antlr4::atn::ATN _atn; 66 | static std::vector _serializedATN; 67 | 68 | 69 | struct Initializer { 70 | Initializer(); 71 | }; 72 | static Initializer _init; 73 | }; 74 | 75 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionVisitor.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Generated from Expression.g4 by ANTLR 4.9.2 3 | 4 | 5 | #include "ExpressionVisitor.h" 6 | 7 | 8 | -------------------------------------------------------------------------------- /ANTLR/Expression/ExpressionVisitor.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from Expression.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | #include "ExpressionParser.h" 9 | 10 | 11 | 12 | /** 13 | * This class defines an abstract visitor for a parse tree 14 | * produced by ExpressionParser. 15 | */ 16 | class ExpressionVisitor : public antlr4::tree::AbstractParseTreeVisitor { 17 | public: 18 | 19 | /** 20 | * Visit parse trees produced by ExpressionParser. 21 | */ 22 | virtual antlrcpp::Any visitExpr(ExpressionParser::ExprContext *context) = 0; 23 | 24 | 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /ANTLR/Expression/expr.txt: -------------------------------------------------------------------------------- 1 | 1+2*{3-4}-5/-1 -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLang.g4: -------------------------------------------------------------------------------- 1 | grammar NodeLang; 2 | 3 | // Parser rule 4 | 5 | program: nodeDecl+; 6 | nodeDecl: '(' 'NODE' (varDecl | funcDecl) ')'; 7 | funcDecl: ID '(' ID* ')' node+; 8 | node: nodeDecl | expr | '(' ID node* ')'; 9 | varDecl: ID expr; 10 | expr: 11 | '-' expr 12 | | ( '*' | '/') expr expr 13 | | ( '+' | '-') expr expr 14 | | '(' expr ')' 15 | | INT 16 | | ID; 17 | 18 | // Lexer rules 19 | ID: [a-zA-Z_]+; 20 | INT: [0-9]+; 21 | WS: [ \t\r\n]+ -> skip; 22 | 23 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLang.interp: -------------------------------------------------------------------------------- 1 | token literal names: 2 | null 3 | '(' 4 | 'NODE' 5 | ')' 6 | '-' 7 | '*' 8 | '/' 9 | '+' 10 | null 11 | null 12 | null 13 | 14 | token symbolic names: 15 | null 16 | null 17 | null 18 | null 19 | null 20 | null 21 | null 22 | null 23 | ID 24 | INT 25 | WS 26 | 27 | rule names: 28 | program 29 | nodeDecl 30 | funcDecl 31 | node 32 | varDecl 33 | expr 34 | 35 | 36 | atn: 37 | [3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 12, 76, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 3, 2, 6, 2, 16, 10, 2, 13, 2, 14, 2, 17, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 24, 10, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 7, 4, 31, 10, 4, 12, 4, 14, 4, 34, 11, 4, 3, 4, 3, 4, 6, 4, 38, 10, 4, 13, 4, 14, 4, 39, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 7, 5, 47, 10, 5, 12, 5, 14, 5, 50, 11, 5, 3, 5, 5, 5, 53, 10, 5, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 74, 10, 7, 3, 7, 2, 2, 8, 2, 4, 6, 8, 10, 12, 2, 4, 3, 2, 7, 8, 4, 2, 6, 6, 9, 9, 2, 81, 2, 15, 3, 2, 2, 2, 4, 19, 3, 2, 2, 2, 6, 27, 3, 2, 2, 2, 8, 52, 3, 2, 2, 2, 10, 54, 3, 2, 2, 2, 12, 73, 3, 2, 2, 2, 14, 16, 5, 4, 3, 2, 15, 14, 3, 2, 2, 2, 16, 17, 3, 2, 2, 2, 17, 15, 3, 2, 2, 2, 17, 18, 3, 2, 2, 2, 18, 3, 3, 2, 2, 2, 19, 20, 7, 3, 2, 2, 20, 23, 7, 4, 2, 2, 21, 24, 5, 10, 6, 2, 22, 24, 5, 6, 4, 2, 23, 21, 3, 2, 2, 2, 23, 22, 3, 2, 2, 2, 24, 25, 3, 2, 2, 2, 25, 26, 7, 5, 2, 2, 26, 5, 3, 2, 2, 2, 27, 28, 7, 10, 2, 2, 28, 32, 7, 3, 2, 2, 29, 31, 7, 10, 2, 2, 30, 29, 3, 2, 2, 2, 31, 34, 3, 2, 2, 2, 32, 30, 3, 2, 2, 2, 32, 33, 3, 2, 2, 2, 33, 35, 3, 2, 2, 2, 34, 32, 3, 2, 2, 2, 35, 37, 7, 5, 2, 2, 36, 38, 5, 8, 5, 2, 37, 36, 3, 2, 2, 2, 38, 39, 3, 2, 2, 2, 39, 37, 3, 2, 2, 2, 39, 40, 3, 2, 2, 2, 40, 7, 3, 2, 2, 2, 41, 53, 5, 4, 3, 2, 42, 53, 5, 12, 7, 2, 43, 44, 7, 3, 2, 2, 44, 48, 7, 10, 2, 2, 45, 47, 5, 8, 5, 2, 46, 45, 3, 2, 2, 2, 47, 50, 3, 2, 2, 2, 48, 46, 3, 2, 2, 2, 48, 49, 3, 2, 2, 2, 49, 51, 3, 2, 2, 2, 50, 48, 3, 2, 2, 2, 51, 53, 7, 5, 2, 2, 52, 41, 3, 2, 2, 2, 52, 42, 3, 2, 2, 2, 52, 43, 3, 2, 2, 2, 53, 9, 3, 2, 2, 2, 54, 55, 7, 10, 2, 2, 55, 56, 5, 12, 7, 2, 56, 11, 3, 2, 2, 2, 57, 58, 7, 6, 2, 2, 58, 74, 5, 12, 7, 2, 59, 60, 9, 2, 2, 2, 60, 61, 5, 12, 7, 2, 61, 62, 5, 12, 7, 2, 62, 74, 3, 2, 2, 2, 63, 64, 9, 3, 2, 2, 64, 65, 5, 12, 7, 2, 65, 66, 5, 12, 7, 2, 66, 74, 3, 2, 2, 2, 67, 68, 7, 3, 2, 2, 68, 69, 5, 12, 7, 2, 69, 70, 7, 5, 2, 2, 70, 74, 3, 2, 2, 2, 71, 74, 7, 11, 2, 2, 72, 74, 7, 10, 2, 2, 73, 57, 3, 2, 2, 2, 73, 59, 3, 2, 2, 2, 73, 63, 3, 2, 2, 2, 73, 67, 3, 2, 2, 2, 73, 71, 3, 2, 2, 2, 73, 72, 3, 2, 2, 2, 74, 13, 3, 2, 2, 2, 9, 17, 23, 32, 39, 48, 52, 73] -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLang.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | T__1=2 3 | T__2=3 4 | T__3=4 5 | T__4=5 6 | T__5=6 7 | T__6=7 8 | ID=8 9 | INT=9 10 | WS=10 11 | '('=1 12 | 'NODE'=2 13 | ')'=3 14 | '-'=4 15 | '*'=5 16 | '/'=6 17 | '+'=7 18 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangBaseListener.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Generated from NodeLang.g4 by ANTLR 4.9.2 3 | 4 | 5 | #include "NodeLangBaseListener.h" 6 | 7 | 8 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangBaseListener.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from NodeLang.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | #include "NodeLangListener.h" 9 | 10 | 11 | /** 12 | * This class provides an empty implementation of NodeLangListener, 13 | * which can be extended to create a listener which only needs to handle a subset 14 | * of the available methods. 15 | */ 16 | class NodeLangBaseListener : public NodeLangListener { 17 | public: 18 | 19 | virtual void enterProgram(NodeLangParser::ProgramContext * /*ctx*/) override { } 20 | virtual void exitProgram(NodeLangParser::ProgramContext * /*ctx*/) override { } 21 | 22 | virtual void enterNodeDecl(NodeLangParser::NodeDeclContext * /*ctx*/) override { } 23 | virtual void exitNodeDecl(NodeLangParser::NodeDeclContext * /*ctx*/) override { } 24 | 25 | virtual void enterFuncDecl(NodeLangParser::FuncDeclContext * /*ctx*/) override { } 26 | virtual void exitFuncDecl(NodeLangParser::FuncDeclContext * /*ctx*/) override { } 27 | 28 | virtual void enterNode(NodeLangParser::NodeContext * /*ctx*/) override { } 29 | virtual void exitNode(NodeLangParser::NodeContext * /*ctx*/) override { } 30 | 31 | virtual void enterVarDecl(NodeLangParser::VarDeclContext * /*ctx*/) override { } 32 | virtual void exitVarDecl(NodeLangParser::VarDeclContext * /*ctx*/) override { } 33 | 34 | virtual void enterExpr(NodeLangParser::ExprContext * /*ctx*/) override { } 35 | virtual void exitExpr(NodeLangParser::ExprContext * /*ctx*/) override { } 36 | 37 | 38 | virtual void enterEveryRule(antlr4::ParserRuleContext * /*ctx*/) override { } 39 | virtual void exitEveryRule(antlr4::ParserRuleContext * /*ctx*/) override { } 40 | virtual void visitTerminal(antlr4::tree::TerminalNode * /*node*/) override { } 41 | virtual void visitErrorNode(antlr4::tree::ErrorNode * /*node*/) override { } 42 | 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangBaseVisitor.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Generated from NodeLang.g4 by ANTLR 4.9.2 3 | 4 | 5 | #include "NodeLangBaseVisitor.h" 6 | 7 | 8 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangBaseVisitor.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from NodeLang.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | #include "NodeLangVisitor.h" 9 | 10 | 11 | /** 12 | * This class provides an empty implementation of NodeLangVisitor, which can be 13 | * extended to create a visitor which only needs to handle a subset of the available methods. 14 | */ 15 | class NodeLangBaseVisitor : public NodeLangVisitor { 16 | public: 17 | 18 | virtual antlrcpp::Any visitProgram(NodeLangParser::ProgramContext *ctx) override { 19 | return visitChildren(ctx); 20 | } 21 | 22 | virtual antlrcpp::Any visitNodeDecl(NodeLangParser::NodeDeclContext *ctx) override { 23 | return visitChildren(ctx); 24 | } 25 | 26 | virtual antlrcpp::Any visitFuncDecl(NodeLangParser::FuncDeclContext *ctx) override { 27 | return visitChildren(ctx); 28 | } 29 | 30 | virtual antlrcpp::Any visitNode(NodeLangParser::NodeContext *ctx) override { 31 | return visitChildren(ctx); 32 | } 33 | 34 | virtual antlrcpp::Any visitVarDecl(NodeLangParser::VarDeclContext *ctx) override { 35 | return visitChildren(ctx); 36 | } 37 | 38 | virtual antlrcpp::Any visitExpr(NodeLangParser::ExprContext *ctx) override { 39 | return visitChildren(ctx); 40 | } 41 | 42 | 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangLexer.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from NodeLang.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | 9 | 10 | 11 | 12 | class NodeLangLexer : public antlr4::Lexer { 13 | public: 14 | enum { 15 | T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6, T__6 = 7, 16 | ID = 8, INT = 9, WS = 10 17 | }; 18 | 19 | explicit NodeLangLexer(antlr4::CharStream *input); 20 | ~NodeLangLexer(); 21 | 22 | virtual std::string getGrammarFileName() const override; 23 | virtual const std::vector& getRuleNames() const override; 24 | 25 | virtual const std::vector& getChannelNames() const override; 26 | virtual const std::vector& getModeNames() const override; 27 | virtual const std::vector& getTokenNames() const override; // deprecated, use vocabulary instead 28 | virtual antlr4::dfa::Vocabulary& getVocabulary() const override; 29 | 30 | virtual const std::vector getSerializedATN() const override; 31 | virtual const antlr4::atn::ATN& getATN() const override; 32 | 33 | private: 34 | static std::vector _decisionToDFA; 35 | static antlr4::atn::PredictionContextCache _sharedContextCache; 36 | static std::vector _ruleNames; 37 | static std::vector _tokenNames; 38 | static std::vector _channelNames; 39 | static std::vector _modeNames; 40 | 41 | static std::vector _literalNames; 42 | static std::vector _symbolicNames; 43 | static antlr4::dfa::Vocabulary _vocabulary; 44 | static antlr4::atn::ATN _atn; 45 | static std::vector _serializedATN; 46 | 47 | 48 | // Individual action functions triggered by action() above. 49 | 50 | // Individual semantic predicate functions triggered by sempred() above. 51 | 52 | struct Initializer { 53 | Initializer(); 54 | }; 55 | static Initializer _init; 56 | }; 57 | 58 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangLexer.interp: -------------------------------------------------------------------------------- 1 | token literal names: 2 | null 3 | '(' 4 | 'NODE' 5 | ')' 6 | '-' 7 | '*' 8 | '/' 9 | '+' 10 | null 11 | null 12 | null 13 | 14 | token symbolic names: 15 | null 16 | null 17 | null 18 | null 19 | null 20 | null 21 | null 22 | null 23 | ID 24 | INT 25 | WS 26 | 27 | rule names: 28 | T__0 29 | T__1 30 | T__2 31 | T__3 32 | T__4 33 | T__5 34 | T__6 35 | ID 36 | INT 37 | WS 38 | 39 | channel names: 40 | DEFAULT_TOKEN_CHANNEL 41 | HIDDEN 42 | 43 | mode names: 44 | DEFAULT_MODE 45 | 46 | atn: 47 | [3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 12, 57, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 6, 9, 42, 10, 9, 13, 9, 14, 9, 43, 3, 10, 6, 10, 47, 10, 10, 13, 10, 14, 10, 48, 3, 11, 6, 11, 52, 10, 11, 13, 11, 14, 11, 53, 3, 11, 3, 11, 2, 2, 12, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 3, 2, 5, 5, 2, 67, 92, 97, 97, 99, 124, 3, 2, 50, 59, 5, 2, 11, 12, 15, 15, 34, 34, 2, 59, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 3, 23, 3, 2, 2, 2, 5, 25, 3, 2, 2, 2, 7, 30, 3, 2, 2, 2, 9, 32, 3, 2, 2, 2, 11, 34, 3, 2, 2, 2, 13, 36, 3, 2, 2, 2, 15, 38, 3, 2, 2, 2, 17, 41, 3, 2, 2, 2, 19, 46, 3, 2, 2, 2, 21, 51, 3, 2, 2, 2, 23, 24, 7, 42, 2, 2, 24, 4, 3, 2, 2, 2, 25, 26, 7, 80, 2, 2, 26, 27, 7, 81, 2, 2, 27, 28, 7, 70, 2, 2, 28, 29, 7, 71, 2, 2, 29, 6, 3, 2, 2, 2, 30, 31, 7, 43, 2, 2, 31, 8, 3, 2, 2, 2, 32, 33, 7, 47, 2, 2, 33, 10, 3, 2, 2, 2, 34, 35, 7, 44, 2, 2, 35, 12, 3, 2, 2, 2, 36, 37, 7, 49, 2, 2, 37, 14, 3, 2, 2, 2, 38, 39, 7, 45, 2, 2, 39, 16, 3, 2, 2, 2, 40, 42, 9, 2, 2, 2, 41, 40, 3, 2, 2, 2, 42, 43, 3, 2, 2, 2, 43, 41, 3, 2, 2, 2, 43, 44, 3, 2, 2, 2, 44, 18, 3, 2, 2, 2, 45, 47, 9, 3, 2, 2, 46, 45, 3, 2, 2, 2, 47, 48, 3, 2, 2, 2, 48, 46, 3, 2, 2, 2, 48, 49, 3, 2, 2, 2, 49, 20, 3, 2, 2, 2, 50, 52, 9, 4, 2, 2, 51, 50, 3, 2, 2, 2, 52, 53, 3, 2, 2, 2, 53, 51, 3, 2, 2, 2, 53, 54, 3, 2, 2, 2, 54, 55, 3, 2, 2, 2, 55, 56, 8, 11, 2, 2, 56, 22, 3, 2, 2, 2, 6, 2, 43, 48, 53, 3, 8, 2, 2] -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangLexer.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | T__1=2 3 | T__2=3 4 | T__3=4 5 | T__4=5 6 | T__5=6 7 | T__6=7 8 | ID=8 9 | INT=9 10 | WS=10 11 | '('=1 12 | 'NODE'=2 13 | ')'=3 14 | '-'=4 15 | '*'=5 16 | '/'=6 17 | '+'=7 18 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangListener.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Generated from NodeLang.g4 by ANTLR 4.9.2 3 | 4 | 5 | #include "NodeLangListener.h" 6 | 7 | 8 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangListener.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from NodeLang.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | #include "NodeLangParser.h" 9 | 10 | 11 | /** 12 | * This interface defines an abstract listener for a parse tree produced by NodeLangParser. 13 | */ 14 | class NodeLangListener : public antlr4::tree::ParseTreeListener { 15 | public: 16 | 17 | virtual void enterProgram(NodeLangParser::ProgramContext *ctx) = 0; 18 | virtual void exitProgram(NodeLangParser::ProgramContext *ctx) = 0; 19 | 20 | virtual void enterNodeDecl(NodeLangParser::NodeDeclContext *ctx) = 0; 21 | virtual void exitNodeDecl(NodeLangParser::NodeDeclContext *ctx) = 0; 22 | 23 | virtual void enterFuncDecl(NodeLangParser::FuncDeclContext *ctx) = 0; 24 | virtual void exitFuncDecl(NodeLangParser::FuncDeclContext *ctx) = 0; 25 | 26 | virtual void enterNode(NodeLangParser::NodeContext *ctx) = 0; 27 | virtual void exitNode(NodeLangParser::NodeContext *ctx) = 0; 28 | 29 | virtual void enterVarDecl(NodeLangParser::VarDeclContext *ctx) = 0; 30 | virtual void exitVarDecl(NodeLangParser::VarDeclContext *ctx) = 0; 31 | 32 | virtual void enterExpr(NodeLangParser::ExprContext *ctx) = 0; 33 | virtual void exitExpr(NodeLangParser::ExprContext *ctx) = 0; 34 | 35 | 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangVisitor.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Generated from NodeLang.g4 by ANTLR 4.9.2 3 | 4 | 5 | #include "NodeLangVisitor.h" 6 | 7 | 8 | -------------------------------------------------------------------------------- /ANTLR/Frontend/NodeLangVisitor.h: -------------------------------------------------------------------------------- 1 | 2 | // Generated from NodeLang.g4 by ANTLR 4.9.2 3 | 4 | #pragma once 5 | 6 | 7 | #include "antlr4-runtime.h" 8 | #include "NodeLangParser.h" 9 | 10 | 11 | 12 | /** 13 | * This class defines an abstract visitor for a parse tree 14 | * produced by NodeLangParser. 15 | */ 16 | class NodeLangVisitor : public antlr4::tree::AbstractParseTreeVisitor { 17 | public: 18 | 19 | /** 20 | * Visit parse trees produced by NodeLangParser. 21 | */ 22 | virtual antlrcpp::Any visitProgram(NodeLangParser::ProgramContext *context) = 0; 23 | 24 | virtual antlrcpp::Any visitNodeDecl(NodeLangParser::NodeDeclContext *context) = 0; 25 | 26 | virtual antlrcpp::Any visitFuncDecl(NodeLangParser::FuncDeclContext *context) = 0; 27 | 28 | virtual antlrcpp::Any visitNode(NodeLangParser::NodeContext *context) = 0; 29 | 30 | virtual antlrcpp::Any visitVarDecl(NodeLangParser::VarDeclContext *context) = 0; 31 | 32 | virtual antlrcpp::Any visitExpr(NodeLangParser::ExprContext *context) = 0; 33 | 34 | 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /ANTLR/Frontend/app.nl: -------------------------------------------------------------------------------- 1 | (NODE alfa 16777216) 2 | (NODE color (x y step) 3 | (- (* step (*x y)) alfa) 4 | ) 5 | (NODE app () 6 | (NODE steps 42) 7 | (LOOP step 0 steps 8 | (LOOP y 0 Y_SIZE 9 | (LOOP x 0 X_SIZE 10 | (PUT_PIXEL x y (color x y step)) 11 | ) 12 | ) 13 | (FLUSH) 14 | ) 15 | ) -------------------------------------------------------------------------------- /ANTLR/Frontend/nodelang.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'top' 2 | source_filename = "top" 3 | 4 | declare void @llvm.sim.putpixel(i32, i32, i32) 5 | 6 | define i32 @PUT_PIXEL(i32 %0, i32 %1, i32 %2) { 7 | entry: 8 | call void @llvm.sim.putpixel(i32 %0, i32 %1, i32 %2) 9 | ret i32 0 10 | } 11 | 12 | declare void @llvm.sim.flush() 13 | 14 | define i32 @FLUSH() { 15 | entry: 16 | call void @llvm.sim.flush() 17 | ret i32 0 18 | } 19 | 20 | define i32 @color(i32 %0, i32 %1, i32 %2) { 21 | entry: 22 | %3 = mul i32 %0, %1 23 | %4 = mul i32 %2, %3 24 | %5 = sub i32 %4, 16777216 25 | ret i32 %5 26 | } 27 | 28 | define i32 @app() { 29 | entry: 30 | br label %0 31 | 32 | 0: ; preds = %9, %entry 33 | %1 = phi i32 [ 0, %entry ], [ %11, %9 ] 34 | %2 = icmp eq i32 %1, 42 35 | br i1 %2, label %4, label %3 36 | 37 | 3: ; preds = %0 38 | br label %5 39 | 40 | 4: ; preds = %0 41 | ret i32 %1 42 | 43 | 5: ; preds = %19, %3 44 | %6 = phi i32 [ 0, %3 ], [ %20, %19 ] 45 | %7 = icmp eq i32 %6, 256 46 | br i1 %7, label %9, label %8 47 | 48 | 8: ; preds = %5 49 | br label %12 50 | 51 | 9: ; preds = %5 52 | %10 = call i32 @FLUSH() 53 | %11 = add i32 %1, 1 54 | br label %0 55 | 56 | 12: ; preds = %15, %8 57 | %13 = phi i32 [ 0, %8 ], [ %18, %15 ] 58 | %14 = icmp eq i32 %13, 512 59 | br i1 %14, label %19, label %15 60 | 61 | 15: ; preds = %12 62 | %16 = call i32 @color(i32 %13, i32 %6, i32 %1) 63 | %17 = call i32 @PUT_PIXEL(i32 %13, i32 %6, i32 %16) 64 | %18 = add i32 %13, 1 65 | br label %12 66 | 67 | 19: ; preds = %12 68 | %20 = add i32 %6, 1 69 | br label %5 70 | } 71 | -------------------------------------------------------------------------------- /ANTLR/Frontend/nodelang.opt.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'nodelang.ll' 2 | source_filename = "top" 3 | 4 | declare void @llvm.sim.putpixel(i32, i32, i32) 5 | 6 | define noundef i32 @PUT_PIXEL(i32 %0, i32 %1, i32 %2) local_unnamed_addr { 7 | entry: 8 | tail call void @llvm.sim.putpixel(i32 %0, i32 %1, i32 %2) 9 | ret i32 0 10 | } 11 | 12 | declare void @llvm.sim.flush() 13 | 14 | define noundef i32 @FLUSH() local_unnamed_addr { 15 | entry: 16 | tail call void @llvm.sim.flush() 17 | ret i32 0 18 | } 19 | 20 | ; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 21 | define i32 @color(i32 %0, i32 %1, i32 %2) local_unnamed_addr #0 { 22 | entry: 23 | %3 = mul i32 %1, %0 24 | %4 = mul i32 %3, %2 25 | %5 = add i32 %4, -16777216 26 | ret i32 %5 27 | } 28 | 29 | define noundef i32 @app() local_unnamed_addr { 30 | entry: 31 | br label %.preheader2 32 | 33 | .preheader2: ; preds = %entry, %4 34 | %0 = phi i32 [ 0, %entry ], [ %5, %4 ] 35 | br label %.preheader 36 | 37 | 1: ; preds = %4 38 | ret i32 42 39 | 40 | .preheader: ; preds = %.preheader2, %13 41 | %2 = phi i32 [ 0, %.preheader2 ], [ %14, %13 ] 42 | %3 = mul nuw nsw i32 %2, %0 43 | br label %7 44 | 45 | 4: ; preds = %13 46 | tail call void @llvm.sim.flush() 47 | %5 = add nuw nsw i32 %0, 1 48 | %6 = icmp eq i32 %5, 42 49 | br i1 %6, label %1, label %.preheader2 50 | 51 | 7: ; preds = %.preheader, %7 52 | %8 = phi i32 [ 0, %.preheader ], [ %11, %7 ] 53 | %9 = mul nuw nsw i32 %3, %8 54 | %10 = add nuw nsw i32 %9, -16777216 55 | tail call void @llvm.sim.putpixel(i32 %8, i32 %2, i32 %10) 56 | %11 = add nuw nsw i32 %8, 1 57 | %12 = icmp eq i32 %11, 512 58 | br i1 %12, label %13, label %7 59 | 60 | 13: ; preds = %7 61 | %14 = add nuw nsw i32 %2, 1 62 | %15 = icmp eq i32 %14, 256 63 | br i1 %15, label %4, label %.preheader 64 | } 65 | 66 | attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 67 | -------------------------------------------------------------------------------- /ANTLR/Frontend/nodelang.opt.s: -------------------------------------------------------------------------------- 1 | .file "top" 2 | .text 3 | .globl PUT_PIXEL ; -- Begin function PUT_PIXEL 4 | .type PUT_PIXEL,@function 5 | PUT_PIXEL: ; @PUT_PIXEL 6 | ; %bb.0: ; %entry 7 | PUTPIXEL r9 r10 r11 8 | MOVli r9 0 9 | BR r0 10 | .Lfunc_end0: 11 | .size PUT_PIXEL, .Lfunc_end0-PUT_PIXEL 12 | ; -- End function 13 | .globl FLUSH ; -- Begin function FLUSH 14 | .type FLUSH,@function 15 | FLUSH: ; @FLUSH 16 | ; %bb.0: ; %entry 17 | FLUSH 18 | MOVli r9 0 19 | BR r0 20 | .Lfunc_end1: 21 | .size FLUSH, .Lfunc_end1-FLUSH 22 | ; -- End function 23 | .globl color ; -- Begin function color 24 | .type color,@function 25 | color: ; @color 26 | ; %bb.0: ; %entry 27 | MUL r2 r10 r9 28 | MUL r2 r2 r11 29 | MOVhi r4 65280 30 | ADD r9 r2 r4 31 | BR r0 32 | .Lfunc_end2: 33 | .size color, .Lfunc_end2-color 34 | ; -- End function 35 | .globl app ; -- Begin function app 36 | .type app,@function 37 | app: ; @app 38 | ; %bb.0: ; %entry 39 | MOVli r2 0 40 | .LBB3_1: ; %.preheader2 41 | ; =>This Loop Header: Depth=1 42 | ; Child Loop BB3_3 Depth 2 43 | ; Child Loop BB3_5 Depth 3 44 | MOVli r4 0 45 | MOVli r9 0 46 | B .LBB3_3 47 | .LBB3_3: ; %.preheader 48 | ; Parent Loop BB3_1 Depth=1 49 | ; => This Loop Header: Depth=2 50 | ; Child Loop BB3_5 Depth 3 51 | MOVli r10 0 52 | MOVhi r11 65280 53 | B .LBB3_5 54 | .LBB3_5: ; Parent Loop BB3_1 Depth=1 55 | ; Parent Loop BB3_3 Depth=2 56 | ; => This Inner Loop Header: Depth=3 57 | PUTPIXEL r10 r9 r11 58 | INC_NEi r12 r10 512 59 | ADD r11 r11 r4 60 | BR_COND r12 .LBB3_5 61 | B .LBB3_6 62 | .LBB3_6: ; in Loop: Header=BB3_3 Depth=2 63 | INC_EQi r10 r9 256 64 | ADD r4 r4 r2 65 | BR_COND r10 .LBB3_4 66 | B .LBB3_3 67 | .LBB3_4: ; in Loop: Header=BB3_1 Depth=1 68 | INC_EQi r4 r2 42 69 | FLUSH 70 | BR_COND r4 .LBB3_2 71 | B .LBB3_1 72 | .LBB3_2: 73 | MOVli r9 42 74 | BR r0 75 | .Lfunc_end3: 76 | .size app, .Lfunc_end3-app 77 | ; -- End function 78 | .section ".note.GNU-stack","",@progbits 79 | -------------------------------------------------------------------------------- /ANTLR/Frontend/test.nl: -------------------------------------------------------------------------------- 1 | (NODE alfa 16777216) 2 | 3 | (NODE color (x y step) 4 | (- (* step (*x y)) alfa) 5 | ) 6 | 7 | (NODE loop_test () 8 | (LOOP i 0 10 9 | ) 10 | ) 11 | 12 | (NODE call_loop_test () 13 | (LOOP i 0 10 14 | (loop_test) 15 | ) 16 | ) 17 | 18 | (NODE app () 19 | (PUT_PIXEL (/ X_SIZE 2) (/ Y_SIZE 2) -1) 20 | (FLUSH) 21 | ) -------------------------------------------------------------------------------- /ANTLR/README.md: -------------------------------------------------------------------------------- 1 | # ANTLR + LLVM Examples 2 | 3 | ## Prerequsites 4 | ``` 5 | sudo apt install antlr4 6 | sudo apt install libantlr4-runtime-dev 7 | ``` 8 | 9 | ## Examples 10 | 1) Simple Expression 11 | > 1+2*{3-4}-5/-1 12 | ``` 13 | cd Expression 14 | antlr4 -Dlanguage=Cpp Expression.g4 -visitor 15 | clang++ *.cpp -I /usr/include/antlr4-runtime/ -lantlr4-runtime $(llvm-config --cppflags --ldflags --libs) 16 | ./a.out expr.txt 17 | ``` 18 | 2) NodeLang 19 | ``` 20 | (NODE alfa 16777216) 21 | (NODE color (x y step) 22 | (- (* step (*x y)) alfa) 23 | ) 24 | (NODE app () 25 | (NODE step_size 42) 26 | (LOOP step 0 step_size 27 | (LOOP y 0 SIM_Y_SIZE 28 | (LOOP x 0 SIM_X_SIZE 29 | (PUT_PIXEL x y (color x y step)) 30 | ) 31 | ) 32 | (FLUSH) 33 | ) 34 | ) 35 | ``` 36 | ``` 37 | cd Frontend 38 | antlr4 -Dlanguage=Cpp NodeLang.g4 -visitor 39 | clang++ *.cpp -I /usr/include/antlr4-runtime/ -lantlr4-runtime $(llvm-config --cppflags --ldflags --libs) ../../SDL/sim.c -lSDL2 40 | ``` 41 | Interpretation: 42 | ``` 43 | ./a.out test.nl 44 | ./a.out app.nl 45 | ``` 46 | Compilation: 47 | ``` 48 | ./a.out test.nl test.ll 49 | opt test.ll -O2 -o test.opt.ll -S 50 | ../../../llvm-add-backend/build/bin/llc test.opt.ll -march sim 51 | ./a.out app.nl app.ll 52 | opt app.ll -O2 -o app.opt.ll -S 53 | ../../../llvm-add-backend/build/bin/llc app.opt.ll -march sim 54 | ``` 55 | 56 | ## Links 57 | [ANTLR](https://github.com/antlr/antlr4) 58 | -------------------------------------------------------------------------------- /Flex_Bison/0.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | int chars = 0; 3 | int words = 0; 4 | int lines = 0; 5 | int yywrap(void) { return 1; } 6 | %} 7 | 8 | %% 9 | 10 | [^ \t\n\r\f\v]+ { words++; 11 | chars += strlen(yytext); } 12 | 13 | \n { chars++; 14 | lines++; } 15 | 16 | . { chars++; } 17 | 18 | %% 19 | 20 | int main(int argc, char **argv) 21 | { 22 | yylex(); 23 | printf("Lines:%d Words:%d Chars:%d\n", lines, words, chars); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /Flex_Bison/0.sh: -------------------------------------------------------------------------------- 1 | flex 0.lex 2 | clang lex.yy.c || exit 1 3 | rm lex.yy.c 4 | printf "Hello ,\nworld!\n" 5 | printf "Hello ,\nworld!\n" | ./a.out 6 | -------------------------------------------------------------------------------- /Flex_Bison/1.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | int res = 0; 3 | char op = '+'; 4 | int unmin = 0; 5 | %} 6 | 7 | %option main 8 | %option yylineno 9 | 10 | %% 11 | 12 | [/][/].*\n ; // comment 13 | [1-9][0-9]* { int opnd = atoi(yytext); 14 | if (unmin) opnd = -opnd; unmin=0; 15 | switch(op) { 16 | default : 17 | printf("Unexpected operator in line %d\n", yylineno); 18 | exit(1); 19 | case '+': res += opnd; break; 20 | case '-': res -= opnd; break; 21 | case '*': res *= opnd; break; 22 | case '/': res /= opnd; break; 23 | } 24 | op = 0; 25 | } 26 | [-+*/] { if (op) { 27 | if (*yytext=='-') 28 | unmin = unmin ^ 1; 29 | else { 30 | printf("Unexpected operator in line %d\n", yylineno); 31 | exit(1); 32 | } 33 | } else 34 | op = *yytext; 35 | } 36 | [;] { if (op) { 37 | printf("Unexpected semicolon in line %d\n", yylineno); 38 | exit(1); 39 | } 40 | printf("=%d\n", res); 41 | res = 0; 42 | op = '+'; 43 | } 44 | [ \t\r\n] ; // whitespace 45 | . { printf("Syntax error in line %d\n", yylineno); exit(1); } 46 | %% 47 | -------------------------------------------------------------------------------- /Flex_Bison/1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | flex 1.lex || exit 1 6 | clang lex.yy.c || exit 1 7 | rm lex.yy.c 8 | printf "10---20--15; // comment\n--42;\n" 9 | printf "10---20--15; // comment\n--42;\n" | ./a.out 10 | -------------------------------------------------------------------------------- /Flex_Bison/10.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #define YYSTYPE void* 3 | #include "10.tab.h" 4 | extern "C" int yylex(); 5 | %} 6 | 7 | %option yylineno 8 | %option noyywrap 9 | 10 | %% 11 | 12 | [/][/].*\n ; // comment 13 | [0-9]* { 14 | printf("IntLiteral %s\n", yytext); 15 | yylval = strdup(yytext); 16 | return IntLiteral; 17 | } 18 | "func" { printf("FunctionBegin\n"); return FunctionBegin; } 19 | "end" { printf("FunctionEnd\n"); return FunctionEnd; } 20 | "call" { printf("CallFunction\n"); return CallFunction; } 21 | "if" { printf("IfToken\n"); return IfToken; } 22 | "goto" { printf("GotoToken\n"); return GotoToken; } 23 | [A-Za-z_]+ { // identifier or array 24 | printf("Identifier %s\n", yytext); 25 | yylval = strdup(yytext); 26 | return Identifier; 27 | } 28 | [ \t\r\n] ; // whitespace 29 | . { return *yytext; } 30 | 31 | %% -------------------------------------------------------------------------------- /Flex_Bison/10.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | lex 10.lex || exit 1 6 | bison -d 10.y || exit 1 7 | clang++ lex.yy.c 10.tab.c $(llvm-config --cppflags --ldflags --libs) || exit 1 8 | rm 10.tab.c 10.tab.h lex.yy.c 9 | cat 10.txt 10 | cat 10.txt | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/10.txt: -------------------------------------------------------------------------------- 1 | i = 0; 2 | 3 | func main 4 | i = 1; 5 | goto loop; 6 | loop: 7 | if i < 20 | iteration | loop_end; 8 | iteration: 9 | i = i + 1; 10 | goto loop; 11 | loop_end: 12 | end 13 | -------------------------------------------------------------------------------- /Flex_Bison/11.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #define YYSTYPE void* 3 | #include "11.tab.h" 4 | extern "C" int yylex(); 5 | %} 6 | 7 | %option yylineno 8 | %option noyywrap 9 | 10 | %% 11 | 12 | [/][/].*\n ; // comment 13 | [0-9]* { 14 | printf("IntLiteral %s\n", yytext); 15 | yylval = strdup(yytext); 16 | return IntLiteral; 17 | } 18 | "func" { printf("FunctionBegin\n"); return FunctionBegin; } 19 | "end" { printf("FunctionEnd\n"); return FunctionEnd; } 20 | "call" { printf("CallFunction\n"); return CallFunction; } 21 | "if" { printf("IfToken\n"); return IfToken; } 22 | "goto" { printf("GotoToken\n"); return GotoToken; } 23 | "PUT" { printf("PutToken\n"); return PutToken; } 24 | "FLUSH" { printf("FlushToken\n"); return FlushToken; } 25 | [A-Za-z_]+ { // identifier or array 26 | printf("Identifier %s\n", yytext); 27 | yylval = strdup(yytext); 28 | return Identifier; 29 | } 30 | [ \t\r\n] ; // whitespace 31 | . { return *yytext; } 32 | 33 | %% -------------------------------------------------------------------------------- /Flex_Bison/11.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | bison -d 11.y || exit 1 6 | lex 11.lex || exit 1 7 | clang++ lex.yy.c 11.tab.c ../SDL/sim.c $(llvm-config --cppflags --ldflags --libs) -lSDL2 || exit 1 8 | rm 11.tab.c 11.tab.h lex.yy.c 9 | cat 11.txt 10 | cat 11.txt | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/11.txt: -------------------------------------------------------------------------------- 1 | step = 0; 2 | y = 0; 3 | x = 0; 4 | 5 | func main 6 | step = 0; 7 | goto loopStep; 8 | 9 | loopStep: 10 | y = 0; 11 | if step < 1000 | loopY | loopStep_end; 12 | loopY: 13 | x = 0; 14 | if y < 256 | loopX | loopY_end; 15 | loopX: 16 | if x < 512 | iterX | loopX_end; 17 | iterX: 18 | PUT(x, y, x*y*step - 16777216); 19 | x = x + 1; 20 | goto loopX; 21 | loopX_end: 22 | y = y + 1; 23 | goto loopY; 24 | loopY_end: 25 | step = step + 1; 26 | FLUSH; 27 | goto loopStep; 28 | loopStep_end: 29 | end 30 | -------------------------------------------------------------------------------- /Flex_Bison/12.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #define YYSTYPE void* 3 | #include "12.tab.h" 4 | extern "C" int yylex(); 5 | %} 6 | 7 | %option yylineno 8 | %option noyywrap 9 | 10 | %% 11 | 12 | [/][/].*\n ; // comment 13 | [0-9]* { 14 | yylval = strdup(yytext); 15 | return IntLiteral; 16 | } 17 | "func" { return FunctionBegin; } 18 | "end" { return FunctionEnd; } 19 | "call" { return CallFunction; } 20 | "if" { return IfToken; } 21 | "goto" { return GotoToken; } 22 | "PUT" { return PutToken; } 23 | "FLUSH" { return FlushToken; } 24 | [A-Za-z_]+ { // identifier or array 25 | yylval = strdup(yytext); 26 | return Identifier; 27 | } 28 | [ \t\r\n] ; // whitespace 29 | . { return *yytext; } 30 | 31 | %% -------------------------------------------------------------------------------- /Flex_Bison/12.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | bison -d 12.y || exit 1 6 | lex 12.lex || exit 1 7 | clang++ lex.yy.c 12.tab.c $(llvm-config --cppflags --ldflags --libs) ../SDL/sim.c -lSDL2 || exit 1 8 | rm 12.tab.c 12.tab.h lex.yy.c 9 | cat 12.txt 10 | cat 12.txt | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/12.txt: -------------------------------------------------------------------------------- 1 | func main 2 | step = 0; 3 | loopStep: 4 | y = 0; 5 | if step != 1000 | loopY | loopStep_end; 6 | loopY: 7 | x = 0; 8 | if y != 256 | loopX | loopY_end; 9 | loopX: 10 | if x != 512 | iterX | loopX_end; 11 | iterX: 12 | PUT(x, y, x*y*step - 16777216); 13 | x = x + 1; 14 | goto loopX; 15 | loopX_end: 16 | y = y + 1; 17 | goto loopY; 18 | loopY_end: 19 | step = step + 1; 20 | FLUSH; 21 | goto loopStep; 22 | loopStep_end: 23 | end 24 | -------------------------------------------------------------------------------- /Flex_Bison/2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | bison 2.y -v || exit 1 6 | clang 2.tab.c || exit 1 7 | rm 2.tab.c 2.output 8 | echo "22+3*4-5;" 9 | echo "22+3*4-5;" | ./a.out 10 | -------------------------------------------------------------------------------- /Flex_Bison/2.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | int yylex() { return getc(stdin); } 4 | void yyerror(char *s) { 5 | fprintf (stderr, "%s\n", s); 6 | } 7 | %} 8 | 9 | %% 10 | 11 | EVALUATE: EXPR ';' { printf("%d\n", $$); YYACCEPT; }; 12 | 13 | EXPR: TERM 14 | | EXPR '+' TERM { $$ = $1 + $3; } 15 | | EXPR '-' TERM { $$ = $1 - $3; } 16 | ; 17 | 18 | TERM: NUM 19 | | TERM '*' NUM { $$ = $1 * $3; } 20 | | TERM '/' NUM { $$ = $1 / $3; } 21 | ; 22 | 23 | NUM: DIGIT 24 | | NUM DIGIT { $$ = $1*10+$2; } 25 | ; 26 | 27 | DIGIT: '0' { $$=0; } | '1' { $$=1; } | '2' { $$=2; } | '3' { $$=3; } 28 | | '4' { $$=4; } | '5' { $$=5; } | '6' { $$=6; } | '7' { $$=7; } 29 | | '8' { $$=8; } | '9' { $$=9; } 30 | ; 31 | 32 | %% 33 | 34 | int main(int argc, char **argv) 35 | { 36 | yyparse(); 37 | } 38 | -------------------------------------------------------------------------------- /Flex_Bison/3.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "3.tab.h" 3 | %} 4 | 5 | %% 6 | 7 | [/][/].*\n ; // comment 8 | [0-9]+ { yylval = atoi(yytext); 9 | return NUM; 10 | } 11 | [ \t\r\n] ; // whitespace 12 | . { return *yytext; } 13 | 14 | %% 15 | 16 | -------------------------------------------------------------------------------- /Flex_Bison/3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | bison 3.y -d || exit 1 6 | flex 3.lex || exit 1 7 | clang lex.yy.c 3.tab.c || exit 1 8 | rm 3.tab.c 3.tab.h lex.yy.c 9 | echo "1 - 2*3/6*7 - 8 + 9;" 10 | echo "1 - 2*3/6*7 - 8 + 9;" | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/3.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | int yyparse(); 4 | int yylex(); 5 | void yyerror(char *s) { 6 | fprintf (stderr, "%s\n", s); 7 | } 8 | int yywrap(void) { return 1; } 9 | %} 10 | 11 | %token NUM 12 | 13 | %% 14 | 15 | EVALUATE: EXPR ';' { printf("=%d\n", $$); YYACCEPT; } ; 16 | 17 | EXPR: TERM 18 | | EXPR '+' TERM { $$ = $1 + $3; } 19 | | EXPR '-' TERM { $$ = $1 - $3; } 20 | ; 21 | 22 | TERM: NUM 23 | | TERM '*' NUM { $$ = $1 * $3; } 24 | | TERM '/' NUM { $$ = $1 / $3; } 25 | ; 26 | 27 | %% 28 | 29 | int main(int argc, char **argv) 30 | { 31 | yyparse(); 32 | } 33 | -------------------------------------------------------------------------------- /Flex_Bison/4.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "4.tab.h" 3 | %} 4 | 5 | %% 6 | 7 | "+" { return ADD; } 8 | "-" { return SUB; } 9 | "*" { return MUL; } 10 | "/" { return DIV; } 11 | [0-9]+ { yylval = atoi(yytext); return NUM; } 12 | \n { return EOL; } 13 | [ \t] { /* ignore whitespace */ } 14 | . { printf("Mystery character %c\n", *yytext); } 15 | 16 | %% 17 | 18 | -------------------------------------------------------------------------------- /Flex_Bison/4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | bison 4.y -d || exit 1 6 | flex 4.lex || exit 1 7 | clang lex.yy.c 4.tab.c || exit 1 8 | rm 4.tab.c 4.tab.h lex.yy.c 9 | echo "1 - 2*3/6*7 - 8 + 9" 10 | echo "1 - 2*3/6*7 - 8 + 9" | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/4.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | int yyparse(); 4 | int yylex(); 5 | void yyerror(char *s) { 6 | fprintf (stderr, "%s\n", s); 7 | } 8 | int yywrap(void) { return 1; } 9 | %} 10 | 11 | %token NUM 12 | %token ADD SUB MUL DIV EOL 13 | 14 | %% 15 | 16 | EVALUATE: EXPR EOL { printf("=%d\n", $$); YYACCEPT; } ; 17 | 18 | EXPR: TERM 19 | | EXPR ADD TERM { $$ = $1 + $3; } 20 | | EXPR SUB TERM { $$ = $1 - $3; } 21 | ; 22 | 23 | TERM: NUM 24 | | TERM MUL NUM { $$ = $1 * $3; } 25 | | TERM DIV NUM { $$ = $1 / $3; } 26 | ; 27 | 28 | %% 29 | 30 | int main(int argc, char **argv) 31 | { 32 | yyparse(); 33 | } 34 | -------------------------------------------------------------------------------- /Flex_Bison/5.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #define YYSTYPE llvm::Value* 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "5.tab.h" 5 | extern "C" int yylex(); 6 | extern llvm::IRBuilder<>* builder; 7 | %} 8 | 9 | %option yylineno 10 | %option noyywrap 11 | 12 | %% 13 | 14 | [/][/].*\n ; // comment 15 | [0-9]+ { 16 | yylval = builder->getInt32(atoi(yytext)); 17 | return NUM; 18 | } 19 | [ \t\r\n] ; // whitespace 20 | . { return *yytext; } 21 | 22 | %% -------------------------------------------------------------------------------- /Flex_Bison/5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | bison -d 5.y || exit 1 6 | lex 5.lex || exit 1 7 | clang++ lex.yy.c 5.tab.c $(llvm-config --cppflags --ldflags --libs) || exit 1 8 | rm 5.tab.c 5.tab.h lex.yy.c 9 | echo "22+ 3/4 -5;" 10 | echo "22+ 3/4 -5;" | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/5.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include "llvm/Support/raw_ostream.h" 4 | #include "llvm/IR/LLVMContext.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/IRBuilder.h" 7 | #include "llvm/IR/Verifier.h" 8 | using namespace llvm; 9 | 10 | #define YYSTYPE Value* 11 | extern "C" { 12 | int yyparse(); 13 | int yylex(); 14 | void yyerror(char *s) { 15 | std::cerr << s << "\n"; 16 | } 17 | int yywrap(void){return 1;} 18 | } 19 | IRBuilder<>* builder; 20 | 21 | int main(int argc, char **argv) 22 | { 23 | LLVMContext context; 24 | // ; ModuleID = 'top' 25 | // source_filename = "top" 26 | Module* module = new Module("top", context); 27 | builder = new IRBuilder<> (context); 28 | 29 | // declare void @main() 30 | FunctionType *funcType = 31 | FunctionType::get(builder->getInt32Ty(), false); 32 | Function *mainFunc = 33 | Function::Create(funcType, Function::ExternalLinkage, "main", module); 34 | // entry: 35 | BasicBlock *entryBB = BasicBlock::Create(context, "entry", mainFunc); 36 | builder->SetInsertPoint(entryBB); 37 | 38 | yyparse(); 39 | 40 | outs() << "[LLVM IR]:\n"; 41 | module->print(outs(), nullptr); 42 | outs() << "\n"; 43 | bool verif = verifyFunction(*mainFunc, &outs()); 44 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 45 | 46 | return 0; 47 | } 48 | %} 49 | 50 | %token NUM 51 | 52 | %% 53 | 54 | EVALUATE: EXPR ';' { builder->CreateRet($$); YYACCEPT; }; 55 | 56 | EXPR: TERM 57 | | EXPR '+' TERM { $$ = builder->CreateAdd($1, $3); } 58 | | EXPR '-' TERM { $$ = builder->CreateSub($1, $3); } 59 | ; 60 | 61 | TERM: NUM 62 | | TERM '*' NUM { $$ = builder->CreateMul($1, $3); } 63 | | TERM '/' NUM { $$ = builder->CreateUDiv($1, $3); } 64 | ; 65 | 66 | %% -------------------------------------------------------------------------------- /Flex_Bison/6.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #define YYSTYPE llvm::Value* 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "6.tab.h" 5 | extern "C" int yylex(); 6 | extern llvm::IRBuilder<>* builder; 7 | %} 8 | 9 | %option yylineno 10 | %option noyywrap 11 | 12 | %% 13 | 14 | [/][/].*\n ; // comment 15 | [0-9]+ { 16 | yylval = builder->getInt32(atoi(yytext)); 17 | return NUM; 18 | } 19 | [ \t\r\n] ; // whitespace 20 | . { return *yytext; } 21 | 22 | %% -------------------------------------------------------------------------------- /Flex_Bison/6.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | lex 6.lex || exit 1 6 | bison -d 6.y || exit 1 7 | clang++ lex.yy.c 6.tab.c $(llvm-config --cppflags --ldflags --libs) || exit 1 8 | rm 6.tab.c 6.tab.h lex.yy.c 9 | echo "Example for lex6: 22+ 3*5*? -5;" 10 | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/6.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include "llvm/Support/raw_ostream.h" 4 | #include "llvm/IR/LLVMContext.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/IRBuilder.h" 7 | #include "llvm/IR/Verifier.h" 8 | #include "llvm/ExecutionEngine/ExecutionEngine.h" 9 | #include "llvm/ExecutionEngine/GenericValue.h" 10 | #include "llvm/Support/TargetSelect.h" 11 | using namespace llvm; 12 | 13 | #define YYSTYPE Value* 14 | extern "C" { 15 | int yyparse(); 16 | int yylex(); 17 | void yyerror(char *s) { 18 | std::cerr << s << "\n"; 19 | } 20 | int yywrap(void){return 1;} 21 | } 22 | IRBuilder<>* builder; 23 | 24 | Function *readFunc; 25 | int readVal() { 26 | std::cout << "Enter a number: "; 27 | int res = 0; 28 | std::cin >> res; 29 | return res; 30 | } 31 | 32 | int main(int argc, char **argv) 33 | { 34 | InitializeNativeTarget(); 35 | InitializeNativeTargetAsmPrinter(); 36 | 37 | LLVMContext context; 38 | // ; ModuleID = 'top' 39 | // source_filename = "top" 40 | Module* module = new Module("top", context); 41 | builder = new IRBuilder<> (context); 42 | 43 | // declare void @main() 44 | FunctionType *funcType = 45 | FunctionType::get(builder->getInt32Ty(), false); 46 | Function *mainFunc = 47 | Function::Create(funcType, Function::ExternalLinkage, "main", module); 48 | // entry: 49 | BasicBlock *entryBB = BasicBlock::Create(context, "entry", mainFunc); 50 | 51 | builder->SetInsertPoint(entryBB); 52 | 53 | readFunc = Function::Create(funcType, Function::ExternalLinkage, "readVal", module); 54 | 55 | yyparse(); 56 | 57 | outs() << "[LLVM IR]:\n"; 58 | module->print(outs(), nullptr); 59 | outs() << "\n"; 60 | bool verif = verifyFunction(*mainFunc, &outs()); 61 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 62 | 63 | // Interpreter of LLVM IR 64 | outs() << "[EE] Run\n"; 65 | ExecutionEngine *ee = EngineBuilder(std::unique_ptr(module)).create(); 66 | ee->InstallLazyFunctionCreator([=](const std::string &fnName) -> void * { 67 | if (fnName == "readVal") { return reinterpret_cast(readVal); } 68 | return nullptr; 69 | }); 70 | ee->finalizeObject(); 71 | std::vector noargs; 72 | GenericValue res = ee->runFunction(mainFunc, noargs); 73 | outs() << "[EE] Result: " << res.IntVal << "\n"; 74 | 75 | return 0; 76 | } 77 | %} 78 | 79 | %token NUM 80 | 81 | %% 82 | 83 | EVALUATE: EXPR ';' { builder->CreateRet($$); YYACCEPT; }; 84 | 85 | EXPR: TERM 86 | | EXPR '+' TERM { $$ = builder->CreateAdd($1, $3); } 87 | | EXPR '-' TERM { $$ = builder->CreateSub($1, $3); } 88 | ; 89 | 90 | TERM: VAL 91 | | TERM '*' VAL { $$ = builder->CreateMul($1, $3); } 92 | | TERM '/' VAL { $$ = builder->CreateUDiv($1, $3); } 93 | ; 94 | 95 | VAL: NUM 96 | | '?' { $$ = builder->CreateCall(readFunc); } 97 | 98 | %% -------------------------------------------------------------------------------- /Flex_Bison/7.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "llvm/IR/IRBuilder.h" 3 | #include 4 | 5 | #define YYSTYPE llvm::Value* 6 | #include "7.tab.h" 7 | extern "C" int yylex(); 8 | extern llvm::IRBuilder<>* builder; 9 | extern std::map IdentifierMap; 10 | extern llvm::Module* module; 11 | %} 12 | 13 | %option yylineno 14 | %option noyywrap 15 | 16 | %% 17 | 18 | [/][/].*\n ; // comment 19 | [0-9]+ { 20 | yylval = builder->getInt32(atoi(yytext)); 21 | return IntLiteral; 22 | } 23 | [A-Za-z_]+ { // identifier 24 | // printf("Identifier: %s\n", yytext); 25 | if (IdentifierMap.find(yytext) == IdentifierMap.end()) { 26 | module->getOrInsertGlobal(yytext, builder->getInt32Ty()); 27 | IdentifierMap.insert({yytext, module->getNamedGlobal(yytext)}); 28 | } 29 | yylval = builder->CreateConstGEP1_32(builder->getInt32Ty(), IdentifierMap[yytext], 0); 30 | return Identifier; 31 | } 32 | [ \t\r\n] ; // whitespace 33 | . { return *yytext; } 34 | 35 | %% -------------------------------------------------------------------------------- /Flex_Bison/7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | lex 7.lex || exit 1 6 | bison -d 7.y || exit 1 7 | clang++ lex.yy.c 7.tab.c $(llvm-config --cppflags --ldflags --libs) || exit 1 8 | rm 7.tab.c 7.tab.h lex.yy.c 9 | echo "x + 10*y - (0 == -x) != 0;" 10 | echo "x + 10*y - (0 == -x) != 0;" | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/7.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include "llvm/Support/raw_ostream.h" 4 | #include "llvm/IR/LLVMContext.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/IRBuilder.h" 7 | #include "llvm/IR/Verifier.h" 8 | #include "llvm/ExecutionEngine/ExecutionEngine.h" 9 | #include "llvm/ExecutionEngine/GenericValue.h" 10 | #include "llvm/Support/TargetSelect.h" 11 | using namespace llvm; 12 | 13 | #define YYSTYPE Value* 14 | extern "C" { 15 | int yyparse(); 16 | int yylex(); 17 | void yyerror(char *s) { 18 | std::cerr << s << "\n"; 19 | } 20 | int yywrap(void){return 1;} 21 | } 22 | IRBuilder<>* builder; 23 | Module* module; 24 | 25 | std::map IdentifierMap; 26 | 27 | int main(int argc, char **argv) 28 | { 29 | InitializeNativeTarget(); 30 | InitializeNativeTargetAsmPrinter(); 31 | 32 | LLVMContext context; 33 | // ; ModuleID = 'top' 34 | // source_filename = "top" 35 | module = new Module("top", context); 36 | builder = new IRBuilder<> (context); 37 | 38 | // declare void @main() 39 | FunctionType *funcType = 40 | FunctionType::get(builder->getInt32Ty(), false); 41 | Function *mainFunc = 42 | Function::Create(funcType, Function::ExternalLinkage, "main", module); 43 | // entry: 44 | BasicBlock *entryBB = BasicBlock::Create(context, "entry", mainFunc); 45 | 46 | builder->SetInsertPoint(entryBB); 47 | 48 | yyparse(); 49 | 50 | outs() << "[LLVM IR]:\n"; 51 | module->print(outs(), nullptr); 52 | outs() << "\n"; 53 | bool verif = verifyFunction(*mainFunc, &outs()); 54 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 55 | 56 | // Interpreter of LLVM IR 57 | outs() << "[EE] Run\n"; 58 | ExecutionEngine *ee = EngineBuilder(std::unique_ptr(module)).create(); 59 | for (auto& value : IdentifierMap) { 60 | ee->addGlobalMapping(value.second, new int(0)); 61 | } 62 | ee->finalizeObject(); 63 | std::vector noargs; 64 | GenericValue res = ee->runFunction(mainFunc, noargs); 65 | outs() << "[EE] Result: " << res.IntVal << "\n"; 66 | return 0; 67 | } 68 | %} 69 | 70 | %token IntLiteral 71 | %token Identifier 72 | 73 | %% 74 | 75 | Program: Expression ';' { builder->CreateRet($$); YYACCEPT; }; 76 | 77 | Expression: Simple 78 | | Expression '!''=' Simple { $$ = builder->CreateZExt(builder->CreateICmpNE($1, $4), builder->getInt32Ty()); } 79 | | Expression '=''=' Simple { $$ = builder->CreateZExt(builder->CreateICmpEQ($1, $4), builder->getInt32Ty()); } 80 | | Expression '<' Simple { $$ = builder->CreateZExt(builder->CreateICmpSLT($1, $3), builder->getInt32Ty()); } 81 | | Expression '<''=' Simple { $$ = builder->CreateZExt(builder->CreateICmpSLE($1, $4), builder->getInt32Ty()); } 82 | | Expression '>' Simple { $$ = builder->CreateZExt(builder->CreateICmpSGT($1, $3), builder->getInt32Ty()); } 83 | | Expression '>''=' Simple { $$ = builder->CreateZExt(builder->CreateICmpSGE($1, $4), builder->getInt32Ty()); } 84 | ; 85 | Simple: Summand 86 | | Simple '+' Summand { $$ = builder->CreateAdd($1, $3); } 87 | | Simple '-' Summand { $$ = builder->CreateSub($1, $3); } 88 | 89 | Summand: Factor 90 | | Summand '*' Factor { $$ = builder->CreateMul($1, $3); } 91 | | Summand '/' Factor { $$ = builder->CreateSDiv($1, $3); } 92 | | Summand '%' Factor { $$ = builder->CreateSRem($1, $3); } 93 | ; 94 | 95 | Factor: Primary { $$ = $1; } 96 | | '-' Primary { $$ = builder->CreateNeg($2); } 97 | | '(' Expression ')' { $$ =$2; } 98 | ; 99 | 100 | Primary: IntLiteral { $$ = $1; } 101 | | Value { $$ = $1; } 102 | ; 103 | 104 | Value: Identifier { $$ = builder->CreateLoad(builder->getInt32Ty(), $1); } 105 | 106 | %% -------------------------------------------------------------------------------- /Flex_Bison/8.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #define YYSTYPE void* 3 | #include "8.tab.h" 4 | extern "C" int yylex(); 5 | %} 6 | 7 | %option yylineno 8 | %option noyywrap 9 | 10 | %% 11 | 12 | [/][/].*\n ; // comment 13 | [0-9]+ { 14 | yylval = strdup(yytext); 15 | return IntLiteral; 16 | } 17 | [A-Za-z_]+ { // identifier or array 18 | yylval = strdup(yytext); 19 | return Identifier; 20 | } 21 | [ \t\r\n] ; // whitespace 22 | . { return *yytext; } 23 | 24 | %% -------------------------------------------------------------------------------- /Flex_Bison/8.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | lex 8.lex || exit 1 6 | bison -d 8.y || exit 1 7 | clang++ lex.yy.c 8.tab.c $(llvm-config --cppflags --ldflags --libs) || exit 1 8 | rm 8.tab.c 8.tab.h lex.yy.c 9 | echo "x + 10*y[3*5 + x] - (0 == -x) != 0;" 10 | echo "x + 10*y[3*5 + x] - (0 == -x) != 0;" | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/8.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include "llvm/Support/raw_ostream.h" 4 | #include "llvm/IR/LLVMContext.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/IRBuilder.h" 7 | #include "llvm/IR/Verifier.h" 8 | #include "llvm/ExecutionEngine/ExecutionEngine.h" 9 | #include "llvm/ExecutionEngine/GenericValue.h" 10 | #include "llvm/Support/TargetSelect.h" 11 | using namespace llvm; 12 | 13 | #define YYSTYPE Value* 14 | extern "C" { 15 | int yyparse(); 16 | int yylex(); 17 | void yyerror(char *s) { 18 | std::cerr << s << "\n"; 19 | } 20 | int yywrap(void){return 1;} 21 | } 22 | IRBuilder<>* builder; 23 | Module* module; 24 | 25 | std::map ValueMap; 26 | std::map ArrayMap; 27 | 28 | int main(int argc, char **argv) 29 | { 30 | InitializeNativeTarget(); 31 | InitializeNativeTargetAsmPrinter(); 32 | 33 | LLVMContext context; 34 | // ; ModuleID = 'top' 35 | // source_filename = "top" 36 | module = new Module("top", context); 37 | builder = new IRBuilder<> (context); 38 | 39 | // declare void @main() 40 | FunctionType *funcType = 41 | FunctionType::get(builder->getInt32Ty(), false); 42 | Function *mainFunc = 43 | Function::Create(funcType, Function::ExternalLinkage, "main", module); 44 | // entry: 45 | BasicBlock *entryBB = BasicBlock::Create(context, "entry", mainFunc); 46 | 47 | builder->SetInsertPoint(entryBB); 48 | 49 | yyparse(); 50 | 51 | outs() << "[LLVM IR]:\n"; 52 | module->print(outs(), nullptr); 53 | outs() << "\n"; 54 | bool verif = verifyFunction(*mainFunc, &outs()); 55 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 56 | 57 | // Interpreter of LLVM IR 58 | outs() << "[EE] Run\n"; 59 | ExecutionEngine *ee = EngineBuilder(std::unique_ptr(module)).create(); 60 | for (auto& value : ValueMap) { 61 | ee->addGlobalMapping(value.second, new int(0)); 62 | } 63 | for (auto& array : ArrayMap) { 64 | ee->addGlobalMapping(array.second, new int[100]); 65 | } 66 | ee->finalizeObject(); 67 | std::vector noargs; 68 | GenericValue res = ee->runFunction(mainFunc, noargs); 69 | outs() << "[EE] Result: " << res.IntVal << "\n"; 70 | return 0; 71 | } 72 | %} 73 | 74 | %token IntLiteral 75 | %token Identifier 76 | 77 | %% 78 | 79 | Program: Expression ';' { builder->CreateRet($$); YYACCEPT; }; 80 | 81 | Expression: Simple 82 | | Expression '!''=' Simple { $$ = builder->CreateZExt(builder->CreateICmpNE($1, $4), builder->getInt32Ty()); } 83 | | Expression '=''=' Simple { $$ = builder->CreateZExt(builder->CreateICmpEQ($1, $4), builder->getInt32Ty()); } 84 | | Expression '<' Simple { $$ = builder->CreateZExt(builder->CreateICmpSLT($1, $3), builder->getInt32Ty()); } 85 | | Expression '<''=' Simple { $$ = builder->CreateZExt(builder->CreateICmpSLE($1, $4), builder->getInt32Ty()); } 86 | | Expression '>' Simple { $$ = builder->CreateZExt(builder->CreateICmpSGT($1, $3), builder->getInt32Ty()); } 87 | | Expression '>''=' Simple { $$ = builder->CreateZExt(builder->CreateICmpSGE($1, $4), builder->getInt32Ty()); } 88 | ; 89 | Simple: Summand 90 | | Simple '+' Summand { $$ = builder->CreateAdd($1, $3); } 91 | | Simple '-' Summand { $$ = builder->CreateSub($1, $3); } 92 | 93 | Summand: Factor 94 | | Summand '*' Factor { $$ = builder->CreateMul($1, $3); } 95 | | Summand '/' Factor { $$ = builder->CreateSDiv($1, $3); } 96 | | Summand '%' Factor { $$ = builder->CreateSRem($1, $3); } 97 | ; 98 | 99 | Factor: Primary { $$ = $1; } 100 | | '-' Primary { $$ = builder->CreateNeg($2); } 101 | | '(' Expression ')' { $$ =$2; } 102 | ; 103 | 104 | Primary: IntLiteral { $$ = builder->getInt32(atoi((char*)$1)); } 105 | | Value { $$ = $1; } 106 | ; 107 | 108 | Value: Identifier { 109 | if (ValueMap.find((char*)$1) == ValueMap.end()) { 110 | module->getOrInsertGlobal((char*)$1, builder->getInt32Ty()); 111 | ValueMap.insert({(char*)$1, module->getNamedGlobal((char*)$1)}); 112 | } 113 | $$ = builder->CreateLoad(builder->getInt32Ty(), builder->CreateConstGEP1_32(builder->getInt32Ty(), ValueMap[(char*)$1], 0)); 114 | } 115 | | Identifier '[' Expression ']' { 116 | ArrayType *arrayType = ArrayType::get(builder->getInt32Ty(), 100); 117 | if (ArrayMap.find((char*)$1) == ArrayMap.end()) { 118 | module->getOrInsertGlobal((char*)$1, arrayType); 119 | ArrayMap.insert({(char*)$1, module->getNamedGlobal((char*)$1)}); 120 | } 121 | std::vector gepArgs; 122 | gepArgs.push_back(builder->getInt32(0)); 123 | gepArgs.push_back($3); 124 | $$ = builder->CreateLoad(builder->getInt32Ty(), builder->CreateGEP(arrayType, ArrayMap[(char*)$1], gepArgs)); 125 | } 126 | 127 | %% -------------------------------------------------------------------------------- /Flex_Bison/9.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #define YYSTYPE void* 3 | #include "9.tab.h" 4 | extern "C" int yylex(); 5 | %} 6 | 7 | %option yylineno 8 | %option noyywrap 9 | 10 | %% 11 | 12 | [/][/].*\n ; // comment 13 | [0-9]* { 14 | printf("IntLiteral %s\n", yytext); 15 | yylval = strdup(yytext); 16 | return IntLiteral; 17 | } 18 | "func" { printf("FunctionBegin\n"); return FunctionBegin; } 19 | [e][n][d] { printf("FunctionEnd\n"); return FunctionEnd; } 20 | [A-Za-z_]+ { // identifier or array 21 | printf("Identifier %s\n", yytext); 22 | yylval = strdup(yytext); 23 | return Identifier; 24 | } 25 | [ \t\r\n] ; // whitespace 26 | . { return *yytext; } 27 | 28 | %% -------------------------------------------------------------------------------- /Flex_Bison/9.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | lex 9.lex || exit 1 6 | bison -d 9.y || exit 1 7 | clang++ lex.yy.c 9.tab.c $(llvm-config --cppflags --ldflags --libs) || exit 1 8 | rm 9.tab.c 9.tab.h lex.yy.c 9 | cat 9.txt 10 | cat 9.txt | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/9.txt: -------------------------------------------------------------------------------- 1 | x = 3; 2 | y[20] = 10; 3 | 4 | func main 5 | y[2 + x] = -7; 6 | x = x + 3; 7 | y[2*x] = 3; 8 | end -------------------------------------------------------------------------------- /Flex_Bison/FrontEnd.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #define YYSTYPE void* 3 | #include "FrontEnd.tab.h" 4 | extern "C" int yylex(); 5 | %} 6 | 7 | %option yylineno 8 | %option noyywrap 9 | 10 | %% 11 | 12 | [/][/].*\n ; // comment 13 | [0-9]* { 14 | yylval = strdup(yytext); 15 | return IntLiteral; 16 | } 17 | "func" { return FunctionBegin; } 18 | "end" { return FunctionEnd; } 19 | "call" { return CallFunction; } 20 | "if" { return IfToken; } 21 | "goto" { return GotoToken; } 22 | "PUT" { return PutToken; } 23 | "FLUSH" { return FlushToken; } 24 | [A-Za-z_]+ { // identifier or array 25 | yylval = strdup(yytext); 26 | return Identifier; 27 | } 28 | [ \t\r\n] ; // whitespace 29 | . { return *yytext; } 30 | 31 | %% -------------------------------------------------------------------------------- /Flex_Bison/FrontEnd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | bison -d FrontEnd.y || exit 1 6 | lex FrontEnd.lex || exit 1 7 | clang++ lex.yy.c FrontEnd.tab.c $(llvm-config --cppflags --ldflags --libs) || exit 1 8 | rm FrontEnd.tab.c FrontEnd.tab.h lex.yy.c 9 | cat app.lang 10 | cat app.lang | ./a.out 11 | -------------------------------------------------------------------------------- /Flex_Bison/README.md: -------------------------------------------------------------------------------- 1 | ## Examples of parsers based on Flex and Bison 2 | Use N.sh script for run examples. 3 | 4 | 0. Flex `hello world` example. 5 | 1. Simple Flex arithmetic parsing. 6 | 2. Simple Bison arithmetic parsing. 7 | 3. Simple Flex&Bison arithmetic parsing. 8 | 4. Simple Flex&Bison arithmetic parsing. 9 | 5. Simple Flex&Bison arithmetic parsing + LLVM IR generation. 10 | 6. Simple Flex&Bison arithmetic parsing + LLVM IR generation with values reading + interpretation. 11 | 7. Simple Flex&Bison expressions parsing + LLVM IR generation with variables + interpretation. 12 | 8. Simple Flex&Bison expressions parsing + LLVM IR generation with variables and arrays + interpretation. 13 | 9. Flex&Bison simple CFG lang file parsing + LLVM IR generation with variables and arrays + interpretation. 14 | 10. Flex&Bison lang file parsing + LLVM IR generation with variables and arrays + interpretation. 15 | 11. Flex&Bison lang file with graphic parsing + LLVM IR generation with variables and arrays + interpretation. 16 | 12. Final FrontEnd: Flex&Bison lang file with graphic parsing + LLVM IR generation + interpretation. 17 | FrontEnd: Flex&Bison lang file with graphic parsing + LLVM IR generation with Sim intrisics 18 | -------------------------------------------------------------------------------- /Flex_Bison/app.lang: -------------------------------------------------------------------------------- 1 | func app 2 | step = 0; 3 | loopStep: 4 | y = 0; 5 | if step != 1000 | loopY | loopStep_end; 6 | loopY: 7 | x = 0; 8 | if y != 256 | loopX | loopY_end; 9 | loopX: 10 | if x != 512 | iterX | loopX_end; 11 | iterX: 12 | PUT(x, y, x*y*step - 16777216); 13 | x = x + 1; 14 | goto loopX; 15 | loopX_end: 16 | y = y + 1; 17 | goto loopY; 18 | loopY_end: 19 | step = step + 1; 20 | FLUSH; 21 | goto loopStep; 22 | loopStep_end: 23 | end 24 | -------------------------------------------------------------------------------- /Flex_Bison/lang.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'top' 2 | source_filename = "top" 3 | 4 | declare void @llvm.sim.putpixel(i32, i32, i32) 5 | 6 | declare void @llvm.sim.flush() 7 | 8 | define void @app() { 9 | entry: 10 | %0 = alloca i32, align 4 11 | %1 = getelementptr i32, ptr %0, i32 0 12 | store i32 0, ptr %1, align 4 13 | %2 = alloca i32, align 4 14 | %3 = alloca i32, align 4 15 | br label %loopStep 16 | 17 | loopStep: ; preds = %loopY_end, %entry 18 | %4 = getelementptr i32, ptr %3, i32 0 19 | store i32 0, ptr %4, align 4 20 | %5 = getelementptr i32, ptr %0, i32 0 21 | %6 = load i32, ptr %5, align 4 22 | %7 = icmp ne i32 %6, 1000 23 | %8 = zext i1 %7 to i32 24 | %9 = icmp ne i32 %8, 0 25 | br i1 %9, label %loopY, label %loopStep_end 26 | 27 | loopY: ; preds = %loopX_end, %loopStep 28 | %10 = getelementptr i32, ptr %2, i32 0 29 | store i32 0, ptr %10, align 4 30 | %11 = getelementptr i32, ptr %3, i32 0 31 | %12 = load i32, ptr %11, align 4 32 | %13 = icmp ne i32 %12, 256 33 | %14 = zext i1 %13 to i32 34 | %15 = icmp ne i32 %14, 0 35 | br i1 %15, label %loopX, label %loopY_end 36 | 37 | loopStep_end: ; preds = %loopStep 38 | ret void 39 | 40 | loopX: ; preds = %iterX, %loopY 41 | %16 = getelementptr i32, ptr %2, i32 0 42 | %17 = load i32, ptr %16, align 4 43 | %18 = icmp ne i32 %17, 512 44 | %19 = zext i1 %18 to i32 45 | %20 = icmp ne i32 %19, 0 46 | br i1 %20, label %iterX, label %loopX_end 47 | 48 | loopY_end: ; preds = %loopY 49 | %21 = getelementptr i32, ptr %0, i32 0 50 | %22 = getelementptr i32, ptr %0, i32 0 51 | %23 = load i32, ptr %22, align 4 52 | %24 = add i32 %23, 1 53 | store i32 %24, ptr %21, align 4 54 | call void @llvm.sim.flush() 55 | br label %loopStep 56 | 57 | iterX: ; preds = %loopX 58 | %25 = getelementptr i32, ptr %2, i32 0 59 | %26 = load i32, ptr %25, align 4 60 | %27 = getelementptr i32, ptr %3, i32 0 61 | %28 = load i32, ptr %27, align 4 62 | %29 = getelementptr i32, ptr %2, i32 0 63 | %30 = load i32, ptr %29, align 4 64 | %31 = getelementptr i32, ptr %3, i32 0 65 | %32 = load i32, ptr %31, align 4 66 | %33 = mul i32 %30, %32 67 | %34 = getelementptr i32, ptr %0, i32 0 68 | %35 = load i32, ptr %34, align 4 69 | %36 = mul i32 %33, %35 70 | %37 = sub i32 %36, 16777216 71 | call void @llvm.sim.putpixel(i32 %26, i32 %28, i32 %37) 72 | %38 = getelementptr i32, ptr %2, i32 0 73 | %39 = getelementptr i32, ptr %2, i32 0 74 | %40 = load i32, ptr %39, align 4 75 | %41 = add i32 %40, 1 76 | store i32 %41, ptr %38, align 4 77 | br label %loopX 78 | 79 | loopX_end: ; preds = %loopX 80 | %42 = getelementptr i32, ptr %3, i32 0 81 | %43 = getelementptr i32, ptr %3, i32 0 82 | %44 = load i32, ptr %43, align 4 83 | %45 = add i32 %44, 1 84 | store i32 %45, ptr %42, align 4 85 | br label %loopY 86 | } 87 | -------------------------------------------------------------------------------- /Flex_Bison/lang.opt.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'lang.ll' 2 | source_filename = "top" 3 | 4 | declare void @llvm.sim.putpixel(i32, i32, i32) 5 | 6 | declare void @llvm.sim.flush() 7 | 8 | define void @app() local_unnamed_addr { 9 | entry: 10 | br label %loopY.preheader 11 | 12 | loopY.preheader: ; preds = %entry, %loopY_end 13 | %.01217 = phi i32 [ 0, %entry ], [ %1, %loopY_end ] 14 | br label %loopX.preheader 15 | 16 | loopX.preheader: ; preds = %loopY.preheader, %loopX_end 17 | %.016 = phi i32 [ 0, %loopY.preheader ], [ %5, %loopX_end ] 18 | %0 = mul nuw nsw i32 %.016, %.01217 19 | br label %iterX 20 | 21 | loopStep_end: ; preds = %loopY_end 22 | ret void 23 | 24 | loopY_end: ; preds = %loopX_end 25 | %1 = add nuw nsw i32 %.01217, 1 26 | tail call void @llvm.sim.flush() 27 | %.not = icmp eq i32 %1, 1000 28 | br i1 %.not, label %loopStep_end, label %loopY.preheader 29 | 30 | iterX: ; preds = %loopX.preheader, %iterX 31 | %.01115 = phi i32 [ 0, %loopX.preheader ], [ %4, %iterX ] 32 | %2 = mul nuw nsw i32 %0, %.01115 33 | %3 = add nsw i32 %2, -16777216 34 | tail call void @llvm.sim.putpixel(i32 %.01115, i32 %.016, i32 %3) 35 | %4 = add nuw nsw i32 %.01115, 1 36 | %.not14 = icmp eq i32 %4, 512 37 | br i1 %.not14, label %loopX_end, label %iterX 38 | 39 | loopX_end: ; preds = %iterX 40 | %5 = add nuw nsw i32 %.016, 1 41 | %.not13 = icmp eq i32 %5, 256 42 | br i1 %.not13, label %loopY_end, label %loopX.preheader 43 | } 44 | -------------------------------------------------------------------------------- /Flex_Bison/lang.opt.s: -------------------------------------------------------------------------------- 1 | .file "top" 2 | .text 3 | .globl app ; -- Begin function app 4 | .type app,@function 5 | app: ; @app 6 | ; %bb.0: ; %entry 7 | MOVli r2 0 8 | .LBB0_1: ; %loopY.preheader 9 | ; =>This Loop Header: Depth=1 10 | ; Child Loop BB0_2 Depth 2 11 | ; Child Loop BB0_5 Depth 3 12 | MOVli r4 0 13 | MOVli r9 0 14 | .LBB0_2: ; %loopX.preheader 15 | ; Parent Loop BB0_1 Depth=1 16 | ; => This Loop Header: Depth=2 17 | ; Child Loop BB0_5 Depth 3 18 | MOVli r10 0 19 | MOVhi r11 65280 20 | B .LBB0_5 21 | .LBB0_5: ; %iterX 22 | ; Parent Loop BB0_1 Depth=1 23 | ; Parent Loop BB0_2 Depth=2 24 | ; => This Inner Loop Header: Depth=3 25 | PUTPIXEL r10 r9 r11 26 | INC_NEi r12 r10 512 27 | ADD r11 r11 r4 28 | BR_COND r12 .LBB0_5 29 | B .LBB0_6 30 | .LBB0_6: ; %loopX_end 31 | ; in Loop: Header=BB0_2 Depth=2 32 | INC_EQi r10 r9 256 33 | ADD r4 r4 r2 34 | BR_COND r10 .LBB0_4 35 | B .LBB0_2 36 | .LBB0_4: ; %loopY_end 37 | ; in Loop: Header=BB0_1 Depth=1 38 | INC_EQi r4 r2 1000 39 | FLUSH 40 | BR_COND r4 .LBB0_3 41 | B .LBB0_1 42 | .LBB0_3: ; %loopStep_end 43 | BR r0 44 | .Lfunc_end0: 45 | .size app, .Lfunc_end0-app 46 | ; -- End function 47 | .section ".note.GNU-stack","",@progbits 48 | -------------------------------------------------------------------------------- /Full_Pipeline/README.md: -------------------------------------------------------------------------------- 1 | ## Prerequisites 2 | * Lang FrontEnd ../Flex_Bison/a.out 3 | * NodeLang FrontEnd ../ANTLR/Frontend/a.out 4 | * clang with `sim` target 5 | * llc with `sim` target 6 | * Simulator in ../Sim/ 7 | 8 | ## Full pipeline for one white point 9 | ``` 10 | ./compile_sim.sh graphic.lang 11 | ./compile_sim.sh graphic.nl 12 | ./compile_sim.sh graphic.c 13 | ``` 14 | ## Full pipeline for graphical application 15 | ``` 16 | ./compile_sim.sh app.lang 17 | ./compile_sim.sh app.nl 18 | ./compile_sim.sh app.c 19 | ./compile_sim.sh app2.c 20 | ``` -------------------------------------------------------------------------------- /Full_Pipeline/app.c: -------------------------------------------------------------------------------- 1 | #define SIM_X_SIZE 512 2 | #define SIM_Y_SIZE 256 3 | 4 | void app() { 5 | for (int step = 0; step < 1000; ++step) { 6 | for (int y = 0; y < SIM_Y_SIZE; ++y) 7 | for (int x = 0; x < SIM_X_SIZE; ++x) 8 | simPutPixel(x, y, 0xFF000000 + x * y * step); 9 | simFlush(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Full_Pipeline/app.lang: -------------------------------------------------------------------------------- 1 | func app 2 | step = 0; 3 | loopStep: 4 | y = 0; 5 | if step != 1000 | loopY | loopStep_end; 6 | loopY: 7 | x = 0; 8 | if y != 256 | loopX | loopY_end; 9 | loopX: 10 | if x != 512 | iterX | loopX_end; 11 | iterX: 12 | PUT(x, y, x*y*step - 16777216); 13 | x = x + 1; 14 | goto loopX; 15 | loopX_end: 16 | y = y + 1; 17 | goto loopY; 18 | loopY_end: 19 | step = step + 1; 20 | FLUSH; 21 | goto loopStep; 22 | loopStep_end: 23 | end 24 | -------------------------------------------------------------------------------- /Full_Pipeline/app.nl: -------------------------------------------------------------------------------- 1 | (NODE alfa 16777216) 2 | (NODE color (x y step) 3 | (- (* step (*x y)) alfa) 4 | ) 5 | (NODE app () 6 | (NODE steps 42) 7 | (LOOP step 0 steps 8 | (LOOP y 0 Y_SIZE 9 | (LOOP x 0 X_SIZE 10 | (PUT_PIXEL x y (color x y step)) 11 | ) 12 | ) 13 | (FLUSH) 14 | ) 15 | ) -------------------------------------------------------------------------------- /Full_Pipeline/app2.c: -------------------------------------------------------------------------------- 1 | #define SIM_X_SIZE 512 2 | #define SIM_Y_SIZE 256 3 | 4 | #define STEPS 10 5 | 6 | int getAbsVelocity(int v1, int v2) { 7 | if (v1 < 0) { 8 | v1 = -v1; 9 | } 10 | if (v2 < 0) { 11 | v2 = -v2; 12 | } 13 | return (v1 + v2)*2 & 0xFF; 14 | } 15 | 16 | void drawLine(int x, int y, int v_x, int v_y) { 17 | int x_len = v_x / 5; 18 | int y_len = v_y / 5; 19 | int v_abs = getAbsVelocity(v_x, v_y); 20 | for (int step = 0; step < STEPS; step++) { 21 | simPutPixel(x + x_len * step / STEPS, y + y_len * step / STEPS, 22 | 0xFF0000FF + (v_abs << 16)); 23 | } 24 | } 25 | 26 | void app() { 27 | int x = (simRand() % SIM_X_SIZE) / 10; 28 | int y = (simRand() % SIM_Y_SIZE) / 10; 29 | int v_x = simRand() % 10; 30 | int v_y = simRand() % 10; 31 | while (1) { 32 | drawLine(x, y, v_x, v_y); 33 | simFlush(); 34 | x += v_x / 5; 35 | y += v_y / 5; 36 | v_x += (SIM_X_SIZE / 2 - x) * 10 / SIM_X_SIZE; 37 | v_y += (SIM_Y_SIZE / 2 - y) * 10 / SIM_Y_SIZE; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Full_Pipeline/compile_sim.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | LLVM_BUILD="../../llvm-add-backend/build" 6 | LLC="$LLVM_BUILD/bin/llc" 7 | CLANG="$LLVM_BUILD/bin/clang" 8 | LANG="../Flex_Bison/a.out" 9 | NODELANG="../ANTLR/Frontend/a.out" 10 | SIM="../Sim/a.out" 11 | 12 | NAME="${1%.*}" 13 | 14 | if [[ $1 == *.lang ]]; then 15 | # Lang source 16 | cat $1 | $LANG >$NAME.ll || exit 1 17 | $CLANG $NAME.ll -O2 -emit-llvm -S -target sim -o $NAME.opt.ll || exit 1 18 | elif [[ $1 == *.nl ]]; then 19 | # NodeLAng source 20 | $NODELANG $1 $NAME.ll || exit 1 21 | $CLANG $NAME.ll -O2 -emit-llvm -S -target sim -o $NAME.opt.ll || exit 1 22 | else 23 | # Clang source 24 | $CLANG $1 -emit-llvm -S -target sim -O2 -o $NAME.opt.ll 25 | fi 26 | 27 | $LLC $NAME.opt.ll -march sim --filetype=asm || exit 1 28 | $LLC $NAME.opt.ll -march sim --filetype=obj || exit 1 29 | $SIM $NAME.opt.o 1 30 | 31 | rm $NAME.ll $NAME.opt.ll $NAME.opt.o $NAME.opt.s 32 | -------------------------------------------------------------------------------- /Full_Pipeline/graphic.c: -------------------------------------------------------------------------------- 1 | void app() { 2 | simPutPixel(5, 5, 0xFFFFFFFF); 3 | simFlush(); 4 | } -------------------------------------------------------------------------------- /Full_Pipeline/graphic.lang: -------------------------------------------------------------------------------- 1 | func app 2 | x = 5; 3 | y = 5; 4 | color = -1; 5 | PUT(x, y, color); 6 | FLUSH; 7 | end 8 | -------------------------------------------------------------------------------- /Full_Pipeline/graphic.nl: -------------------------------------------------------------------------------- 1 | 2 | (NODE app () 3 | (PUT_PIXEL 5 5 -1) 4 | (FLUSH) 5 | ) -------------------------------------------------------------------------------- /LLVM_BackEnd/TableGen/test.td: -------------------------------------------------------------------------------- 1 | class SimReg Enc = 0, string n> { 2 | bits<4> HWEncoding = Enc; 3 | string Name = n; 4 | string purpose; 5 | } 6 | 7 | class SimRegGPR Enc, string n> : SimReg { 8 | let purpose = "GPR"; 9 | } 10 | 11 | foreach I = 0-3 in { 12 | def R#I : SimRegGPR; 13 | } 14 | 15 | class SimRegVEC Enc, string n, int s> : SimReg { 16 | let purpose = "VEC"; 17 | int size = s; 18 | } 19 | 20 | multiclass SimRegVEC Enc, string n> { 21 | def D#NAME : SimRegVEC; 22 | def Q#NAME : SimRegVEC; 23 | } 24 | 25 | foreach I = 0-3 in { 26 | defm ""#I : SimRegVEC; 27 | } 28 | 29 | /* 30 | class SimGPReg Enc, string n> : SimReg { 31 | int size; 32 | } 33 | 34 | let purpose = "GPR", size = 32 in { 35 | foreach I = 1-4 in { 36 | def R#I : SimGPReg; 37 | } 38 | } 39 | 40 | 41 | class SimVecReg Enc, string n, int size> : SimReg { 42 | int Size = size; 43 | let purpose = "Vec"; 44 | bits<2> part = Enc{1...0}; 45 | } 46 | 47 | multiclass SimDQReg Enc, string n> { 48 | def D#NAME : SimVecReg; 49 | def Q#NAME : SimVecReg; 50 | } 51 | 52 | foreach I = 1-4 in { 53 | defm ""#I : SimDQReg; 54 | } 55 | 56 | 57 | 58 | 59 | 60 | let purpose = "GPR" in { 61 | foreach I = 1-15 in { 62 | def R#I : SimGPReg; 63 | } 64 | } 65 | 66 | class SimVecReg Enc, string n, int size> : SimReg { 67 | int Size = size; 68 | let purpose = "Vec"; 69 | bits<2> part = Enc{1...0}; 70 | } 71 | 72 | multiclass SimDQReg Enc, string n> { 73 | def D#NAME : SimVecReg; 74 | def Q#NAME : SimVecReg; 75 | } 76 | 77 | foreach I = 1-4 in { 78 | defm ""#I : SimDQReg; 79 | } 80 | */ -------------------------------------------------------------------------------- /LLVM_BackEnd/TableGen/test_i.td: -------------------------------------------------------------------------------- 1 | def add; 2 | def mul; 3 | def GPR; 4 | def Imm; 5 | 6 | class Inst { 7 | int Opcode = opc; 8 | string AsmString = asmstr; 9 | dag Pattern = pattern; 10 | } 11 | 12 | class Inst_A : 13 | Inst; 14 | 15 | def ADD : Inst_A <0b111, "add", (add)>; 16 | 17 | def MADD : Inst <0b100000, "madd $src1, $src2, $src3", 18 | (add GPR:$dst, GPR:$src1, (mul GPR:$dst2, GPR:$src2, GPR:$src3))>; 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /LLVM_BackEnd/app.c: -------------------------------------------------------------------------------- 1 | #include "../SDL/sim.h" 2 | 3 | void app() { 4 | for (int step = 0; step < 1000; ++step) { 5 | for (int y = 0; y < SIM_Y_SIZE; ++y) 6 | for (int x = 0; x < SIM_X_SIZE; ++x) 7 | simPutPixel(x, y, 0xFF000000 + x * y * step); 8 | simFlush(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /LLVM_BackEnd/app.ll: -------------------------------------------------------------------------------- 1 | define dso_local void @app() local_unnamed_addr { 2 | entry: 3 | br label %for.cond1.preheader 4 | 5 | for.cond1.preheader: ; preds = %entry, %for.cond.cleanup3 6 | %step.026 = phi i32 [ 0, %entry ], [ %inc14, %for.cond.cleanup3 ] 7 | br label %for.cond5.preheader 8 | 9 | for.cond.cleanup: ; preds = %for.cond.cleanup3 10 | ret void 11 | 12 | for.cond5.preheader: ; preds = %for.cond1.preheader, %for.cond.cleanup7 13 | %y.025 = phi i32 [ 0, %for.cond1.preheader ], [ %inc11, %for.cond.cleanup7 ] 14 | %mul = mul nuw nsw i32 %y.025, %step.026 15 | br label %for.body8 16 | 17 | for.cond.cleanup3: ; preds = %for.cond.cleanup7 18 | tail call void @llvm.sim.flush() 19 | %inc14 = add nuw nsw i32 %step.026, 1 20 | %exitcond28.not = icmp eq i32 %inc14, 1000 21 | br i1 %exitcond28.not, label %for.cond.cleanup, label %for.cond1.preheader 22 | 23 | for.cond.cleanup7: ; preds = %for.body8 24 | %inc11 = add nuw nsw i32 %y.025, 1 25 | %exitcond27.not = icmp eq i32 %inc11, 256 26 | br i1 %exitcond27.not, label %for.cond.cleanup3, label %for.cond5.preheader 27 | 28 | for.body8: ; preds = %for.cond5.preheader, %for.body8 29 | %x.024 = phi i32 [ 0, %for.cond5.preheader ], [ %inc, %for.body8 ] 30 | %mul9 = mul nuw nsw i32 %mul, %x.024 31 | %add = add nsw i32 %mul9, -16777216 32 | tail call void @llvm.sim.putpixel(i32 %x.024, i32 %y.025, i32 %add) 33 | %inc = add nuw nsw i32 %x.024, 1 34 | %exitcond.not = icmp eq i32 %inc, 512 35 | br i1 %exitcond.not, label %for.cond.cleanup7, label %for.body8 36 | } 37 | 38 | declare void @llvm.sim.putpixel(i32, i32, i32) 39 | 40 | declare void @llvm.sim.flush() 41 | -------------------------------------------------------------------------------- /LLVM_BackEnd/app.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lisitsynSA/llvm_course/bc5c420881a38874293a8fca8ddb29713d8445be/LLVM_BackEnd/app.o -------------------------------------------------------------------------------- /LLVM_BackEnd/app.s: -------------------------------------------------------------------------------- 1 | .text 2 | .file "app.ll" 3 | .globl app ; -- Begin function app 4 | .type app,@function 5 | app: ; @app 6 | ; %bb.0: ; %entry 7 | MOVli r2 0 8 | MOVli r9 512 9 | MOVli r10 256 10 | MOVli r11 1000 11 | .LBB0_1: ; %for.cond1.preheader 12 | ; =>This Loop Header: Depth=1 13 | ; Child Loop BB0_2 Depth 2 14 | ; Child Loop BB0_3 Depth 3 15 | MOVli r12 0 16 | MOVli r13 0 17 | .LBB0_2: ; %for.cond5.preheader 18 | ; Parent Loop BB0_1 Depth=1 19 | ; => This Loop Header: Depth=2 20 | ; Child Loop BB0_3 Depth 3 21 | MOVli r14 0 22 | MOVhi r15 65280 23 | .LBB0_3: ; %for.body8 24 | ; Parent Loop BB0_1 Depth=1 25 | ; Parent Loop BB0_2 Depth=2 26 | ; => This Inner Loop Header: Depth=3 27 | PUTPIXEL r14 r13 r15 28 | ADD r15 r15 r12 29 | ADDi r14 r14 1 30 | B.NE r14 r9 .LBB0_3 31 | ; %bb.4: ; %for.cond.cleanup7 32 | ; in Loop: Header=BB0_2 Depth=2 33 | ADD r12 r12 r2 34 | ADDi r13 r13 1 35 | B.NE r13 r10 .LBB0_2 36 | ; %bb.5: ; %for.cond.cleanup3 37 | ; in Loop: Header=BB0_1 Depth=1 38 | FLUSH 39 | ADDi r2 r2 1 40 | B.NE r2 r11 .LBB0_1 41 | ; %bb.6: ; %for.cond.cleanup 42 | BR r0 43 | .Lfunc_end0: 44 | .size app, .Lfunc_end0-app 45 | ; -- End function 46 | .section ".note.GNU-stack","",@progbits 47 | -------------------------------------------------------------------------------- /LLVM_BackEnd/graphic.c: -------------------------------------------------------------------------------- 1 | void app() { 2 | simPutPixel(5, 5, 0xFFFFFFFF); 3 | simFlush(); 4 | } -------------------------------------------------------------------------------- /LLVM_BackEnd/graphic.ll: -------------------------------------------------------------------------------- 1 | define dso_local void @app() { 2 | entry: 3 | call void @llvm.sim.putpixel(i32 5, i32 5, i32 -1) 4 | call void @llvm.sim.flush() 5 | ret void 6 | } 7 | 8 | declare void @llvm.sim.putpixel(i32, i32, i32) 9 | 10 | declare void @llvm.sim.flush() 11 | -------------------------------------------------------------------------------- /LLVM_BackEnd/graphic.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lisitsynSA/llvm_course/bc5c420881a38874293a8fca8ddb29713d8445be/LLVM_BackEnd/graphic.o -------------------------------------------------------------------------------- /LLVM_BackEnd/graphic.s: -------------------------------------------------------------------------------- 1 | .text 2 | .file "graphic.ll" 3 | .globl app ; -- Begin function app 4 | .type app,@function 5 | app: ; @app 6 | ; %bb.0: ; %entry 7 | MOVhi r2 65535 8 | ORi r2 r2 65535 9 | MOVli r9 5 10 | PUTPIXEL r9 r9 r2 11 | FLUSH 12 | BR r0 13 | .Lfunc_end0: 14 | .size app, .Lfunc_end0-app 15 | ; -- End function 16 | .section ".note.GNU-stack","",@progbits 17 | -------------------------------------------------------------------------------- /LLVM_BackEnd/test.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | return 12; 3 | } -------------------------------------------------------------------------------- /LLVM_BackEnd/test.ll: -------------------------------------------------------------------------------- 1 | define dso_local i32 @main() { 2 | ret i32 12 3 | } -------------------------------------------------------------------------------- /LLVM_BackEnd/test.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lisitsynSA/llvm_course/bc5c420881a38874293a8fca8ddb29713d8445be/LLVM_BackEnd/test.o -------------------------------------------------------------------------------- /LLVM_BackEnd/test.s: -------------------------------------------------------------------------------- 1 | .text 2 | .file "test.ll" 3 | .globl main ; -- Begin function main 4 | .type main,@function 5 | main: ; @main 6 | ; %bb.0: 7 | MOVli r9 12 8 | BR r0 9 | .Lfunc_end0: 10 | .size main, .Lfunc_end0-main 11 | ; -- End function 12 | .section ".note.GNU-stack","",@progbits 13 | -------------------------------------------------------------------------------- /LLVM_IRGen/0_IR_reader.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/Module.h" 2 | #include "llvm/IRReader/IRReader.h" 3 | #include "llvm/Support/SourceMgr.h" 4 | using namespace llvm; 5 | 6 | int main(int argc, char **argv) { 7 | if (argc < 2) { 8 | errs() << "Expected at least one argument - IR file name\n"; 9 | exit(1); 10 | } 11 | 12 | LLVMContext Context; 13 | SMDiagnostic Err; 14 | std::unique_ptr Mod = parseIRFile(argv[1], Err, Context); 15 | 16 | if (!Mod) { 17 | Err.print(argv[0], errs()); 18 | return 1; 19 | } 20 | for (auto &G : Mod->globals()) { 21 | outs() << "[Global Variable] " << G.getName() << "\n"; 22 | } 23 | for (auto &F : *Mod) { 24 | outs() << "[Function] " << F.getName() << "\n"; 25 | } 26 | if (argc == 3) { 27 | std::error_code EC; 28 | raw_fd_ostream OutputFile(argv[2], EC); 29 | if (!EC) { 30 | Mod->print(OutputFile, nullptr); 31 | } 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /LLVM_IRGen/1_ir_gen.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/LLVMContext.h" 3 | #include "llvm/IR/Module.h" 4 | using namespace llvm; 5 | 6 | int main() { 7 | LLVMContext context; 8 | // ; ModuleID = 'top' 9 | // source_filename = "top" 10 | Module *module = new Module("top", context); 11 | IRBuilder<> builder(context); 12 | 13 | // declare void @main() 14 | FunctionType *funcType = FunctionType::get(builder.getVoidTy(), false); 15 | Function *mainFunc = 16 | Function::Create(funcType, Function::ExternalLinkage, "main", module); 17 | // entry: 18 | BasicBlock *entryBB = BasicBlock::Create(context, "entry", mainFunc); 19 | 20 | builder.SetInsertPoint(entryBB); 21 | builder.CreateRetVoid(); 22 | 23 | module->print(outs(), nullptr); 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /LLVM_IRGen/2_ir_gen+ee.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/ExecutionEngine/ExecutionEngine.h" 2 | #include "llvm/ExecutionEngine/GenericValue.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "llvm/IR/LLVMContext.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/Verifier.h" 7 | #include "llvm/Support/TargetSelect.h" 8 | using namespace llvm; 9 | 10 | int main() { 11 | LLVMContext context; 12 | // ; ModuleID = 'top' 13 | // source_filename = "top" 14 | Module *module = new Module("top", context); 15 | IRBuilder<> builder(context); 16 | 17 | // declare void @main() 18 | FunctionType *funcType = FunctionType::get(builder.getVoidTy(), false); 19 | Function *mainFunc = 20 | Function::Create(funcType, Function::ExternalLinkage, "main", module); 21 | // entry: 22 | BasicBlock *entryBB = BasicBlock::Create(context, "entry", mainFunc); 23 | 24 | builder.SetInsertPoint(entryBB); 25 | builder.CreateRet(builder.getInt32(42)); 26 | 27 | outs() << "[LLVM IR]\n"; 28 | module->print(outs(), nullptr); 29 | outs() << "\n"; 30 | bool verif = verifyFunction(*mainFunc, &outs()); 31 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 32 | 33 | // LLVM IR Interpreter 34 | outs() << "[EE] Run\n"; 35 | InitializeNativeTarget(); 36 | InitializeNativeTargetAsmPrinter(); 37 | 38 | ExecutionEngine *ee = EngineBuilder(std::unique_ptr(module)).create(); 39 | ee->finalizeObject(); 40 | ArrayRef noargs; 41 | GenericValue v = ee->runFunction(mainFunc, noargs); 42 | outs() << "[EE] Result: " << v.IntVal << "\n"; 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /LLVM_IRGen/3_hello_ir_gen.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/ExecutionEngine/ExecutionEngine.h" 2 | #include "llvm/ExecutionEngine/GenericValue.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "llvm/IR/LLVMContext.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/Verifier.h" 7 | #include "llvm/Support/TargetSelect.h" 8 | #include "llvm/Support/raw_ostream.h" 9 | using namespace llvm; 10 | 11 | int main() { 12 | LLVMContext context; 13 | // ; ModuleID = 'top' 14 | // source_filename = "top" 15 | Module *module = new Module("top", context); 16 | IRBuilder<> builder(context); 17 | 18 | // declare void @main() 19 | FunctionType *funcType = FunctionType::get(builder.getInt32Ty(), false); 20 | Function *mainFunc = 21 | Function::Create(funcType, Function::ExternalLinkage, "main", module); 22 | 23 | // entrypoint: 24 | BasicBlock *entry = BasicBlock::Create(context, "entrypoint", mainFunc); 25 | builder.SetInsertPoint(entry); 26 | 27 | // @0 = private unnamed_addr constant [13 x i8] c"hello world!\00", align 1 28 | Value *helloWorld = builder.CreateGlobalStringPtr("hello world!"); 29 | 30 | // declare i32 @puts(i8*) 31 | ArrayRef argsRef(builder.getInt8PtrTy()); 32 | FunctionType *putsType = 33 | FunctionType::get(builder.getInt32Ty(), argsRef, false); 34 | FunctionCallee putsFunc = module->getOrInsertFunction("puts", putsType); 35 | 36 | // %0 = call i32 @puts(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @0, 37 | // i32 0, i32 0)) 38 | builder.CreateCall(putsFunc, helloWorld); 39 | // ret i32 0 40 | builder.CreateRet(builder.getInt32(0)); 41 | 42 | // Dump LLVM IR 43 | module->print(outs(), nullptr); 44 | outs() << "\n"; 45 | bool verif = verifyFunction(*mainFunc, &outs()); 46 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 47 | 48 | // LLVM IR Interpreter 49 | outs() << "[EE] Run\n"; 50 | InitializeNativeTarget(); 51 | InitializeNativeTargetAsmPrinter(); 52 | 53 | ExecutionEngine *ee = EngineBuilder(std::unique_ptr(module)).create(); 54 | ee->finalizeObject(); 55 | ArrayRef noargs; 56 | GenericValue v = ee->runFunction(mainFunc, noargs); 57 | outs() << "[EE] Result: " << v.IntVal << "\n"; 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /LLVM_IRGen/4_ext_funcs.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/ExecutionEngine/ExecutionEngine.h" 2 | #include "llvm/ExecutionEngine/GenericValue.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "llvm/IR/LLVMContext.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/Verifier.h" 7 | #include "llvm/Support/TargetSelect.h" 8 | #include "llvm/Support/raw_ostream.h" 9 | using namespace llvm; 10 | 11 | void func() { outs() << "Hello from \'external\' function:)\n"; } 12 | 13 | int main() { 14 | LLVMContext context; 15 | // ; ModuleID = 'top' 16 | // source_filename = "top" 17 | Module *module = new Module("top", context); 18 | IRBuilder<> builder(context); 19 | 20 | // declare void @main() 21 | FunctionType *funcType = FunctionType::get(builder.getInt32Ty(), false); 22 | Function *mainFunc = 23 | Function::Create(funcType, Function::ExternalLinkage, "main", module); 24 | 25 | // entrypoint: 26 | BasicBlock *entry = BasicBlock::Create(context, "entrypoint", mainFunc); 27 | builder.SetInsertPoint(entry); 28 | 29 | // @0 = private unnamed_addr constant [14 x i8] c"hello world!\0A\00", align 1 30 | Value *helloWorld = builder.CreateGlobalStringPtr("hello world!"); 31 | 32 | // declare i32 @puts(i8*) 33 | ArrayRef argsRef(builder.getInt8PtrTy()); 34 | FunctionType *putsType = 35 | FunctionType::get(builder.getInt32Ty(), argsRef, false); 36 | FunctionCallee putsFunc = module->getOrInsertFunction("puts", putsType); 37 | 38 | // %0 = call i32 @puts(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @0, 39 | // i32 0, i32 0)) 40 | builder.CreateCall(putsFunc, helloWorld); 41 | // declare void @func(void) 42 | Function *ExtFunc = 43 | Function::Create(FunctionType::get(builder.getVoidTy(), false), 44 | Function::ExternalLinkage, "func", module); 45 | // call void @func() 46 | builder.CreateCall(ExtFunc); 47 | // ret i32 0 48 | builder.CreateRet(builder.getInt32(0)); 49 | 50 | // Dump LLVM IR 51 | module->print(outs(), nullptr); 52 | outs() << "\n"; 53 | bool verif = verifyFunction(*mainFunc, &outs()); 54 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 55 | 56 | // LLVM IR Interpreter 57 | outs() << "[EE] Run\n"; 58 | InitializeNativeTarget(); 59 | InitializeNativeTargetAsmPrinter(); 60 | 61 | ExecutionEngine *ee = EngineBuilder(std::unique_ptr(module)).create(); 62 | ee->InstallLazyFunctionCreator([=](const std::string &fnName) -> void * { 63 | if (fnName == "func") { 64 | return reinterpret_cast(func); 65 | } 66 | return nullptr; 67 | }); 68 | ee->finalizeObject(); 69 | ArrayRef noargs; 70 | GenericValue v = ee->runFunction(mainFunc, noargs); 71 | outs() << "[EE] Result: " << v.IntVal << "\n"; 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /LLVM_IRGen/5.s: -------------------------------------------------------------------------------- 1 | addi x4 x7 105 2 | addi x1 x7 9 3 | add x7 x1 x4 4 | sort 5 | -------------------------------------------------------------------------------- /LLVM_IRGen/5_asm_ir_func.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/ExecutionEngine/ExecutionEngine.h" 2 | #include "llvm/ExecutionEngine/GenericValue.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "llvm/IR/LLVMContext.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/Verifier.h" 7 | #include "llvm/Support/TargetSelect.h" 8 | #include "llvm/Support/raw_ostream.h" 9 | #include 10 | using namespace llvm; 11 | 12 | const int REG_FILE_SIZE = 8; 13 | uint32_t REG_FILE[REG_FILE_SIZE] = {}; 14 | 15 | void dumpRegFile() { 16 | outs() << "[REG FILE]:\n"; 17 | for (int i = 0; i < REG_FILE_SIZE; i++) { 18 | outs() << "[" << i << "] " << REG_FILE[i] << "\n"; 19 | } 20 | } 21 | 22 | void INSTR_sort() { 23 | printf("SORT is called\n"); 24 | std::sort(REG_FILE, REG_FILE + REG_FILE_SIZE); 25 | } 26 | 27 | int main(int argc, char **argv) { 28 | if (argc != 2) { 29 | outs() << "[ERROR] Need 1 argument: file with assembler\n"; 30 | return 1; 31 | } 32 | std::ifstream input; 33 | input.open(argv[1]); 34 | if (!input.is_open()) { 35 | outs() << "[ERROR] Can't open " << argv[1] << "\n"; 36 | return 1; 37 | } 38 | 39 | LLVMContext context; 40 | // ; ModuleID = 'top' 41 | // source_filename = "top" 42 | Module *module = new Module("top", context); 43 | IRBuilder<> builder(context); 44 | Type *voidType = builder.getVoidTy(); 45 | Type *int32Type = builder.getInt32Ty(); 46 | 47 | // declare void @INSTR_sort(void) 48 | Function *CalleeINSTR_sort = 49 | Function::Create(FunctionType::get(voidType, false), 50 | Function::ExternalLinkage, "INSTR_sort", module); 51 | 52 | //[8 x i32] regFile = {0, 0, 0, 0} 53 | ArrayType *regFileType = ArrayType::get(int32Type, REG_FILE_SIZE); 54 | module->getOrInsertGlobal("regFile", regFileType); 55 | GlobalVariable *regFile = module->getNamedGlobal("regFile"); 56 | 57 | // declare void @main() 58 | FunctionType *funcType = FunctionType::get(int32Type, false); 59 | Function *mainFunc = 60 | Function::Create(funcType, Function::ExternalLinkage, "main", module); 61 | 62 | // entrypoint: 63 | BasicBlock *entry = BasicBlock::Create(context, "entrypoint", mainFunc); 64 | builder.SetInsertPoint(entry); 65 | 66 | std::string name; 67 | std::string arg; 68 | while (input >> name) { 69 | if (!name.compare("sort")) { 70 | outs() << "sort \n"; 71 | builder.CreateCall(CalleeINSTR_sort); 72 | continue; 73 | } 74 | if (!name.compare("add")) { 75 | input >> arg; 76 | outs() << arg; 77 | // res 78 | Value *res_p = builder.CreateConstGEP2_32(regFileType, regFile, 0, 79 | std::stoi(arg.substr(1))); 80 | input >> arg; 81 | outs() << " = " << arg; 82 | // arg1 83 | Value *arg1_p = builder.CreateConstGEP2_32(regFileType, regFile, 0, 84 | std::stoi(arg.substr(1))); 85 | input >> arg; 86 | outs() << " + " << arg << "\n"; 87 | // arg2 88 | Value *arg2_p = builder.CreateConstGEP2_32(regFileType, regFile, 0, 89 | std::stoi(arg.substr(1))); 90 | Value *add_arg1_arg2 = 91 | builder.CreateAdd(builder.CreateLoad(int32Type, arg1_p), 92 | builder.CreateLoad(int32Type, arg2_p)); 93 | builder.CreateStore(add_arg1_arg2, res_p); 94 | continue; 95 | } 96 | if (!name.compare("addi")) { 97 | input >> arg; 98 | outs() << arg; 99 | // res 100 | Value *res_p = builder.CreateConstGEP2_32(regFileType, regFile, 0, 101 | std::stoi(arg.substr(1))); 102 | input >> arg; 103 | outs() << " = " << arg; 104 | // arg1 105 | Value *arg1_p = builder.CreateConstGEP2_32(regFileType, regFile, 0, 106 | std::stoi(arg.substr(1))); 107 | input >> arg; 108 | outs() << " + " << arg << "\n"; 109 | // arg2 110 | Value *arg2 = builder.getInt32(std::stoi(arg)); 111 | Value *add_arg1_arg2 = 112 | builder.CreateAdd(builder.CreateLoad(int32Type, arg1_p), arg2); 113 | builder.CreateStore(add_arg1_arg2, res_p); 114 | continue; 115 | } 116 | } 117 | input.close(); 118 | 119 | // ret i32 0 120 | builder.CreateRet(builder.getInt32(0)); 121 | 122 | // Dump LLVM IR 123 | outs() << "[LLVM IR]\n"; 124 | module->print(outs(), nullptr); 125 | outs() << "\n"; 126 | bool verif = verifyFunction(*mainFunc, &outs()); 127 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 128 | 129 | dumpRegFile(); 130 | 131 | // Interpreter of LLVM IR 132 | outs() << "[EE] Run\n"; 133 | InitializeNativeTarget(); 134 | InitializeNativeTargetAsmPrinter(); 135 | 136 | ExecutionEngine *ee = EngineBuilder(std::unique_ptr(module)).create(); 137 | ee->addGlobalMapping(regFile, (void *)REG_FILE); 138 | ee->InstallLazyFunctionCreator([=](const std::string &fnName) -> void * { 139 | if (fnName == "INSTR_sort") { 140 | return reinterpret_cast(INSTR_sort); 141 | } 142 | return nullptr; 143 | }); 144 | ee->finalizeObject(); 145 | ArrayRef noargs; 146 | GenericValue v = ee->runFunction(mainFunc, noargs); 147 | outs() << "[EE] Result: " << v.IntVal << "\n"; 148 | 149 | dumpRegFile(); 150 | return 0; 151 | } 152 | -------------------------------------------------------------------------------- /LLVM_IRGen/6.s: -------------------------------------------------------------------------------- 1 | ENTRY 2 | read x2 3 | addi x3 x3 1 4 | b LOOP 5 | EXIT 6 | exit 7 | LOOP 8 | addi x1 x1 1 9 | mul x3 x3 x1 10 | dump x3 11 | bne x2 x1 LOOP 12 | preEXIT 13 | sort 14 | b EXIT 15 | -------------------------------------------------------------------------------- /LLVM_IRGen/7_0.s: -------------------------------------------------------------------------------- 1 | exit -------------------------------------------------------------------------------- /LLVM_IRGen/7_1.s: -------------------------------------------------------------------------------- 1 | read x1 2 | add x2 x1 x1 3 | mul x1 x2 x1 4 | write x1 5 | exit -------------------------------------------------------------------------------- /LLVM_IRGen/7_2.s: -------------------------------------------------------------------------------- 1 | read x1 2 | addi x3 x3 1 3 | addi x2 x2 1 4 | mul x3 x3 x2 5 | bne x1 x2 3 6 | write x3 7 | exit -------------------------------------------------------------------------------- /LLVM_IRGen/8_0.s: -------------------------------------------------------------------------------- 1 | ENTRY 2 | read x1 3 | addi x3 x3 1 4 | LOOP 5 | addi x2 x2 1 6 | mul x3 x3 x2 7 | bne x1 x2 LOOP 8 | EXIT 9 | write x3 10 | exit -------------------------------------------------------------------------------- /LLVM_IRGen/9_0.txt: -------------------------------------------------------------------------------- 1 | 10 * 7 - 20 2 | -------------------------------------------------------------------------------- /LLVM_IRGen/9_1.txt: -------------------------------------------------------------------------------- 1 | 5 - 10 / 2 * 3 + 12 -------------------------------------------------------------------------------- /LLVM_IRGen/9_2.txt: -------------------------------------------------------------------------------- 1 | 10 * 7 + sqr(4)/2 2 | -------------------------------------------------------------------------------- /LLVM_IRGen/README.md: -------------------------------------------------------------------------------- 1 | # LLVM IR Generators examples 2 | This is example of LLVM IR generators: from simple "hello world" generator to binary lifter and mathematical expressions frontend. Need to install `llvm-dev` package for build examples. 3 | 4 | ## Example for IR Reader: 5 | ``` 6 | clang++ -O2 0_IR_reader.cpp $(llvm-config --cppflags --ldflags --libs) 7 | ./a.out hello.ll out.ll 8 | ``` 9 | 10 | ## Usage for IR Generators: 11 | ``` 12 | clang++ $(llvm-config --cppflags --ldflags --libs) main.cpp 13 | ./a.out 14 | ``` 15 | 16 | ## List of IR Generator examples: 17 | 1. Empty main function 18 | 2. Empty main function and IR interpretation (ExecutionEngine) 19 | 3. Main function generation with "hello world" printing. 20 | 4. Main function generation with "hello world" printing + external function. 21 | 5. LLVM IR generation for simple calculation with external functions. 22 | 5. LLVM IR generation for simple calculation with IR functions. 23 | ``` 24 | addi x4 x0 105 25 | addi x1 x0 9 26 | add x0 x1 x4 27 | sort 28 | ``` 29 | 6. LLVM IR generation for calculation with branches: 30 | ``` 31 | ENTRY 32 | read x2 33 | addi x3 x3 1 34 | b LOOP 35 | EXIT 36 | exit 37 | LOOP 38 | addi x1 x1 1 39 | mul x3 x3 x1 40 | dump x3 41 | bne x2 x1 LOOP 42 | preEXIT 43 | sort 44 | b EXIT 45 | ``` 46 | 7. Simulator that work in 2 ways: calling instruction simulation functions and build IR from input application: 47 | ``` 48 | read x1 49 | addi x3 x3 1 50 | addi x2 x2 1 51 | mul x3 x3 x2 52 | bne x1 x2 3 53 | write x3 54 | exit 55 | ``` 56 | 8. Simulator extended with complex control flow: 57 | ``` 58 | ENTRY 59 | read x1 60 | addi x3 x3 1 61 | LOOP 62 | addi x2 x2 1 63 | mul x3 x3 x2 64 | bne x1 x2 LOOP 65 | EXIT 66 | write x3 67 | exit 68 | ``` 69 | 9. Simple expressions parser, that build LLVM IR for calculation: 70 | ``` 71 | 10 * 7 - 20 72 | ``` 73 | 9. Expression parser with function support: 74 | ``` 75 | 10 * 7 - sqr(4)/2 76 | ``` 77 | -------------------------------------------------------------------------------- /LLVM_IRGen/expr.s: -------------------------------------------------------------------------------- 1 | push 5 2 | push -10 3 | push 0.5 4 | push 3 5 | mul_s 6 | mul_s 7 | push 12 8 | add_s 9 | add_s 10 | pop x1 11 | write x1 12 | exit -------------------------------------------------------------------------------- /LLVM_IRGen/expression_check.txt: -------------------------------------------------------------------------------- 1 | (+(5)(+(*(-10)(*(0.5)(3)))(12))) 2 | ((5)+(((-10)*((0.5)*(3)))+(12))) 3 | ((5)(((-10)((0.5)(3)*)*)(12)+)+) 4 | -------------------------------------------------------------------------------- /LLVM_IRGen/hello.c: -------------------------------------------------------------------------------- 1 | # include 2 | 3 | int main() 4 | { 5 | printf("Hello world!\n"); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /LLVM_Pass/Legacy/ModPass_dump.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/LegacyPassManager.h" 2 | #include "llvm/IR/Module.h" 3 | #include "llvm/Pass.h" 4 | #include "llvm/Support/raw_ostream.h" 5 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 6 | using namespace llvm; 7 | 8 | namespace { 9 | struct MyPass : public ModulePass { 10 | static char ID; 11 | MyPass() : ModulePass(ID) {} 12 | 13 | virtual bool runOnModule(Module &M) { 14 | // M.print(outs(), nullptr); 15 | 16 | for (auto &G : M.globals()) { 17 | // outs() << "Global Variable: "; 18 | G.print(outs()); 19 | outs() << "\n"; 20 | } 21 | for (auto &F : M) { 22 | // outs() << "Function: "; 23 | F.print(outs()); 24 | outs() << "\n"; 25 | /*for (auto &B : F) { 26 | outs() << "Basic block:\n"; 27 | B.print(outs()); 28 | 29 | for (auto &I : B) { 30 | outs() << "Instruction: \n"; 31 | I.print(outs(), true); 32 | outs() << "\n"; 33 | } 34 | }*/ 35 | } 36 | return false; 37 | } 38 | }; 39 | } // namespace 40 | 41 | char MyPass::ID = 0; 42 | 43 | // Automatically enable the pass. 44 | // http://adriansampson.net/blog/clangpass.html 45 | static void registerMyPass(const PassManagerBuilder &, 46 | legacy::PassManagerBase &PM) { 47 | PM.add(new MyPass()); 48 | } 49 | static RegisterStandardPasses 50 | RegisterMyPass(PassManagerBuilder::EP_ModuleOptimizerEarly, registerMyPass); 51 | -------------------------------------------------------------------------------- /LLVM_Pass/Legacy/Pass_change.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/Function.h" 2 | #include "llvm/IR/IRBuilder.h" 3 | #include "llvm/IR/InstrTypes.h" 4 | #include "llvm/IR/LegacyPassManager.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/Pass.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 9 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" 10 | using namespace llvm; 11 | 12 | namespace { 13 | struct MyPass : public FunctionPass { 14 | static char ID; 15 | MyPass() : FunctionPass(ID) {} 16 | 17 | virtual bool runOnFunction(Function &F) { 18 | outs() << "\nIn a function called " << F.getName() << "!\n"; 19 | 20 | // Prepare builder for IR modification 21 | LLVMContext &Ctx = F.getContext(); 22 | IRBuilder<> builder(Ctx); 23 | bool changed = false; 24 | 25 | for (auto &B : F) { 26 | for (auto &I : B) { 27 | if (auto *op = dyn_cast(&I)) { 28 | outs() << "Modified instruction:\n"; 29 | I.print(outs(), true); 30 | outs() << "\n"; 31 | // Insert at the point where the instruction `op` appears. 32 | IRBuilder<> builder(op); 33 | 34 | // Make a sub with the same operands as `op`. 35 | Value *lhs = op->getOperand(0); 36 | Value *rhs = op->getOperand(1); 37 | Value *sub = builder.CreateSub(lhs, rhs); 38 | 39 | // Everywhere the old instruction was used as an operand, use our 40 | // new sub instruction instead. 41 | for (auto &U : op->uses()) { 42 | User *user = U.getUser(); // A User is anything with operands. 43 | user->setOperand(U.getOperandNo(), sub); 44 | } 45 | 46 | changed = true; 47 | } 48 | } 49 | } 50 | return changed; 51 | } 52 | }; 53 | } // namespace 54 | 55 | char MyPass::ID = 0; 56 | 57 | // Automatically enable the pass. 58 | // http://adriansampson.net/blog/clangpass.html 59 | static void registerMyPass(const PassManagerBuilder &, 60 | legacy::PassManagerBase &PM) { 61 | PM.add(new MyPass()); 62 | } 63 | static RegisterStandardPasses 64 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, registerMyPass); 65 | //RegisterMyPass(PassManagerBuilder::EP_OptimizerLast, registerMyPass); // only with -O2 66 | -------------------------------------------------------------------------------- /LLVM_Pass/Legacy/Pass_dump.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/Pass.h" 2 | #include "llvm/IR/Function.h" 3 | #include "llvm/Support/raw_ostream.h" 4 | #include "llvm/IR/LegacyPassManager.h" 5 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 6 | using namespace llvm; 7 | 8 | namespace { 9 | struct MyPass : public FunctionPass { 10 | static char ID; 11 | MyPass() : FunctionPass(ID) {} 12 | 13 | virtual bool runOnFunction(Function &F) { 14 | outs() << "In a function called " << F.getName() << "!\n"; 15 | 16 | outs() << "Function body:\n"; 17 | F.print(outs()); 18 | 19 | for (auto &B : F) { 20 | outs() << "Basic block:\n"; 21 | B.print(outs()); 22 | 23 | for (auto &I : B) { 24 | outs() << "Instruction: \n"; 25 | I.print(outs(), true); 26 | outs() << "\n"; 27 | } 28 | } 29 | 30 | return false; 31 | } 32 | }; 33 | } 34 | 35 | char MyPass::ID = 0; 36 | 37 | // Automatically enable the pass. 38 | // http://adriansampson.net/blog/clangpass.html 39 | static void registerMyPass(const PassManagerBuilder &, 40 | legacy::PassManagerBase &PM) { 41 | PM.add(new MyPass()); 42 | } 43 | static RegisterStandardPasses 44 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 45 | registerMyPass); 46 | -------------------------------------------------------------------------------- /LLVM_Pass/Legacy/Pass_opt.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/Function.h" 2 | #include "llvm/IR/IRBuilder.h" 3 | #include "llvm/IR/InstrTypes.h" 4 | #include "llvm/IR/LegacyPassManager.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/Pass.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 9 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" 10 | using namespace llvm; 11 | 12 | namespace { 13 | struct SkeletonPass : public FunctionPass { 14 | static char ID; 15 | SkeletonPass() : FunctionPass(ID) {} 16 | 17 | virtual bool runOnFunction(Function &F) { 18 | outs() << "In a function " << F.getName() << "\n"; 19 | F.print(outs()); 20 | outs() << "\n"; 21 | 22 | bool changed = false; 23 | for (auto &B : F) { 24 | for (auto &I : B) { 25 | if (AllocaInst *Alloca = dyn_cast(&I)) { 26 | outs() << "\nAllocation: (BB " << &B << "):\n"; 27 | Alloca->print(outs(), true); 28 | outs() << "\n"; 29 | StoreInst *Store = nullptr; 30 | LoadInst *Load = nullptr; 31 | 32 | for (auto &U : Alloca->uses()) { 33 | Instruction *UseInst = cast(U.getUser()); 34 | outs() << "\tUsers: "; 35 | UseInst->print(outs(), true); 36 | 37 | if (StoreInst *S = dyn_cast(UseInst)) { 38 | if (Store == nullptr) { 39 | Store = S; 40 | outs() << " == STORE\n"; 41 | } else { 42 | outs() << " == EXTRA STORE\n"; 43 | Store = nullptr; 44 | break; 45 | } 46 | } else if (LoadInst *L = dyn_cast(UseInst)) { 47 | if (Load == nullptr) { 48 | Load = L; 49 | outs() << " == LOAD\n"; 50 | } else { 51 | Load = nullptr; 52 | outs() << " == EXTRA LOAD\n"; 53 | break; 54 | } 55 | } else { 56 | Load = nullptr; 57 | outs() << " == EXTRA INSTR\n"; 58 | break; 59 | } 60 | } 61 | if (Load != nullptr && Store != nullptr) { 62 | BasicBlock *LoadBB = Load->getParent(); 63 | BasicBlock *StoreBB = Store->getParent(); 64 | if (LoadBB == StoreBB) { 65 | outs() << "[PASS] Store and load in the same BB\n"; 66 | continue; 67 | } 68 | outs() << "[PASS] Allocation is candidate\n"; 69 | changed = true; 70 | Value *Val = Store->getOperand(0); 71 | Instruction *ValInst = dyn_cast(Val); 72 | 73 | if (ValInst) { 74 | if (ValInst->isEHPad() || ValInst->mayThrow()) { 75 | continue; 76 | } 77 | ValInst->moveBefore(&*LoadBB->getFirstInsertionPt()); 78 | 79 | Store->removeFromParent(); 80 | for (auto &U : Load->uses()) { 81 | Instruction *UseInst = cast(U.getUser()); 82 | outs() << "\t Load Users: "; 83 | UseInst->print(outs(), true); 84 | outs() << "\n"; 85 | for (int i = 0; i < UseInst->getNumOperands(); i++) { 86 | if (UseInst->getOperand(i) == Load) { 87 | UseInst->setOperand(i, Val); 88 | } 89 | } 90 | outs() << "\t Fixed Load Users: "; 91 | UseInst->print(outs(), true); 92 | outs() << "\n"; 93 | } 94 | Load->removeFromParent(); 95 | } 96 | } 97 | } 98 | } 99 | } 100 | 101 | return changed; 102 | } 103 | }; 104 | } // namespace 105 | 106 | char SkeletonPass::ID = 0; 107 | 108 | // Automatically enable the pass. 109 | // http://adriansampson.net/blog/clangpass.html 110 | static void registerSkeletonPass(const PassManagerBuilder &, 111 | legacy::PassManagerBase &PM) { 112 | PM.add(new SkeletonPass()); 113 | } 114 | static RegisterStandardPasses 115 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, // EP_OptimizerLast 116 | registerSkeletonPass); 117 | -------------------------------------------------------------------------------- /LLVM_Pass/Legacy/Pass_start.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/Pass.h" 2 | #include "llvm/IR/Function.h" 3 | #include "llvm/Support/raw_ostream.h" 4 | #include "llvm/IR/LegacyPassManager.h" 5 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 6 | using namespace llvm; 7 | 8 | namespace { 9 | struct MyPass : public FunctionPass { 10 | static char ID; 11 | MyPass() : FunctionPass(ID) {} 12 | 13 | virtual bool runOnFunction(Function &F) { 14 | outs() << "In a function called " << F.getName() << "!\n"; 15 | return false; 16 | } 17 | }; 18 | } 19 | 20 | char MyPass::ID = 0; 21 | 22 | // Automatically enable the pass. 23 | // http://adriansampson.net/blog/clangpass.html 24 | static void registerMyPass(const PassManagerBuilder &, 25 | legacy::PassManagerBase &PM) { 26 | PM.add(new MyPass()); 27 | } 28 | static RegisterStandardPasses 29 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 30 | registerMyPass); 31 | -------------------------------------------------------------------------------- /LLVM_Pass/Legacy/Pass_uses.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/Pass.h" 2 | #include "llvm/IR/Function.h" 3 | #include "llvm/Support/raw_ostream.h" 4 | #include "llvm/IR/LegacyPassManager.h" 5 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 6 | using namespace llvm; 7 | 8 | namespace { 9 | struct MyPass : public FunctionPass { 10 | static char ID; 11 | MyPass() : FunctionPass(ID) {} 12 | 13 | virtual bool runOnFunction(Function &F) { 14 | outs() << "\nIn a function called " << F.getName() << "!\n"; 15 | F.print(outs()); 16 | outs() << "\nFunction Users: \n"; 17 | for (auto &U : F.uses()) { 18 | User *user = U.getUser(); 19 | user->print(outs(), true); 20 | outs() << "\n"; 21 | } 22 | 23 | for (auto &B : F) { 24 | outs() << "\nBasic block:"; 25 | B.print(outs()); 26 | outs() << "BasicBlock Users: \n"; 27 | for (auto &U : B.uses()) { 28 | User *user = U.getUser(); 29 | user->print(outs(), true); 30 | outs() << "\n"; 31 | } 32 | 33 | for (auto &I : B) { 34 | outs() << "\nInstruction: \n"; 35 | I.print(outs(), true); 36 | outs() << "\nUsers: \n"; 37 | for (auto &U : I.uses()) { 38 | User *user = U.getUser(); 39 | user->print(outs(), true); 40 | outs() << "\n"; 41 | } 42 | outs() << "Opernads: \n"; 43 | for (auto &U : I.operands()) { 44 | Value *use = U.get(); 45 | use->print(outs(), true); 46 | outs() << "\n"; 47 | } 48 | } 49 | } 50 | 51 | return false; 52 | } 53 | }; 54 | } 55 | 56 | char MyPass::ID = 0; 57 | 58 | // Automatically enable the pass. 59 | // http://adriansampson.net/blog/clangpass.html 60 | static void registerMyPass(const PassManagerBuilder &, 61 | legacy::PassManagerBase &PM) { 62 | PM.add(new MyPass()); 63 | } 64 | static RegisterStandardPasses 65 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 66 | registerMyPass); 67 | -------------------------------------------------------------------------------- /LLVM_Pass/Legacy/README.md: -------------------------------------------------------------------------------- 1 | # LLVM Pass example 2 | This is example of LLVM pass that collect static inforamtion about app IR and insert instrumentation for collecting dynamic information. 3 | 4 | 5 | ## Usage: 6 | ``` 7 | sudo apt install llvm 8 | clang++ Pass.cpp -c -fPIC -I$(llvm-config --includedir) -o Pass.o 9 | clang++ Pass.o -fPIC -shared -o libPass.so 10 | clang sim.c app2.c -lSDL2 -Xclang -load -Xclang ../LLVM_PASS/libPass.so -flegacy-pass-manager 11 | ``` 12 | 13 | ## Examples for Functions processing: 14 | 1. Print Functions name 15 | ``` 16 | clang++ Pass_start.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 17 | clang -Xclang -load -Xclang ./libPass.so ./c_examples/hello.c -flegacy-pass-manager 18 | ``` 19 | 2. Dump Functions, BasicBlocks and Instructions 20 | ``` 21 | clang++ Pass_dump.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 22 | clang -Xclang -load -Xclang ./libPass.so ./c_examples/hello.c -flegacy-pass-manager 23 | ``` 24 | 3. Dump Uses of Functions, BasicBlocks and Instructions 25 | ``` 26 | clang++ Pass_uses.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 27 | clang -Xclang -load -Xclang ./libPass.so ./c_examples/hello.c -flegacy-pass-manager 28 | ``` 29 | 4. Change Binary operations to substruction 30 | ``` 31 | clang++ Pass_change.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 32 | 33 | clang c_examples/calc.c 34 | ./a.out 35 | 36 | clang -Xclang -load -Xclang ./libPass.so c_examples/calc.c -emit-llvm -S -o calc.ll -flegacy-pass-manager 37 | clang -Xclang -load -Xclang ./libPass.so c_examples/calc.c -flegacy-pass-manager 38 | ./a.out 39 | ``` 40 | 5. Instrumentation for code profiling 41 | ``` 42 | clang++ Pass_cfg.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 43 | 44 | clang -Xclang -load -Xclang ./libPass.so c_examples/calc.c -emit-llvm -S -o calc.ll -flegacy-pass-manager 45 | clang -Xclang -load -Xclang ./libPass.so c_examples/calc.c log.c -flegacy-pass-manager 46 | ./a.out 47 | 48 | clang -Xclang -load -Xclang ./libPass.so c_examples/fact.c -emit-llvm -S -o calc.ll -flegacy-pass-manager 49 | clang -Xclang -load -Xclang ./libPass.so c_examples/fact.c log.c -flegacy-pass-manager 50 | ./a.out 4 51 | ``` 52 | 6. Example of bad optimization Pass 53 | ``` 54 | clang++ Pass_opt.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 55 | 56 | clang c_examples/exp1.c 57 | time ./a.out 1000 58 | clang -Xclang -load -Xclang ./libPass.so c_examples/exp1.c -flegacy-pass-manager 59 | time ./a.out 1000 60 | 61 | clang c_examples/exp2.c 62 | time ./a.out 1000 63 | clang -Xclang -load -Xclang ./libPass.so c_examples/exp2.c -flegacy-pass-manager 64 | time ./a.out 1000 65 | ``` 66 | ## Examples for IR Modules: 67 | 1. IR reading 68 | ``` 69 | clang++ -O3 IR_reader.cpp $(llvm-config --cppflags --ldflags --libs) -o IR_reader 70 | ./IR_reader hello.ll 71 | ``` 72 | 2. Pass for Module dump 73 | ``` 74 | clang++ ModPass_dump.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 75 | clang -Xclang -load -Xclang ./libPass.so ./c_examples/hello.c -flegacy-pass-manager -O1 &> test.ll 76 | clang test.ll -o test 77 | ./test 78 | ``` 79 | 80 | ## Possible instructions classes: 81 | https://llvm.org/doxygen/classllvm_1_1Instruction.html -------------------------------------------------------------------------------- /LLVM_Pass/Pass1_reg.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/Passes/PassBuilder.h" 2 | #include "llvm/Passes/PassPlugin.h" 3 | using namespace llvm; 4 | 5 | PassPluginLibraryInfo getPassPluginInfo() { 6 | const auto callback = [](PassBuilder &PB) { 7 | // clang hello.c -fpass-plugin=./libPass.so 8 | PB.registerPipelineStartEPCallback([=](ModulePassManager &MPM, auto) { 9 | outs() << "Add pass to ModulePassManager in " 10 | "registerPipelineStartEPCallback\n"; 11 | return true; 12 | }); 13 | PB.registerOptimizerLastEPCallback([=](ModulePassManager &MPM, auto) { 14 | outs() << "Add pass to ModulePassManager in " 15 | "registerOptimizerLastEPCallback\n"; 16 | return true; 17 | }); 18 | // opt hello.ll -load-pass-plugin ./libPass.so -passes myFuncPass -o a.out 19 | PB.registerPipelineParsingCallback( 20 | [](StringRef name, FunctionPassManager &FPM, 21 | ArrayRef) -> bool { 22 | if (name == "myFuncPass") { 23 | outs() << "Add pass to FunctionPassManager from " 24 | "registerPipelineParsingCallback\n"; 25 | return true; 26 | } 27 | return false; 28 | }); 29 | // opt hello.ll -load-pass-plugin ./libPass.so -passes myModPass -o a.out 30 | PB.registerPipelineParsingCallback( 31 | [](StringRef name, ModulePassManager &MPM, 32 | ArrayRef) -> bool { 33 | if (name == "myModPass") { 34 | outs() << "Add pass to ModulePassManager from " 35 | "registerPipelineParsingCallback\n"; 36 | return true; 37 | } 38 | return false; 39 | }); 40 | }; 41 | 42 | return {LLVM_PLUGIN_API_VERSION, "MyPlugin", "0.0.1", callback}; 43 | }; 44 | 45 | /* When a plugin is loaded by the driver, it will call this entry point to 46 | obtain information about this plugin and about how to register its passes. 47 | */ 48 | extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() { 49 | outs() << "Entry point for a plugin\n"; 50 | return getPassPluginInfo(); 51 | } 52 | -------------------------------------------------------------------------------- /LLVM_Pass/Pass2_names.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/Passes/PassBuilder.h" 2 | #include "llvm/Passes/PassPlugin.h" 3 | using namespace llvm; 4 | 5 | struct MyModPass : public PassInfoMixin { 6 | PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { 7 | outs() << "\n[Module Pass] Module: " << M.getName() << "\n"; 8 | for (auto &G : M.globals()) { 9 | outs() << "[Global Variable] " << G.getName() << "\n"; 10 | } 11 | for (auto &F : M) { 12 | outs() << "[Function] " << F.getName() << "\n"; 13 | } 14 | return PreservedAnalyses::all(); 15 | }; 16 | }; 17 | 18 | struct MyFuncPass : public PassInfoMixin { 19 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) { 20 | outs() << "\n[Function Pass] Module: " << F.getParent()->getName() << "\n"; 21 | outs() << "[Function] " << F.getName() << "\n"; 22 | return PreservedAnalyses::all(); 23 | }; 24 | static bool isRequired() { return true; } 25 | }; 26 | 27 | PassPluginLibraryInfo getPassPluginInfo() { 28 | const auto callback = [](PassBuilder &PB) { 29 | // clang hello.c -fpass-plugin=./libPass.so -O1 (w/o isRequired) 30 | PB.registerPipelineStartEPCallback([=](ModulePassManager &MPM, auto) { 31 | outs() << "Add pass to ModulePassManager in " 32 | "registerPipelineStartEPCallback\n"; 33 | MPM.addPass(MyModPass{}); 34 | return true; 35 | }); 36 | PB.registerOptimizerLastEPCallback([=](ModulePassManager &MPM, auto) { 37 | outs() << "Add pass to ModulePassManager in " 38 | "registerOptimizerLastEPCallback\n"; 39 | MPM.addPass(createModuleToFunctionPassAdaptor(MyFuncPass{})); 40 | return true; 41 | }); 42 | }; 43 | 44 | return {LLVM_PLUGIN_API_VERSION, "MyPlugin", "0.0.1", callback}; 45 | }; 46 | 47 | /* When a plugin is loaded by the driver, it will call this entry point to 48 | obtain information about this plugin and about how to register its passes. 49 | */ 50 | extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() { 51 | outs() << "Entry point for a plugin\n"; 52 | return getPassPluginInfo(); 53 | } 54 | -------------------------------------------------------------------------------- /LLVM_Pass/Pass3_dump.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/Passes/PassBuilder.h" 2 | #include "llvm/Passes/PassPlugin.h" 3 | using namespace llvm; 4 | 5 | struct MyModPass : public PassInfoMixin { 6 | PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { 7 | outs() << "[Module] " << M.getName() << "\n"; 8 | for (auto &G : M.globals()) { 9 | outs() << "[Global Variable] " << G.getName() << "\n"; 10 | G.print(outs()); 11 | outs() << "\n"; 12 | } 13 | for (auto &F : M) { 14 | outs() << "[Function] " << F.getName() << " (arg_size: " << F.arg_size() 15 | << ")\n"; 16 | F.print(outs()); 17 | 18 | for (auto &B : F) { 19 | outs() << "\n#[Basic block]"; 20 | B.print(outs()); 21 | 22 | for (auto &I : B) { 23 | outs() << "##[Instruction]\n"; 24 | I.print(outs(), true); 25 | outs() << "\n"; 26 | } 27 | } 28 | outs() << "\n"; 29 | } 30 | outs() << "\n"; 31 | return PreservedAnalyses::all(); 32 | }; 33 | }; 34 | 35 | PassPluginLibraryInfo getPassPluginInfo() { 36 | const auto callback = [](PassBuilder &PB) { 37 | PB.registerPipelineStartEPCallback([=](ModulePassManager &MPM, auto) { 38 | MPM.addPass(MyModPass{}); 39 | return true; 40 | }); 41 | PB.registerOptimizerLastEPCallback([=](ModulePassManager &MPM, auto) { 42 | MPM.addPass(MyModPass{}); 43 | return true; 44 | }); 45 | }; 46 | 47 | return {LLVM_PLUGIN_API_VERSION, "MyPlugin", "0.0.1", callback}; 48 | }; 49 | 50 | /* When a plugin is loaded by the driver, it will call this entry point to 51 | obtain information about this plugin and about how to register its passes. 52 | */ 53 | extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() { 54 | return getPassPluginInfo(); 55 | } 56 | -------------------------------------------------------------------------------- /LLVM_Pass/Pass4_uses.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/Passes/PassBuilder.h" 2 | #include "llvm/Passes/PassPlugin.h" 3 | using namespace llvm; 4 | 5 | struct MyModPass : public PassInfoMixin { 6 | PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { 7 | outs() << "[Module] " << M.getName() << "\n"; 8 | for (auto &F : M) { 9 | outs() << "[Function] " << F.getName() << " (arg_size: " << F.arg_size() 10 | << ")\n"; 11 | F.print(outs()); 12 | outs() << "\n[Function Users]\n"; 13 | for (auto &U : F.uses()) { 14 | User *user = U.getUser(); 15 | user->print(outs(), true); 16 | outs() << "\n"; 17 | } 18 | 19 | for (auto &B : F) { 20 | outs() << "\n#[Basic block]"; 21 | B.print(outs()); 22 | outs() << "#[BasicBlock Users]\n"; 23 | for (auto &U : B.uses()) { 24 | User *user = U.getUser(); 25 | user->print(outs(), true); 26 | outs() << "\n"; 27 | } 28 | 29 | for (auto &I : B) { 30 | outs() << "\n##[Instruction]\n"; 31 | I.print(outs(), true); 32 | outs() << "\n##[Users]\n"; 33 | for (auto &U : I.uses()) { 34 | User *user = U.getUser(); 35 | user->print(outs(), true); 36 | outs() << "\n"; 37 | } 38 | outs() << "##[Opernads]\n"; 39 | for (auto &U : I.operands()) { 40 | Value *use = U.get(); 41 | use->print(outs(), true); 42 | outs() << "\n"; 43 | } 44 | } 45 | } 46 | outs() << "\n"; 47 | } 48 | outs() << "\n"; 49 | return PreservedAnalyses::all(); 50 | }; 51 | }; 52 | 53 | PassPluginLibraryInfo getPassPluginInfo() { 54 | const auto callback = [](PassBuilder &PB) { 55 | PB.registerPipelineStartEPCallback([=](ModulePassManager &MPM, auto) { 56 | MPM.addPass(MyModPass{}); 57 | return true; 58 | }); 59 | PB.registerOptimizerLastEPCallback([=](ModulePassManager &MPM, auto) { 60 | MPM.addPass(MyModPass{}); 61 | return true; 62 | }); 63 | }; 64 | 65 | return {LLVM_PLUGIN_API_VERSION, "MyPlugin", "0.0.1", callback}; 66 | }; 67 | 68 | /* When a plugin is loaded by the driver, it will call this entry point to 69 | obtain information about this plugin and about how to register its passes. 70 | */ 71 | extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() { 72 | return getPassPluginInfo(); 73 | } 74 | -------------------------------------------------------------------------------- /LLVM_Pass/Pass5_change.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/IRBuilder.h" 2 | #include "llvm/IR/Verifier.h" 3 | #include "llvm/Passes/PassBuilder.h" 4 | #include "llvm/Passes/PassPlugin.h" 5 | #include 6 | using namespace llvm; 7 | 8 | struct MyModPass : public PassInfoMixin { 9 | PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { 10 | outs() << "[Module] " << M.getName() << "\n"; 11 | bool changed = false; 12 | std::list RemoveInstrs; 13 | for (auto &F : M) { 14 | outs() << "[Function] " << F.getName() << " (arg_size: " << F.arg_size() 15 | << ")\n"; 16 | if (F.isDeclaration()) { 17 | continue; 18 | } 19 | F.print(outs()); 20 | 21 | for (auto &B : F) { 22 | for (auto &I : B) { 23 | if (auto *op = dyn_cast(&I)) { 24 | outs() << "Modified instruction:\n"; 25 | I.print(outs(), true); 26 | outs() << "\n"; 27 | // Insert at the point where the instruction `op` appears. 28 | IRBuilder<> builder(op); 29 | 30 | // Make a sub with the same operands as `op`. 31 | Value *lhs = op->getOperand(0); 32 | Value *rhs = op->getOperand(1); 33 | Value *sub = builder.CreateSub(lhs, rhs); 34 | 35 | // Everywhere the old instruction was used as an operand, use our 36 | // new sub instruction instead. 37 | for (auto &U : op->uses()) { 38 | User *user = U.getUser(); // A User is anything with operands. 39 | user->setOperand(U.getOperandNo(), sub); 40 | } 41 | // 2 variants for removing (only RemoveInstrs works): 42 | // I.eraseFromParent(); 43 | // RemoveInstrs.push_back(&I); 44 | changed = true; 45 | outs() << "\n"; 46 | bool verif = verifyFunction(F, &outs()); 47 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 48 | } 49 | } 50 | } 51 | } 52 | for (auto I : RemoveInstrs) { 53 | I->eraseFromParent(); 54 | } 55 | return changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); 56 | }; 57 | }; 58 | 59 | PassPluginLibraryInfo getPassPluginInfo() { 60 | const auto callback = [](PassBuilder &PB) { 61 | PB.registerPipelineStartEPCallback([=](ModulePassManager &MPM, auto) { 62 | MPM.addPass(MyModPass{}); 63 | return true; 64 | }); 65 | }; 66 | 67 | return {LLVM_PLUGIN_API_VERSION, "MyPlugin", "0.0.1", callback}; 68 | }; 69 | 70 | /* When a plugin is loaded by the driver, it will call this entry point to 71 | obtain information about this plugin and about how to register its passes. 72 | */ 73 | extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() { 74 | return getPassPluginInfo(); 75 | } 76 | -------------------------------------------------------------------------------- /LLVM_Pass/Pass7_opt.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/IR/Verifier.h" 2 | #include "llvm/Passes/PassBuilder.h" 3 | #include "llvm/Passes/PassPlugin.h" 4 | using namespace llvm; 5 | 6 | struct MyModPass : public PassInfoMixin { 7 | PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { 8 | outs() << "[Module] " << M.getName() << "\n"; 9 | bool changed = false; 10 | for (auto &F : M) { 11 | outs() << "[Function] " << F.getName() << " (arg_size: " << F.arg_size() 12 | << ")\n"; 13 | if (F.isDeclaration()) { 14 | continue; 15 | } 16 | 17 | F.print(outs()); 18 | outs() << "\n"; 19 | 20 | for (auto &B : F) { 21 | for (auto &I : B) { 22 | if (AllocaInst *Alloca = dyn_cast(&I)) { 23 | outs() << "\nAllocation: (BB " << &B << "):\n"; 24 | Alloca->print(outs(), true); 25 | outs() << "\n"; 26 | StoreInst *Store = nullptr; 27 | LoadInst *Load = nullptr; 28 | 29 | for (auto &U : Alloca->uses()) { 30 | Instruction *UseInst = cast(U.getUser()); 31 | outs() << "\tUsers: "; 32 | UseInst->print(outs(), true); 33 | 34 | if (StoreInst *S = dyn_cast(UseInst)) { 35 | if (Store == nullptr) { 36 | Store = S; 37 | outs() << " == STORE\n"; 38 | } else { 39 | outs() << " == EXTRA STORE\n"; 40 | Store = nullptr; 41 | break; 42 | } 43 | } else if (LoadInst *L = dyn_cast(UseInst)) { 44 | if (Load == nullptr) { 45 | Load = L; 46 | outs() << " == LOAD\n"; 47 | } else { 48 | Load = nullptr; 49 | outs() << " == EXTRA LOAD\n"; 50 | break; 51 | } 52 | } else { 53 | Load = nullptr; 54 | outs() << " == EXTRA INSTR\n"; 55 | break; 56 | } 57 | } 58 | if (Load != nullptr && Store != nullptr) { 59 | BasicBlock *LoadBB = Load->getParent(); 60 | BasicBlock *StoreBB = Store->getParent(); 61 | if (LoadBB == StoreBB) { 62 | outs() << "[PASS] Store and load in the same BB\n"; 63 | continue; 64 | } 65 | outs() << "[PASS] Allocation is candidate\n"; 66 | changed = true; 67 | Value *Val = Store->getOperand(0); 68 | Instruction *ValInst = dyn_cast(Val); 69 | 70 | if (ValInst) { 71 | if (ValInst->isEHPad() || ValInst->mayThrow()) { 72 | continue; 73 | } 74 | ValInst->moveBefore(&*LoadBB->getFirstInsertionPt()); 75 | 76 | Store->eraseFromParent(); 77 | for (auto &U : Load->uses()) { 78 | Instruction *UseInst = cast(U.getUser()); 79 | outs() << "\t Load Users: "; 80 | UseInst->print(outs(), true); 81 | outs() << "\n"; 82 | for (int i = 0; i < UseInst->getNumOperands(); i++) { 83 | if (UseInst->getOperand(i) == Load) { 84 | UseInst->setOperand(i, Val); 85 | } 86 | } 87 | outs() << "\t Fixed Load Users: "; 88 | UseInst->print(outs(), true); 89 | outs() << "\n"; 90 | } 91 | Load->eraseFromParent(); 92 | } 93 | } 94 | } 95 | } 96 | } 97 | outs() << "\n"; 98 | bool verif = verifyFunction(F, &outs()); 99 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 100 | } 101 | outs() << "\n"; 102 | return changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); 103 | }; 104 | }; 105 | 106 | PassPluginLibraryInfo getPassPluginInfo() { 107 | const auto callback = [](PassBuilder &PB) { 108 | PB.registerPipelineStartEPCallback([=](ModulePassManager &MPM, auto) { 109 | MPM.addPass(MyModPass{}); 110 | return true; 111 | }); 112 | }; 113 | 114 | return {LLVM_PLUGIN_API_VERSION, "MyPlugin", "0.0.1", callback}; 115 | }; 116 | 117 | /* When a plugin is loaded by the driver, it will call this entry point to 118 | obtain information about this plugin and about how to register its passes. 119 | */ 120 | extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() { 121 | return getPassPluginInfo(); 122 | } 123 | -------------------------------------------------------------------------------- /LLVM_Pass/README.md: -------------------------------------------------------------------------------- 1 | # LLVM Pass example 2 | This is example of LLVM pass that collect static inforamtion about app IR and insert instrumentation for collecting dynamic information. 3 | 4 | 5 | ## Usage: 6 | ``` 7 | sudo apt install llvm 8 | clang++ Pass6_cfg.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 9 | clang -fpass-plugin=./libPass.so log.c ../SDL/sim.c ../SDL/app2.c ../SDL/start.c -lSDL2 10 | ``` 11 | ![Lissajous curve](https://github.com/user-attachments/assets/0fded2a6-a511-4505-8995-47a2670a1c8d) 12 | 13 | 14 | ## Examples for Functions processing: 15 | 1. Pass registration 16 | ``` 17 | clang++ Pass1_reg.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 18 | clang -fpass-plugin=./libPass.so c_examples/hello.c 19 | opt hello.ll -load-pass-plugin ./libPass.so -passes="function(mem2reg,sroa,myFuncPass),module(myModPass)" -o a.out -print-pipeline-passes 20 | ``` 21 | > For Mac arm64 (arm64-apple-darwin) add `-undefined dynamic_lookup` to the Pass compilation line (llvm version should be > 15). 22 | 2. Print Functions name 23 | ``` 24 | clang++ Pass2_names.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 25 | clang -fpass-plugin=./libPass.so c_examples/hello.c -O2 26 | ``` 27 | 3. Dump Functions, BasicBlocks and Instructions 28 | ``` 29 | clang++ Pass3_dump.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 30 | clang -fpass-plugin=./libPass.so c_examples/hello.c -O2 31 | ``` 32 | 4. Dump Uses of Functions, BasicBlocks and Instructions 33 | ``` 34 | clang++ Pass4_uses.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 35 | clang -fpass-plugin=./libPass.so c_examples/hello.c 36 | ``` 37 | 5. Change Binary operations to substruction 38 | ``` 39 | clang++ Pass5_change.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 40 | 41 | clang c_examples/calc.c 42 | ./a.out 43 | 44 | clang -fpass-plugin=./libPass.so c_examples/calc.c -emit-llvm -S -o calc.ll 45 | clang -fpass-plugin=./libPass.so c_examples/calc.c 46 | ./a.out 47 | ``` 48 | 6. Instrumentation for code profiling 49 | ``` 50 | clang++ Pass6_cfg.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 51 | 52 | clang -fpass-plugin=./libPass.so c_examples/calc.c -emit-llvm -S -o calc.ll 53 | clang -fpass-plugin=./libPass.so c_examples/calc.c log.c 54 | ./a.out 55 | 56 | clang -fpass-plugin=./libPass.so c_examples/fact.c -emit-llvm -S -o fact.ll 57 | clang -fpass-plugin=./libPass.so c_examples/fact.c log.c 58 | ./a.out 4 59 | 60 | ./trace.sh c_examples/fact.c 61 | ./a.out 4 62 | ./trace.sh ../SDL/app.c ../SDL/start.c ../SDL/sim.c -lSDL2 63 | ./a.out 64 | ``` 65 | 7. Example of bad optimization Pass 66 | ``` 67 | clang++ Pass7_opt.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so 68 | 69 | clang c_examples/exp1.c 70 | time ./a.out 1000 71 | clang -fpass-plugin=./libPass.so c_examples/exp1.c 72 | time ./a.out 1000 73 | 74 | clang c_examples/exp2.c 75 | time ./a.out 1000 76 | clang -fpass-plugin=./libPass.so c_examples/exp2.c 77 | time ./a.out 1000 78 | ``` 79 | 80 | ## Possible instructions classes: 81 | https://llvm.org/doxygen/classllvm_1_1Instruction.html 82 | -------------------------------------------------------------------------------- /LLVM_Pass/c_examples/calc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static int func(int arg1, int arg2) { return arg1 + arg2 * 2; } 6 | 7 | int main() { 8 | printf("%d\n", func(func(3, 4), func(5, 6)) + func(3, 4)); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /LLVM_Pass/c_examples/exp1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | double fact(uint64_t arg) { 7 | double res = 1.0; 8 | for (uint64_t j = 1.0; j <= arg; ++j) { 9 | res *= j; 10 | } 11 | return res; 12 | } 13 | 14 | double calc_exp(uint64_t len) { 15 | double exp = 0.0; 16 | for (uint64_t i = len; i > 0; --i) { 17 | exp += 1.0 / fact(i); 18 | } 19 | return exp + 1.0; 20 | } 21 | 22 | int main(int argc, char **argv) { 23 | uint64_t arg = 0; 24 | if (argc != 2 || (arg = atoi(argv[1])) > 10000 || errno != 0) { 25 | printf("Usage: 1 argument - exponent series len < 10000\n"); 26 | return 1; 27 | } 28 | 29 | for (uint64_t i = 0; i < 10000; i++) { 30 | double exp = calc_exp(arg); 31 | if (i == arg) { 32 | printf("Exp (len %lu) = %.10lf\n", arg, exp); 33 | } 34 | } 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /LLVM_Pass/c_examples/exp2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | double fact(uint64_t arg) { 7 | double res = 1.0; 8 | for (uint64_t j = 1; j <= arg; ++j) { 9 | res *= j; 10 | } 11 | return res; 12 | } 13 | 14 | double calc_exp(uint64_t len) { 15 | double exp = 0.0; 16 | for (uint64_t i = len; i > 0; --i) { 17 | exp += 1.0 / fact(i); 18 | } 19 | return exp + 1.0; 20 | } 21 | 22 | int main(int argc, char **argv) { 23 | uint64_t arg = 0; 24 | if (argc != 2 || (arg = atoi(argv[1])) > 10000 || errno != 0) { 25 | printf("Usage: 1 argument - exponent series len < 10000\n"); 26 | return 1; 27 | } 28 | 29 | double exp = calc_exp(arg); 30 | double res = 0.0; 31 | for (uint64_t i = 0; i < 10000; i++) { 32 | res += exp; 33 | } 34 | printf("Res = %.10lf\n", res); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /LLVM_Pass/c_examples/fact.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | uint64_t fact(uint64_t arg) { 7 | uint64_t res = 0; 8 | if (arg < 2) { 9 | res = 1; 10 | } else { 11 | uint64_t next = fact(arg - 1); 12 | res = arg * next; 13 | } 14 | return res; 15 | } 16 | 17 | int main(int argc, char **argv) { 18 | if (argc != 2) { 19 | printf("Usage: 1 argument - factorial len\n"); 20 | return 1; 21 | } 22 | uint64_t arg = atoi(argv[1]); 23 | if (errno == 0) { 24 | printf("Fact(%lu) = %lu\n", arg, fact(arg)); 25 | } else { 26 | printf("Usage: 1 argument - factorial len\n"); 27 | return 1; 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /LLVM_Pass/c_examples/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void func(int x) { 4 | if (x) { 5 | printf("Hello, world!\n"); 6 | } else { 7 | printf("Hell, world!\n"); 8 | } 9 | } 10 | 11 | int main() { 12 | func(1); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /LLVM_Pass/c_examples/test.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | return 42; 3 | } -------------------------------------------------------------------------------- /LLVM_Pass/log.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void funcStartLogger(char *funcName) { 4 | printf("[LOG] Start function '%s'\n", funcName); 5 | } 6 | 7 | void callLogger(char *callerName, char *calleeName, long int valID) { 8 | printf("[LOG] CALL '%s' -> '%s' {%ld}\n", callerName, calleeName, valID); 9 | } 10 | 11 | void funcEndLogger(char *funcName, long int valID) { 12 | printf("[LOG] End function '%s' {%ld}\n", funcName, valID); 13 | } 14 | 15 | void binOptLogger(int val, int arg0, int arg1, char *opName, char *funcName, 16 | long int valID) { 17 | printf("[LOG] In function '%s': %d = %d %s %d {%ld}\n", funcName, val, arg0, 18 | opName, arg1, valID); 19 | } 20 | 21 | void resIntLogger(long int res, long int valID) { 22 | printf("[LOG] Result %ld {%ld}\n", res, valID); 23 | } 24 | -------------------------------------------------------------------------------- /LLVM_Pass/trace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | if [ $# -eq 0 ]; then 6 | echo "Error: Need arguments with source code" 7 | exit 1 8 | fi 9 | 10 | if [ ! -f $1 ]; then 11 | echo "Error: $1 not found!" 12 | exit 1 13 | fi 14 | 15 | NAME=$(basename -- "$1") 16 | NAME="${NAME%.*}" 17 | 18 | clang++ Pass_trace.cpp -fPIC -shared -I$(llvm-config --includedir) -o libPass.so || exit 1 19 | 20 | clang -O2 $1 -emit-llvm -S -o $NAME.ll || exit 1 21 | clang -O2 -fpass-plugin=./libPass.so $1 -emit-llvm -S -o $NAME.log.ll || exit 1 22 | clang -O2 log.c $NAME.log.ll ${@:2} || exit 1 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LLVM Cource examples 2 | LLVM passes, IR generations, Flex&Bison and ANTLR parsers, LLVM BackEnd and simulator code examples for simple graphical SDL2 applications. 3 | 4 | ## SDL 5 | Simple examples of graphical application with simple interface based on the SDL 2.0. 6 | IRGen: LLVM IR generation for graphical application. Asm2IR LLVM IR generator for graphical application. 7 | 8 | ## LLVM Pass 9 | Examples of LLVM passes that collect static application IR inforamtion, insert instrumentation for collecting dynamic information and dummy optimization passes. 10 | Legacy: Examples of LLVM passes with old Pass Manager version. 11 | 12 | ## LLVM IRGen 13 | LLVM IR generators examples: 14 | "hello world" LLVM IR generator => Calculator based on LLVM IR => assembly file to LLVM IR lifter => mathematical expressions frontend. 15 | 16 | ## Flex_Bison 17 | Examples of parsers based on Flex and Bison: 18 | "hello world" => simple mathematical expressions => expressions with variables and arrays => simple programming language files => interpretation and LLVM IR building => simple FrontEnd. 19 | 20 | ## ANTLR 21 | Examples of parsers based on ANTLR: Expressions parser and Frontend. 22 | 23 | ## LLVM_Backend 24 | TableGen examples. Descriptions for simple steps for LLVM Backend implimentation for `sim` target. 25 | Steps are placed in https://github.com/lisitsynSA/llvm-add-backend. 26 | 27 | ## Sim 28 | Simple simulator for generated object files for `sim` target. Simulator ELF parsing is based on elfio. 29 | 30 | ## Full_Pipeline 31 | "Compiler driver" example for programming language files. 32 | `*.lang`/`*.nl`/`*.c` => Flex_Bison/ANTLR/Clang FrontEnd => `*.ll` => opt => `*.opt.ll` => Custom llc => `*.opt.s` + `*.opt.o` => simulator 33 | -------------------------------------------------------------------------------- /SDL/IRGen/app.s: -------------------------------------------------------------------------------- 1 | entry 2 | XOR x1 x1 x1 3 | main_loop 4 | XOR x2 x2 x2 5 | loop_y 6 | XOR x5 x5 x5 7 | MUL x3 x2 x1 8 | loop_x 9 | MUL x6 x3 x5 10 | SUBi x6 x6 16777216 11 | PUT_PIXEL x5 x2 x6 12 | INC_NEi x4 x5 512 13 | BR_COND x4 loop_x 14 | inc_y 15 | INC_NEi x4 x2 256 16 | BR_COND x4 loop_y 17 | inc_step 18 | FLUSH 19 | INC_NEi x4 x1 1000 20 | BR_COND x4 main_loop 21 | exit 22 | EXIT 23 | -------------------------------------------------------------------------------- /SDL/IRGen/app2isa.txt: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'app.c' 2 | source_filename = "app.c" 3 | target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 4 | target triple = "x86_64-pc-linux-gnu" 5 | 6 | ; Function Attrs: nounwind uwtable 7 | define dso_local void @app() local_unnamed_addr #0 { 8 | br label %1 9 | ## XOR x1 x1 x1 10 | ## XOR x2 x2 x2 11 | 12 | 1: ; preds = %0, %7 13 | x1 %2 = phi i32 [ 0, %0 ], [ %8, %7 ] 14 | br label %4 15 | 16 | 3: ; preds = %7 17 | ret void 18 | ## EXIT 19 | 20 | 4: ; preds = %1, %10 21 | x2 %5 = phi i32 [ 0, %1 ], [ %11, %10 ] 22 | x3 %6 = mul nuw nsw i32 %5, %2 23 | ## MUL x3 x2 x1 24 | br label %13 25 | 26 | 7: ; preds = %10 27 | tail call void (...) @simFlush() #2 28 | ## FLUSH 29 | x1 %8 = add nuw nsw i32 %2, 1 30 | x4 %9 = icmp eq i32 %8, 1000 31 | ## INC_EQ x4 x1 1000 32 | br i1 %9, label %3, label %1, !llvm.loop !5 33 | ## BR_COND x4 label_3 label_1 //fall 34 | 35 | 10: ; preds = %13 36 | x2 %11 = add nuw nsw i32 %5, 1 37 | x4 %12 = icmp eq i32 %11, 256 38 | ## INC_EQ x4 x2 256 39 | br i1 %12, label %7, label %4, !llvm.loop !7 40 | ## BR_COND x4 label_7 label_4 //fall 41 | 42 | 13: ; preds = %4, %13 43 | x5 %14 = phi i32 [ 0, %4 ], [ %17, %13 ] 44 | x6 %15 = mul nuw nsw i32 %6, %14 45 | ## MUL x6 x3 x5 46 | x6 %16 = add nsw i32 %15, -16777216 47 | ## SUB x6 x6 16777216 48 | tail call void @simPutPixel(i32 noundef %14, i32 noundef %5, i32 noundef %16) #2 49 | ## PUT_PIXEL x5 x2 x6 50 | x5 %17 = add nuw nsw i32 %14, 1 51 | x4 %18 = icmp eq i32 %17, 512 52 | ## INC_EQ x4 x5 512 53 | br i1 %18, label %10, label %13, !llvm.loop !8 54 | ## BR_COND x4 label_10 label_13 //fall 55 | } 56 | 57 | declare void @simPutPixel(i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr #1 58 | 59 | declare void @simFlush(...) local_unnamed_addr #1 60 | 61 | attributes #0 = { nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 62 | attributes #1 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 63 | attributes #2 = { nounwind } 64 | 65 | !llvm.module.flags = !{!0, !1, !2, !3} 66 | !llvm.ident = !{!4} 67 | 68 | !0 = !{i32 1, !"wchar_size", i32 4} 69 | !1 = !{i32 7, !"PIC Level", i32 2} 70 | !2 = !{i32 7, !"PIE Level", i32 2} 71 | !3 = !{i32 7, !"uwtable", i32 1} 72 | !4 = !{!"Ubuntu clang version 14.0.0-1ubuntu1.1"} 73 | !5 = distinct !{!5, !6} 74 | !6 = !{!"llvm.loop.mustprogress"} 75 | !7 = distinct !{!7, !6} 76 | !8 = distinct !{!8, !6} 77 | -------------------------------------------------------------------------------- /SDL/IRGen/app_pre.s: -------------------------------------------------------------------------------- 1 | label_0: 2 | XOR x1 x1 x1 // step = 0 3 | label_1: // main loop start 4 | XOR x2 x2 x2 // y = 0 5 | B label_4 6 | label_3: // main loop end 7 | EXIT 8 | label_4: // loop y start 9 | XOR x5 x5 x5 // x = 0 10 | MUL x3 x2 x1 // step*y 11 | B label_13 12 | label_7: // loop y end 13 | FLUSH 14 | INC_EQ x4 x1 1000 15 | BR_COND x4 label_3 label_1//fall 16 | label_10: // increment y 17 | INC_EQ x4 x2 256 18 | BR_COND x4 label_7 label_4//fall 19 | label_13: // loop x 20 | MUL x6 x3 x5 // step*y*x 21 | SUB x6 x6 16777216 // argb 22 | PUT_PIXEL x5 x2 x6 23 | INC_EQ x4 x5 512 24 | BR_COND x4 label_10 label_13//fall -------------------------------------------------------------------------------- /SDL/IRGen/app_pre2.s: -------------------------------------------------------------------------------- 1 | label_0: 2 | XOR x1 x1 x1 // step = 0 3 | label_1: // main loop start 4 | XOR x2 x2 x2 // y = 0 5 | label_4: // loop y start 6 | XOR x5 x5 x5 // x = 0 7 | MUL x3 x2 x1 // step*y 8 | label_13: // loop x 9 | MUL x6 x3 x5 // step*y*x 10 | SUB x6 x6 16777216 // argb 11 | PUT_PIXEL x5 x2 x6 12 | INC_NE x4 x5 512 13 | BR_COND x4 label_13 14 | label_10: // increment y 15 | INC_NE x4 x2 256 16 | BR_COND x4 label_4 17 | label_7: // loop y end 18 | FLUSH 19 | INC_NE x4 x1 1000 20 | BR_COND x4 label_1 21 | label_3: // main loop end 22 | EXIT -------------------------------------------------------------------------------- /SDL/README.md: -------------------------------------------------------------------------------- 1 | # Simple graphical example 2 | This is example of graphical application with simple interface based on the SDL 2.0. 3 | 4 | ## Usage: 5 | Simple run: 6 | ``` 7 | sudo apt install libsdl2-dev 8 | clang start.c sim.c app.c -lSDL2 9 | ./a.out 10 | ``` 11 | Run with your LLVM Pass: 12 | ``` 13 | # Old Pass Manager 14 | clang start.c sim.c app.c -lSDL2 -Xclang -load -Xclang ../LLVM_PASS/libPass.so -flegacy-pass-manager 15 | # New Pass Manager 16 | clang start.c sim.c app.c -lSDL2 -fpass-plugin=../LLVM_PASS/libPass.so 17 | ``` 18 | 19 | ## Graphical Interface: 20 | ``` 21 | #define SIM_X_SIZE 512 22 | #define SIM_Y_SIZE 256 23 | 24 | void simFlush(); 25 | void simPutPixel(int x, int y, int argb); 26 | int simRand(); 27 | ``` 28 | 29 | ## Graphical app instrumentation: 30 | ``` 31 | clang++ ../LLVM_Pass/Pass_cfg.cpp -c -fPIC -I$(llvm-config --includedir) -o Pass.o 32 | clang++ Pass.o -fPIC -shared -o libPass.so 33 | clang app.c -c -fpass-plugin=../LLVM_PASS/libPass.so 34 | clang start.c sim.c app.o ../LLVM_Pass/log.c -lSDL2 35 | ./a.out 36 | 37 | ``` 38 | ## Graphical app IR generations: 39 | ``` 40 | clang++ $(llvm-config --cppflags --ldflags --libs) sim.c IRGen/app_ir_gen.cpp -lSDL2 41 | ./a.out 42 | 43 | clang++ $(llvm-config --cppflags --ldflags --libs) sim.c IRGen/app_asm_IRgen_1.cpp -lSDL2 44 | ./a.out IRGen/app.s 45 | 46 | clang++ $(llvm-config --cppflags --ldflags --libs) sim.c IRGen/app_asm_IRgen_2.cpp -lSDL2 47 | ./a.out IRGen/app.s 48 | ``` 49 | 50 | ## SDL 2.0 documentation: 51 | https://wiki.libsdl.org -------------------------------------------------------------------------------- /SDL/app.c: -------------------------------------------------------------------------------- 1 | #include "sim.h" 2 | 3 | void app() { 4 | for (int step = 0; step < 1000; ++step) { 5 | for (int y = 0; y < SIM_Y_SIZE; ++y) 6 | for (int x = 0; x < SIM_X_SIZE; ++x) 7 | simPutPixel(x, y, 0xFF000000 + x * y * step); 8 | simFlush(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /SDL/app2.c: -------------------------------------------------------------------------------- 1 | #include "sim.h" 2 | 3 | #define STEPS 10 4 | 5 | int getAbsVelocity(int v1, int v2) { 6 | if (v1 < 0) { 7 | v1 = -v1; 8 | } 9 | if (v2 < 0) { 10 | v2 = -v2; 11 | } 12 | return (v1 + v2)*2 & 0xFF; 13 | } 14 | 15 | void drawLine(int x, int y, int v_x, int v_y) { 16 | int x_len = v_x / 5; 17 | int y_len = v_y / 5; 18 | int v_abs = getAbsVelocity(v_x, v_y); 19 | for (int step = 0; step < STEPS; step++) { 20 | simPutPixel(x + x_len * step / STEPS, y + y_len * step / STEPS, 21 | 0xFF0000FF + (v_abs << 16)); 22 | } 23 | } 24 | 25 | void app() { 26 | int x = (simRand() % SIM_X_SIZE) / 10; 27 | int y = (simRand() % SIM_Y_SIZE) / 10; 28 | int v_x = simRand() % 10; 29 | int v_y = simRand() % 10; 30 | while (1) { 31 | drawLine(x, y, v_x, v_y); 32 | simFlush(); 33 | x += v_x / 5; 34 | y += v_y / 5; 35 | v_x += (SIM_X_SIZE / 2 - x) * 10 / SIM_X_SIZE; 36 | v_y += (SIM_Y_SIZE / 2 - y) * 10 / SIM_Y_SIZE; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SDL/sim.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "sim.h" 6 | 7 | #define FRAME_TICKS 50 8 | 9 | static SDL_Renderer *Renderer = NULL; 10 | static SDL_Window *Window = NULL; 11 | static Uint32 Ticks = 0; 12 | 13 | void simInit() 14 | { 15 | SDL_Init(SDL_INIT_VIDEO); 16 | SDL_CreateWindowAndRenderer(SIM_X_SIZE, SIM_Y_SIZE, 0, &Window, &Renderer); 17 | SDL_SetRenderDrawColor(Renderer, 0, 0, 0, 0); 18 | SDL_RenderClear(Renderer); 19 | srand(time(NULL)); 20 | simPutPixel(0, 0, 0); 21 | simFlush(); 22 | } 23 | 24 | void simExit() 25 | { 26 | SDL_Event event; 27 | while (1) 28 | { 29 | if (SDL_PollEvent(&event) && event.type == SDL_QUIT) 30 | break; 31 | } 32 | SDL_DestroyRenderer(Renderer); 33 | SDL_DestroyWindow(Window); 34 | SDL_Quit(); 35 | } 36 | 37 | void simFlush() 38 | { 39 | SDL_PumpEvents(); 40 | assert(SDL_TRUE != SDL_HasEvent(SDL_QUIT) && "User-requested quit"); 41 | Uint32 cur_ticks = SDL_GetTicks() - Ticks; 42 | if (cur_ticks < FRAME_TICKS) 43 | { 44 | SDL_Delay(FRAME_TICKS - cur_ticks); 45 | } 46 | SDL_RenderPresent(Renderer); 47 | } 48 | 49 | void simPutPixel(int x, int y, int argb) 50 | { 51 | assert(0 <= x && x < SIM_X_SIZE && "Out of range"); 52 | assert(0 <= y && y < SIM_Y_SIZE && "Out of range"); 53 | Uint8 a = argb >> 24; 54 | Uint8 r = (argb >> 16) & 0xFF; 55 | Uint8 g = (argb >> 8) & 0xFF; 56 | Uint8 b = argb & 0xFF; 57 | SDL_SetRenderDrawColor(Renderer, r, g, b, a); 58 | SDL_RenderDrawPoint(Renderer, x, y); 59 | Ticks = SDL_GetTicks(); 60 | } 61 | 62 | int simRand() 63 | { 64 | return rand(); 65 | } -------------------------------------------------------------------------------- /SDL/sim.h: -------------------------------------------------------------------------------- 1 | #define SIM_X_SIZE 512 2 | #define SIM_Y_SIZE 256 3 | 4 | #ifndef __sim__ 5 | void simInit(); 6 | void app(); 7 | void simExit(); 8 | void simFlush(); 9 | void simPutPixel(int x, int y, int argb); 10 | int simRand(); 11 | #endif 12 | -------------------------------------------------------------------------------- /SDL/start.c: -------------------------------------------------------------------------------- 1 | #include "sim.h" 2 | 3 | int main(void) 4 | { 5 | simInit(); 6 | app(); 7 | simExit(); 8 | return 0; 9 | } -------------------------------------------------------------------------------- /Sim/README.md: -------------------------------------------------------------------------------- 1 | ## Simple Simulator implementation: 2 | The ISA description is placed in the `include/ISA.h`. 3 | 4 | Application needs 2 argument: file with assembler or binary code and execution mod (1-3): 5 | 1. Simulation 6 | 2. IR with emulate funcs 7 | 3. Full IR generation 8 | ``` 9 | clang++ $(llvm-config --cppflags --ldflags --libs) *.cpp ../SDL/sim.c -I ../SDL -lSDL2 10 | ./a.out examples/app.sim 1-3 11 | ./a.out examples/graphic.sim 1-3 12 | ./a.out examples/graphic.o 1-3 13 | ./a.out examples/clang.o 1-3 14 | ./a.out examples/lang.o 1-3 15 | ./a.out examples/nodelang.o 1-3 16 | ./a.out examples/app2.o 1-3 17 | ``` 18 | ## Endless compilation: 19 | Choose IR Generation: 20 | ``` 21 | ./a.out examples/app.sim 3 tmp1_.ll 22 | ./a.out examples/clang.o 3 tmp1_.ll 23 | ./a.out examples/lang.o 3 tmp1_.ll 24 | ./a.out examples/nodelang.o 3 tmp1_.ll 25 | ./a.out examples/app2.o 3 tmp1_.ll 26 | ``` 27 | Compilation loop.sh: 28 | ``` 29 | IR -> OptIR : opt tmp(i)_.ll -O2 -o tmp(i).ll -S 30 | OptIR -> Bin : llc tmp(i).ll -march sim -filetype=obj 31 | Bin -> IR : ./a.out tmp(i).o 3 tmp(i+1)_.ll 32 | ``` 33 | ## ELFIO repository: 34 | https://github.com/serge1/ELFIO 35 | -------------------------------------------------------------------------------- /Sim/bin.cpp: -------------------------------------------------------------------------------- 1 | #include "include/bin.h" 2 | #include "include/instr.h" 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | bool Binary::searchBBs(ifstream &InputFile, string &ErrorMsg) { 9 | string Name; 10 | string Arg; 11 | uint32_t PC = 0; 12 | uint32_t Opcode = 0; 13 | while (InputFile >> Name) { 14 | Opcode = Instr::getOpcode(Name); 15 | switch (Opcode) { 16 | default: 17 | if (BBName2PC.find(Name) != BBName2PC.end()) { 18 | ErrorMsg = string("Repetition of label: " + Name); 19 | return true; 20 | } 21 | BBName2PC[Name] = PC; 22 | if (PC2BBName.find(PC) != PC2BBName.end()) { 23 | ErrorMsg = string("2 labels can't be on the one PC: " + Name + " and " + 24 | PC2BBName[PC]); 25 | return true; 26 | } 27 | PC2BBName[PC] = Name; 28 | continue; 29 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 30 | _IRGenExecute) \ 31 | case (_Opcode): \ 32 | _SkipArgs; \ 33 | break; 34 | #include "include/ISA.h" 35 | #undef _ISA 36 | } 37 | PC++; 38 | } 39 | return false; 40 | } 41 | 42 | string Binary::writeBBs() { 43 | stringstream Stream; 44 | for (auto &it : BBName2PC) { 45 | Stream << " " << it.second << ": " << it.first << "\n"; 46 | } 47 | return Stream.str(); 48 | } 49 | 50 | bool Binary::readInstrs(ifstream &InputFile, string &ErrorMsg) { 51 | string Name; 52 | string Arg; 53 | uint32_t Opcode = 0; 54 | while (InputFile >> Name) { 55 | Opcode = Instr::getOpcode(Name); 56 | Instr I; 57 | I.Op = Opcode; 58 | switch (Opcode) { 59 | default: 60 | if (BBName2PC.find(Name) != BBName2PC.end()) 61 | continue; 62 | ErrorMsg = string("Wrong Opcode for " + Name); 63 | return true; 64 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 65 | _IRGenExecute) \ 66 | case (_Opcode): \ 67 | _ReadArgs; \ 68 | break; 69 | #include "include/ISA.h" 70 | #undef _ISA 71 | } 72 | Instrs.push_back(I); 73 | } 74 | return false; 75 | } 76 | 77 | string Binary::writeInstrs() { 78 | stringstream Stream; 79 | uint32_t PC = 0; 80 | for (Instr &I : Instrs) { 81 | auto Label = PC2BBName.find(PC); 82 | if (Label != PC2BBName.end()) { 83 | Stream << Label->second << "\n"; 84 | } 85 | switch (I.Op) { 86 | default: 87 | Stream << "\nWrong Opcode: " << I.Op << "\n"; 88 | break; 89 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 90 | _IRGenExecute) \ 91 | case (_Opcode): \ 92 | Stream << " " << #_Name; \ 93 | _WriteArgs; \ 94 | Stream << "\n"; \ 95 | break; 96 | #include "include/ISA.h" 97 | #undef _ISA 98 | } 99 | PC++; 100 | } 101 | return Stream.str(); 102 | } 103 | 104 | bool Binary::readFile(string FileName, string &ErrorMsg) { 105 | ifstream Input; 106 | Input.open(FileName); 107 | if (!Input.is_open()) { 108 | ErrorMsg = string("Can't open " + FileName); 109 | return true; 110 | } 111 | string LocalErrorMsg; 112 | if (searchBBs(Input, LocalErrorMsg)) { 113 | ErrorMsg = string("In searchBBs: " + LocalErrorMsg); 114 | return true; 115 | } 116 | Input.clear(); 117 | Input.seekg(0, ios::beg); 118 | if (readInstrs(Input, LocalErrorMsg)) { 119 | ErrorMsg = string("In readInstrs: " + LocalErrorMsg); 120 | return true; 121 | } 122 | return false; 123 | } 124 | -------------------------------------------------------------------------------- /Sim/binElf.cpp: -------------------------------------------------------------------------------- 1 | #include "elfio/elfio.hpp" 2 | #include "include/bin.h" 3 | #include "include/instr.h" 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | using namespace ELFIO; 9 | 10 | string hexCode(uint32_t i, uint32_t code) { 11 | std::stringstream stream; 12 | stream << setfill('0') << setw(4) << i << ": " << setw(8) << hex << code; 13 | return stream.str(); 14 | } 15 | 16 | bool Binary::readBin(string FileName, string &ErrorMsg) { 17 | // Create an elfio reader 18 | elfio reader; 19 | 20 | // Load ELF data 21 | if (!reader.load(FileName)) { 22 | ErrorMsg = string("Can't find or process ELF file" + FileName); 23 | return true; 24 | } 25 | 26 | // Print ELF file sections info 27 | Elf_Half secNum = reader.sections.size(); 28 | const uint32_t *code = nullptr; 29 | Elf_Xword appStart = 0; 30 | Elf_Xword appSize = 0; 31 | stringstream Stream; 32 | for (int sec = 0; sec < secNum; ++sec) { 33 | section *psec = reader.sections[sec]; 34 | if (psec->get_name() == ".text") { 35 | code = (const uint32_t *)reader.sections[sec]->get_data(); 36 | Stream << "[Section " << sec << "] " << psec->get_name() 37 | << " Size: " << psec->get_size() << "\n"; 38 | } 39 | if (psec->get_type() == SHT_SYMTAB) { 40 | const symbol_section_accessor symbols(reader, psec); 41 | for (unsigned int symbol = 0; symbol < symbols.get_symbols_num(); 42 | ++symbol) { 43 | string name; 44 | Elf64_Addr value; 45 | Elf_Xword size; 46 | unsigned char bind; 47 | unsigned char type; 48 | Elf_Half section_index; 49 | unsigned char other; 50 | 51 | // Read symbol properties 52 | symbols.get_symbol(symbol, name, value, size, bind, type, section_index, 53 | other); 54 | if (name == "app") { 55 | appStart = value / 4; 56 | appSize = size / 4; 57 | Stream << "[Symbol " << symbol << "] " << name << " Offset: " << value 58 | << " Size: " << size << endl; 59 | } 60 | } 61 | } 62 | } 63 | 64 | if (!code) { 65 | ErrorMsg = string("Can't find Entrypooint in " + FileName); 66 | return true; 67 | } 68 | 69 | PC2BBName[0] = "L0"; 70 | BBName2PC["L0"] = 0; 71 | // Add Instructions and Labels 72 | for (uint32_t PC = 0; PC < appSize; ++PC) { 73 | uint32_t instr = code[appStart + PC]; 74 | Instr I; 75 | // Parse Instruction 76 | I.R3Imm = instr & 0xFFFF; 77 | I.R2 = (instr >> 16) & 0xF; 78 | I.R1 = (instr >> 20) & 0xF; 79 | I.Op = instr >> 24; 80 | // Add Label 81 | if (I.Op == Instr::B || I.Op == Instr::BR_COND) { 82 | I.R3Imm = PC + (int16_t)I.R3Imm; 83 | string label = "L" + to_string(I.R3Imm); 84 | PC2BBName[I.R3Imm] = label; 85 | BBName2PC[label] = I.R3Imm; 86 | } 87 | Stream << hexCode(PC, instr) << " "; 88 | switch (I.Op) { 89 | default: 90 | Stream << "Wrong Opcode\n"; 91 | cout << Stream.str(); 92 | return true; 93 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 94 | _IRGenExecute) \ 95 | case (_Opcode): \ 96 | Stream << #_Name; \ 97 | _WriteArgs; \ 98 | Stream << "\n"; \ 99 | break; 100 | #include "include/ISA.h" 101 | #undef _ISA 102 | } 103 | Instrs.push_back(I); 104 | // Add Label 105 | if (PC != appSize - 1 && (I.Op == Instr::B || I.Op == Instr::BR_COND)) { 106 | string label = "L" + to_string(PC + 1); 107 | PC2BBName[PC + 1] = label; 108 | BBName2PC[label] = PC + 1; 109 | } 110 | } 111 | cout << Stream.str(); 112 | return false; 113 | } -------------------------------------------------------------------------------- /Sim/cpu.cpp: -------------------------------------------------------------------------------- 1 | #include "include/cpu.h" 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | CPU *CPU::C; 7 | 8 | bool CPU::Execute(Binary &Bin, string &ErrorMsg) { 9 | PC = 0; 10 | Run = 1; 11 | setCPU(this); 12 | simInit(); 13 | while (Run) { 14 | Instr I = Bin.Instrs[PC]; 15 | // cout << dumpStatus(Bin); 16 | NextPC = PC + 1; 17 | switch (I.Op) { 18 | default: 19 | ErrorMsg = string("Wrong Opcode: " + to_string(Bin.Instrs[PC].Op)); 20 | return true; 21 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 22 | _IRGenExecute) \ 23 | case (_Opcode): \ 24 | do_##_Name(I.R1, I.R2, I.R3Imm); \ 25 | break; 26 | #include "include/ISA.h" 27 | #undef _ISA 28 | } 29 | PC = NextPC; 30 | } 31 | simExit(); 32 | return false; 33 | } 34 | 35 | string CPU::dumpStatus(Binary &Bin) { 36 | stringstream Stream; 37 | for (uint32_t i = 0; i < RegSize; i++) { 38 | Stream << " x" << i << ":" << (int32_t)RegFile[i] << "(" << hex 39 | << RegFile[i] << ")" << dec; 40 | } 41 | Stream << " PC:" << PC << "\n"; 42 | Instr I = Bin.Instrs[PC]; 43 | std::map &PC2BBName = Bin.PC2BBName; 44 | switch (I.Op) { 45 | default: 46 | Stream << "\nWrong Opcode: " << I.Op << "\n"; 47 | break; 48 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 49 | _IRGenExecute) \ 50 | case (_Opcode): \ 51 | Stream << " " << #_Name; \ 52 | _WriteArgs; \ 53 | Stream << "\n"; \ 54 | break; 55 | #include "include/ISA.h" 56 | #undef _ISA 57 | } 58 | return Stream.str(); 59 | } -------------------------------------------------------------------------------- /Sim/elfio/elfio_array.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_ARRAY_HPP 24 | #define ELFIO_ARRAY_HPP 25 | 26 | #include 27 | 28 | namespace ELFIO { 29 | 30 | //------------------------------------------------------------------------------ 31 | template class array_section_accessor_template 32 | { 33 | public: 34 | //------------------------------------------------------------------------------ 35 | explicit array_section_accessor_template( const elfio& elf_file, 36 | S* section ) 37 | : elf_file( elf_file ), array_section( section ) 38 | { 39 | } 40 | 41 | //------------------------------------------------------------------------------ 42 | Elf_Xword get_entries_num() const 43 | { 44 | Elf_Xword entry_size = sizeof( T ); 45 | return array_section->get_size() / entry_size; 46 | } 47 | 48 | //------------------------------------------------------------------------------ 49 | bool get_entry( Elf_Xword index, Elf64_Addr& address ) const 50 | { 51 | if ( index >= get_entries_num() ) { // Is index valid 52 | return false; 53 | } 54 | 55 | const endianess_convertor& convertor = elf_file.get_convertor(); 56 | 57 | const T temp = *reinterpret_cast( array_section->get_data() + 58 | index * sizeof( T ) ); 59 | address = convertor( temp ); 60 | 61 | return true; 62 | } 63 | 64 | //------------------------------------------------------------------------------ 65 | void add_entry( Elf64_Addr address ) 66 | { 67 | const endianess_convertor& convertor = elf_file.get_convertor(); 68 | 69 | T temp = convertor( (T)address ); 70 | array_section->append_data( reinterpret_cast( &temp ), 71 | sizeof( temp ) ); 72 | } 73 | 74 | private: 75 | //------------------------------------------------------------------------------ 76 | const elfio& elf_file; 77 | S* array_section; 78 | }; 79 | 80 | template 81 | using array_section_accessor = array_section_accessor_template; 82 | template 83 | using const_array_section_accessor = 84 | array_section_accessor_template; 85 | 86 | } // namespace ELFIO 87 | 88 | #endif // ELFIO_ARRAY_HPP 89 | -------------------------------------------------------------------------------- /Sim/elfio/elfio_modinfo.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_MODINFO_HPP 24 | #define ELFIO_MODINFO_HPP 25 | 26 | #include 27 | #include 28 | 29 | namespace ELFIO { 30 | 31 | //------------------------------------------------------------------------------ 32 | template class modinfo_section_accessor_template 33 | { 34 | public: 35 | //------------------------------------------------------------------------------ 36 | explicit modinfo_section_accessor_template( S* section ) 37 | : modinfo_section( section ) 38 | { 39 | process_section(); 40 | } 41 | 42 | //------------------------------------------------------------------------------ 43 | Elf_Word get_attribute_num() const { return (Elf_Word)content.size(); } 44 | 45 | //------------------------------------------------------------------------------ 46 | bool 47 | get_attribute( Elf_Word no, std::string& field, std::string& value ) const 48 | { 49 | if ( no < content.size() ) { 50 | field = content[no].first; 51 | value = content[no].second; 52 | return true; 53 | } 54 | 55 | return false; 56 | } 57 | 58 | //------------------------------------------------------------------------------ 59 | bool get_attribute( const std::string_view& field_name, 60 | std::string& value ) const 61 | { 62 | for ( const auto [first, second] : content ) { 63 | if ( field_name == first ) { 64 | value = second; 65 | return true; 66 | } 67 | } 68 | 69 | return false; 70 | } 71 | 72 | //------------------------------------------------------------------------------ 73 | Elf_Word add_attribute( const std::string& field, const std::string& value ) 74 | { 75 | Elf_Word current_position = 0; 76 | 77 | if ( modinfo_section ) { 78 | // Strings are addeded to the end of the current section data 79 | current_position = (Elf_Word)modinfo_section->get_size(); 80 | 81 | std::string attribute = field + "=" + value; 82 | 83 | modinfo_section->append_data( attribute + '\0' ); 84 | content.emplace_back( field, value ); 85 | } 86 | 87 | return current_position; 88 | } 89 | 90 | //------------------------------------------------------------------------------ 91 | private: 92 | void process_section() 93 | { 94 | const char* pdata = modinfo_section->get_data(); 95 | if ( pdata ) { 96 | ELFIO::Elf_Xword i = 0; 97 | while ( i < modinfo_section->get_size() ) { 98 | while ( i < modinfo_section->get_size() && !pdata[i] ) 99 | i++; 100 | if ( i < modinfo_section->get_size() ) { 101 | std::string info = pdata + i; 102 | size_t loc = info.find( '=' ); 103 | content.emplace_back( info.substr( 0, loc ), 104 | info.substr( loc + 1 ) ); 105 | 106 | i += info.length(); 107 | } 108 | } 109 | } 110 | } 111 | 112 | //------------------------------------------------------------------------------ 113 | private: 114 | S* modinfo_section; 115 | std::vector> content; 116 | }; 117 | 118 | using modinfo_section_accessor = modinfo_section_accessor_template
; 119 | using const_modinfo_section_accessor = 120 | modinfo_section_accessor_template; 121 | 122 | } // namespace ELFIO 123 | 124 | #endif // ELFIO_MODINFO_HPP 125 | -------------------------------------------------------------------------------- /Sim/elfio/elfio_strings.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_STRINGS_HPP 24 | #define ELFIO_STRINGS_HPP 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace ELFIO { 31 | 32 | //------------------------------------------------------------------------------ 33 | template class string_section_accessor_template 34 | { 35 | public: 36 | //------------------------------------------------------------------------------ 37 | explicit string_section_accessor_template( S* section ) 38 | : string_section( section ) 39 | { 40 | } 41 | 42 | //------------------------------------------------------------------------------ 43 | const char* get_string( Elf_Word index ) const 44 | { 45 | if ( string_section ) { 46 | const char* data = string_section->get_data(); 47 | if ( index < string_section->get_size() && nullptr != data ) { 48 | size_t string_length = 49 | strnlen( data + index, string_section->get_size() - index ); 50 | if ( string_length < ( string_section->get_size() - index ) ) 51 | return data + index; 52 | } 53 | } 54 | 55 | return nullptr; 56 | } 57 | 58 | //------------------------------------------------------------------------------ 59 | Elf_Word add_string( const char* str ) 60 | { 61 | Elf_Word current_position = 0; 62 | 63 | if ( string_section ) { 64 | // Strings are addeded to the end of the current section data 65 | current_position = 66 | static_cast( string_section->get_size() ); 67 | 68 | if ( current_position == 0 ) { 69 | char empty_string = '\0'; 70 | string_section->append_data( &empty_string, 1 ); 71 | current_position++; 72 | } 73 | string_section->append_data( 74 | str, static_cast( std::strlen( str ) + 1 ) ); 75 | } 76 | 77 | return current_position; 78 | } 79 | 80 | //------------------------------------------------------------------------------ 81 | Elf_Word add_string( const std::string& str ) 82 | { 83 | return add_string( str.c_str() ); 84 | } 85 | 86 | //------------------------------------------------------------------------------ 87 | private: 88 | S* string_section; 89 | }; 90 | 91 | using string_section_accessor = string_section_accessor_template
; 92 | using const_string_section_accessor = 93 | string_section_accessor_template; 94 | 95 | } // namespace ELFIO 96 | 97 | #endif // ELFIO_STRINGS_HPP 98 | -------------------------------------------------------------------------------- /Sim/elfio/elfio_version.hpp: -------------------------------------------------------------------------------- 1 | #define ELFIO_VERSION "3.12" 2 | -------------------------------------------------------------------------------- /Sim/examples/app.sim: -------------------------------------------------------------------------------- 1 | entry 2 | XOR x1 x1 x1 3 | main_loop 4 | XOR x2 x2 x2 5 | loop_y 6 | XOR x5 x5 x5 7 | MUL x3 x2 x1 8 | loop_x 9 | MUL x6 x3 x5 10 | SUBi x6 x6 16777216 11 | PUT_PIXEL x5 x2 x6 12 | INC_NEi x4 x5 512 13 | BR_COND x4 loop_x 14 | inc_y 15 | INC_NEi x4 x2 256 16 | BR_COND x4 loop_y 17 | inc_step 18 | FLUSH 19 | INC_NEi x4 x1 1000 20 | BR_COND x4 main_loop 21 | exit 22 | EXIT 23 | -------------------------------------------------------------------------------- /Sim/examples/app2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lisitsynSA/llvm_course/bc5c420881a38874293a8fca8ddb29713d8445be/Sim/examples/app2.o -------------------------------------------------------------------------------- /Sim/examples/app2.s: -------------------------------------------------------------------------------- 1 | .file "app2.c" 2 | .text 3 | .globl getAbsVelocity ; -- Begin function getAbsVelocity 4 | .type getAbsVelocity,@function 5 | getAbsVelocity: ; @getAbsVelocity 6 | ; %bb.0: ; %entry 7 | ABS r2 r9 8 | ABS r4 r10 9 | ADD r2 r4 r2 10 | ANDi r9 r2 255 11 | BR r0 12 | .Lfunc_end0: 13 | .size getAbsVelocity, .Lfunc_end0-getAbsVelocity 14 | ; -- End function 15 | .globl drawLine ; -- Begin function drawLine 16 | .type drawLine,@function 17 | drawLine: ; @drawLine 18 | ; %bb.0: ; %entry 19 | ABS r2 r11 20 | ABS r4 r12 21 | ADD r2 r4 r2 22 | SHLi r2 r2 16 23 | MOVhi r4 65280 24 | ORi r4 r4 255 25 | OR r2 r2 r4 26 | PUTPIXEL r9 r10 r2 27 | DIVi r4 r12 50 28 | ADD r4 r4 r10 29 | DIVi r13 r11 50 30 | ADD r13 r13 r9 31 | PUTPIXEL r13 r4 r2 32 | DIVi r4 r12 25 33 | ADD r4 r4 r10 34 | DIVi r13 r11 25 35 | ADD r13 r13 r9 36 | PUTPIXEL r13 r4 r2 37 | DIVi r4 r12 5 38 | MULi r13 r4 3 39 | DIVi r13 r13 10 40 | ADD r14 r13 r10 41 | DIVi r13 r11 5 42 | MULi r15 r13 3 43 | DIVi r15 r15 10 44 | ADD r15 r15 r9 45 | PUTPIXEL r15 r14 r2 46 | SHLi r14 r4 2 47 | DIVi r14 r14 10 48 | ADD r14 r14 r10 49 | SHLi r15 r13 2 50 | DIVi r15 r15 10 51 | ADD r15 r15 r9 52 | PUTPIXEL r15 r14 r2 53 | DIVi r12 r12 10 54 | ADD r12 r12 r10 55 | DIVi r11 r11 10 56 | ADD r11 r11 r9 57 | PUTPIXEL r11 r12 r2 58 | MULi r11 r4 6 59 | DIVi r11 r11 10 60 | ADD r11 r11 r10 61 | MULi r12 r13 6 62 | DIVi r12 r12 10 63 | ADD r12 r12 r9 64 | PUTPIXEL r12 r11 r2 65 | MULi r11 r4 7 66 | DIVi r11 r11 10 67 | ADD r11 r11 r10 68 | MULi r12 r13 7 69 | DIVi r12 r12 10 70 | ADD r12 r12 r9 71 | PUTPIXEL r12 r11 r2 72 | SHLi r11 r4 3 73 | DIVi r11 r11 10 74 | ADD r11 r11 r10 75 | SHLi r12 r13 3 76 | DIVi r12 r12 10 77 | ADD r12 r12 r9 78 | PUTPIXEL r12 r11 r2 79 | MULi r4 r4 9 80 | DIVi r4 r4 10 81 | ADD r4 r4 r10 82 | MULi r10 r13 9 83 | DIVi r10 r10 10 84 | ADD r9 r10 r9 85 | PUTPIXEL r9 r4 r2 86 | BR r0 87 | .Lfunc_end1: 88 | .size drawLine, .Lfunc_end1-drawLine 89 | ; -- End function 90 | .globl app ; -- Begin function app 91 | .type app,@function 92 | app: ; @app 93 | ; %bb.0: ; %entry 94 | RAND r9 95 | RAND r10 96 | RAND r2 97 | UREMi r2 r2 10 98 | RAND r4 99 | UREMi r4 r4 10 100 | ANDi r9 r9 510 101 | ORi r9 r9 512 102 | MULi r9 r9 6554 103 | SRLi r9 r9 16 104 | ANDi r10 r10 254 105 | ORi r10 r10 256 106 | MULi r10 r10 6554 107 | SRLi r10 r10 16 108 | MOVhi r11 65280 109 | ORi r11 r11 255 110 | MOVli r12 128 111 | MOVli r13 256 112 | .LBB2_1: ; %while.cond 113 | ; =>This Inner Loop Header: Depth=1 114 | ABS r14 r2 115 | ABS r15 r4 116 | ADD r14 r15 r14 117 | SHLi r14 r14 16 118 | OR r14 r14 r11 119 | PUTPIXEL r9 r10 r14 120 | DIVi r15 r4 50 121 | ADD r15 r15 r10 122 | DIVi r0 r2 50 123 | ADD r0 r0 r9 124 | PUTPIXEL r0 r15 r14 125 | DIVi r15 r4 25 126 | ADD r15 r15 r10 127 | DIVi r0 r2 25 128 | ADD r0 r0 r9 129 | PUTPIXEL r0 r15 r14 130 | DIVi r0 r4 5 131 | MULi r15 r0 3 132 | DIVi r15 r15 10 133 | ADD r3 r15 r10 134 | DIVi r15 r2 5 135 | MULi r5 r15 3 136 | DIVi r5 r5 10 137 | ADD r5 r5 r9 138 | PUTPIXEL r5 r3 r14 139 | SHLi r3 r0 2 140 | DIVi r3 r3 10 141 | ADD r3 r3 r10 142 | SHLi r5 r15 2 143 | DIVi r5 r5 10 144 | ADD r5 r5 r9 145 | PUTPIXEL r5 r3 r14 146 | DIVi r3 r4 10 147 | ADD r3 r3 r10 148 | DIVi r5 r2 10 149 | ADD r5 r5 r9 150 | PUTPIXEL r5 r3 r14 151 | MULi r3 r0 6 152 | DIVi r3 r3 10 153 | ADD r3 r3 r10 154 | MULi r5 r15 6 155 | DIVi r5 r5 10 156 | ADD r5 r5 r9 157 | PUTPIXEL r5 r3 r14 158 | MULi r3 r0 7 159 | DIVi r3 r3 10 160 | ADD r3 r3 r10 161 | MULi r5 r15 7 162 | DIVi r5 r5 10 163 | ADD r5 r5 r9 164 | PUTPIXEL r5 r3 r14 165 | SHLi r3 r0 3 166 | DIVi r3 r3 10 167 | ADD r3 r3 r10 168 | SHLi r5 r15 3 169 | DIVi r5 r5 10 170 | ADD r5 r5 r9 171 | PUTPIXEL r5 r3 r14 172 | MULi r3 r0 9 173 | DIVi r3 r3 10 174 | ADD r3 r3 r10 175 | MULi r5 r15 9 176 | DIVi r5 r5 10 177 | ADD r5 r5 r9 178 | PUTPIXEL r5 r3 r14 179 | ADD r10 r0 r10 180 | SUB r14 r12 r10 181 | MULi r14 r14 10 182 | SRAi r0 r14 31 183 | SRLi r0 r0 24 184 | ADD r14 r14 r0 185 | ADD r9 r15 r9 186 | SRAi r14 r14 8 187 | ADD r4 r14 r4 188 | SUB r14 r13 r9 189 | MULi r14 r14 10 190 | SRAi r15 r14 31 191 | SRLi r15 r15 23 192 | ADD r14 r14 r15 193 | SRAi r14 r14 9 194 | ADD r2 r14 r2 195 | FLUSH 196 | B .LBB2_1 197 | .Lfunc_end2: 198 | .size app, .Lfunc_end2-app 199 | ; -- End function 200 | .ident "clang version 20.1.0 (https://github.com/lisitsynSA/llvm-add-backend.git 35713b455254b19f34e2bfaf423b5dfa6444bbb9)" 201 | .section ".note.GNU-stack","",@progbits 202 | -------------------------------------------------------------------------------- /Sim/examples/clang.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lisitsynSA/llvm_course/bc5c420881a38874293a8fca8ddb29713d8445be/Sim/examples/clang.o -------------------------------------------------------------------------------- /Sim/examples/clang.s: -------------------------------------------------------------------------------- 1 | .file "app.c" 2 | .text 3 | .globl app ; -- Begin function app 4 | .type app,@function 5 | app: ; @app 6 | ; %bb.0: ; %entry 7 | MOVli r2 0 8 | .LBB0_1: ; %for.cond1.preheader 9 | ; =>This Loop Header: Depth=1 10 | ; Child Loop BB0_3 Depth 2 11 | ; Child Loop BB0_6 Depth 3 12 | MOVli r4 0 13 | MOVli r9 0 14 | B .LBB0_3 15 | .LBB0_3: ; %for.cond5.preheader 16 | ; Parent Loop BB0_1 Depth=1 17 | ; => This Loop Header: Depth=2 18 | ; Child Loop BB0_6 Depth 3 19 | MOVli r10 0 20 | MOVhi r11 65280 21 | B .LBB0_6 22 | .LBB0_6: ; %for.body8 23 | ; Parent Loop BB0_1 Depth=1 24 | ; Parent Loop BB0_3 Depth=2 25 | ; => This Inner Loop Header: Depth=3 26 | PUTPIXEL r10 r9 r11 27 | INC_EQi r12 r10 512 28 | ADD r11 r11 r4 29 | BR_COND r12 .LBB0_5 30 | B .LBB0_6 31 | .LBB0_5: ; %for.cond.cleanup7 32 | ; in Loop: Header=BB0_3 Depth=2 33 | INC_EQi r10 r9 256 34 | ADD r4 r4 r2 35 | BR_COND r10 .LBB0_4 36 | B .LBB0_3 37 | .LBB0_4: ; %for.cond.cleanup3 38 | ; in Loop: Header=BB0_1 Depth=1 39 | INC_EQi r4 r2 1000 40 | FLUSH 41 | BR_COND r4 .LBB0_2 42 | B .LBB0_1 43 | .LBB0_2: ; %for.cond.cleanup 44 | BR r0 45 | .Lfunc_end0: 46 | .size app, .Lfunc_end0-app 47 | ; -- End function 48 | .ident "clang version 20.1.0 (https://github.com/lisitsynSA/llvm-add-backend.git 0c2e205d16d270e0f5100d8ff81a7fbae0d2bbce)" 49 | .section ".note.GNU-stack","",@progbits 50 | -------------------------------------------------------------------------------- /Sim/examples/graphic.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lisitsynSA/llvm_course/bc5c420881a38874293a8fca8ddb29713d8445be/Sim/examples/graphic.o -------------------------------------------------------------------------------- /Sim/examples/graphic.s: -------------------------------------------------------------------------------- 1 | .text 2 | .file "graphic.ll" 3 | .globl app ; -- Begin function app 4 | .type app,@function 5 | app: ; @app 6 | ; %bb.0: ; %entry 7 | MOVhi r2 65535 8 | ORi r2 r2 65535 9 | MOVli r9 5 10 | PUTPIXEL r9 r9 r2 11 | FLUSH 12 | BR r0 13 | .Lfunc_end0: 14 | .size app, .Lfunc_end0-app 15 | ; -- End function 16 | .section ".note.GNU-stack","",@progbits 17 | -------------------------------------------------------------------------------- /Sim/examples/graphic.sim: -------------------------------------------------------------------------------- 1 | entry 2 | MOVhi x2 65535 3 | ORi x2 x2 65535 4 | MOVli x9 5 5 | PUT_PIXEL x9 x9 x2 6 | FLUSH 7 | EXIT 8 | -------------------------------------------------------------------------------- /Sim/examples/lang.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lisitsynSA/llvm_course/bc5c420881a38874293a8fca8ddb29713d8445be/Sim/examples/lang.o -------------------------------------------------------------------------------- /Sim/examples/lang.s: -------------------------------------------------------------------------------- 1 | .file "top" 2 | .text 3 | .globl app ; -- Begin function app 4 | .type app,@function 5 | app: ; @app 6 | ; %bb.0: ; %entry 7 | MOVli r2 0 8 | .LBB0_1: ; %loopY.preheader 9 | ; =>This Loop Header: Depth=1 10 | ; Child Loop BB0_2 Depth 2 11 | ; Child Loop BB0_5 Depth 3 12 | MOVli r4 0 13 | MOVli r9 0 14 | .LBB0_2: ; %loopX.preheader 15 | ; Parent Loop BB0_1 Depth=1 16 | ; => This Loop Header: Depth=2 17 | ; Child Loop BB0_5 Depth 3 18 | MOVli r10 0 19 | MOVhi r11 65280 20 | B .LBB0_5 21 | .LBB0_5: ; %iterX 22 | ; Parent Loop BB0_1 Depth=1 23 | ; Parent Loop BB0_2 Depth=2 24 | ; => This Inner Loop Header: Depth=3 25 | PUTPIXEL r10 r9 r11 26 | INC_NEi r12 r10 512 27 | ADD r11 r11 r4 28 | BR_COND r12 .LBB0_5 29 | B .LBB0_6 30 | .LBB0_6: ; %loopX_end 31 | ; in Loop: Header=BB0_2 Depth=2 32 | INC_EQi r10 r9 256 33 | ADD r4 r4 r2 34 | BR_COND r10 .LBB0_4 35 | B .LBB0_2 36 | .LBB0_4: ; %loopY_end 37 | ; in Loop: Header=BB0_1 Depth=1 38 | INC_EQi r4 r2 1000 39 | FLUSH 40 | BR_COND r4 .LBB0_3 41 | B .LBB0_1 42 | .LBB0_3: ; %loopStep_end 43 | BR r0 44 | .Lfunc_end0: 45 | .size app, .Lfunc_end0-app 46 | ; -- End function 47 | .section ".note.GNU-stack","",@progbits 48 | -------------------------------------------------------------------------------- /Sim/examples/nodelang.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lisitsynSA/llvm_course/bc5c420881a38874293a8fca8ddb29713d8445be/Sim/examples/nodelang.o -------------------------------------------------------------------------------- /Sim/examples/nodelang.s: -------------------------------------------------------------------------------- 1 | .file "top" 2 | .text 3 | .globl PUT_PIXEL ; -- Begin function PUT_PIXEL 4 | .type PUT_PIXEL,@function 5 | PUT_PIXEL: ; @PUT_PIXEL 6 | ; %bb.0: ; %entry 7 | PUTPIXEL r9 r10 r11 8 | MOVli r9 0 9 | BR r0 10 | .Lfunc_end0: 11 | .size PUT_PIXEL, .Lfunc_end0-PUT_PIXEL 12 | ; -- End function 13 | .globl FLUSH ; -- Begin function FLUSH 14 | .type FLUSH,@function 15 | FLUSH: ; @FLUSH 16 | ; %bb.0: ; %entry 17 | FLUSH 18 | MOVli r9 0 19 | BR r0 20 | .Lfunc_end1: 21 | .size FLUSH, .Lfunc_end1-FLUSH 22 | ; -- End function 23 | .globl color ; -- Begin function color 24 | .type color,@function 25 | color: ; @color 26 | ; %bb.0: ; %entry 27 | MUL r2 r10 r9 28 | MUL r2 r2 r11 29 | MOVhi r4 65280 30 | ADD r9 r2 r4 31 | BR r0 32 | .Lfunc_end2: 33 | .size color, .Lfunc_end2-color 34 | ; -- End function 35 | .globl app ; -- Begin function app 36 | .type app,@function 37 | app: ; @app 38 | ; %bb.0: ; %entry 39 | MOVli r2 0 40 | .LBB3_1: ; %.preheader2 41 | ; =>This Loop Header: Depth=1 42 | ; Child Loop BB3_3 Depth 2 43 | ; Child Loop BB3_5 Depth 3 44 | MOVli r4 0 45 | MOVli r9 0 46 | B .LBB3_3 47 | .LBB3_3: ; %.preheader 48 | ; Parent Loop BB3_1 Depth=1 49 | ; => This Loop Header: Depth=2 50 | ; Child Loop BB3_5 Depth 3 51 | MOVli r10 0 52 | MOVhi r11 65280 53 | B .LBB3_5 54 | .LBB3_5: ; Parent Loop BB3_1 Depth=1 55 | ; Parent Loop BB3_3 Depth=2 56 | ; => This Inner Loop Header: Depth=3 57 | PUTPIXEL r10 r9 r11 58 | INC_NEi r12 r10 512 59 | ADD r11 r11 r4 60 | BR_COND r12 .LBB3_5 61 | B .LBB3_6 62 | .LBB3_6: ; in Loop: Header=BB3_3 Depth=2 63 | INC_EQi r10 r9 256 64 | ADD r4 r4 r2 65 | BR_COND r10 .LBB3_4 66 | B .LBB3_3 67 | .LBB3_4: ; in Loop: Header=BB3_1 Depth=1 68 | INC_EQi r4 r2 42 69 | FLUSH 70 | BR_COND r4 .LBB3_2 71 | B .LBB3_1 72 | .LBB3_2: 73 | MOVli r9 42 74 | BR r0 75 | .Lfunc_end3: 76 | .size app, .Lfunc_end3-app 77 | ; -- End function 78 | .section ".note.GNU-stack","",@progbits 79 | -------------------------------------------------------------------------------- /Sim/extIR.cpp: -------------------------------------------------------------------------------- 1 | #include "include/extIR.h" 2 | #include "llvm/ExecutionEngine/ExecutionEngine.h" 3 | #include "llvm/ExecutionEngine/GenericValue.h" 4 | #include "llvm/IR/IRBuilder.h" 5 | #include "llvm/IR/Verifier.h" 6 | #include "llvm/Support/TargetSelect.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | 9 | using namespace llvm; 10 | 11 | void ExtIR::buildIR(Binary &Bin) { 12 | module = new Module("top", context); 13 | IRBuilder<> builder(context); 14 | voidType = Type::getVoidTy(context); 15 | int32Type = Type::getInt32Ty(context); 16 | 17 | //[32 x i32] regFile = {0, 0, 0, 0} 18 | ArrayType *regFileType = ArrayType::get(int32Type, CPU::RegSize); 19 | module->getOrInsertGlobal("regFile", regFileType); 20 | regFile = module->getNamedGlobal("regFile"); 21 | 22 | // declare void @main() 23 | FunctionType *funcType = FunctionType::get(voidType, false); 24 | mainFunc = 25 | Function::Create(funcType, Function::ExternalLinkage, "main", module); 26 | // Funcions types 27 | FunctionType *voidFuncType = FunctionType::get(voidType, false); 28 | ArrayRef int32x3Types = {int32Type, int32Type, int32Type}; 29 | FunctionType *int32x3FuncType = 30 | FunctionType::get(voidType, int32x3Types, false); 31 | 32 | // Functions 33 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 34 | _IRGenExecute) \ 35 | FunctionCallee Callee##_Name = \ 36 | module->getOrInsertFunction("do_" #_Name, int32x3FuncType); 37 | #include "include/ISA.h" 38 | #undef _ISA 39 | 40 | std::unordered_map BBMap; 41 | for (auto &BB : Bin.BBName2PC) { 42 | BBMap[BB.second] = BasicBlock::Create(context, BB.first, mainFunc); 43 | } 44 | 45 | uint32_t PC = 0; 46 | builder.SetInsertPoint(BBMap[0]); 47 | for (Instr &I : Bin.Instrs) { 48 | Value *arg1 = builder.getInt32(I.R1); 49 | Value *arg2 = builder.getInt32(I.R2); 50 | Value *arg3 = builder.getInt32(I.R3Imm); 51 | Value *args[] = {arg1, arg2, arg3}; 52 | switch (I.Op) { 53 | default: 54 | break; 55 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 56 | _IRGenExecute) \ 57 | case (_Opcode): \ 58 | builder.CreateCall(Callee##_Name, args); \ 59 | break; 60 | #include "include/ISA.h" 61 | #undef _ISA 62 | } 63 | PC++; 64 | auto BB = BBMap.find(PC); 65 | 66 | switch (I.Op) { 67 | default: 68 | if (BB != BBMap.end()) { 69 | builder.CreateBr(BB->second); 70 | } 71 | break; 72 | case Instr::BR_COND: 73 | arg1 = builder.CreateConstGEP2_32(regFileType, regFile, 0, I.R1); 74 | arg2 = builder.CreateTrunc(builder.CreateLoad(int32Type, arg1), 75 | builder.getInt1Ty()); 76 | if (BB != BBMap.end()) { 77 | builder.CreateCondBr(arg2, BBMap[I.R3Imm], BB->second); 78 | } 79 | break; 80 | case Instr::B: 81 | builder.CreateBr(BBMap[I.R3Imm]); 82 | break; 83 | case Instr::EXIT: 84 | builder.CreateRetVoid(); 85 | break; 86 | } 87 | if (BB != BBMap.end()) { 88 | builder.SetInsertPoint(BB->second); 89 | } 90 | } 91 | } 92 | 93 | void ExtIR::dumpIR() { 94 | outs() << "\n[LLVM IR]:\n"; 95 | module->print(outs(), nullptr); 96 | outs() << "\n"; 97 | } 98 | bool ExtIR::verifyIR() { 99 | bool verif = verifyFunction(*mainFunc, &outs()); 100 | outs() << "[VERIFICATION] " << (!verif ? "OK\n\n" : "FAIL\n\n"); 101 | return verif; 102 | } 103 | 104 | void ExtIR::executeIR(CPU &Cpu) { 105 | InitializeNativeTarget(); 106 | InitializeNativeTargetAsmPrinter(); 107 | 108 | ExecutionEngine *ee = EngineBuilder(std::unique_ptr(module)).create(); 109 | ee->InstallLazyFunctionCreator([=](const std::string &fnName) -> void * { 110 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 111 | _IRGenExecute) \ 112 | if (fnName == "do_" #_Name) \ 113 | return reinterpret_cast(CPU::do_##_Name); 114 | #include "include/ISA.h" 115 | #undef _ISA 116 | return nullptr; 117 | }); 118 | 119 | ee->addGlobalMapping(regFile, (void *)Cpu.RegFile); 120 | ee->finalizeObject(); 121 | 122 | simInit(); 123 | CPU::setCPU(&Cpu); 124 | // Cpu.DumpInstrs = true; 125 | 126 | ArrayRef noargs; 127 | outs() << "\n#[Running code]\n"; 128 | ee->runFunction(mainFunc, noargs); 129 | outs() << "#[Code was run]\n"; 130 | 131 | simExit(); 132 | } -------------------------------------------------------------------------------- /Sim/include/bin.h: -------------------------------------------------------------------------------- 1 | #ifndef BIN_H 2 | #define BIN_H 3 | #include "instr.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct Binary { 10 | std::vector Instrs; 11 | std::map BBName2PC; 12 | std::map PC2BBName; 13 | 14 | bool searchBBs(std::ifstream &InputFile, std::string &ErrorMsg); 15 | 16 | std::string writeBBs(); 17 | 18 | bool readInstrs(std::ifstream &InputFile, std::string &ErrorMsg); 19 | 20 | std::string writeInstrs(); 21 | 22 | bool readFile(std::string FileName, std::string &ErrorMsg); 23 | 24 | bool readBin(std::string FileName, std::string &ErrorMsg); 25 | }; 26 | #endif // BIN_H 27 | -------------------------------------------------------------------------------- /Sim/include/cpu.h: -------------------------------------------------------------------------------- 1 | #ifndef CPU_H 2 | #define CPU_H 3 | #include "sim.h" 4 | #include "bin.h" 5 | #include "llvm/Support/raw_ostream.h" 6 | #include 7 | #include 8 | 9 | struct CPU { 10 | static constexpr uint32_t RegSize = 16; 11 | uint32_t RegFile[RegSize] = {}; 12 | uint32_t PC; 13 | uint32_t NextPC; 14 | uint32_t Run; 15 | bool DumpInstrs = false; 16 | 17 | bool Execute(Binary &Bin, std::string &ErrorMsg); 18 | std::string dumpStatus(Binary &Bin); 19 | 20 | static CPU *C; 21 | static void setCPU(CPU *Cpu) { C = Cpu; } 22 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 23 | _IRGenExecute) \ 24 | static void do_##_Name(uint32_t R1, uint32_t R2, uint32_t R3Imm) { \ 25 | if (C->DumpInstrs) \ 26 | llvm::outs() << #_Name "\n"; \ 27 | _Execute; \ 28 | } 29 | #include "ISA.h" 30 | #undef _ISA 31 | }; 32 | #endif // CPU_H 33 | -------------------------------------------------------------------------------- /Sim/include/extIR.h: -------------------------------------------------------------------------------- 1 | #ifndef EXTIR_H 2 | #define EXTIR_H 3 | #include "bin.h" 4 | #include "cpu.h" 5 | #include "llvm/IR/LLVMContext.h" 6 | #include "llvm/IR/Module.h" 7 | 8 | struct ExtIR { 9 | llvm::LLVMContext context; 10 | llvm::Module *module; 11 | llvm::Function *mainFunc; 12 | llvm::GlobalVariable *regFile; 13 | llvm::Type *voidType; 14 | llvm::Type *int32Type; 15 | 16 | void buildIR(Binary &Bin); 17 | void dumpIR(); 18 | bool verifyIR(); 19 | void executeIR(CPU &Cpu); 20 | }; 21 | 22 | #endif // EXTIR_H -------------------------------------------------------------------------------- /Sim/include/fullIR.h: -------------------------------------------------------------------------------- 1 | #ifndef FULLIR_H 2 | #define FULLIR_H 3 | #include "bin.h" 4 | #include "cpu.h" 5 | #include "extIR.h" 6 | #include "llvm/IR/LLVMContext.h" 7 | #include "llvm/IR/Module.h" 8 | 9 | struct FullIR : ExtIR { 10 | void buildIR(Binary &Bin); 11 | void executeIR(CPU &Cpu); 12 | bool printIR(std::string FileName, std::string &ErrorMsg); 13 | }; 14 | 15 | #endif // FULLIR_H -------------------------------------------------------------------------------- /Sim/include/instr.h: -------------------------------------------------------------------------------- 1 | #ifndef INSTR_H 2 | #define INSTR_H 3 | #include 4 | #include 5 | #include 6 | 7 | struct Instr { 8 | enum { 9 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 10 | _IRGenExecute) \ 11 | _Name = _Opcode, 12 | #include "ISA.h" 13 | #undef _ISA 14 | }; 15 | uint32_t Op; 16 | uint32_t R1; 17 | uint32_t R2; 18 | uint32_t R3Imm; 19 | static std::map Str2Op; 20 | static std::map Op2Str; 21 | static void prepareDicts(); 22 | static uint32_t getOpcode(std::string &InstrName); 23 | }; 24 | #endif // INSTR_H 25 | -------------------------------------------------------------------------------- /Sim/include/sim.h: -------------------------------------------------------------------------------- 1 | #define SIM_X_SIZE 512 2 | #define SIM_Y_SIZE 256 3 | 4 | #ifndef __sim__ 5 | void simFlush(); 6 | void simPutPixel(int x, int y, int argb); 7 | int simRand(); 8 | #endif 9 | 10 | extern void simInit(); 11 | extern void app(); 12 | extern void simExit(); 13 | -------------------------------------------------------------------------------- /Sim/instr.cpp: -------------------------------------------------------------------------------- 1 | #include "include/instr.h" 2 | #include 3 | using namespace std; 4 | 5 | map Instr::Str2Op; 6 | map Instr::Op2Str; 7 | 8 | void Instr::prepareDicts() { 9 | #define _ISA(_Opcode, _Name, _SkipArgs, _ReadArgs, _WriteArgs, _Execute, \ 10 | _IRGenExecute) \ 11 | Str2Op[#_Name] = _Opcode; \ 12 | Op2Str[_Opcode] = #_Name; 13 | #include "include/ISA.h" 14 | #undef _ISA 15 | } 16 | 17 | uint32_t Instr::getOpcode(string &InstrName) { 18 | auto InstrRec = Str2Op.find(InstrName); 19 | if (InstrRec == Str2Op.end()) 20 | return 0; 21 | return InstrRec->second; 22 | } 23 | -------------------------------------------------------------------------------- /Sim/loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd $(dirname "$0") 3 | set -x 4 | 5 | LLVM_BUILD="../../llvm-add-backend/build" 6 | LLC="$LLVM_BUILD/bin/llc" 7 | CLANG="$LLVM_BUILD/bin/clang" 8 | SIM="./a.out" 9 | 10 | if [ ! -f ./tmp_0.ll ]; then 11 | echo "Need tmp_0.ll to start loop!" 12 | exit 1 13 | fi 14 | 15 | for ((i = 0; i < 10; i++)); do 16 | NAME="tmp_$i" 17 | $CLANG $NAME.ll -O2 -emit-llvm -S -target sim -o $NAME.opt.ll || exit 1 18 | $LLC $NAME.opt.ll -march sim --filetype=asm || exit 1 19 | $LLC $NAME.opt.ll -march sim --filetype=obj || exit 1 20 | $SIM $NAME.opt.o 1 21 | $SIM $NAME.opt.o 3 tmp_$((i + 1)).ll 22 | done 23 | -------------------------------------------------------------------------------- /Sim/main.cpp: -------------------------------------------------------------------------------- 1 | #include "include/bin.h" 2 | #include "include/cpu.h" 3 | #include "include/extIR.h" 4 | #include "include/fullIR.h" 5 | #include "llvm/Support/raw_ostream.h" 6 | using namespace llvm; 7 | 8 | // Function to check if a string ends with another string 9 | bool endsWith(const std::string &str, const std::string &end) { 10 | if (end.size() > str.size()) 11 | return false; 12 | return str.compare(str.size() - end.size(), end.size(), end) == 0; 13 | } 14 | 15 | int main(int argc, char *argv[]) { 16 | if (argc != 3 && argc != 4) { 17 | outs() 18 | << "\n[ERROR] Need 2 argument: file with assembler/binary code and " 19 | "execution mod (1-3)\n 1: Simulation\n 2: IR with emulate funcs\n " 20 | " 3: Full IR generation (optional 3rd argument for IR output)\n"; 21 | return 1; 22 | } 23 | Instr::prepareDicts(); 24 | Binary Bin; 25 | std::string ErrorMsg; 26 | if (endsWith(argv[1], ".o")) { 27 | if (Bin.readBin(argv[1], ErrorMsg)) { 28 | outs() << "\n[BIN READ ERROR] " << ErrorMsg << "\n"; 29 | return 1; 30 | } 31 | } else if (Bin.readFile(argv[1], ErrorMsg)) { 32 | outs() << "\n[ASM READ ERROR] " << ErrorMsg << "\n"; 33 | return 1; 34 | } 35 | outs() << "\n[BasicBlocks]\n" << Bin.writeBBs(); 36 | outs() << "\n[Binary]\n" << Bin.writeInstrs(); 37 | CPU Cpu; 38 | 39 | int Mode = atoi(argv[2]); 40 | switch (Mode) { 41 | case 1: 42 | // Simulation 43 | if (Cpu.Execute(Bin, ErrorMsg)) { 44 | outs() << "\n[CPU RUN ERROR] " << ErrorMsg << "\n"; 45 | return 1; 46 | } 47 | break; 48 | case 2: 49 | // IR with emulate funcs 50 | { 51 | ExtIR Ext; 52 | Ext.buildIR(Bin); 53 | Ext.dumpIR(); 54 | if (Ext.verifyIR()) 55 | return 1; 56 | Ext.executeIR(Cpu); 57 | } 58 | break; 59 | case 3: 60 | // only IR 61 | { 62 | FullIR Full; 63 | Full.buildIR(Bin); 64 | Full.dumpIR(); 65 | if (Full.verifyIR()) 66 | return 1; 67 | if (argc == 4) { 68 | outs() << "Print LLVM IR to " << argv[3] << "\n"; 69 | if (Full.printIR(argv[3], ErrorMsg)) { 70 | outs() << "\n[IR DUMP ERROR] " << ErrorMsg << "\n"; 71 | return 1; 72 | } 73 | } else { 74 | Full.executeIR(Cpu); 75 | } 76 | } 77 | break; 78 | default: 79 | outs() << "\n[ERROR] Incorrect 2nd argument, mode should be 1-3\n 1: " 80 | "Simulation 2: IR with emulate funcs 3: Full IR generation\n"; 81 | return 1; 82 | } 83 | 84 | return 0; 85 | } --------------------------------------------------------------------------------