├── mu ├── llvmc │ ├── ast_t.hpp │ ├── skeleton_t.hpp │ ├── node_result.cpp │ ├── predicates.hpp │ ├── node_result.hpp │ ├── CMakeLists.txt │ ├── compiler.hpp │ ├── instruction_type.hpp │ ├── compiler.cpp │ ├── parser_t.hpp │ ├── generator.hpp │ ├── analyzer.hpp │ ├── parser.hpp │ ├── ast.hpp │ └── ast.cpp ├── core │ ├── types.cpp │ ├── error.cpp │ ├── stream.hpp │ ├── CMakeLists.txt │ ├── string_hash.hpp │ ├── stream_token.hpp │ ├── error_string.hpp │ ├── error_string.cpp │ ├── types.hpp │ ├── string_hash.cpp │ ├── stream_token.cpp │ ├── region.hpp │ ├── tokens.cpp │ ├── tokens.hpp │ ├── lexer.hpp │ ├── region.cpp │ ├── siphash24.c │ ├── error.hpp │ └── lexer.cpp ├── muc │ ├── CMakeLists.txt │ └── entry.cpp └── test │ ├── entry.cpp │ ├── CMakeLists.txt │ ├── io_stream_istream.cpp │ ├── partial_ast.cpp │ ├── llvmc_skeleton.cpp │ └── io_lexer.cpp ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── examples ├── murmurhash3.mu └── file.mu └── FindLLVM.cmake /mu/llvmc/ast_t.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /mu/llvmc/skeleton_t.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include -------------------------------------------------------------------------------- /mu/llvmc/node_result.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.user 3 | /llvm 4 | /boost 5 | /googletest 6 | /gc 7 | /build 8 | /nbproject 9 | CMakeFiles/ 10 | -------------------------------------------------------------------------------- /mu/core/types.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::string std_from_mu_string (mu::string const & string_a) 4 | { 5 | std::string result (string_a.begin (), string_a.end ()); 6 | return result; 7 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LLVM_LINK_COMPONENTS 2 | Core 3 | MC) 4 | 5 | include_directories (${CMAKE_CURRENT_SOURCE_DIR}) 6 | 7 | add_subdirectory (mu/core) 8 | add_subdirectory (mu/llvmc) 9 | add_subdirectory (mu/test) 10 | add_subdirectory (mu/muc) 11 | -------------------------------------------------------------------------------- /mu/core/error.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | mu::core::error::~error () 6 | { 7 | } 8 | 9 | std::string mu::core::error::string () 10 | { 11 | std::stringstream buffer; 12 | output (buffer); 13 | return buffer.str (); 14 | } -------------------------------------------------------------------------------- /mu/muc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | set (LLVM_LINK_COMPONENTS 4 | ${LLVM_TARGETS_TO_BUILD} 5 | ExecutionEngine 6 | IPO 7 | MC 8 | MCJIT) 9 | 10 | add_llvm_tool (muc 11 | entry.cpp) 12 | 13 | target_link_libraries (muc 14 | mu_core 15 | mu_llvmc) -------------------------------------------------------------------------------- /mu/core/stream.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace mu 6 | { 7 | namespace io 8 | { 9 | template 10 | class stream 11 | { 12 | public: 13 | virtual void consume (size_t size_a) = 0; 14 | virtual T & operator [] (size_t size_a) = 0; 15 | virtual size_t size () = 0; 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /mu/test/entry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | extern "C" void LLVMLinkInMCJIT(); 6 | 7 | int main (int argc, char ** argv) 8 | { 9 | llvm::InitializeNativeTarget (); 10 | llvm::InitializeNativeTargetAsmPrinter (); 11 | LLVMLinkInMCJIT (); 12 | ::testing::InitGoogleTest (&argc, argv); 13 | return RUN_ALL_TESTS (); 14 | } -------------------------------------------------------------------------------- /mu/llvmc/predicates.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace mu 4 | { 5 | namespace llvmc 6 | { 7 | enum class predicates 8 | { 9 | icmp_eq, 10 | icmp_ne, 11 | icmp_ugt, 12 | icmp_uge, 13 | icmp_ult, 14 | icmp_ule, 15 | icmp_sgt, 16 | icmp_sge, 17 | icmp_slt, 18 | icmp_sle 19 | }; 20 | } 21 | } -------------------------------------------------------------------------------- /mu/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | add_llvm_library (mu_core 4 | error.cpp 5 | error.hpp 6 | error_string.cpp 7 | error_string.hpp 8 | lexer.cpp 9 | lexer.hpp 10 | region.cpp 11 | region.hpp 12 | siphash24.c 13 | stream_token.cpp 14 | stream_token.hpp 15 | string_hash.cpp 16 | string_hash.hpp 17 | tokens.cpp 18 | tokens.hpp 19 | types.cpp 20 | types.hpp) 21 | -------------------------------------------------------------------------------- /mu/llvmc/node_result.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace mu 4 | { 5 | namespace core 6 | { 7 | class error; 8 | } 9 | namespace llvmc 10 | { 11 | namespace ast 12 | { 13 | class node; 14 | } 15 | class node_result 16 | { 17 | public: 18 | mu::llvmc::ast::node * node; 19 | mu::core::error * error; 20 | }; 21 | } 22 | } -------------------------------------------------------------------------------- /mu/core/string_hash.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace mu 8 | { 9 | namespace core 10 | { 11 | class string_hash 12 | { 13 | public: 14 | string_hash (mu::string const & string_a); 15 | string_hash (std::string const & string_a); 16 | std::array hash; 17 | mu::string text (); 18 | }; 19 | } 20 | } -------------------------------------------------------------------------------- /mu/llvmc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | add_llvm_library (mu_llvmc 4 | ast.cpp 5 | ast.hpp 6 | ast_t.hpp 7 | analyzer.cpp 8 | analyzer.hpp 9 | compiler.cpp 10 | compiler.hpp 11 | generator.cpp 12 | generator.hpp 13 | instruction_type.hpp 14 | node_result.cpp 15 | node_result.hpp 16 | parser.cpp 17 | parser.hpp 18 | parser_t.hpp 19 | predicates.hpp 20 | skeleton.cpp 21 | skeleton.hpp 22 | skeleton_t.hpp) -------------------------------------------------------------------------------- /mu/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | set (LLVM_LINK_COMPONENTS 4 | ${LLVM_TARGETS_TO_BUILD} 5 | ExecutionEngine 6 | IPO 7 | MC 8 | MCJIT) 9 | 10 | include_directories (${PROJECT_SOURCE_DIR}/utils/unittest/googletest/include) 11 | 12 | add_llvm_tool (mu_test 13 | entry.cpp 14 | io_lexer.cpp 15 | io_stream_istream.cpp 16 | llvmc_analyzer.cpp 17 | llvmc_generator.cpp 18 | llvmc_parser.cpp 19 | llvmc_skeleton.cpp 20 | partial_ast.cpp 21 | literals.cpp) 22 | 23 | target_link_libraries (mu_test 24 | gtest 25 | LLVMSupport 26 | mu_core 27 | mu_llvmc) -------------------------------------------------------------------------------- /mu/core/stream_token.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace mu 7 | { 8 | namespace io 9 | { 10 | class token; 11 | class lexer; 12 | class stream_token : public mu::io::stream 13 | { 14 | public: 15 | stream_token (mu::io::lexer & lexer_a, size_t size_a); 16 | void consume (size_t size_a) override; 17 | mu::io::token * & operator [] (size_t size_a) override; 18 | size_t size () override; 19 | private: 20 | void refill (); 21 | size_t size_m; 22 | std::deque buffer; 23 | mu::io::lexer & lexer; 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /mu/core/error_string.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace mu 9 | { 10 | namespace core 11 | { 12 | class error_string : public mu::core::error 13 | { 14 | public: 15 | error_string (mu::string const & message_a, mu::core::error_type type_a, mu::core::region const & region_a = mu::empty_region); 16 | void output (std::ostream & out) override; 17 | mu::core::error_type type () override; 18 | mu::core::region region () override; 19 | mu::core::error_type type_m; 20 | mu::string message; 21 | mu::core::region region_m; 22 | }; 23 | } 24 | } -------------------------------------------------------------------------------- /mu/core/error_string.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | mu::core::error_string::error_string (mu::string const & message_a, mu::core::error_type type_a, mu::core::region const & region_a): 4 | type_m (type_a), 5 | message (message_a), 6 | region_m (region_a) 7 | { 8 | } 9 | 10 | mu::core::error_type mu::core::error_string::type () 11 | { 12 | return type_m; 13 | } 14 | 15 | void mu::core::error_string::output (std::ostream & out) 16 | { 17 | std::string string (message.begin (), message.end ()); 18 | mu::string const & region_mu (region_m.string ()); 19 | std::string region (region_mu.begin (), region_mu.end ()); 20 | out << string << "(" << region << ")"; 21 | } 22 | 23 | mu::core::region mu::core::error_string::region () 24 | { 25 | return region_m; 26 | } -------------------------------------------------------------------------------- /mu/test/io_stream_istream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | TEST (sscanf, test1) 8 | { 9 | auto string ("42, is a test"); 10 | char buffer1 [32]; 11 | int val1; 12 | auto number (sscanf (string, "%d %s", &val1, buffer1)); 13 | ASSERT_EQ (2, number); 14 | ASSERT_EQ (42, val1); 15 | ASSERT_EQ (std::string (","), std::string (buffer1)); 16 | } 17 | 18 | TEST (sscanf, test2) 19 | { 20 | auto string ("42"); 21 | char buffer1 [32]; 22 | int val1; 23 | auto number (sscanf (string, "%d %s", &val1, buffer1)); 24 | ASSERT_EQ (1, number); 25 | ASSERT_EQ (42, val1); 26 | } 27 | 28 | TEST (strtoull, test1) 29 | { 30 | auto string ("42 is a test"); 31 | errno = 0; 32 | auto value (strtoull (string, nullptr, 0)); 33 | auto newerr (errno); 34 | } -------------------------------------------------------------------------------- /mu/llvmc/compiler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace llvm 8 | { 9 | class formatted_raw_ostream; 10 | class Function; 11 | class raw_pwrite_stream; 12 | } 13 | namespace mu 14 | { 15 | namespace llvmc 16 | { 17 | class compiler 18 | { 19 | public: 20 | compiler (mu::io::string_range const &, llvm::raw_pwrite_stream & output_a); 21 | void compile (mu::string const & name_a, mu::string const & path_a); 22 | void inject_entry (llvm::Module & module_a, llvm::Function * entry); 23 | mu::io::lexer lexer; 24 | mu::io::stream_token stream_token; 25 | mu::llvmc::parser parser; 26 | llvm::raw_pwrite_stream & output; 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mu/core/types.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace mu 11 | { 12 | using string = std::basic_string ; 13 | template 14 | using vector = std::vector ; 15 | template 16 | using map = std::map ; 17 | template 18 | using unordered_map = std::unordered_map ; 19 | template 20 | using multimap = std::multimap ; 21 | template 22 | using unordered_multimap = std::unordered_multimap ; 23 | template 24 | using set = std::set ; 25 | template 26 | T * cast (U * x) 27 | { 28 | auto result (dynamic_cast (x)); 29 | assert (result != nullptr); 30 | return result; 31 | } 32 | std::string std_from_mu_string (mu::string const & string_a); 33 | } 34 | -------------------------------------------------------------------------------- /mu/core/string_hash.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern "C" int siphash (uint8_t *out, uint8_t const * in, uint64_t inlen, uint8_t const * k); 4 | 5 | mu::core::string_hash::string_hash (mu::string const & string_a) : 6 | hash ({}) 7 | { 8 | auto result (siphash (hash.data (), reinterpret_cast (string_a.c_str ()), string_a.size () * sizeof (mu::string::value_type), hash.data ())); 9 | assert (result == 0); (void) result; 10 | } 11 | 12 | mu::core::string_hash::string_hash (std::string const & string_a) : 13 | hash ({}) 14 | { 15 | auto result (siphash (hash.data (), reinterpret_cast (string_a.c_str ()), string_a.size () * sizeof (std::string::value_type), hash.data ())); 16 | assert (result == 0); (void) result; 17 | } 18 | 19 | mu::string mu::core::string_hash::text () 20 | { 21 | mu::string result; 22 | for (auto i: hash) 23 | { 24 | char buffer [2]; 25 | sprintf (buffer, "%02x", i); 26 | result.push_back (buffer [0]); 27 | result.push_back (buffer [1]); 28 | } 29 | return result; 30 | } 31 | -------------------------------------------------------------------------------- /mu/core/stream_token.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | mu::io::stream_token::stream_token (mu::io::lexer & lexer_a, size_t size_a): 7 | size_m (size_a), 8 | lexer (lexer_a) 9 | { 10 | refill (); 11 | } 12 | 13 | void mu::io::stream_token::consume (size_t size_a) 14 | { 15 | assert (size_a <= size ()); 16 | buffer.erase (buffer.begin (), buffer.begin () + size_a); 17 | refill (); 18 | } 19 | 20 | mu::io::token * & mu::io::stream_token::operator [] (size_t size_a) 21 | { 22 | assert (size_a <= size ()); 23 | auto & result (buffer [size_a]); 24 | return result; 25 | } 26 | 27 | size_t mu::io::stream_token::size () 28 | { 29 | return size_m; 30 | } 31 | 32 | void mu::io::stream_token::refill () 33 | { 34 | auto needed (size () - buffer.size ()); 35 | auto & lexer_l (lexer); 36 | for (size_t i (0); i < needed; ++i) 37 | { 38 | auto token (lexer_l.lex ()); 39 | if (token.error != nullptr) 40 | { 41 | buffer.push_back (new mu::io::end (mu::core::region (lexer.position, lexer.position))); 42 | } 43 | else 44 | { 45 | buffer.push_back (token.token); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /mu/core/region.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace mu 6 | { 7 | namespace core 8 | { 9 | class position 10 | { 11 | public: 12 | position (); 13 | position (uint64_t offset_a, uint64_t row_a, uint64_t column_a); 14 | bool operator == (mu::core::position const & other_a) const; 15 | mu::string string (); 16 | void character (); 17 | void line (); 18 | uint64_t offset; 19 | uint64_t row; 20 | uint64_t column; 21 | }; 22 | class region 23 | { 24 | public: 25 | region (); 26 | region (uint64_t offset1_a, uint64_t row1_a, uint64_t column1_a, uint64_t offset2_a, uint64_t row2_a, uint64_t column2_a); 27 | region (mu::core::position const & first_a, mu::core::position const & last_a); 28 | bool operator == (mu::core::region const & other_a) const; 29 | bool operator != (mu::core::region const & other_a) const; 30 | mu::string string (); 31 | mu::core::position first; 32 | mu::core::position last; 33 | }; 34 | } 35 | mu::core::region const empty_region (0, 0, 0, 0, 0, 0); 36 | } -------------------------------------------------------------------------------- /mu/core/tokens.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | mu::io::token::token (mu::core::region const & region_a): 4 | region (region_a) 5 | { 6 | } 7 | 8 | mu::io::token::~token () 9 | { 10 | } 11 | 12 | mu::io::left_square::left_square (mu::core::region const & region_a): 13 | token (region_a) 14 | { 15 | } 16 | 17 | mu::io::token_id mu::io::left_square::id () 18 | { 19 | return mu::io::token_id::left_square; 20 | } 21 | 22 | mu::io::right_square::right_square (mu::core::region const & region_a): 23 | token (region_a) 24 | { 25 | } 26 | 27 | mu::io::token_id mu::io::right_square::id () 28 | { 29 | return mu::io::token_id::right_square; 30 | } 31 | 32 | mu::io::terminator::terminator (mu::core::region const & region_a): 33 | token (region_a) 34 | { 35 | } 36 | 37 | mu::io::token_id mu::io::terminator::id () 38 | { 39 | return mu::io::token_id::terminator; 40 | } 41 | 42 | mu::io::end::end (mu::core::region const & region_a): 43 | token (region_a) 44 | { 45 | } 46 | 47 | mu::io::token_id mu::io::end::id () 48 | { 49 | return mu::io::token_id::end; 50 | } 51 | 52 | mu::io::identifier::identifier (mu::core::region const & region_a): 53 | token (region_a) 54 | { 55 | } 56 | 57 | mu::io::token_id mu::io::identifier::id () 58 | { 59 | return mu::io::token_id::identifier; 60 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, 2012, 2013, Colin LeMahieu 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /mu/test/partial_ast.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class test_parser 10 | { 11 | public: 12 | test_parser (char const * const text_a): 13 | lexer (text_a), 14 | stream_token (lexer, 2), 15 | parser (stream_token) 16 | { 17 | }; 18 | mu::io::lexer lexer; 19 | mu::io::stream_token stream_token; 20 | mu::llvmc::parser parser; 21 | }; 22 | 23 | TEST (partial_ast, empty) 24 | { 25 | test_parser parser (""); 26 | auto token (parser.parser.peek ()); 27 | ASSERT_NE (nullptr, token.token); 28 | auto end (dynamic_cast (token.token)); 29 | EXPECT_NE (nullptr, end); 30 | } 31 | 32 | TEST (partial_ast, tokens) 33 | { 34 | test_parser parser ("]a;"); 35 | auto token1 (parser.parser.peek ()); 36 | ASSERT_NE (nullptr, token1.token); 37 | auto right_square (dynamic_cast (token1.token)); 38 | EXPECT_NE (nullptr, right_square); 39 | auto token2 (parser.parser.peek ()); 40 | auto identifier (dynamic_cast (token2.token)); 41 | EXPECT_NE (nullptr, identifier); 42 | auto token3 (parser.parser.peek ()); 43 | auto terminator (dynamic_cast (token3.token)); 44 | EXPECT_NE (nullptr, terminator); 45 | } -------------------------------------------------------------------------------- /mu/core/tokens.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace mu 7 | { 8 | namespace io 9 | { 10 | enum class token_id 11 | { 12 | end, 13 | identifier, 14 | left_square, 15 | right_square, 16 | terminator 17 | }; 18 | class token 19 | { 20 | public: 21 | token (mu::core::region const &); 22 | virtual ~token (); 23 | virtual token_id id () = 0; 24 | mu::core::region region; 25 | }; 26 | class left_square : public token 27 | { 28 | public: 29 | left_square (mu::core::region const &); 30 | token_id id () override; 31 | }; 32 | class right_square : public token 33 | { 34 | public: 35 | right_square (mu::core::region const &); 36 | token_id id () override; 37 | }; 38 | class terminator : public token 39 | { 40 | public: 41 | terminator (mu::core::region const &); 42 | token_id id () override; 43 | }; 44 | class identifier : public token 45 | { 46 | public: 47 | identifier (mu::core::region const &); 48 | token_id id () override; 49 | mu::string string; 50 | }; 51 | class end : public token 52 | { 53 | public: 54 | end (mu::core::region const &); 55 | token_id id () override; 56 | }; 57 | } 58 | } -------------------------------------------------------------------------------- /mu/llvmc/instruction_type.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace mu 4 | { 5 | namespace llvmc 6 | { 7 | enum class instruction_type 8 | { 9 | add, 10 | alloca, 11 | and_i, 12 | ashr, 13 | asm_i, 14 | atomicrmw, 15 | bitcast, 16 | br, 17 | call, 18 | cmpxchg, 19 | extractelement, 20 | extractvalue, 21 | fadd, 22 | fcmp, 23 | fdiv, 24 | fence, 25 | fmul, 26 | fpext, 27 | fptoi, 28 | fptosi, 29 | fptoui, 30 | fptrunc, 31 | frem, 32 | fsub, 33 | getelementptr, 34 | icmp, 35 | identity, 36 | if_i, 37 | indirectbr, 38 | insertelement, 39 | insertvalue, 40 | inttoptr, 41 | invoke, 42 | landingpad, 43 | load, 44 | lshr, 45 | mul, 46 | or_i, 47 | phi, 48 | ptrtoint, 49 | resume, 50 | ret, 51 | sdiv, 52 | select, 53 | sext, 54 | shl, 55 | shufflevector, 56 | sitofp, 57 | srem, 58 | store, 59 | sub, 60 | switch_i, 61 | trunc, 62 | typeof_i, 63 | udiv, 64 | uitofp, 65 | unreachable, 66 | urem, 67 | vaarg, 68 | xor_i, 69 | zext 70 | }; 71 | } 72 | } -------------------------------------------------------------------------------- /mu/muc/entry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | static llvm::cl::opt input_filename (llvm::cl::Positional, llvm::cl::desc(""), llvm::cl::init("-")); 14 | 15 | int main (int argc, char const * const argv []) 16 | { 17 | llvm::cl::ParseCommandLineOptions (argc, argv); 18 | llvm::InitializeNativeTarget (); 19 | llvm::InitializeNativeTargetAsmPrinter (); 20 | llvm::InitializeNativeTargetAsmParser (); 21 | int result; 22 | if (!input_filename.empty ()) 23 | { 24 | result = 0; 25 | auto buffer (llvm::MemoryBuffer::getFileOrSTDIN (input_filename)); 26 | auto directory (llvm::sys::path::root_directory (input_filename)); 27 | auto name (llvm::sys::path::root_name (input_filename)); 28 | if (buffer) 29 | { 30 | std::string raw_string ((*buffer)->getBuffer ().str ()); 31 | std::error_code error; 32 | llvm::raw_fd_ostream output ("test.o", error, llvm::sys::fs::OpenFlags::F_RW); 33 | mu::llvmc::compiler compiler (raw_string, output); 34 | compiler.compile (mu::string (name.begin (), name.end ()), mu::string (directory.begin (), directory.end ())); 35 | } 36 | else 37 | { 38 | std::cout << "Unable to open: " << input_filename << '\n'; 39 | result = 1; 40 | } 41 | } 42 | else 43 | { 44 | std::cout << "No input files specified\n"; 45 | result = 1; 46 | } 47 | return result; 48 | } 49 | -------------------------------------------------------------------------------- /mu/core/lexer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace mu 6 | { 7 | namespace core 8 | { 9 | class error; 10 | } 11 | namespace io 12 | { 13 | class token; 14 | struct token_result 15 | { 16 | ~token_result (); 17 | mu::io::token * token; 18 | mu::core::error * error; 19 | }; 20 | struct character_result 21 | { 22 | ~character_result (); 23 | char32_t character; 24 | mu::core::error * error; 25 | }; 26 | class string_range 27 | { 28 | public: 29 | string_range (std::string const &); 30 | string_range (char const * const &); 31 | string_range (uint8_t const *, uint8_t const *); 32 | mu::io::string_range substr (size_t) const; 33 | mu::io::string_range substr (size_t, size_t) const; 34 | uint8_t const * begin (); 35 | uint8_t const * end (); 36 | bool operator == (mu::io::string_range const &) const; 37 | bool operator != (mu::io::string_range const &) const; 38 | bool empty () const; 39 | size_t size () const; 40 | char32_t operator [] (size_t) const; 41 | uint8_t const * begin_m; 42 | uint8_t const * end_m; 43 | }; 44 | class token; 45 | class lexer 46 | { 47 | public: 48 | lexer (mu::io::string_range const &); 49 | mu::io::token_result identifier (); 50 | mu::io::token_result complex_identifier (); 51 | void line_comment (); 52 | void consume (size_t size_a); 53 | mu::core::position position; 54 | mu::core::error * region_comment (); 55 | mu::io::character_result hex_code (int size_a); 56 | mu::io::token_result lex (); 57 | mu::io::string_range source; 58 | }; 59 | } 60 | } -------------------------------------------------------------------------------- /mu/core/region.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | mu::core::position::position () 6 | { 7 | } 8 | 9 | mu::core::region::region () 10 | { 11 | } 12 | 13 | mu::core::position::position (uint64_t offset_a, uint64_t row_a, uint64_t column_a): 14 | offset (offset_a), 15 | row (row_a), 16 | column (column_a) 17 | { 18 | } 19 | 20 | bool mu::core::position::operator == (mu::core::position const & other_a) const 21 | { 22 | bool result (offset == other_a.offset && row == other_a.row && column == other_a.column); 23 | return result; 24 | } 25 | 26 | bool mu::core::region::operator != (mu::core::region const & other_a) const 27 | { 28 | auto result (!(*this == other_a)); 29 | return result; 30 | } 31 | 32 | void mu::core::position::character () 33 | { 34 | ++offset; 35 | ++column; 36 | } 37 | 38 | void mu::core::position::line () 39 | { 40 | ++offset; 41 | ++row; 42 | column = 1; 43 | } 44 | 45 | mu::string mu::core::position::string () 46 | { 47 | char buffer [32 * 3]; 48 | sprintf (buffer, "%" PRId64 " %" PRId64 " %" PRId64, row, column, offset); 49 | std::string result_string (buffer); 50 | mu::string result (result_string.begin (), result_string.end ()); 51 | return result; 52 | } 53 | 54 | mu::core::region::region (uint64_t offset1_a, uint64_t row1_a, uint64_t column1_a, uint64_t offset2_a, uint64_t row2_a, uint64_t column2_a): 55 | first (offset1_a, row1_a, column1_a), 56 | last (offset2_a, row2_a, column2_a) 57 | { 58 | } 59 | 60 | mu::core::region::region (mu::core::position const & first_a, mu::core::position const & last_a): 61 | first (first_a), 62 | last (last_a) 63 | { 64 | } 65 | 66 | bool mu::core::region::operator == (mu::core::region const & other_a) const 67 | { 68 | bool result (first == other_a.first && last == other_a.last); 69 | return result; 70 | } 71 | 72 | mu::string mu::core::region::string () 73 | { 74 | mu::string result (first.string ()); 75 | result += U":"; 76 | result += last.string (); 77 | return result; 78 | } -------------------------------------------------------------------------------- /examples/murmurhash3.mu: -------------------------------------------------------------------------------- 1 | function rotl32 2 | [int32 x int32 r] 3 | [ 4 | let result [or [shl x r] [lshr x [sub cint32 #32 r]]] 5 | ] 6 | [[int32 result]] 7 | 8 | function rotl64 9 | [int64 x int64 r] 10 | [ 11 | let result [or [shl x r] [lshr x [sub cint64 #64 r]]] 12 | ] 13 | [[int64 result]] 14 | 15 | function getblock32 16 | [ptr int32 p int32 i] 17 | [ 18 | let result [load [getelementptr p i]] 19 | ] 20 | [[int32 result]] 21 | 22 | function getblock64 23 | [ptr int64 p int32 i] 24 | [ 25 | let result [load [getelementptr p i]] 26 | ] 27 | [[int64 result]] 28 | 29 | function fmix32 30 | [int32 h] 31 | [ 32 | let h1 [xor h [lshr h cint32 #16]] 33 | let h2 [mul h1 cint32 #h85ebca6b] 34 | let h3 [xor h2 [lshr h2 cint32 #13]] 35 | let h4 [mul h3 cint32 #hc2b2ae35] 36 | let h5 [xor h4 [lshr h4 cint32 #16]] 37 | ] 38 | [[int32 h5]] 39 | 40 | function fmix64 41 | [int64 k] 42 | [ 43 | let k1 [xor k [lshr k cint64 #33]] 44 | let k2 [mul k1 cint64 #hff51afd7ed558ccd] 45 | let k3 [xor k2 [lshr k2 cint64 #33]] 46 | let k4 [mul k3 cint64 #hc4ceb9fe1a85ec53] 47 | let k5 [xor k4 [lshr k4 cint64 #33]] 48 | ] 49 | [[int64 k5]] 50 | 51 | function murmurhash3_x86_32 52 | [ptr int32 key int32 len int32 seed ptr int32 out] 53 | [ 54 | let nblocks [udiv len cint32 #4] 55 | let kn 56 | loop 57 | [[sub cint32 #0 nblocks] seed] 58 | [i h1] 59 | [ 60 | let k1 [getblock32 key i] 61 | let k2 [mul k1 cint32 #hcc9e2d51] 62 | let k3 [rotl32 k2 cint32 #15] 63 | let h2 [xor h1 k3] 64 | let h3 [rotl32 h2 cint32 #13] 65 | let h4 [add [mul h3 cint32 #5] cint32 #he6546b64] 66 | let exit continue [if [icmp eq i cint32 #0]] 67 | let in [sub i cint32 #1] 68 | ] 69 | [[in h4; continue][h4; exit]] 70 | let t3 t2 t1 [switch [and len cint32 #3] cint32 #3 cint32 #2 cint32 #1] 71 | let k1 [xor cint32 #0 [shl [load [getelementptr key cint32 #2]] cint32 #16]; t3] 72 | let k2 [join k1 [~ cint32 #0; t2]] 73 | let k3 [xor k2 [shl [load [getelementptr key cint32 #1]] cint32 #8]] 74 | let k4 [join k3 [~ cint32 #0; t1]] 75 | let k5 [xor k4 [load key]] 76 | let k6 [mul k5 cint32 #hcc9e2d51] 77 | let k7 [rotl32 k6 cint32 #15] 78 | let k8 [mul k7 cint32 #h1b873593] 79 | let hn [xor kn k8] 80 | let result1 [xor hn len] 81 | let result2 [fmix32 result1] 82 | let result3 [store result2 out] 83 | ] 84 | [[; result3]] 85 | 86 | function entry 87 | [] 88 | [] 89 | [[; unit_v [rotl32 cint32 #8 cint32 #8] [rotl64 cint64 #16 cint64 #8]]] 90 | -------------------------------------------------------------------------------- /mu/llvmc/compiler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | mu::llvmc::compiler::compiler (mu::io::string_range const & source_a, llvm::raw_pwrite_stream & output_a) : 19 | lexer (source_a), 20 | stream_token (lexer, 2), 21 | parser (stream_token), 22 | output (output_a) 23 | { 24 | } 25 | 26 | void mu::llvmc::compiler::compile (mu::string const & name_a, mu::string const & path_a) 27 | { 28 | auto parse_result (parser.parse ()); 29 | if (parse_result.error == nullptr) 30 | { 31 | mu::llvmc::analyzer analyzer; 32 | auto analyze_result (analyzer.analyze (parse_result.node)); 33 | if (analyze_result.error == nullptr) 34 | { 35 | mu::llvmc::generator generator; 36 | llvm::LLVMContext context; 37 | auto module (generator.generate (context, analyze_result.module, name_a, path_a, 0)); 38 | std::string contents; 39 | llvm::raw_string_ostream stream (contents); 40 | module.module->print (stream, nullptr); 41 | std::cout << contents; 42 | std::string info; 43 | llvm::raw_string_ostream info_stream (info); 44 | assert (!llvm::verifyModule (*module.module, &info_stream)); 45 | if (module.entry != nullptr) 46 | { 47 | auto entry_function (module.entry); 48 | assert (entry_function->getReturnType ()->isVoidTy ()); 49 | assert (entry_function->getArgumentList ().empty ()); 50 | inject_entry (*module.module, entry_function); 51 | auto triple (llvm::sys::getDefaultTargetTriple ()); 52 | std::string error; 53 | auto target (llvm::TargetRegistry::lookupTarget (triple, error)); 54 | if (target != nullptr) 55 | { 56 | module.module->setTargetTriple (llvm::sys::getDefaultTargetTriple ()); 57 | llvm::TargetOptions options; 58 | auto machine (target->createTargetMachine (triple, "", "", options, llvm::Reloc::Default, llvm::CodeModel::Default, llvm::CodeGenOpt::None)); 59 | llvm::legacy::PassManager pass_manager; 60 | auto failed (machine->addPassesToEmitFile (pass_manager, output, llvm::TargetMachine::CodeGenFileType::CGFT_ObjectFile)); 61 | pass_manager.run (*module.module); 62 | } 63 | else 64 | { 65 | std::cout << "Unable to lookup target triple: " << error; 66 | } 67 | } 68 | else 69 | { 70 | std::cout << "Module has no entry point function specified"; 71 | } 72 | } 73 | else 74 | { 75 | std::cout << "Error analyzing (" << (uint64_t)analyze_result.error->type () << "): " << analyze_result.error->string () << '\n'; 76 | } 77 | } 78 | else 79 | { 80 | std::cout << "Error parsing (" << (uint64_t)parse_result.error->type () << "): " << parse_result.error->string () << '\n'; 81 | } 82 | } 83 | 84 | void mu::llvmc::compiler::inject_entry (llvm::Module & module_a, llvm::Function * entry_a) 85 | { 86 | auto & context (module_a.getContext ()); 87 | auto entry_type (llvm::FunctionType::get (llvm::Type::getVoidTy (context), llvm::ArrayRef (), false)); 88 | auto entry (llvm::Function::Create (entry_type, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "\x01start")); 89 | auto block (llvm::BasicBlock::Create (context)); 90 | entry->getBasicBlockList ().push_back (block); 91 | auto call_entry (llvm::CallInst::Create (entry_a)); 92 | block->getInstList ().push_back (call_entry); 93 | block->getInstList ().push_back (new llvm::UnreachableInst (context)); 94 | module_a.getFunctionList().push_back (entry); 95 | } -------------------------------------------------------------------------------- /mu/test/llvmc_skeleton.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | TEST (llvmc_skeleton, most_specific_branch1) 7 | { 8 | mu::llvmc::skeleton::branch branch1 (nullptr); 9 | mu::llvmc::skeleton::branch branch2 (nullptr); 10 | auto branch3 (branch1.most_specific (&branch2)); 11 | ASSERT_EQ (nullptr, branch3); 12 | } 13 | 14 | TEST (llvmc_skeleton, most_specific_branch2) 15 | { 16 | mu::llvmc::skeleton::branch branch1 (nullptr); 17 | mu::llvmc::skeleton::branch branch2 (&branch1); 18 | auto branch3 (branch1.most_specific (&branch2)); 19 | ASSERT_EQ (&branch2, branch3); 20 | } 21 | 22 | TEST (llvmc_skeleton, most_specific_branch3) 23 | { 24 | mu::llvmc::skeleton::branch branch1 (nullptr); 25 | mu::llvmc::skeleton::branch branch2 (&branch1); 26 | auto branch3 (branch2.most_specific (&branch1)); 27 | ASSERT_EQ (&branch2, branch3); 28 | } 29 | 30 | TEST (llvmc_skeleton, most_specific_branch4) 31 | { 32 | mu::llvmc::skeleton::branch branch1 (nullptr); 33 | mu::llvmc::skeleton::branch branch2 (&branch1); 34 | mu::llvmc::skeleton::branch branch3 (&branch1); 35 | auto branch4 (branch2.most_specific (&branch3)); 36 | ASSERT_EQ (nullptr, branch4); 37 | } 38 | 39 | TEST (llvmc_skeleton, ptr_equality) 40 | { 41 | mu::llvmc::skeleton::integer_type type1 (8); 42 | mu::llvmc::skeleton::pointer_type type2 (&type1); 43 | mu::llvmc::skeleton::integer_type type3 (8); 44 | mu::llvmc::skeleton::pointer_type type4 (&type3); 45 | ASSERT_EQ (type2, type4); 46 | } 47 | 48 | TEST (llvmc_skeleton, error_integer_type_match_pointer) 49 | { 50 | mu::llvmc::skeleton::integer_type type1 (8); 51 | mu::llvmc::skeleton::integer_type type3 (8); 52 | mu::llvmc::skeleton::pointer_type type4 (&type3); 53 | ASSERT_NE (type1, type4); 54 | } 55 | 56 | TEST (llvmc_skeleton, function_type_name) 57 | { 58 | mu::llvmc::skeleton::function function (mu::empty_region); 59 | mu::llvmc::skeleton::function_type function_type (&function); 60 | auto name (function_type.name ()); 61 | ASSERT_EQ (U"function [] []", name); 62 | } 63 | 64 | TEST (llvmc_skeleton, function_type_name2) 65 | { 66 | mu::llvmc::skeleton::function function (mu::empty_region); 67 | mu::llvmc::skeleton::function_type function_type (&function); 68 | mu::llvmc::skeleton::integer_type type1 (8); 69 | mu::llvmc::skeleton::parameter parameter1 (mu::empty_region, function.entry, &type1, U"p0"); 70 | function.parameters.push_back (¶meter1); 71 | mu::llvmc::skeleton::parameter parameter2 (mu::empty_region, function.entry, &type1, U"p1"); 72 | function.parameters.push_back (¶meter2); 73 | auto name (function_type.name ()); 74 | ASSERT_EQ (U"function [int8 int8] []", name); 75 | } 76 | 77 | TEST (llvmc_skeleton, function_type_name3) 78 | { 79 | mu::llvmc::skeleton::function function (mu::empty_region); 80 | mu::llvmc::skeleton::function_type function_type (&function); 81 | mu::llvmc::skeleton::integer_type type1 (8); 82 | mu::llvmc::skeleton::constant_integer constant1 (mu::empty_region, &type1, 42); 83 | function.returns = {{&type1, &type1}}; 84 | function.results = {{{&constant1, &constant1}, {}}}; 85 | auto name (function_type.name ()); 86 | ASSERT_EQ (U"function [] [[int8 int8]]", name); 87 | } 88 | 89 | TEST (llvmc_skeleton, function_type_name4) 90 | { 91 | mu::llvmc::skeleton::function function (mu::empty_region); 92 | mu::llvmc::skeleton::function_type function_type (&function); 93 | mu::llvmc::skeleton::integer_type type1 (8); 94 | mu::llvmc::skeleton::constant_integer constant1 (mu::empty_region, &type1, 42); 95 | function.returns = {{&type1}}; 96 | function.results = {{{&constant1}, {&constant1}}}; 97 | auto name (function_type.name ()); 98 | ASSERT_EQ (U"function [] [[int8]]", name); 99 | } 100 | 101 | TEST (llvmc_skeleton, function_type_name5) 102 | { 103 | mu::llvmc::skeleton::function function (mu::empty_region); 104 | mu::llvmc::skeleton::function_type function_type (&function); 105 | mu::llvmc::skeleton::integer_type type1 (8); 106 | mu::llvmc::skeleton::constant_integer constant1 (mu::empty_region, &type1, 42); 107 | function.returns = {{&type1}, {&type1}}; 108 | function.results = {{{&constant1}, {}}, {{&constant1}, {}}}; 109 | auto name (function_type.name ()); 110 | ASSERT_EQ (U"function [] [[int8][int8]]", name); 111 | } 112 | 113 | TEST (llvmc_skeleton, fixed_array_type) 114 | { 115 | mu::llvmc::skeleton::integer_type type1 (8); 116 | mu::llvmc::skeleton::fixed_array_type farray (&type1, 4); 117 | auto name (farray.name ()); 118 | ASSERT_EQ (U"farray int8 #4", name); 119 | } 120 | 121 | TEST (llvmc_skeleton, unit_type) 122 | { 123 | mu::llvmc::skeleton::unit_type type1; 124 | auto name (type1.name ()); 125 | ASSERT_EQ (U"unit", name); 126 | } 127 | 128 | TEST (llvmc_skeleton, pointer_type) 129 | { 130 | mu::llvmc::skeleton::integer_type type1 (8); 131 | mu::llvmc::skeleton::pointer_type type2 (&type1); 132 | auto name (type2.name ()); 133 | ASSERT_EQ (U"ptr int8", name); 134 | } 135 | 136 | TEST (llvmc_skeleton, number_bits_0) 137 | { 138 | mu::llvmc::skeleton::number number1 (0); 139 | auto bits (number1.bits_required ()); 140 | ASSERT_EQ (1, bits); 141 | } 142 | 143 | TEST (llvmc_skeleton, number_bits_1) 144 | { 145 | mu::llvmc::skeleton::number number1 (1); 146 | auto bits (number1.bits_required ()); 147 | ASSERT_EQ (1, bits); 148 | } 149 | 150 | TEST (llvmc_skeleton, number_bits_255) 151 | { 152 | mu::llvmc::skeleton::number number1 (255); 153 | auto bits (number1.bits_required ()); 154 | ASSERT_EQ (8, bits); 155 | } 156 | 157 | TEST (llvmc_skeleton, number_bits_256) 158 | { 159 | mu::llvmc::skeleton::number number1 (256); 160 | auto bits (number1.bits_required ()); 161 | ASSERT_EQ (9, bits); 162 | } -------------------------------------------------------------------------------- /mu/llvmc/parser_t.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | template 9 | mu::core::error * mu::llvmc::parser::parse_ast_or_refer (T op) 10 | { 11 | mu::core::error * result (nullptr); 12 | auto item (peek ()); 13 | if (item.ast != nullptr) 14 | { 15 | op (item.ast, item.ast->region); 16 | } 17 | else if (item.token != nullptr) 18 | { 19 | auto id (item.token->id ()); 20 | switch (id) 21 | { 22 | case mu::io::token_id::identifier: 23 | { 24 | current_mapping->refer (static_cast (item.token)->string, item.token->region, op); 25 | break; 26 | } 27 | default: 28 | { 29 | result = new mu::core::error_string (U"Expecting ast or reference", mu::core::error_type::expecting_ast_or_reference, item.token->region); 30 | break; 31 | } 32 | } 33 | } 34 | else 35 | { 36 | result = item.error; 37 | } 38 | return result; 39 | } 40 | 41 | template 42 | mu::core::error * mu::llvmc::parser::parse_identifier (T identifier_op, char32_t const * error_message_a, mu::core::error_type error_type_a) 43 | { 44 | mu::core::error * result; 45 | auto item (stream [0]); 46 | auto id (item->id ()); 47 | switch (id) 48 | { 49 | case mu::io::token_id::identifier: 50 | stream.consume (1); 51 | result = identifier_op (mu::cast (item)); 52 | break; 53 | default: 54 | result = new mu::core::error_string (error_message_a, error_type_a, item->region); 55 | break; 56 | } 57 | return result; 58 | } 59 | 60 | template 61 | mu::core::error * mu::llvmc::parser::parse_identifier_or_right_square (T identifier_op, U right_square_op, char32_t const * error_message_a, mu::core::error_type error_type_a) 62 | { 63 | mu::core::error * result; 64 | auto item (stream [0]); 65 | auto id (item->id ()); 66 | switch (id) 67 | { 68 | case mu::io::token_id::identifier: 69 | stream.consume (1); 70 | result = identifier_op (mu::cast (item)); 71 | break; 72 | case mu::io::token_id::right_square: 73 | stream.consume (1); 74 | result = right_square_op (mu::cast (item)); 75 | break; 76 | default: 77 | result = new mu::core::error_string (error_message_a, error_type_a, item->region); 78 | break; 79 | } 80 | return result; 81 | } 82 | 83 | template 84 | mu::core::error * mu::llvmc::parser::parse_ast_or_refer_or_right_square (T op, U right_square_op, char32_t const * error_message_a, mu::core::error_type error_type_a) 85 | { 86 | mu::core::error * result (nullptr); 87 | auto item (peek ()); 88 | if (item.ast != nullptr) 89 | { 90 | op (item.ast, item.ast->region); 91 | } 92 | else if (item.token != nullptr) 93 | { 94 | auto id (item.token->id ()); 95 | switch (id) 96 | { 97 | case mu::io::token_id::identifier: 98 | { 99 | auto identifier (mu::cast (item.token)); 100 | current_mapping->refer (identifier->string, identifier->region, op); 101 | break; 102 | } 103 | case mu::io::token_id::right_square: 104 | { 105 | right_square_op (mu::cast (item.token)); 106 | break; 107 | } 108 | default: 109 | { 110 | result = new mu::core::error_string (error_message_a, error_type_a, item.token->region); 111 | break; 112 | } 113 | } 114 | } 115 | else 116 | { 117 | assert (item.error != nullptr); 118 | result = item.error; 119 | } 120 | return result; 121 | } 122 | 123 | template 124 | mu::core::error * mu::llvmc::parser::parse_left_or_right_square (T left_square_op, U right_square_op, char32_t const * error_message_a, mu::core::error_type error_type_a) 125 | { 126 | mu::core::error * result (nullptr); 127 | auto item (stream [0]); 128 | switch (item->id ()) 129 | { 130 | case mu::io::token_id::left_square: 131 | stream.consume (1); 132 | result = left_square_op (item->region); 133 | break; 134 | case mu::io::token_id::right_square: 135 | stream.consume (1); 136 | result = right_square_op (item->region); 137 | break; 138 | default: 139 | result = new mu::core::error_string (error_message_a, error_type_a, item->region); 140 | break; 141 | } 142 | return result; 143 | } 144 | 145 | template 146 | mu::core::error * mu::llvmc::parser::parse_ast_or_refer_or_right_square_or_terminator (T node_op, U right_square_op, V terminator_op, char32_t const * error_message_a, mu::core::error_type error_type_a) 147 | { 148 | mu::core::error * error (nullptr); 149 | auto item (peek ()); 150 | if (item.ast != nullptr) 151 | { 152 | node_op (item.ast, item.ast->region); 153 | } 154 | else if (item.token != nullptr) 155 | { 156 | switch (item.token->id ()) 157 | { 158 | case mu::io::token_id::identifier: 159 | { 160 | auto identifier (mu::cast (item.token)); 161 | current_mapping->refer (identifier->string, identifier->region, node_op); 162 | break; 163 | } 164 | case mu::io::token_id::right_square: 165 | right_square_op (item.token->region); 166 | break; 167 | case mu::io::token_id::terminator: 168 | terminator_op (item.token->region); 169 | break; 170 | default: 171 | error = new mu::core::error_string (error_message_a, error_type_a, item.token->region); 172 | break; 173 | } 174 | } 175 | else 176 | { 177 | error = item.error; 178 | } 179 | return error; 180 | } -------------------------------------------------------------------------------- /mu/core/siphash24.c: -------------------------------------------------------------------------------- 1 | /* 2 | SipHash reference C implementation 3 | 4 | Copyright (c) 2012-2014 Jean-Philippe Aumasson 5 | 6 | Copyright (c) 2012-2014 Daniel J. Bernstein 7 | 8 | To the extent possible under law, the author(s) have dedicated all copyright 9 | and related and neighboring rights to this software to the public domain 10 | worldwide. This software is distributed without any warranty. 11 | 12 | You should have received a copy of the CC0 Public Domain Dedication along 13 | with 14 | this software. If not, see 15 | . 16 | */ 17 | #include 18 | #include 19 | #include 20 | 21 | #define DOUBLE 22 | /* default: SipHash-2-4 */ 23 | #define cROUNDS 2 24 | #define dROUNDS 4 25 | 26 | #define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) 27 | 28 | #define U32TO8_LE(p, v) \ 29 | (p)[0] = (uint8_t)((v)); \ 30 | (p)[1] = (uint8_t)((v) >> 8); \ 31 | (p)[2] = (uint8_t)((v) >> 16); \ 32 | (p)[3] = (uint8_t)((v) >> 24); 33 | 34 | #define U64TO8_LE(p, v) \ 35 | U32TO8_LE((p), (uint32_t)((v))); \ 36 | U32TO8_LE((p) + 4, (uint32_t)((v) >> 32)); 37 | 38 | #define U8TO64_LE(p) \ 39 | (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \ 40 | ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \ 41 | ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \ 42 | ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56)) 43 | 44 | #define SIPROUND \ 45 | do { \ 46 | v0 += v1; \ 47 | v1 = ROTL(v1, 13); \ 48 | v1 ^= v0; \ 49 | v0 = ROTL(v0, 32); \ 50 | v2 += v3; \ 51 | v3 = ROTL(v3, 16); \ 52 | v3 ^= v2; \ 53 | v0 += v3; \ 54 | v3 = ROTL(v3, 21); \ 55 | v3 ^= v0; \ 56 | v2 += v1; \ 57 | v1 = ROTL(v1, 17); \ 58 | v1 ^= v2; \ 59 | v2 = ROTL(v2, 32); \ 60 | } while (0) 61 | 62 | #ifdef DEBUG 63 | #define TRACE \ 64 | do { \ 65 | printf("(%3d) v0 %08x %08x\n", (int)inlen, (uint32_t)(v0 >> 32), \ 66 | (uint32_t)v0); \ 67 | printf("(%3d) v1 %08x %08x\n", (int)inlen, (uint32_t)(v1 >> 32), \ 68 | (uint32_t)v1); \ 69 | printf("(%3d) v2 %08x %08x\n", (int)inlen, (uint32_t)(v2 >> 32), \ 70 | (uint32_t)v2); \ 71 | printf("(%3d) v3 %08x %08x\n", (int)inlen, (uint32_t)(v3 >> 32), \ 72 | (uint32_t)v3); \ 73 | } while (0) 74 | #else 75 | #define TRACE 76 | #endif 77 | 78 | int siphash(uint8_t *out, const uint8_t *in, uint64_t inlen, const uint8_t *k) { 79 | /* "somepseudorandomlygeneratedbytes" */ 80 | uint64_t v0 = 0x736f6d6570736575ULL; 81 | uint64_t v1 = 0x646f72616e646f6dULL; 82 | uint64_t v2 = 0x6c7967656e657261ULL; 83 | uint64_t v3 = 0x7465646279746573ULL; 84 | uint64_t b; 85 | uint64_t k0 = U8TO64_LE(k); 86 | uint64_t k1 = U8TO64_LE(k + 8); 87 | uint64_t m; 88 | int i; 89 | const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t)); 90 | const int left = inlen & 7; 91 | b = ((uint64_t)inlen) << 56; 92 | v3 ^= k1; 93 | v2 ^= k0; 94 | v1 ^= k1; 95 | v0 ^= k0; 96 | 97 | #ifdef DOUBLE 98 | v1 ^= 0xee; 99 | #endif 100 | 101 | for (; in != end; in += 8) { 102 | m = U8TO64_LE(in); 103 | v3 ^= m; 104 | 105 | TRACE; 106 | for (i = 0; i < cROUNDS; ++i) 107 | SIPROUND; 108 | 109 | v0 ^= m; 110 | } 111 | 112 | switch (left) { 113 | case 7: 114 | b |= ((uint64_t)in[6]) << 48; 115 | case 6: 116 | b |= ((uint64_t)in[5]) << 40; 117 | case 5: 118 | b |= ((uint64_t)in[4]) << 32; 119 | case 4: 120 | b |= ((uint64_t)in[3]) << 24; 121 | case 3: 122 | b |= ((uint64_t)in[2]) << 16; 123 | case 2: 124 | b |= ((uint64_t)in[1]) << 8; 125 | case 1: 126 | b |= ((uint64_t)in[0]); 127 | break; 128 | case 0: 129 | break; 130 | } 131 | 132 | v3 ^= b; 133 | 134 | TRACE; 135 | for (i = 0; i < cROUNDS; ++i) 136 | SIPROUND; 137 | 138 | v0 ^= b; 139 | 140 | #ifndef DOUBLE 141 | v2 ^= 0xff; 142 | #else 143 | v2 ^= 0xee; 144 | #endif 145 | 146 | TRACE; 147 | for (i = 0; i < dROUNDS; ++i) 148 | SIPROUND; 149 | 150 | b = v0 ^ v1 ^ v2 ^ v3; 151 | U64TO8_LE(out, b); 152 | 153 | #ifdef DOUBLE 154 | v1 ^= 0xdd; 155 | 156 | TRACE; 157 | for (i = 0; i < dROUNDS; ++i) 158 | SIPROUND; 159 | 160 | b = v0 ^ v1 ^ v2 ^ v3; 161 | U64TO8_LE(out + 8, b); 162 | #endif 163 | 164 | return 0; 165 | } 166 | 167 | -------------------------------------------------------------------------------- /mu/llvmc/generator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace llvm 13 | { 14 | class Module; 15 | class Function; 16 | class Type; 17 | class BasicBlock; 18 | class Value; 19 | class PHINode; 20 | class Instruction; 21 | class ConstantInt; 22 | class TerminatorInst; 23 | class DIBuilder; 24 | } 25 | namespace mu 26 | { 27 | namespace core 28 | { 29 | class error; 30 | } 31 | namespace llvmc 32 | { 33 | namespace skeleton 34 | { 35 | class module; 36 | class function; 37 | class type; 38 | class value; 39 | class branch; 40 | class node; 41 | class switch_element; 42 | class constant_integer; 43 | class function_call; 44 | class constant; 45 | enum class function_return_type; 46 | } 47 | class generator_result 48 | { 49 | public: 50 | llvm::Function * entry; 51 | std::unique_ptr module; 52 | }; 53 | class generator 54 | { 55 | public: 56 | mu::llvmc::generator_result generate (llvm::LLVMContext & context_a, mu::llvmc::skeleton::module * module_a, mu::string const & name_a, mu::string const & path_a, uint64_t module_id_a); 57 | }; 58 | class generate_system : public mu::llvmc::skeleton::visitor 59 | { 60 | public: 61 | generate_system (llvm::LLVMContext & context_a, mu::string const & name_a, mu::string const & path_a, uint64_t module_id_a); 62 | void generate_value (mu::llvmc::skeleton::value * node_a); 63 | void generate_type (mu::llvmc::skeleton::type * node_a); 64 | void module (mu::llvmc::skeleton::module * node_a) override; 65 | mu::llvmc::skeleton::visitor * current_generator; 66 | mu::string const & name; 67 | mu::string const & path; 68 | uint64_t module_id; 69 | mu::llvmc::generator_result result; 70 | }; 71 | class generate_module : public mu::llvmc::skeleton::visitor 72 | { 73 | public: 74 | generate_module (mu::llvmc::generate_system & system_a, mu::llvmc::skeleton::module * module_a); 75 | ~generate_module (); 76 | void constant_aggregate_zero (mu::llvmc::skeleton::constant_aggregate_zero * node_a) override; 77 | void unit_value (mu::llvmc::skeleton::unit_value * node_a) override; 78 | void constant_array (mu::llvmc::skeleton::constant_array * constant_array) override; 79 | void constant_pointer_null (mu::llvmc::skeleton::constant_pointer_null * value_a) override; 80 | void constant_integer (mu::llvmc::skeleton::constant_integer * constant_int) override; 81 | void global_variable (mu::llvmc::skeleton::global_variable * global_variable) override; 82 | void undefined (mu::llvmc::skeleton::undefined * node_a) override; 83 | void function (mu::llvmc::skeleton::function * node_a) override; 84 | void named (mu::llvmc::skeleton::named * node_a) override; 85 | void integer_type (mu::llvmc::skeleton::integer_type * integer_type) override; 86 | void pointer_type (mu::llvmc::skeleton::pointer_type * pointer_type) override; 87 | void unit_type (mu::llvmc::skeleton::unit_type * unit_type) override; 88 | void function_type (mu::llvmc::skeleton::function_type * function_type_a) override; 89 | void fixed_array_type (mu::llvmc::skeleton::fixed_array_type * array_type) override; 90 | void struct_type (mu::llvmc::skeleton::struct_type * struct_type) override; 91 | void node (mu::llvmc::skeleton::node * node_a) override; 92 | std::string get_global_name (mu::string const & name_a); 93 | void generate (); 94 | llvm::DIBuilder builder; 95 | mu::llvmc::skeleton::module * module; 96 | llvm::DIFile * file; 97 | uint64_t global_id; 98 | mu::llvmc::skeleton::visitor * previous; 99 | mu::llvmc::generate_system & system; 100 | }; 101 | class generate_function : public mu::llvmc::skeleton::visitor 102 | { 103 | public: 104 | generate_function (mu::llvmc::generate_module & module_a, mu::llvmc::skeleton::function * function_a); 105 | ~generate_function (); 106 | void call_element (mu::llvmc::skeleton::call_element * node_a) override; 107 | void loop_element (mu::llvmc::skeleton::loop_element * loop_element) override; 108 | void identity_element (mu::llvmc::skeleton::identity_element * identity_value) override; 109 | void join_element (mu::llvmc::skeleton::join_element * join) override; 110 | void inline_asm (mu::llvmc::skeleton::inline_asm * asm_l) override; 111 | void switch_element (mu::llvmc::skeleton::switch_element * element) override; 112 | void named (mu::llvmc::skeleton::named * named) override; 113 | void instruction (mu::llvmc::skeleton::instruction * instruction) override; 114 | void icmp (mu::llvmc::skeleton::icmp * icmp) override; 115 | void store (mu::llvmc::skeleton::store * store) override; 116 | void node (mu::llvmc::skeleton::node * node_a) override; 117 | void generate_loop_arguments (mu::llvmc::skeleton::loop_element * loop_element, llvm::Value * & loop_predicate); 118 | void generate (); 119 | llvm::Value * generate_rejoin (llvm::BasicBlock * entry, llvm::BasicBlock * predicate, llvm::BasicBlock * successor, llvm::Value * value_a); 120 | void write_selector (llvm::LLVMContext & context, llvm::Value * & selector, uint8_t selector_number); 121 | llvm::Value * process_predicates (llvm::Value * predicate_a, mu::vector const & arguments_a); 122 | llvm::Value * and_predicates (llvm::Value * left_a, llvm::Value * right_a); 123 | std::vector generate_result_set (); 124 | mu::llvmc::generate_module & module; 125 | llvm::BasicBlock * last; 126 | llvm::Function * function_m; 127 | mu::llvmc::skeleton::function * function; 128 | mu::llvmc::skeleton::function_return_type function_return_type; 129 | llvm::DILexicalBlock * block_d; 130 | mu::llvmc::skeleton::visitor * previous; 131 | }; 132 | } 133 | } -------------------------------------------------------------------------------- /mu/llvmc/analyzer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "ast.hpp" 6 | 7 | namespace mu 8 | { 9 | namespace core 10 | { 11 | class error; 12 | class region; 13 | } 14 | namespace llvmc 15 | { 16 | namespace skeleton 17 | { 18 | class value; 19 | class node; 20 | class module; 21 | class function; 22 | class type; 23 | class branch; 24 | class number; 25 | class global_value; 26 | } 27 | namespace ast 28 | { 29 | class node; 30 | class expression; 31 | class function; 32 | class instruction; 33 | class element; 34 | class integer_type; 35 | class pointer_type; 36 | class constant_int; 37 | class number; 38 | class loop; 39 | class asm_c; 40 | class array_type; 41 | class constant_array; 42 | class join; 43 | } 44 | class module_result 45 | { 46 | public: 47 | mu::llvmc::skeleton::module * module; 48 | mu::core::error * error; 49 | }; 50 | class function_result 51 | { 52 | public: 53 | mu::llvmc::skeleton::function * function; 54 | mu::core::error * error; 55 | }; 56 | class global_processor : public mu::llvmc::ast::visitor 57 | { 58 | public: 59 | global_processor (mu::core::error * & error_a); 60 | void process_node (mu::llvmc::ast::node * node_a); 61 | void node (mu::llvmc::ast::node * node_a) override; 62 | void module (mu::llvmc::ast::module * node_a) override; 63 | void number (mu::llvmc::ast::number * node_a) override; 64 | void template_parameter (mu::llvmc::ast::template_parameter * node_a) override; 65 | mu::llvmc::skeleton::number * process_number (mu::llvmc::ast::node *); 66 | std::string print_analysis_stack (); 67 | mu::vector analysis_stack; 68 | mu::llvmc::ast::visitor * current_context; 69 | mu::core::error * & error; 70 | mu::llvmc::skeleton::branch * current_origin; 71 | }; 72 | class module_processor : public mu::llvmc::ast::visitor 73 | { 74 | public: 75 | module_processor (mu::llvmc::global_processor &); 76 | ~module_processor (); 77 | void function (mu::llvmc::ast::function *) override; 78 | void function_overload (mu::llvmc::ast::function_overload *) override; 79 | void function_family (mu::llvmc::ast::function_family *) override; 80 | void node (mu::llvmc::ast::node *) override; 81 | void element (mu::llvmc::ast::element *) override; 82 | void set (mu::llvmc::ast::set *) override; 83 | void entry (mu::llvmc::ast::entry *) override; 84 | void fixed_array_type (mu::llvmc::ast::fixed_array_type *) override; 85 | void integer_type (mu::llvmc::ast::integer_type *) override; 86 | void pointer_type (mu::llvmc::ast::pointer_type *) override; 87 | void unit_type (mu::llvmc::ast::unit_type *) override; 88 | void struct_type (mu::llvmc::ast::struct_type *) override; 89 | void process_single_node (mu::llvmc::ast::node *); 90 | void global_variable (mu::llvmc::ast::global_variable *) override; 91 | void constant_int (mu::llvmc::ast::constant_int *) override; 92 | void constant_array (mu::llvmc::ast::constant_array *) override; 93 | void constant_pointer_null (mu::llvmc::ast::constant_pointer_null *) override; 94 | void expression (mu::llvmc::ast::expression *) override; 95 | void process_identity (mu::llvmc::ast::expression *); 96 | void template_c (mu::llvmc::ast::template_c *) override; 97 | void value (mu::llvmc::ast::value *) override; 98 | void process_template (mu::llvmc::ast::expression *); 99 | void process_expression_value_arguments (mu::vector const &, mu::vector &, mu::vector &, mu::llvmc::skeleton::branch * &); 100 | void process_constant_int (mu::llvmc::ast::expression *); 101 | mu::llvmc::skeleton::type * process_type (mu::llvmc::ast::node *); 102 | mu::llvmc::global_processor & global_m; 103 | mu::llvmc::skeleton::module * module_m; 104 | mu::set unnamed_globals; 105 | mu::set named_globals; 106 | mu::set current_expression_generation; 107 | mu::llvmc::ast::visitor * previous; 108 | }; 109 | class function_processor : public mu::llvmc::ast::visitor 110 | { 111 | public: 112 | function_processor (mu::llvmc::module_processor & module_a, mu::llvmc::ast::function * node_a); 113 | ~function_processor (); 114 | void process (); 115 | void process_value_call (mu::llvmc::ast::expression * expression_a); 116 | void process_marker (mu::llvmc::ast::expression * expression_a); 117 | void process_asm (mu::llvmc::ast::expression * expression_a); 118 | void process_binary_integer_instruction (mu::llvmc::ast::expression *, mu::vector &, mu::vector &, mu::llvmc::skeleton::branch *); 119 | mu::llvmc::skeleton::value * process_value (mu::llvmc::ast::node * node_a); 120 | void process_expression (mu::llvmc::ast::expression * node_a); 121 | void node (mu::llvmc::ast::node * node_a) override; 122 | void unit (mu::llvmc::ast::unit * node_a) override; 123 | void asm_c (mu::llvmc::ast::asm_c * asm_l) override; 124 | void join (mu::llvmc::ast::join * node_a) override; 125 | void loop (mu::llvmc::ast::loop * loop_a) override; 126 | void sequence (mu::llvmc::ast::sequence *) override; 127 | void expression (mu::llvmc::ast::expression * expression_a) override; 128 | void undefined (mu::llvmc::ast::undefined * node_a) override; 129 | void namespace_c (mu::llvmc::ast::namespace_c * node_a) override; 130 | void process_parameters (); 131 | void process_returns (); 132 | void process_results (); 133 | mu::llvmc::module_processor & module_m; 134 | mu::llvmc::skeleton::function * function_m; 135 | mu::llvmc::ast::function * node_m; 136 | mu::llvmc::ast::visitor * previous; 137 | mu::llvmc::skeleton::branch * previous_origin; 138 | }; 139 | class branch_analyzer 140 | { 141 | public: 142 | branch_analyzer (mu::llvmc::skeleton::branch *, mu::core::error * &); 143 | mu::llvmc::skeleton::branch * add_branch (mu::llvmc::skeleton::branch *, mu::core::region const &); 144 | void new_set (); 145 | mu::llvmc::skeleton::branch * start; 146 | mu::llvmc::skeleton::branch * most_specific; 147 | mu::set ancestors; 148 | mu::set leaves; 149 | mu::core::error * & result; 150 | }; 151 | class analyzer 152 | { 153 | public: 154 | module_result analyze (mu::llvmc::ast::node * module_a); 155 | }; 156 | } 157 | } -------------------------------------------------------------------------------- /mu/core/error.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace mu 7 | { 8 | namespace core 9 | { 10 | enum class error_type 11 | { 12 | unknown, 13 | unknown_control_character, 14 | terminator_token_too_long, 15 | end_of_stream_inside_complex_identifier, 16 | non_hex_character, 17 | end_of_stream_inside_region_comment, 18 | expecting_type_in_parameters, 19 | unknown_expression_subclass, 20 | no_value_at_index, 21 | value_has_only_one_element, 22 | expecting_one_value, 23 | node_is_not_a_value, 24 | expecting_a_type, 25 | result_branch_is_not_distinct, 26 | expecting_a_function, 27 | expecting_a_module, 28 | expecting_a_target, 29 | unit_cannot_be_target_of_call, 30 | expecting_first_argument_to_be_call_target, 31 | expecting_a_call_target, 32 | cycle_in_expressions, 33 | argument_type_does_not_match_parameter_type, 34 | argument_to_function_is_not_a_value, 35 | pointer_does_not_point_to_a_function, 36 | only_function_pointers_can_be_target_of_call, 37 | join_arguments_must_be_values, 38 | branches_are_not_disjoint, 39 | joining_types_are_different, 40 | must_be_joining_at_least_two_values, 41 | if_instruction_expects_one_bit_integer, 42 | if_instruction_expects_integer_type_value, 43 | if_instruction_expects_a_value_argument, 44 | if_instruction_expects_one_argument, 45 | add_arguments_must_have_same_bit_width, 46 | add_arguments_must_be_integers, 47 | add_arguments_must_be_values, 48 | add_expects_two_arguments, 49 | arguments_are_disjoint, 50 | expecting_function, 51 | expecting_function_or_end_of_stream, 52 | function_name_already_used, 53 | expecting_identifier, 54 | expecting_function_name, 55 | parsing_parameters_expecting_left_square, 56 | unable_to_use_identifier, 57 | parsing_parameters_expecting_identifier, 58 | expecting_a_parameter_name, 59 | expecting_type_or_right_square, 60 | expecting_expression, 61 | expecting_left_square, 62 | expecting_identifier_or_right_square, 63 | expecting_result_reference, 64 | expecting_right_square, 65 | bit_width_too_wide, 66 | unable_to_convert_number_to_unsigned_integer, 67 | expecting_argument_or_right_square, 68 | expecting_name, 69 | expecting_identifier_or_left_square, 70 | unknown_token_in_let_statement, 71 | expecting_expression_or_right_square, 72 | expecting_loop_body, 73 | expecting_result_set_or_right_square, 74 | expecting_loop_results, 75 | already_parsing_predicates, 76 | unresolved_symbols, 77 | incorrect_number_of_arguments, 78 | expecting_a_number, 79 | error_converting_string_to_number, 80 | store_expects_two_arguments, 81 | store_arguments_must_be_values, 82 | store_right_argument_pointer_type, 83 | store_right_pointed_type_doesnt_match_left, 84 | load_expects_one_argument, 85 | load_argument_must_be_values, 86 | load_argument_pointer_type, 87 | mismatch_number_of_arguments_number_of_parameters, 88 | loop_argument_must_be_value, 89 | loop_result_must_be_value, 90 | loop_not_enough_branches, 91 | icmp_expects_predicate_two_arguments, 92 | icmp_first_argument_predicate, 93 | icmp_left_argument_value, 94 | icmp_right_argument_value, 95 | icmp_arguments_integers, 96 | icmp_arguments_same_type, 97 | branch_analyzer_leaves_exist, 98 | branch_analyzer_ancestor_exists, 99 | branch_analyzer_already_ancestor, 100 | branch_analyzer_disjoint, 101 | branch_analyzer_intersection_exists, 102 | sub_arguments_must_have_same_bit_width, 103 | sub_arguments_must_be_integers, 104 | sub_arguments_must_be_values, 105 | sub_expects_two_arguments, 106 | asm_hook_expecting_identifier, 107 | asm_hook_expecting_type, 108 | asm_hook_expecting_constraints, 109 | inline_asm_requires_values, 110 | alloca_expects_one_argument, 111 | alloca_argument_type, 112 | instruction_arguments_must_have_same_bit_width, 113 | instruction_arguments_must_be_integers, 114 | instruction_arguments_must_be_values, 115 | instruction_expects_two_arguments, 116 | cmpxchg_requires_three_arguments, 117 | cmpxchg_argument_one_pointer, 118 | cmpxchg_one_point_two, 119 | cmpxchg_one_point_three, 120 | getelementptr_requires_two, 121 | getelementptr_requires_values, 122 | getelementptr_requires_pointer_type, 123 | getelementptr_first_argument_integer_type, 124 | getelementptr_trailing_constant, 125 | getelementptr_trailing_32bit, 126 | expecting_a_result, 127 | expecting_an_expression, 128 | numbers_parsed_by_keyword, 129 | actual_formal_result_type_mismatch, 130 | switch_requires_input, 131 | switch_requires_value, 132 | switch_requires_integer, 133 | switch_requires_case_constant, 134 | switch_requires_matching_case_types, 135 | switch_requires_unique_case, 136 | expecting_ast_or_reference, 137 | expecting_function_declaration, 138 | initializer_must_be_constant, 139 | initializer_type_doesnt_match, 140 | expecting_array_initializers, 141 | argument_must_be_pointer_type, 142 | character_does_not_fit_in_to_an_ascii_character, 143 | expecting_a_value, 144 | ptr_to_int_expects_two, 145 | expecting_pointer_type, 146 | expecting_integer_type, 147 | global_one_initializer, 148 | global_constant_initializer, 149 | expecting_a_pointer_type, 150 | must_be_joining_at_least_two_branches, 151 | join_branches_same_cardinality, 152 | expecting_branch_or_right_square, 153 | struct_must_contain_types, 154 | insertvalue_expects_three_arguments, 155 | expecting_value_to_be_struct, 156 | expecting_an_aggregate, 157 | index_out_of_bounds, 158 | value_does_not_match_aggregate, 159 | unexpected_node_type, 160 | select_three_arguments, 161 | expecting_one_bit_integer, 162 | select_arguments_same_type, 163 | expecting_a_constant, 164 | template_instantiations_cannot_have_predicates, 165 | only_one_entry_point, 166 | entry_point_must_be_a_function, 167 | entry_point_must_have_no_arguments, 168 | entry_point_must_have_one_return_branch, 169 | entry_point_must_return_unit, 170 | function_already_named, 171 | global_already_named, 172 | not_a_namespace_container, 173 | not_a_member, 174 | can_only_extract_from_one, 175 | template_argument_count_mismatch, 176 | expecting_an_integer_type, 177 | expecting_type_or_right_square_or_terminator, 178 | expecting_left_square_or_right_square, 179 | functions_must_return_results_or_sequences, 180 | branches_must_return_a_value, 181 | number_of_formal_return_branches_not_matching_number_of_actual_results, 182 | number_of_formal_returns_not_matching_number_of_actual_results 183 | }; 184 | class error 185 | { 186 | public: 187 | virtual ~error (); 188 | virtual void output (std::ostream & out) = 0; 189 | std::string string (); 190 | virtual mu::core::error_type type () = 0; 191 | virtual mu::core::region region () = 0; 192 | }; 193 | } 194 | } -------------------------------------------------------------------------------- /FindLLVM.cmake: -------------------------------------------------------------------------------- 1 | # - Find LLVM headers and libraries. 2 | # This module locates LLVM and adapts the llvm-config output for use with 3 | # CMake. 4 | # 5 | # A given list of COMPONENTS is passed to llvm-config. 6 | # 7 | # The following variables are defined: 8 | # LLVM_FOUND - true if LLVM was found 9 | # LLVM_CXXFLAGS - C++ compiler flags for files that include LLVM headers. 10 | # LLVM_HOST_TARGET - Target triple used to configure LLVM. 11 | # LLVM_INCLUDE_DIRS - Directory containing LLVM include files. 12 | # LLVM_LDFLAGS - Linker flags to add when linking against LLVM 13 | # (includes -LLLVM_LIBRARY_DIRS). 14 | # LLVM_LIBRARIES - Full paths to the library files to link against. 15 | # LLVM_LIBRARY_DIRS - Directory containing LLVM libraries. 16 | # LLVM_ROOT_DIR - The root directory of the LLVM installation. 17 | # llvm-config is searched for in ${LLVM_ROOT_DIR}/bin. 18 | # LLVM_VERSION_MAJOR - Major version of LLVM. 19 | # LLVM_VERSION_MINOR - Minor version of LLVM. 20 | # LLVM_VERSION_STRING - Full LLVM version string (e.g. 2.9). 21 | # 22 | # Note: The variable names were chosen in conformance with the offical CMake 23 | # guidelines, see ${CMAKE_ROOT}/Modules/readme.txt. 24 | 25 | # Try suffixed versions to pick up the newest LLVM install available on Debian 26 | # derivatives. 27 | # We also want an user-specified LLVM_ROOT_DIR to take precedence over the 28 | # system default locations such as /usr/local/bin. Executing find_program() 29 | # multiples times is the approach recommended in the docs. 30 | set(llvm_config_names llvm-config-3.8 llvm-config38 31 | llvm-config-3.7 llvm-config37 32 | llvm-config-3.6 llvm-config36 33 | llvm-config-3.5 llvm-config35 34 | llvm-config-3.4 llvm-config34 35 | llvm-config-3.3 llvm-config33 36 | llvm-config-3.2 llvm-config32 37 | llvm-config-3.1 llvm-config31 llvm-config) 38 | find_program(LLVM_CONFIG 39 | NAMES ${llvm_config_names} 40 | PATHS ${LLVM_ROOT_DIR}/bin NO_DEFAULT_PATH 41 | DOC "Path to llvm-config tool.") 42 | find_program(LLVM_CONFIG NAMES ${llvm_config_names}) 43 | 44 | if ((WIN32 AND NOT(MINGW OR CYGWIN)) OR NOT LLVM_CONFIG) 45 | if (WIN32) 46 | # A bit of a sanity check: 47 | if( NOT EXISTS ${LLVM_ROOT_DIR}/include/llvm ) 48 | message(FATAL_ERROR "LLVM_ROOT_DIR (${LLVM_ROOT_DIR}) is not a valid LLVM install") 49 | endif() 50 | # We incorporate the CMake features provided by LLVM: 51 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LLVM_ROOT_DIR}/share/llvm/cmake") 52 | include(LLVMConfig) 53 | # Set properties 54 | set(LLVM_HOST_TARGET ${TARGET_TRIPLE}) 55 | set(LLVM_VERSION_STRING ${LLVM_PACKAGE_VERSION}) 56 | set(LLVM_CXXFLAGS ${LLVM_DEFINITIONS}) 57 | set(LLVM_LDFLAGS "") 58 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "all-targets" index) 59 | list(APPEND LLVM_FIND_COMPONENTS ${LLVM_TARGETS_TO_BUILD}) 60 | # Work around LLVM bug 21016 61 | list(FIND LLVM_TARGETS_TO_BUILD "X86" TARGET_X86) 62 | if(TARGET_X86 GREATER -1) 63 | list(APPEND LLVM_FIND_COMPONENTS x86utils) 64 | endif() 65 | # Similar to the work around above, but for AArch64 66 | list(FIND LLVM_TARGETS_TO_BUILD "AArch64" TARGET_AArch64) 67 | if(TARGET_AArch64 GREATER -1) 68 | list(APPEND LLVM_FIND_COMPONENTS AArch64Utils) 69 | endif() 70 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "backend" index) 71 | if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-2][\\.0-9A-Za-z]*") 72 | # Versions below 3.3 do not support components objcarcopts, option 73 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "objcarcopts" index) 74 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "option" index) 75 | endif() 76 | if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-4][\\.0-9A-Za-z]*") 77 | # Versions below 3.5 do not support components lto, profiledata 78 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "lto" index) 79 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "profiledata" index) 80 | endif() 81 | if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-6][\\.0-9A-Za-z]*") 82 | # Versions below 3.7 do not support components debuginfodwarf 83 | # Only debuginfo is available 84 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "debuginfodwarf" index) 85 | list(APPEND LLVM_FIND_COMPONENTS "debuginfo") 86 | endif() 87 | if(${LLVM_VERSION_STRING} MATCHES "^3\\.[8-9][\\.0-9A-Za-z]*") 88 | # Versions beginning with 3.8 do not support component ipa 89 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "ipa" index) 90 | endif() 91 | 92 | if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-4][\\.0-9A-Za-z]*") 93 | llvm_map_components_to_libraries(tmplibs ${LLVM_FIND_COMPONENTS}) 94 | else() 95 | llvm_map_components_to_libnames(tmplibs ${LLVM_FIND_COMPONENTS}) 96 | endif() 97 | if(MSVC) 98 | foreach(lib ${tmplibs}) 99 | list(APPEND LLVM_LIBRARIES "${LLVM_LIBRARY_DIRS}/${CMAKE_STATIC_LIBRARY_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX}") 100 | endforeach() 101 | else() 102 | # Rely on the library search path being set correctly via -L on 103 | # MinGW and others, as the library list returned by 104 | # llvm_map_components_to_libraries also includes imagehlp and psapi. 105 | set(LLVM_LDFLAGS "-L${LLVM_LIBRARY_DIRS}") 106 | set(LLVM_LIBRARIES ${tmplibs}) 107 | endif() 108 | 109 | # When using the CMake LLVM module, LLVM_DEFINITIONS is a list 110 | # instead of a string. Later, the list seperators would entirely 111 | # disappear, replace them by spaces instead. A better fix would be 112 | # to switch to add_definitions() instead of throwing strings around. 113 | string(REPLACE ";" " " LLVM_CXXFLAGS "${LLVM_CXXFLAGS}") 114 | else() 115 | if (NOT FIND_LLVM_QUIETLY) 116 | message(WARNING "Could not find llvm-config. Try manually setting LLVM_CONFIG to the llvm-config executable of the installation to use.") 117 | endif() 118 | endif() 119 | else() 120 | macro(llvm_set var flag) 121 | if(LLVM_FIND_QUIETLY) 122 | set(_quiet_arg ERROR_QUIET) 123 | endif() 124 | execute_process( 125 | COMMAND ${LLVM_CONFIG} --${flag} 126 | OUTPUT_VARIABLE LLVM_${var} 127 | OUTPUT_STRIP_TRAILING_WHITESPACE 128 | ${_quiet_arg} 129 | ) 130 | if(${ARGV2}) 131 | file(TO_CMAKE_PATH "${LLVM_${var}}" LLVM_${var}) 132 | endif() 133 | endmacro() 134 | macro(llvm_set_libs var flag) 135 | if(LLVM_FIND_QUIETLY) 136 | set(_quiet_arg ERROR_QUIET) 137 | endif() 138 | execute_process( 139 | COMMAND ${LLVM_CONFIG} --${flag} ${LLVM_FIND_COMPONENTS} 140 | OUTPUT_VARIABLE tmplibs 141 | OUTPUT_STRIP_TRAILING_WHITESPACE 142 | ${_quiet_arg} 143 | ) 144 | file(TO_CMAKE_PATH "${tmplibs}" tmplibs) 145 | string(REGEX MATCHALL "${pattern}[^ ]+" LLVM_${var} ${tmplibs}) 146 | endmacro() 147 | 148 | llvm_set(VERSION_STRING version) 149 | llvm_set(CXXFLAGS cxxflags) 150 | llvm_set(HOST_TARGET host-target) 151 | llvm_set(INCLUDE_DIRS includedir true) 152 | llvm_set(ROOT_DIR prefix true) 153 | 154 | if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-2][\\.0-9A-Za-z]*") 155 | # Versions below 3.3 do not support components objcarcopts, option 156 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "objcarcopts" index) 157 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "option" index) 158 | endif() 159 | if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-4][\\.0-9A-Za-z]*") 160 | # Versions below 3.5 do not support components lto, profiledata 161 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "lto" index) 162 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "profiledata" index) 163 | endif() 164 | if(${LLVM_VERSION_STRING} MATCHES "^3\\.[0-6][\\.0-9A-Za-z]*") 165 | # Versions below 3.7 do not support components debuginfodwarf 166 | # Only debuginfo is available 167 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "debuginfodwarf" index) 168 | list(APPEND LLVM_FIND_COMPONENTS "debuginfo") 169 | endif() 170 | if(${LLVM_VERSION_STRING} MATCHES "^3\\.[8-9][\\.0-9A-Za-z]*") 171 | # Versions beginning with 3.8 do not support component ipa 172 | list(REMOVE_ITEM LLVM_FIND_COMPONENTS "ipa" index) 173 | endif() 174 | 175 | llvm_set(LDFLAGS ldflags) 176 | if(NOT ${LLVM_VERSION_STRING} MATCHES "^3\\.[0-4][\\.0-9A-Za-z]*") 177 | # In LLVM 3.5+, the system library dependencies (e.g. "-lz") are accessed 178 | # using the separate "--system-libs" flag. 179 | llvm_set(SYSTEM_LIBS system-libs) 180 | string(REPLACE "\n" " " LLVM_LDFLAGS "${LLVM_LDFLAGS} ${LLVM_SYSTEM_LIBS}") 181 | endif() 182 | llvm_set(LIBRARY_DIRS libdir true) 183 | llvm_set_libs(LIBRARIES libs) 184 | endif() 185 | 186 | MESSAGE(STATUS ${LLVM_CXXFLAGS}) 187 | # On CMake builds of LLVM, the output of llvm-config --cxxflags does not 188 | # include -fno-rtti, leading to linker errors. Be sure to add it. 189 | if(CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")) 190 | if(NOT ${LLVM_CXXFLAGS} MATCHES "-fno-rtti") 191 | set(LLVM_CXXFLAGS "${LLVM_CXXFLAGS} -fno-rtti") 192 | endif() 193 | endif() 194 | MESSAGE(STATUS ${LLVM_CXXFLAGS}) 195 | string(REPLACE "-fno-rtti" "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS}) 196 | string(REPLACE "-fno-exceptions" "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS}) 197 | MESSAGE(STATUS ${LLVM_CXXFLAGS}) 198 | 199 | string(REGEX REPLACE "([0-9]+).*" "\\1" LLVM_VERSION_MAJOR "${LLVM_VERSION_STRING}" ) 200 | string(REGEX REPLACE "[0-9]+\\.([0-9]+).*[A-Za-z]*" "\\1" LLVM_VERSION_MINOR "${LLVM_VERSION_STRING}" ) 201 | 202 | # Use the default CMake facilities for handling QUIET/REQUIRED. 203 | include(FindPackageHandleStandardArgs) 204 | 205 | if(${CMAKE_VERSION} VERSION_LESS "2.8.4") 206 | # The VERSION_VAR argument is not supported on pre-2.8.4, work around this. 207 | set(VERSION_VAR dummy) 208 | endif() 209 | 210 | find_package_handle_standard_args(LLVM 211 | REQUIRED_VARS LLVM_ROOT_DIR LLVM_HOST_TARGET 212 | VERSION_VAR LLVM_VERSION_STRING) 213 | -------------------------------------------------------------------------------- /examples/file.mu: -------------------------------------------------------------------------------- 1 | let size-t int-t # 64 2 | let iptr int-t # 64 3 | 4 | let syscall-0 function 5 | [int-t # 64 id] 6 | [ 7 | let result [asm int-t # 64 syscall {%}={ax},{ax}% id] 8 | ] 9 | [[int-t # 64 result]] 10 | 11 | let syscall-1 function 12 | [int-t # 64 id int-t # 64 arg1] 13 | [ 14 | let result [asm int-t # 64 syscall {%}={ax},{ax},{di}% id arg1] 15 | ] 16 | [[int-t # 64 result]] 17 | 18 | let syscall-2 function 19 | [int-t # 64 id int-t # 64 arg1 int-t # 64 arg2] 20 | [ 21 | let result [asm int-t # 64 syscall {%}={ax},{ax},{di},{si}% id arg1 arg2] 22 | ] 23 | [[int-t # 64 result]] 24 | 25 | let syscall-3 function 26 | [int-t # 64 id int-t # 64 arg1 int-t # 64 arg2 int-t # 64 arg3] 27 | [ 28 | let result [asm int-t # 64 syscall {%}={ax},{ax},{di},{si},{dx}% id arg1 arg2 arg3] 29 | ] 30 | [[int-t # 64 result]] 31 | 32 | let syscall-4-osx function 33 | [int-t # 64 id int-t # 64 arg1 int-t # 64 arg2 int-t # 64 arg3 int-t # 64 arg4] 34 | [ 35 | let result [asm int-t # 64 syscall {%}={ax},{ax},{di},{si},{dx},{cx}% id arg1 arg2 arg3 arg4] 36 | ] 37 | [[int-t # 64 result]] 38 | 39 | let syscall-5-osx function 40 | [int-t # 64 id int-t # 64 arg1 int-t # 64 arg2 int-t # 64 arg3 int-t # 64 arg4 int-t # 64 arg5] 41 | [ 42 | let result [asm int-t # 64 syscall {%}={ax},{ax},{di},{si},{dx},{cx},{r8}% id arg1 arg2 arg3 arg4 arg5] 43 | ] 44 | [[int-t # 64 result]] 45 | 46 | let syscall-6-osx function 47 | [int-t # 64 id int-t # 64 arg1 int-t # 64 arg2 int-t # 64 arg3 int-t # 64 arg4 int-t # 64 arg5 int-t # 64 arg6] 48 | [ 49 | let result [asm int-t # 64 syscall {%}={ax},{ax},{di},{si},{dx},{cx},{r8},{r9}% id arg1 arg2 arg3 arg4 arg5 arg6] 50 | ] 51 | [[int-t # 64 result]] 52 | 53 | let syscall-4-linux function 54 | [int-t # 64 id int-t # 64 arg1 int-t # 64 arg2 int-t # 64 arg3 int-t # 64 arg4] 55 | [ 56 | let result [asm int-t # 64 syscall {%}={ax},{ax},{di},{si},{dx},{r10}% id arg1 arg2 arg3 arg4] 57 | ] 58 | [[int-t # 64 result]] 59 | 60 | let syscall-5-linux function 61 | [int-t # 64 id int-t # 64 arg1 int-t # 64 arg2 int-t # 64 arg3 int-t # 64 arg4 int-t # 64 arg5] 62 | [ 63 | let result [asm int-t # 64 syscall {%}={ax},{ax},{di},{si},{dx},{r10},{r8}% id arg1 arg2 arg3 arg4 arg5] 64 | ] 65 | [[int-t # 64 result]] 66 | 67 | let syscall-6-linux function 68 | [int-t # 64 id int-t # 64 arg1 int-t # 64 arg2 int-t # 64 arg3 int-t # 64 arg4 int-t # 64 arg5 int-t # 64 arg6] 69 | [ 70 | let result [asm int-t # 64 syscall {%}={ax},{ax},{di},{si},{dx},{r10},{r8},{r9}% id arg1 arg2 arg3 arg4 arg5 arg6] 71 | ] 72 | [[int-t # 64 result]] 73 | 74 | let exit-osx-system-code # h2000001 75 | let write-osx-system-code # h2000004 76 | let open-osx-system-code # h2000005 77 | let close-osx-system-code # h2000006 78 | let mmap-osx-system-code # h20000c5 79 | 80 | let write-linux-system-code # h1 81 | let open-linux-system-code # h2 82 | let mmap-linux-system-code # h9 83 | let exit-linux-system-code # h3c 84 | 85 | let O_RDWR-linux # o2 86 | let O_CREAT-linux # o100 87 | 88 | let PROT_READ-linux # h1 89 | let PROT_WRITE-linux # h2 90 | let PROT_EXEC-linux # h4 91 | let PROT_NONE-linux # h0 92 | 93 | let MAP_SHARED-linux # h1 94 | let MAP_PRIVATE-linux # h2 95 | let MAP_ANONYMOUS-linux # h20 96 | let no-fd-linux # hffffffffffffffff 97 | 98 | let exit_linux function 99 | [int-t # 64 code] 100 | [ 101 | let nothing [syscall-1 exit-linux-system-code code] 102 | ] 103 | [[;nothing]] 104 | 105 | let exit_osx function 106 | [int-t # 64 code] 107 | [ 108 | let nothing [syscall-1 exit-osx-system-code code] 109 | ] 110 | [[;nothing]] 111 | 112 | let platform function 113 | [] 114 | [ 115 | let linux osx [if # 0] 116 | ] 117 | [[unit linux][unit osx]] 118 | 119 | let exit function 120 | [int-t # 64 code] 121 | [ 122 | let linux osx [platform] 123 | let result join [ 124 | [[exit_linux code; linux]] 125 | [[exit_osx code; osx]]] 126 | ] 127 | [[; result]] 128 | 129 | let write-linux function 130 | [int-t # 64 file-descriptor ptr int-t # 8 data int-t # 64 size] 131 | [ 132 | let nothing [syscall-3 write-linux-system-code file-descriptor [ptrtoint data int-t # 64] size] 133 | ] 134 | [[;nothing]] 135 | 136 | let write-osx function 137 | [int-t # 64 file-descriptor ptr int-t # 8 data int-t # 64 size] 138 | [ 139 | let nothing [syscall-3 write-osx-system-code file-descriptor [ptrtoint data int-t # 64] size] 140 | ] 141 | [[;nothing]] 142 | 143 | let write function 144 | [int-t # 64 file-descriptor ptr int-t # 8 data int-t # 64 size] 145 | [ 146 | let linux osx [platform] 147 | let result join [ 148 | [[write-linux file-descriptor data size; linux]] 149 | [[write-osx file-descriptor data size; osx]]] 150 | ] 151 | [[;result]] 152 | 153 | let write-test-string global ascii {%}Hello world! 154 | % 155 | 156 | let write-string function 157 | [int-t # 64 fd ` astring type str] 158 | [ 159 | let result [write fd [` astring data str] [` astring size str]] 160 | ] 161 | [[;result]] 162 | 163 | let write-test function 164 | [int-t # 64 fd] 165 | [ 166 | let initial [` astring new-set [bitcast write-test-string ptr int-t # 8] # 13] 167 | let full [` astring append initial initial] 168 | let result [write-string fd full] 169 | ] 170 | [[;result]] 171 | 172 | let open-osx function 173 | [ptr int-t # 8 path int-t # 64 flags int-t # 64 mode] 174 | [ 175 | let fd [syscall-3 open-osx-system-code [ptrtoint path int-t # 64] flags mode] 176 | ] 177 | [[int-t # 64 fd]] 178 | 179 | let open-linux function 180 | [ptr int-t # 8 path int-t # 64 flags int-t # 64 mode] 181 | [ 182 | let fd [syscall-3 open-linux-system-code [ptrtoint path int-t # 64] flags mode] 183 | ] 184 | [[int-t # 64 fd]] 185 | 186 | let open function 187 | [ptr int-t # 8 path int-t # 64 flags int-t # 64 mode] 188 | [ 189 | let linux osx [platform] 190 | let fd join [ 191 | [[open-osx path flags mode; osx]] 192 | [[open-linux path flags mode; linux]]] 193 | ] 194 | [[int-t # 64 fd]] 195 | 196 | let close-osx function 197 | [int-t # 64 fd] 198 | [ 199 | let result [syscall-1 close-osx-system-code fd] 200 | ] 201 | [[int-t # 64 result]] 202 | 203 | let close-linux function 204 | [int-t # 64 fd] 205 | [ 206 | let result [syscall-1 close-osx-system-code fd] 207 | ] 208 | [[int-t # 64 result]] 209 | 210 | let close function 211 | [int-t # 64 fd] 212 | [ 213 | let linux osx [platform] 214 | let result join [ 215 | [[close-osx fd; osx]] 216 | [[close-linux fd; linux]]] 217 | ] 218 | [[int-t # 64 result]] 219 | 220 | let mmap-osx function 221 | [ptr int-t # 8 addr int-t # 64 len int-t # 64 prot int-t # 64 flags int-t # 64 fd int-t # 64 pos] 222 | [ 223 | let result [ptrfromint [syscall-6-osx mmap-osx-system-code [ptrtoint addr int-t # 64] len prot flags fd pos] ptr int-t # 8] 224 | ] 225 | [[ptr int-t # 8 result]] 226 | 227 | let mmap-linux function 228 | [ptr int-t # 8 addr int-t # 64 len int-t # 64 prot int-t # 64 flags int-t # 64 fd int-t # 64 pos] 229 | [ 230 | let result [ptrfromint [syscall-6-linux mmap-linux-system-code [ptrtoint addr int-t # 64] len prot flags fd pos] ptr int-t # 8] 231 | ] 232 | [[ptr int-t # 8 result]] 233 | 234 | let mmap function 235 | [ptr int-t # 8 addr int-t # 64 len int-t # 64 prot int-t # 64 flags int-t # 64 fd int-t # 64 pos] 236 | [ 237 | let linux osx [platform] 238 | let result join [ 239 | [[mmap-osx addr len prot flags fd pos; osx]] 240 | [[mmap-linux addr len prot flags fd pos; linux]]] 241 | ] 242 | [[ptr int-t # 8 result]] 243 | 244 | let generic_mul template [type] 245 | [ 246 | function 247 | [type left type right] 248 | [ 249 | let result [mul left right] 250 | ] 251 | [[type result]] 252 | ] 253 | 254 | let mul64 [generic_mul int-t # 64] 255 | let mul32 [generic_mul int-t # 32] 256 | 257 | let umax function 258 | [int-t # 64 left int-t # 64 right] 259 | [ 260 | let result [select [icmp iugt left right] left right] 261 | ] 262 | [[int-t # 64 result]] 263 | 264 | let umin function 265 | [int-t # 64 left int-t # 64 right] 266 | [ 267 | let result [select [icmp iult left right] left right] 268 | ] 269 | [[int-t # 64 result]] 270 | 271 | let lalloc-base global null ptr int-t # 8 272 | let lalloc-available global [int-c int-t # 64 # h0] 273 | 274 | let lalloc-slab-size [int-c int-t # 64 # h100000] 275 | 276 | let lalloc-slab function 277 | [] 278 | [ 279 | let mem [mmap 280 | [ptrfromint [int-c int-t # 64 # 0] ptr int-t # 8] 281 | lalloc-slab-size 282 | [or PROT_READ-linux PROT_WRITE-linux] 283 | [or MAP_PRIVATE-linux MAP_ANONYMOUS-linux] 284 | no-fd-linux 285 | # 0] 286 | ] 287 | [[ptr int-t # 8 mem]] 288 | 289 | let lalloc function 290 | [int-t # 64 amount] 291 | [ 292 | let current-available [load lalloc-available] 293 | let enough not-enough [if [icmp iuge current-available amount]] 294 | let result available join [ 295 | [[lalloc-slab; not-enough] lalloc-slab-size] 296 | [[load lalloc-base; enough] current-available]] 297 | let store1 [store [getelementptr result amount] lalloc-base] 298 | let store2 [store [sub available amount] lalloc-available] 299 | ] 300 | [[ptr int-t # 8 result; store1 store2]] 301 | 302 | let tlalloc template [element-type] 303 | [ 304 | function 305 | [size-t count] 306 | [ 307 | let result [bitcast [lalloc [mul count [sizeof element-type]]] ptr element-type] 308 | ] 309 | [[ptr element-type result]] 310 | ] 311 | 312 | let lfree function 313 | [ptr int-t # 8 data] 314 | [ 315 | ] 316 | [[;data]] 317 | 318 | let tlfree template [element-type] 319 | [ 320 | function 321 | [ptr element-type data] 322 | [ 323 | let result [lfree [bitcast data ptr int-t # 8]] 324 | ] 325 | [[; result]] 326 | ] 327 | 328 | let file-name-osx global ascii /Users/clemahieu/test.txt:a00 329 | let linux-file-name global ascii /home/colin/mu_build/test.txt:a00 330 | 331 | let sizeof template [sizeof-type] 332 | [ 333 | [sub [ptrtoint [getelementptr let base null ptr sizeof-type [int-c int-t # 32 # 1]] int-t # 64] [ptrtoint [getelementptr base [int-c int-t # 32 # 0]] int-t # 64]] 334 | ] 335 | 336 | let memcopy function 337 | [ptr int-t # 8 source ptr int-t # 8 destination int-t # 64 size] 338 | [ 339 | let end [ptrtoint [getelementptr source size] int-t # 64] 340 | let complete loop 341 | [source destination] 342 | [source_l destination_l] 343 | [ 344 | let done not-done [if [icmp ieq [ptrtoint source_l int-t # 64] end]] 345 | let stored [store [load source_l; not-done] destination_l] 346 | ] 347 | [[[getelementptr source_l [int-c int-t # 64 # 1]] [getelementptr destination_l [int-c int-t # 64 # 1]]; stored][; done]] 348 | ] 349 | [[; complete]] 350 | 351 | let mcopy template [element-type] 352 | [ 353 | function [ptr element-type begin ptr element-type end ptr element-type destination] 354 | [ 355 | let next [int-c int-t # 64 # 1] 356 | let complete loop 357 | [begin destination] 358 | [source-l destination-l] 359 | [ 360 | let done not-done [if [icmp iuge [ptrtoint source-l iptr] [ptrtoint end iptr]]] 361 | let stored [store [load source-l; not-done] destination-l] 362 | ] 363 | [[[getelementptr source-l next] [getelementptr destination-l next]; stored] [; done]] 364 | ] 365 | [[; complete]] 366 | ] 367 | 368 | let vector-template template [template-type] 369 | [ 370 | module [ 371 | let type struct [data ptr template-type 372 | size size-t] 373 | let alloc [tlalloc template-type] 374 | let copy [mcopy template-type] 375 | 376 | let data-set function 377 | [ptr type vector ptr template-type data-a] 378 | [ 379 | let result [store data-a [getelementptr vector [int-c int-t # 32 # 0] ` type data]] 380 | ] 381 | [[; result]] 382 | 383 | let data-get function 384 | [ptr type vector] 385 | [ 386 | let result [load [getelementptr vector [int-c int-t # 32 # 0] ` type data]] 387 | ] 388 | [[ptr template-type result]] 389 | 390 | let size-set function 391 | [ptr type vector size-t size-a] 392 | [ 393 | let result [store size-a [getelementptr vector [int-c int-t # 32 # 0] ` type size]] 394 | ] 395 | [[; result]] 396 | 397 | let size-get function 398 | [ptr type vector] 399 | [ 400 | let result [load [getelementptr vector [int-c int-t # 32 # 0] ` type size]] 401 | ] 402 | [[size-t result]] 403 | 404 | let new-set function 405 | [ptr template-type data-a int-t # 64 size-a] 406 | [ 407 | let result [bitcast [lalloc [sizeof type]] ptr type] 408 | let data [data-set result data-a] 409 | let size [size-set result size-a] 410 | ] 411 | [[ptr type result; data size]] 412 | 413 | let push-back function 414 | [ptr template-type data-a element-type value-a] 415 | [ 416 | let size-set-l [size-set let size-new [add let size-old [size-get data-a] # 1]] 417 | let data-old [data-get data-a] 418 | let data-new [alloc size-new] 419 | let copied [copy data-old [getelementptr data-old size-old] data-new] 420 | let element-set [store [getelementptr data-new size-old] value-a] 421 | ] 422 | [[; set copied element-set]] 423 | 424 | let new function 425 | [] 426 | [ 427 | let result [new-set null ptr template-type # 0] 428 | ] 429 | [[ptr type result]] 430 | ] 431 | ] 432 | 433 | let string-template template [element-type] 434 | [ 435 | module 436 | [ 437 | let type struct [data ptr element-type 438 | size size-t] 439 | let copy [mcopy element-type] 440 | let free [tlfree element-type] 441 | let alloc [tlalloc element-type] 442 | 443 | let empty function 444 | [type string-a] 445 | [ 446 | let result [icmp ieq [extractvalue string-a ` type size] [int-c size-t # 0]] 447 | ] 448 | [[int-t # 1 result]] 449 | 450 | let size function 451 | [type string-a] 452 | [ 453 | let result [extractvalue string-a ` type size] 454 | ] 455 | [[size-t result]] 456 | 457 | let data function 458 | [type string-a] 459 | [ 460 | let result [extractvalue string-a ` type data] 461 | ] 462 | [[ptr element-type result]] 463 | 464 | let append function 465 | [type string-a type other-a] 466 | [ 467 | let new-size [add let string-size [size string-a] let other-size [size other-a]] 468 | let new-data [alloc new-size] 469 | let copied1 [copy let string-data [data string-a] [getelementptr string-data string-size] new-data] 470 | let copied2 [copy let begin [data other-a] [getelementptr begin other-size] [getelementptr new-data string-size]] 471 | let freed [free string-data; copied1] 472 | let result [new-set new-data new-size] 473 | ] 474 | [[type result; copied2 freed]] 475 | 476 | let new-set function 477 | [ptr element-type data-a size-t size-a] 478 | [ 479 | let result [insertvalue [insertvalue undefined type data-a [int-c int-t # 32 # 0]] size-a [int-c int-t # 32 # 1]] 480 | ] 481 | [[type result]] 482 | 483 | let new function 484 | [] 485 | [ 486 | let result [new-set [ptrfromint [int-c size-t # 0] ptr element-type] # 0] 487 | ] 488 | [[type result]] 489 | ] 490 | ] 491 | 492 | let string [string-template int-t # 32] 493 | let astring [string-template int-t # 8] 494 | 495 | let vector [vector-template int-t # 64] 496 | let vector [vector-template int-t # 32] 497 | 498 | entrypoint let entry function 499 | [] 500 | [ 501 | :(let stored [store ascii let text [alloca array int-t # 8 #26]] 502 | let stored [store ascii let text [alloca array int-t # 8 #30]] 503 | let fd [open [bitcast file-name-osx ptr int-t # 8] # h602 # o600] 504 | let fd [open [bitcast file-name-linux ptr int-t # 8] [or O_RDWR-linux O_CREAT-linux] # o600] 505 | let write_l [write-test fd] 506 | let close_l [close fd; write_l]:) 507 | let vector [` vector new] 508 | let hello [write-test # 1] 509 | let alloc1 [lalloc # 100] 510 | let alloc2 [lalloc # 1000] 511 | let result [exit # 0; hello alloc1 alloc2] 512 | ] 513 | [[; result vector]] 514 | -------------------------------------------------------------------------------- /mu/llvmc/parser.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace mu 13 | { 14 | namespace core 15 | { 16 | class error; 17 | } 18 | namespace io 19 | { 20 | template 21 | class stream; 22 | class token; 23 | class stream_token; 24 | } 25 | namespace llvmc 26 | { 27 | class parser; 28 | class hook 29 | { 30 | public: 31 | virtual mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) = 0; 32 | virtual mu::string const & name () = 0; 33 | }; 34 | class hook_result 35 | { 36 | public: 37 | mu::llvmc::hook * hook; 38 | }; 39 | class mapping 40 | { 41 | public: 42 | typedef std::function action_type; 43 | typedef std::tuple unresolved_type; 44 | // Reserves a name from a lower scope, error result if name already is reserved 45 | virtual bool reserve (mu::string const & name_a) = 0; 46 | // Performs `action_a' on the value mapped to `name_a' if a mapping exists, otherwise sets error result 47 | virtual bool get (mu::string const & name_a, mu::core::region const & region_a, action_type action_a) = 0; 48 | // Performs `action_a' on the value mapped to `name_a' if the mapping exists, otherwise stores `action_a' and performs when value is inserted 49 | virtual void refer (mu::string const & name_a, mu::core::region const & region_a, action_type action_a) = 0; 50 | // Maps `identifier_a' to `node_a' and calls stored actions for `identifier_a' if they exist. Returns true if an error while inserting 51 | virtual bool insert (mu::string const & identifier_a, mu::llvmc::ast::node * node_a) = 0; 52 | // Accept unresolved references from child and handle them if they become resolved 53 | virtual void accept (mu::unordered_multimap const & unresolved_a) = 0; 54 | }; 55 | class keywords 56 | { 57 | public: 58 | bool insert (mu::string const & identifier_a, mu::llvmc::hook * hook_a); 59 | // Returns the hook covering `identifier_a' if one exists 60 | hook_result get_hook (mu::string const & identifier_a); 61 | mu::unordered_map mappings; 62 | }; 63 | class global : public mapping 64 | { 65 | public: 66 | global (mu::llvmc::keywords * keywords_a); 67 | bool insert (mu::string const & identifier_a, mu::llvmc::ast::node * node_a) override; 68 | bool reserve (mu::string const & name_a) override; 69 | bool get (mu::string const & name_a, mu::core::region const & region_a, action_type action_a) override; 70 | void refer (mu::string const & name_a, mu::core::region const & region_a, action_type action_a) override; 71 | void accept (mu::unordered_multimap const & unresolved_a) override; 72 | mu::unordered_map mappings; 73 | mu::unordered_multimap unresolved; 74 | mu::llvmc::keywords * keywords; 75 | }; 76 | class block : public mapping 77 | { 78 | public: 79 | block (mu::llvmc::mapping * parent_a); 80 | ~block (); 81 | bool insert (mu::string const & identifier_a, mu::llvmc::ast::node * node_a) override; 82 | bool reserve (mu::string const & name_a) override; 83 | bool get (mu::string const & name_a, mu::core::region const & region_a, action_type action_a) override; 84 | void refer (mu::string const & name_a, mu::core::region const & region_a, action_type action_a) override; 85 | void accept (mu::unordered_multimap const & unresolved_a) override; 86 | mu::llvmc::mapping * parent; 87 | mu::unordered_map mappings; 88 | mu::unordered_multimap unresolved; 89 | }; 90 | template 91 | class scope_set 92 | { 93 | public: 94 | scope_set (T & pointer_a, T value_a) 95 | : pointer (pointer_a) 96 | { 97 | pointer_a = value_a; 98 | } 99 | ~scope_set () 100 | { 101 | pointer = nullptr; 102 | } 103 | T & pointer; 104 | }; 105 | class module_hook : public mu::llvmc::hook 106 | { 107 | public: 108 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 109 | mu::string const & name () override; 110 | }; 111 | class module 112 | { 113 | public: 114 | module (mu::core::region const &, mu::llvmc::parser &); 115 | ~module (); 116 | void parse (); 117 | void parse_internal (); 118 | mu::llvmc::block block; 119 | mu::llvmc::node_result result; 120 | mu::llvmc::parser & parser; 121 | mu::core::region first; 122 | }; 123 | class function_hook : public mu::llvmc::hook 124 | { 125 | public: 126 | mu::llvmc::node_result parse (mu::core::region const &, mu::llvmc::parser &) override; 127 | mu::string const & name () override; 128 | }; 129 | class function_overload_hook : public mu::llvmc::hook 130 | { 131 | public: 132 | function_overload_hook (function_hook &); 133 | mu::llvmc::node_result parse (mu::core::region const &, mu::llvmc::parser &) override; 134 | mu::string const & name () override; 135 | function_hook & function_hook; 136 | }; 137 | class set_hook : public mu::llvmc::hook 138 | { 139 | public: 140 | mu::llvmc::node_result parse (mu::core::region const &, mu::llvmc::parser &) override; 141 | mu::string const & name () override; 142 | }; 143 | class let_hook : public mu::llvmc::hook 144 | { 145 | public: 146 | mu::llvmc::node_result parse (mu::core::region const &, mu::llvmc::parser &) override; 147 | mu::string const & name () override; 148 | }; 149 | class function 150 | { 151 | public: 152 | function (mu::core::region const &, mu::llvmc::parser &); 153 | ~function (); 154 | void parse (); 155 | void parse_parameters (); 156 | void parse_parameter (bool & done_a); 157 | void parse_body (); 158 | void parse_results (); 159 | void parse_result_set (); 160 | mu::llvmc::block block; 161 | mu::llvmc::node_result result; 162 | mu::llvmc::ast::function * function_m; 163 | mu::llvmc::parser & parser; 164 | mu::core::region first; 165 | }; 166 | class expression 167 | { 168 | public: 169 | expression (mu::core::region const &, mu::llvmc::parser &); 170 | void parse (); 171 | mu::llvmc::node_result result; 172 | mu::llvmc::parser & parser; 173 | mu::core::region region; 174 | }; 175 | class int_type : public mu::llvmc::hook 176 | { 177 | public: 178 | mu::llvmc::node_result parse (mu::core::region const &, mu::llvmc::parser &) override; 179 | mu::string const & name () override; 180 | }; 181 | class ptr_type : public mu::llvmc::hook 182 | { 183 | public: 184 | mu::llvmc::node_result parse (mu::core::region const &, mu::llvmc::parser &) override; 185 | mu::string const & name () override; 186 | }; 187 | class number : public mu::llvmc::hook 188 | { 189 | public: 190 | mu::llvmc::node_result parse (mu::core::region const &, mu::llvmc::parser &) override; 191 | mu::string const & name () override; 192 | }; 193 | class constant_int : public mu::llvmc::hook 194 | { 195 | public: 196 | mu::llvmc::node_result parse (mu::core::region const &, mu::llvmc::parser &) override; 197 | mu::string const & name () override; 198 | }; 199 | class loop_hook : public mu::llvmc::hook 200 | { 201 | public: 202 | mu::llvmc::node_result parse (mu::core::region const &, mu::llvmc::parser &) override; 203 | mu::string const & name () override; 204 | }; 205 | class loop 206 | { 207 | public: 208 | loop (mu::llvmc::parser &); 209 | void parse (); 210 | void parse_arguments (); 211 | void parse_binds (); 212 | void parse_body (); 213 | void parse_results (); 214 | mu::llvmc::ast::loop * loop_m; 215 | mu::llvmc::node_result result; 216 | mu::llvmc::parser & parser; 217 | }; 218 | class asm_hook : public mu::llvmc::hook 219 | { 220 | public: 221 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 222 | mu::string const & name () override; 223 | }; 224 | class array_type : public mu::llvmc::hook 225 | { 226 | public: 227 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 228 | mu::string const & name () override; 229 | }; 230 | class constant_array : public mu::llvmc::hook 231 | { 232 | public: 233 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 234 | mu::string const & name () override; 235 | }; 236 | class partial_ast_result 237 | { 238 | public: 239 | partial_ast_result (mu::io::token * token_a, mu::llvmc::ast::node * ast_a, mu::core::error * error_a); 240 | partial_ast_result (mu::llvmc::partial_ast_result const & other_a); 241 | mu::llvmc::partial_ast_result & operator = (mu::llvmc::partial_ast_result const & other_a); 242 | bool valid (); 243 | mu::io::token * token; 244 | mu::llvmc::ast::node * ast; 245 | mu::core::error * error; 246 | }; 247 | class string_hook : public mu::llvmc::hook 248 | { 249 | public: 250 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 251 | mu::string const & name () override; 252 | }; 253 | class ascii_hook : public mu::llvmc::hook 254 | { 255 | public: 256 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 257 | mu::string const & name () override; 258 | }; 259 | class global_variable : public mu::llvmc::hook 260 | { 261 | public: 262 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 263 | mu::string const & name () override; 264 | }; 265 | class constant_pointer_null : public mu::llvmc::hook 266 | { 267 | public: 268 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 269 | mu::string const & name () override; 270 | }; 271 | class join_hook : public mu::llvmc::hook 272 | { 273 | public: 274 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 275 | mu::string const & name () override; 276 | }; 277 | class undefined_hook : public mu::llvmc::hook 278 | { 279 | public: 280 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 281 | mu::string const & name () override; 282 | }; 283 | class struct_hook : public mu::llvmc::hook 284 | { 285 | public: 286 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 287 | mu::string const & name () override; 288 | }; 289 | class parser_frame 290 | { 291 | public: 292 | mu::core::position position; 293 | mu::string const * name; 294 | }; 295 | class template_hook : public mu::llvmc::hook 296 | { 297 | public: 298 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 299 | mu::string const & name () override; 300 | }; 301 | class entry_hook : public mu::llvmc::hook 302 | { 303 | public: 304 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 305 | mu::string const & name () override; 306 | }; 307 | class template_context 308 | { 309 | public: 310 | mu::llvmc::template_context * parent; 311 | bool should_clone (mu::llvmc::template_context * node_a); 312 | }; 313 | class namespace_hook : public mu::llvmc::hook 314 | { 315 | public: 316 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 317 | mu::string const & name () override; 318 | }; 319 | class sequence_hook : public mu::llvmc::hook 320 | { 321 | public: 322 | mu::llvmc::node_result parse (mu::core::region const & region_a, mu::llvmc::parser & parser_a) override; 323 | mu::string const & name () override; 324 | }; 325 | class parser 326 | { 327 | public: 328 | parser (mu::io::stream_token & stream_a); 329 | mu::llvmc::node_result parse (); 330 | void consume (); 331 | template 332 | mu::core::error * parse_ast_or_refer (T op); 333 | template 334 | mu::core::error * parse_ast_or_refer_or_right_square (T op, U right_square_op, char32_t const * error_message_a, mu::core::error_type error_type_a); 335 | template 336 | mu::core::error * parse_identifier (T identifier_op, char32_t const * error_message_a, mu::core::error_type error_type_a); 337 | template 338 | mu::core::error * parse_identifier_or_right_square (T identifier_op, U right_square_op, char32_t const * error_message_a, mu::core::error_type error_type_a); 339 | template 340 | mu::core::error * parse_left_or_right_square (T left_square_op, U right_square_op, char32_t const * error_message_a, mu::core::error_type error_type_a); 341 | template 342 | mu::core::error * parse_ast_or_refer_or_right_square_or_terminator (T node_op, U right_square_op, V terminator_op, char32_t const * error_message_a, mu::core::error_type error_type_a); 343 | mu::core::error * parse_left_square_required (char32_t const * error_message_a, mu::core::error_type error_type_a); 344 | mu::llvmc::partial_ast_result peek (); 345 | mu::llvmc::template_context * current_template; 346 | mu::llvmc::global builtins; 347 | mu::llvmc::mapping * current_mapping; 348 | mu::llvmc::module_hook module_hook; 349 | mu::llvmc::function_hook function; 350 | mu::llvmc::asm_hook asm_hook; 351 | mu::llvmc::int_type int_type; 352 | mu::llvmc::set_hook set_hook; 353 | mu::llvmc::let_hook let_hook; 354 | mu::llvmc::loop_hook loop_hook; 355 | mu::llvmc::ptr_type ptr_type; 356 | mu::llvmc::array_type array_type; 357 | mu::llvmc::string_hook string_hook; 358 | mu::llvmc::ascii_hook ascii_hook; 359 | mu::llvmc::join_hook join_hook; 360 | mu::llvmc::undefined_hook undefined_hook; 361 | mu::llvmc::struct_hook struct_hook; 362 | mu::llvmc::constant_array constant_array; 363 | mu::llvmc::number number; 364 | mu::llvmc::global_variable global_variable; 365 | mu::llvmc::constant_pointer_null constant_pointer_null; 366 | mu::io::stream_token & stream; 367 | mu::llvmc::keywords keywords; 368 | mu::llvmc::template_hook template_hook; 369 | mu::llvmc::entry_hook entry_hook; 370 | mu::llvmc::namespace_hook namespace_hook; 371 | mu::llvmc::sequence_hook sequence_hook; 372 | mu::llvmc::function_overload_hook function_overload_hook; 373 | std::vector parse_stack; 374 | }; 375 | class parser_error : public mu::core::error 376 | { 377 | public: 378 | parser_error (char32_t const * message_a, mu::core::error_type type_a, mu::core::region const & region_a, mu::llvmc::parser & parser_a); 379 | void output (std::ostream & out) override; 380 | mu::core::error_type type () override; 381 | mu::core::region region () override; 382 | mu::core::error_type type_m; 383 | mu::string message; 384 | mu::core::region region_m; 385 | std::vector parse_stack; 386 | }; 387 | class parser_context 388 | { 389 | public: 390 | parser_context (mu::llvmc::parser & parser_a, mu::string const * name_a); 391 | ~parser_context (); 392 | mu::llvmc::parser & parser; 393 | }; 394 | } 395 | } -------------------------------------------------------------------------------- /mu/core/lexer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | mu::io::token_result::~token_result () 10 | { 11 | assert ((token != nullptr) xor (error != nullptr)); 12 | } 13 | 14 | mu::io::character_result::~character_result () 15 | { 16 | assert ((error == nullptr) or ((error != nullptr) and (character == '\0'))); 17 | } 18 | 19 | mu::io::string_range::string_range (std::string const & string_a) : 20 | begin_m (reinterpret_cast (string_a.data ())), 21 | end_m (reinterpret_cast (string_a.data ()) + string_a.size ()) 22 | { 23 | } 24 | 25 | mu::io::string_range::string_range (char const * const & string_a) : 26 | begin_m (reinterpret_cast (string_a)), 27 | end_m (reinterpret_cast (string_a) + strlen (string_a)) 28 | { 29 | } 30 | 31 | mu::io::string_range::string_range (uint8_t const * begin_a, uint8_t const * end_a) : 32 | begin_m (begin_a), 33 | end_m (end_a) 34 | { 35 | } 36 | 37 | uint8_t const * mu::io::string_range::begin () 38 | { 39 | return begin_m; 40 | } 41 | 42 | uint8_t const * mu::io::string_range::end () 43 | { 44 | return end_m; 45 | } 46 | 47 | mu::io::string_range mu::io::string_range::substr (size_t begin_a) const 48 | { 49 | assert (end_m >= begin_m); 50 | assert (begin_a <= static_cast (end_m - begin_m)); 51 | auto begin_l (begin_m); 52 | mu::io::string_range result (begin_l + begin_a, end_m); 53 | return result; 54 | } 55 | 56 | mu::io::string_range mu::io::string_range::substr (size_t begin_a, size_t end_a) const 57 | { 58 | assert (end_m >= begin_m); 59 | assert (begin_a <= static_cast (end_m - begin_m)); 60 | assert (end_a <= static_cast (end_m - begin_m)); 61 | auto begin_l (begin_m); 62 | mu::io::string_range result (begin_l + begin_a, begin_l + end_a); 63 | return result; 64 | } 65 | 66 | bool mu::io::string_range::operator == (mu::io::string_range const & other_a) const 67 | { 68 | return begin_m == other_a.begin_m && end_m == other_a.end_m; 69 | } 70 | 71 | bool mu::io::string_range::operator != (mu::io::string_range const & other_a) const 72 | { 73 | return !(*this == other_a); 74 | } 75 | 76 | bool mu::io::string_range::empty () const 77 | { 78 | return begin_m == end_m; 79 | } 80 | 81 | size_t mu::io::string_range::size () const 82 | { 83 | return end_m - begin_m; 84 | } 85 | 86 | char32_t mu::io::string_range::operator [] (size_t index) const 87 | { 88 | static char32_t const eof = U'\U0000FFFF'; 89 | auto result (index < static_cast (end_m - begin_m) ? *(begin_m + index) : *&eof); 90 | return result; 91 | } 92 | 93 | mu::io::lexer::lexer (mu::io::string_range const & source_a): 94 | position (0, 1, 1), 95 | source (source_a) 96 | { 97 | } 98 | 99 | mu::io::token_result mu::io::lexer::lex () 100 | { 101 | mu::io::token_result result ({nullptr, nullptr}); 102 | while (result.token == nullptr && result.error == nullptr) 103 | { 104 | auto character (source [0]); 105 | switch (character) 106 | { 107 | case U' ': 108 | case U'\f': 109 | case U'\n': 110 | case U'\r': 111 | case U'\t': 112 | case U'\0': 113 | consume (1); 114 | break; 115 | case U'[': 116 | result.token = new mu::io::left_square (mu::core::region (position, position)); 117 | consume (1); 118 | break; 119 | case U']': 120 | result.token = new mu::io::right_square (mu::core::region (position, position)); 121 | consume (1); 122 | break; 123 | case U';': 124 | result.token = new mu::io::terminator (mu::core::region (position, position)); 125 | consume (1); 126 | break; 127 | case U'\U0000FFFF': 128 | result.token = new mu::io::end (mu::core::region (position, position)); 129 | break; 130 | case U'{': 131 | result = complex_identifier (); 132 | break; 133 | case U':': 134 | { 135 | auto character2 (source [1]); 136 | switch (character2) 137 | { 138 | case U'a': 139 | case U'u': 140 | case U'[': 141 | case U']': 142 | case U';': 143 | case U'{': 144 | case U'}': 145 | case U'(': 146 | case U')': 147 | case U'f': 148 | case U'\f': 149 | case U'n': 150 | case U'\n': 151 | case U'r': 152 | case U'\r': 153 | case U't': 154 | case U'\t': 155 | case U'0': 156 | case U'\0': 157 | result = identifier (); 158 | break; 159 | case U'/': 160 | line_comment (); 161 | break; 162 | case U'*': 163 | result.error = region_comment (); 164 | break; 165 | default: 166 | { 167 | auto error (new mu::core::error_string (U"Unknown control character: ", mu::core::error_type::unknown_control_character, mu::core::region (position, position))); 168 | error->message.push_back (character2); 169 | result.error = error; 170 | break; 171 | } 172 | } 173 | break; 174 | } 175 | default: 176 | result = identifier (); 177 | break; 178 | } 179 | } 180 | return result; 181 | } 182 | 183 | mu::io::token_result mu::io::lexer::identifier () 184 | { 185 | auto identifier (new mu::io::identifier (mu::core::region (position, position))); 186 | auto last (position); 187 | mu::io::token_result result ({nullptr, nullptr}); 188 | while (result.token == nullptr && result.error == nullptr) 189 | { 190 | auto character (source [0]); 191 | switch (character) 192 | { 193 | case U' ': 194 | case U'\f': 195 | case U'\n': 196 | case U'\r': 197 | case U'\t': 198 | case U'\0': 199 | case U'[': 200 | case U']': 201 | case U'{': 202 | case U';': 203 | case U'\U0000FFFF': 204 | identifier->region.last = last; 205 | result.token = identifier; 206 | break; 207 | case U':': 208 | { 209 | auto character2 (source [1]); 210 | switch (character2) 211 | { 212 | case U'a': 213 | { 214 | consume (1); 215 | last = position; 216 | consume (1); 217 | auto character (hex_code (2)); 218 | last.offset += 2; 219 | last.column += 2; 220 | if (character.error == nullptr) 221 | { 222 | identifier->string.push_back (character.character); 223 | } 224 | else 225 | { 226 | result.error = character.error; 227 | } 228 | } 229 | break; 230 | case U'u': 231 | { 232 | consume (1); 233 | last = position; 234 | consume (1); 235 | auto character (hex_code (8)); 236 | last.offset += 8; 237 | last.column += 8; 238 | if (character.error == nullptr) 239 | { 240 | identifier->string.push_back (character.character); 241 | } 242 | else 243 | { 244 | result.error = character.error; 245 | } 246 | } 247 | break; 248 | case U'[': 249 | identifier->string.push_back (U'['); 250 | consume (1); 251 | last = position; 252 | consume (1); 253 | break; 254 | case U']': 255 | identifier->string.push_back (U']'); 256 | consume (1); 257 | last = position; 258 | consume (1); 259 | break; 260 | case U':': 261 | identifier->string.push_back (U':'); 262 | consume (1); 263 | last = position; 264 | consume (1); 265 | break; 266 | case U';': 267 | identifier->string.push_back (U';'); 268 | consume (1); 269 | last = position; 270 | consume (1); 271 | break; 272 | case U'{': 273 | identifier->string.push_back (U'{'); 274 | consume (2); 275 | last = position; 276 | break; 277 | case U'}': 278 | identifier->string.push_back (U'}'); 279 | consume (1); 280 | last = position; 281 | consume (1); 282 | break; 283 | case U' ': 284 | identifier->string.push_back (U' '); 285 | consume (1); 286 | last = position; 287 | consume (1); 288 | break; 289 | case U'f': 290 | case U'\f': 291 | identifier->string.push_back (U'\f'); 292 | consume (1); 293 | last = position; 294 | consume (1); 295 | break; 296 | case U'n': 297 | case U'\n': 298 | identifier->string.push_back (U'\n'); 299 | consume (1); 300 | last = position; 301 | consume (1); 302 | break; 303 | case U'r': 304 | case U'\r': 305 | identifier->string.push_back (U'\r'); 306 | consume (1); 307 | last = position; 308 | consume (1); 309 | break; 310 | case U't': 311 | case U'\t': 312 | identifier->string.push_back (U'\t'); 313 | consume (1); 314 | last = position; 315 | consume (1); 316 | break; 317 | case U'0': 318 | case U'\0': 319 | identifier->string.push_back (U'\0'); 320 | consume (1); 321 | last = position; 322 | consume (1); 323 | break; 324 | case U'/': 325 | result.token = identifier; 326 | break; 327 | case U'*': 328 | result.error = region_comment (); 329 | break; 330 | default: 331 | { 332 | auto error (new mu::core::error_string (U"Unknown control character: ", mu::core::error_type::unknown_control_character, mu::core::region (position, position))); 333 | error->message.push_back (character2); 334 | result.error = error; 335 | break; 336 | } 337 | } 338 | } 339 | break; 340 | default: 341 | identifier->string.push_back (character); 342 | last = position; 343 | consume (1); 344 | break; 345 | } 346 | } 347 | return result; 348 | } 349 | 350 | mu::io::token_result mu::io::lexer::complex_identifier () 351 | { 352 | assert (source [0] == U'{'); 353 | mu::io::token_result result ({nullptr, nullptr}); 354 | auto identifier (new mu::io::identifier (mu::core::region (position, position))); 355 | auto last (position); 356 | consume (1); 357 | auto have_terminator (false); 358 | mu::string terminator; 359 | while (result.token == nullptr && result.error == nullptr && !have_terminator && terminator.size () <= 16) 360 | { 361 | auto character (source [0]); 362 | if (character == U'}') 363 | { 364 | last = position; 365 | have_terminator = true; 366 | } 367 | else 368 | { 369 | terminator.push_back (character); 370 | } 371 | consume (1); 372 | } 373 | if (terminator.size () > 16) 374 | { 375 | result.error = new mu::core::error_string (U"Termiator token is greater than 16 characters", mu::core::error_type::terminator_token_too_long, mu::core::region (identifier->region.first, position)); 376 | } 377 | 378 | while (result.token == nullptr && result.error == nullptr) 379 | { 380 | auto have_terminator (true); 381 | for (size_t i (0), j (terminator.size ()); i < j && have_terminator; ++i) 382 | { 383 | have_terminator = (terminator [i] == source [i]); 384 | } 385 | if (have_terminator) 386 | { 387 | result.token = identifier; 388 | if (!terminator.empty ()) 389 | { 390 | consume (terminator.size () - 1); 391 | identifier->region.last = position; 392 | consume (1); 393 | } 394 | else 395 | { 396 | identifier->region.last = last; 397 | } 398 | } 399 | else 400 | { 401 | auto character (source [0]); 402 | if (character != U'\U0000FFFF') 403 | { 404 | identifier->string.push_back (character); 405 | consume (1); 406 | } 407 | else 408 | { 409 | result.error = new mu::core::error_string (U"End of stream inside complex identifier", mu::core::error_type::end_of_stream_inside_complex_identifier, mu::core::region (position, position)); 410 | } 411 | } 412 | } 413 | return result; 414 | } 415 | 416 | void mu::io::lexer::line_comment () 417 | { 418 | assert (source [0] == U':'); 419 | assert (source [1] == U'/'); 420 | consume (2); 421 | auto done (false); 422 | while (!done) 423 | { 424 | auto character (source [0]); 425 | consume (1); 426 | switch (character) 427 | { 428 | case U'\f': 429 | case U'\n': 430 | case U'\r': 431 | done = true; 432 | break; 433 | default: 434 | // Do nothing in comment 435 | break; 436 | } 437 | } 438 | } 439 | 440 | mu::io::character_result mu::io::lexer::hex_code (int size_a) 441 | { 442 | assert (size_a == 2 || size_a == 8); 443 | mu::io::character_result result ({'\0', nullptr}); 444 | auto size_l (size_a >> 1); 445 | for (int i (0); i < size_l && result.error == nullptr; ++i) 446 | { 447 | for (auto j (0); j < 2 && result.error == nullptr; ++j) 448 | { 449 | uint32_t code (source [0]); 450 | switch (code) 451 | { 452 | case U'a': 453 | case U'b': 454 | case U'c': 455 | case U'd': 456 | case U'e': 457 | case U'f': 458 | code -= 0x20; 459 | // Fall through 460 | case U'A': 461 | case U'B': 462 | case U'C': 463 | case U'D': 464 | case U'E': 465 | case U'F': 466 | code -= 0x7; 467 | // Fall through 468 | case U'0': 469 | case U'1': 470 | case U'2': 471 | case U'3': 472 | case U'4': 473 | case U'5': 474 | case U'6': 475 | case U'7': 476 | case U'8': 477 | case U'9': 478 | code -= 0x30; 479 | result.character <<= 4; 480 | result.character |= code; 481 | consume (1); 482 | break; 483 | default: 484 | result.error = new mu::core::error_string (U"Non-hex character", mu::core::error_type::non_hex_character, mu::core::region (position, position)); 485 | break; 486 | } 487 | } 488 | } 489 | return result; 490 | } 491 | 492 | mu::core::error * mu::io::lexer::region_comment () 493 | { 494 | assert (source [0] == U':'); 495 | assert (source [1] == U'*'); 496 | consume (2); 497 | mu::core::error * result (nullptr); 498 | auto done (false); 499 | while (!done) 500 | { 501 | auto character1 (source [0]); 502 | auto character2 (source [1]); 503 | switch (character1) 504 | { 505 | case U':': 506 | switch (character2) 507 | { 508 | case U'*': 509 | result = region_comment (); 510 | break; 511 | default: 512 | consume (1); 513 | break; 514 | } 515 | break; 516 | case U'*': 517 | switch (character2) 518 | { 519 | case U':': 520 | consume (2); 521 | done = true; 522 | break; 523 | default: 524 | consume (1); 525 | break; 526 | } 527 | break; 528 | case U'\U0000ffff': 529 | result = new mu::core::error_string (U"End of stream inside region comment", mu::core::error_type::end_of_stream_inside_region_comment, mu::core::region (position, position)); 530 | done = true; 531 | break; 532 | default: 533 | consume (1); 534 | break; 535 | } 536 | } 537 | return result; 538 | } 539 | 540 | void mu::io::lexer::consume (size_t size_a) 541 | { 542 | for (size_t i (0); i < size_a; ++i) 543 | { 544 | auto character (source [0]); 545 | switch (character) 546 | { 547 | case U'\f': 548 | case U'\n': 549 | case U'\r': 550 | position.line (); 551 | break; 552 | default: 553 | position.character (); 554 | break; 555 | } 556 | source = source.substr (1); 557 | } 558 | } -------------------------------------------------------------------------------- /mu/test/io_lexer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | TEST (stringref, basic) 9 | { 10 | std::array data; 11 | data [0] = 0xcc; 12 | data [1] = 0xdd; 13 | mu::io::string_range string1 (data.data (), data.data () + data.size ()); 14 | auto string2 (string1.substr (1, 2)); 15 | auto string3 (string1.substr (1)); 16 | ASSERT_EQ (string1.end (), string2.end ()); 17 | ASSERT_EQ (string1.begin () + 1, string2.begin ()); 18 | ASSERT_EQ (string2, string3); 19 | ASSERT_NE (string1, string2); 20 | ASSERT_EQ (2, string1.size ()); 21 | ASSERT_FALSE (string1.empty ()); 22 | ASSERT_EQ (1, string2.size ()); 23 | ASSERT_EQ (0xcc, string1 [0]); 24 | ASSERT_EQ (0xdd, string1 [1]); 25 | ASSERT_EQ (0xdd, string2 [0]); 26 | data [1] = 0xee; 27 | ASSERT_EQ (0xee, string3 [0]); 28 | } 29 | 30 | TEST (stringrange, convert) 31 | { 32 | std::string text1 ("text1"); 33 | auto string1 (text1); 34 | auto text2 ("text2"); 35 | auto string2 (text2); 36 | ASSERT_NE (string1, string2); 37 | } 38 | 39 | TEST (io_lexer, empty) 40 | { 41 | std::string text (""); 42 | mu::io::lexer lexer (text); 43 | auto token1 (lexer.lex ()); 44 | EXPECT_EQ (nullptr, token1.error); 45 | EXPECT_NE (nullptr, token1.token); 46 | auto token2 (dynamic_cast (token1.token)); 47 | ASSERT_NE (nullptr, token2); 48 | EXPECT_EQ (mu::core::region (0, 1, 1, 0, 1, 1), token2->region); 49 | auto token3 (lexer.lex ()); 50 | EXPECT_EQ (nullptr, token3.error); 51 | EXPECT_NE (nullptr, token3.token); 52 | auto token4 (dynamic_cast (token3.token)); 53 | EXPECT_EQ (mu::core::region (0, 1, 1, 0, 1, 1), token4->region); 54 | EXPECT_NE (nullptr, token4); 55 | } 56 | 57 | TEST (io_lexer, left_square) 58 | { 59 | std::string text ("["); 60 | mu::io::lexer lexer (text); 61 | auto token1 (lexer.lex ()); 62 | EXPECT_EQ (nullptr, token1.error); 63 | EXPECT_NE (nullptr, token1.token); 64 | auto token2 (dynamic_cast (token1.token)); 65 | ASSERT_NE (nullptr, token2); 66 | EXPECT_EQ (mu::core::region (0, 1, 1, 0, 1, 1), token2->region); 67 | auto token3 (lexer.lex ()); 68 | EXPECT_EQ (nullptr, token3.error); 69 | EXPECT_NE (nullptr, token3.token); 70 | auto token4 (dynamic_cast (token3.token)); 71 | ASSERT_NE (nullptr, token4); 72 | EXPECT_EQ (mu::core::region (1, 1, 2, 1, 1, 2), token4->region); 73 | } 74 | 75 | TEST (io_lexer, right_square) 76 | { 77 | std::string text ("]"); 78 | mu::io::lexer lexer (text); 79 | auto token1 (lexer.lex ()); 80 | EXPECT_EQ (nullptr, token1.error); 81 | EXPECT_NE (nullptr, token1.token); 82 | auto token2 (dynamic_cast (token1.token)); 83 | ASSERT_NE (nullptr, token2); 84 | EXPECT_EQ (mu::core::region (0, 1, 1, 0, 1, 1), token2->region); 85 | auto token3 (lexer.lex ()); 86 | EXPECT_EQ (nullptr, token3.error); 87 | EXPECT_NE (nullptr, token3.token); 88 | auto token4 (dynamic_cast (token3.token)); 89 | ASSERT_NE (nullptr, token4); 90 | EXPECT_EQ (mu::core::region (1, 1, 2, 1, 1, 2), token4->region); 91 | } 92 | 93 | TEST (io_lexer, terminator) 94 | { 95 | std::string text (";"); 96 | mu::io::lexer lexer (text); 97 | auto token1 (lexer.lex ()); 98 | EXPECT_EQ (nullptr, token1.error); 99 | EXPECT_NE (nullptr, token1.token); 100 | auto token2 (dynamic_cast (token1.token)); 101 | ASSERT_NE (nullptr, token2); 102 | EXPECT_EQ (mu::core::region (0, 1, 1, 0, 1, 1), token2->region); 103 | auto token3 (lexer.lex ()); 104 | EXPECT_EQ (nullptr, token3.error); 105 | EXPECT_NE (nullptr, token3.token); 106 | auto token4 (dynamic_cast (token3.token)); 107 | ASSERT_NE (nullptr, token4); 108 | EXPECT_EQ (mu::core::region (1, 1, 2, 1, 1, 2), token4->region); 109 | } 110 | 111 | TEST (io_lexer, whitespace) 112 | { 113 | std::stringstream text; 114 | text << " \f\n\r\t"; 115 | text << '\0'; 116 | text << ';'; 117 | mu::io::lexer lexer (text.str ()); 118 | auto token1 (lexer.lex ()); 119 | EXPECT_EQ (nullptr, token1.error); 120 | EXPECT_NE (nullptr, token1.token); 121 | auto token2 (dynamic_cast (token1.token)); 122 | ASSERT_NE (nullptr, token2); 123 | EXPECT_EQ (mu::core::region (6, 4, 3, 6, 4, 3), token2->region); 124 | auto token3 (lexer.lex ()); 125 | EXPECT_EQ (nullptr, token3.error); 126 | EXPECT_NE (nullptr, token3.token); 127 | auto token4 (dynamic_cast (token3.token)); 128 | ASSERT_NE (nullptr, token4); 129 | EXPECT_EQ (mu::core::region (7, 4, 4, 7, 4, 4), token4->region); 130 | } 131 | 132 | TEST (io_lexer, line_comment) 133 | { 134 | std::string text (":/\n;"); 135 | mu::io::lexer lexer (text); 136 | auto token1 (lexer.lex ()); 137 | EXPECT_EQ (nullptr, token1.error); 138 | EXPECT_NE (nullptr, token1.token); 139 | auto token2 (dynamic_cast (token1.token)); 140 | ASSERT_NE (nullptr, token2); 141 | EXPECT_EQ (mu::core::region (3, 2, 1, 3, 2, 1), token2->region); 142 | auto token3 (lexer.lex ()); 143 | EXPECT_EQ (nullptr, token3.error); 144 | EXPECT_NE (nullptr, token3.token); 145 | auto token4 (dynamic_cast (token3.token)); 146 | ASSERT_NE (nullptr, token4); 147 | EXPECT_EQ (mu::core::region (4, 2, 2, 4, 2, 2), token4->region); 148 | } 149 | 150 | TEST (io_lexer, region_comment) 151 | { 152 | std::string text (":*junk*:;"); 153 | mu::io::lexer lexer (text); 154 | auto token1 (lexer.lex ()); 155 | EXPECT_EQ (nullptr, token1.error); 156 | EXPECT_NE (nullptr, token1.token); 157 | auto token2 (dynamic_cast (token1.token)); 158 | ASSERT_NE (nullptr, token2); 159 | EXPECT_EQ (mu::core::region (8, 1, 9, 8, 1, 9), token2->region); 160 | auto token3 (lexer.lex ()); 161 | EXPECT_EQ (nullptr, token3.error); 162 | EXPECT_NE (nullptr, token3.token); 163 | auto token4 (dynamic_cast (token3.token)); 164 | ASSERT_NE (nullptr, token4); 165 | EXPECT_EQ (mu::core::region (9, 1, 10, 9, 1, 10), token4->region); 166 | } 167 | 168 | TEST (io_lexer, identifier) 169 | { 170 | std::string text ("a"); 171 | mu::io::lexer lexer (text); 172 | auto token1 (lexer.lex ()); 173 | EXPECT_EQ (nullptr, token1.error); 174 | EXPECT_NE (nullptr, token1.token); 175 | auto token2 (dynamic_cast (token1.token)); 176 | ASSERT_NE (nullptr, token2); 177 | EXPECT_EQ (mu::core::region (0, 1, 1, 0, 1, 1), token2->region); 178 | ASSERT_EQ (1, token2->string.size ()); 179 | EXPECT_EQ (U'a', token2->string [0]); 180 | auto token3 (lexer.lex ()); 181 | EXPECT_EQ (nullptr, token3.error); 182 | EXPECT_NE (nullptr, token3.token); 183 | auto token4 (dynamic_cast (token3.token)); 184 | ASSERT_NE (nullptr, token4); 185 | EXPECT_EQ (mu::core::region (1, 1, 2, 1, 1, 2), token4->region); 186 | } 187 | 188 | TEST (io_lexer, identifier_terminator) 189 | { 190 | std::string text ("a;"); 191 | mu::io::lexer lexer (text); 192 | auto token1 (lexer.lex ()); 193 | EXPECT_EQ (nullptr, token1.error); 194 | EXPECT_NE (nullptr, token1.token); 195 | auto token2 (dynamic_cast (token1.token)); 196 | ASSERT_NE (nullptr, token2); 197 | EXPECT_EQ (mu::core::region (0, 1, 1, 0, 1, 1), token2->region); 198 | ASSERT_EQ (1, token2->string.size ()); 199 | EXPECT_EQ (U'a', token2->string [0]); 200 | auto token3 (lexer.lex ()); 201 | EXPECT_EQ (nullptr, token3.error); 202 | EXPECT_NE (nullptr, token3.token); 203 | auto token4 (dynamic_cast (token3.token)); 204 | ASSERT_NE (nullptr, token4); 205 | EXPECT_EQ (mu::core::region (1, 1, 2, 1, 1, 2), token4->region); 206 | auto token5 (lexer.lex ()); 207 | EXPECT_EQ (nullptr, token5.error); 208 | EXPECT_NE (nullptr, token5.token); 209 | auto token6 (dynamic_cast (token5.token)); 210 | ASSERT_NE (nullptr, token6); 211 | EXPECT_EQ (mu::core::region (2, 1, 3, 2, 1, 3), token6->region); 212 | } 213 | 214 | TEST (io_lexer, identifier_left_square) 215 | { 216 | std::string text ("a["); 217 | mu::io::lexer lexer (text); 218 | auto token1 (lexer.lex ()); 219 | EXPECT_EQ (nullptr, token1.error); 220 | EXPECT_NE (nullptr, token1.token); 221 | auto token2 (dynamic_cast (token1.token)); 222 | ASSERT_NE (nullptr, token2); 223 | EXPECT_EQ (mu::core::region (0, 1, 1, 0, 1, 1), token2->region); 224 | ASSERT_EQ (1, token2->string.size ()); 225 | EXPECT_EQ (U'a', token2->string [0]); 226 | auto token3 (lexer.lex ()); 227 | EXPECT_EQ (nullptr, token3.error); 228 | EXPECT_NE (nullptr, token3.token); 229 | auto token4 (dynamic_cast (token3.token)); 230 | ASSERT_NE (nullptr, token4); 231 | EXPECT_EQ (mu::core::region (1, 1, 2, 1, 1, 2), token4->region); 232 | auto token5 (lexer.lex ()); 233 | EXPECT_EQ (nullptr, token5.error); 234 | EXPECT_NE (nullptr, token5.token); 235 | auto token6 (dynamic_cast (token5.token)); 236 | ASSERT_NE (nullptr, token6); 237 | EXPECT_EQ (mu::core::region (2, 1, 3, 2, 1, 3), token6->region); 238 | } 239 | 240 | TEST (io_lexer, identifier_right_square) 241 | { 242 | std::string text ("a]"); 243 | mu::io::lexer lexer (text); 244 | auto token1 (lexer.lex ()); 245 | EXPECT_EQ (nullptr, token1.error); 246 | EXPECT_NE (nullptr, token1.token); 247 | auto token2 (dynamic_cast (token1.token)); 248 | ASSERT_NE (nullptr, token2); 249 | EXPECT_EQ (mu::core::region (0, 1, 1, 0, 1, 1), token2->region); 250 | ASSERT_EQ (1, token2->string.size ()); 251 | EXPECT_EQ (U'a', token2->string [0]); 252 | auto token3 (lexer.lex ()); 253 | EXPECT_EQ (nullptr, token3.error); 254 | EXPECT_NE (nullptr, token3.token); 255 | auto token4 (dynamic_cast (token3.token)); 256 | ASSERT_NE (nullptr, token4); 257 | EXPECT_EQ (mu::core::region (1, 1, 2, 1, 1, 2), token4->region); 258 | auto token5 (lexer.lex ()); 259 | EXPECT_EQ (nullptr, token5.error); 260 | EXPECT_NE (nullptr, token5.token); 261 | auto token6 (dynamic_cast (token5.token)); 262 | ASSERT_NE (nullptr, token6); 263 | EXPECT_EQ (mu::core::region (2, 1, 3, 2, 1, 3), token6->region); 264 | } 265 | 266 | TEST (io_lexer, two_identifiers) 267 | { 268 | std::string text ("a b"); 269 | mu::io::lexer lexer (text); 270 | auto token1 (lexer.lex ()); 271 | EXPECT_EQ (nullptr, token1.error); 272 | EXPECT_NE (nullptr, token1.token); 273 | auto token2 (dynamic_cast (token1.token)); 274 | ASSERT_NE (nullptr, token2); 275 | EXPECT_EQ (mu::core::region (0, 1, 1, 0, 1, 1), token2->region); 276 | ASSERT_EQ (1, token2->string.size ()); 277 | EXPECT_EQ (U'a', token2->string [0]); 278 | auto token3 (lexer.lex ()); 279 | EXPECT_EQ (nullptr, token3.error); 280 | EXPECT_NE (nullptr, token3.token); 281 | auto token4 (dynamic_cast (token3.token)); 282 | ASSERT_NE (nullptr, token4); 283 | EXPECT_EQ (mu::core::region (2, 1, 3, 2, 1, 3), token4->region); 284 | ASSERT_EQ (1, token4->string.size ()); 285 | EXPECT_EQ (U'b', token4->string [0]); 286 | auto token5 (lexer.lex ()); 287 | EXPECT_EQ (nullptr, token5.error); 288 | EXPECT_NE (nullptr, token5.token); 289 | auto token6 (dynamic_cast (token5.token)); 290 | ASSERT_NE (nullptr, token6); 291 | EXPECT_EQ (mu::core::region (3, 1, 4, 3, 1, 4), token6->region); 292 | } 293 | 294 | TEST (io_lexer, escape_sequences) 295 | { 296 | std::stringstream text; 297 | text << ":[:]:;:::\t:t:\n:n:\f:f:\r:r:0"; 298 | text << ':'; 299 | text << '\0'; 300 | mu::io::lexer lexer (text.str ()); 301 | auto token1 (lexer.lex ()); 302 | EXPECT_EQ (nullptr, token1.error); 303 | EXPECT_NE (nullptr, token1.token); 304 | auto token2 (dynamic_cast (token1.token)); 305 | ASSERT_NE (nullptr, token2); 306 | EXPECT_EQ (mu::core::region (0, 1, 1, 27, 4, 6), token2->region); 307 | ASSERT_EQ (14, token2->string.size ()); 308 | EXPECT_EQ (U'[', token2->string [0]); 309 | EXPECT_EQ (U']', token2->string [1]); 310 | EXPECT_EQ (U';', token2->string [2]); 311 | EXPECT_EQ (U':', token2->string [3]); 312 | EXPECT_EQ (U'\t', token2->string [4]); 313 | EXPECT_EQ (U'\t', token2->string [5]); 314 | EXPECT_EQ (U'\n', token2->string [6]); 315 | EXPECT_EQ (U'\n', token2->string [7]); 316 | EXPECT_EQ (U'\f', token2->string [8]); 317 | EXPECT_EQ (U'\f', token2->string [9]); 318 | EXPECT_EQ (U'\r', token2->string [10]); 319 | EXPECT_EQ (U'\r', token2->string [11]); 320 | EXPECT_EQ (U'\0', token2->string [12]); 321 | EXPECT_EQ (U'\0', token2->string [13]); 322 | auto token3 (lexer.lex ()); 323 | EXPECT_EQ (nullptr, token3.error); 324 | EXPECT_NE (nullptr, token3.token); 325 | auto token4 (dynamic_cast (token3.token)); 326 | ASSERT_NE (nullptr, token4); 327 | EXPECT_EQ (mu::core::region (28, 4, 7, 28, 4, 7), token4->region); 328 | } 329 | 330 | TEST (io_lexer, ascii_numbers) 331 | { 332 | std::string text (":a00"); 333 | mu::io::lexer lexer (text); 334 | auto token1 (lexer.lex ()); 335 | EXPECT_EQ (nullptr, token1.error); 336 | EXPECT_NE (nullptr, token1.token); 337 | auto token2 (dynamic_cast (token1.token)); 338 | ASSERT_NE (nullptr, token2); 339 | EXPECT_EQ (mu::core::region (0, 1, 1, 3, 1, 4), token2->region); 340 | ASSERT_EQ (1, token2->string.size ()); 341 | EXPECT_EQ ('\0', token2->string [0]); 342 | auto token3 (lexer.lex ()); 343 | EXPECT_EQ (nullptr, token3.error); 344 | EXPECT_NE (nullptr, token3.token); 345 | auto token4 (dynamic_cast (token3.token)); 346 | ASSERT_NE (nullptr, token4); 347 | EXPECT_EQ (mu::core::region (4, 1, 5, 4, 1, 5), token4->region); 348 | } 349 | 350 | TEST (io_lexer, ascii_upper_letters) 351 | { 352 | std::string text (":a4A"); 353 | mu::io::lexer lexer (text); 354 | auto token1 (lexer.lex ()); 355 | EXPECT_EQ (nullptr, token1.error); 356 | EXPECT_NE (nullptr, token1.token); 357 | auto token2 (dynamic_cast (token1.token)); 358 | ASSERT_NE (nullptr, token2); 359 | EXPECT_EQ (mu::core::region (0, 1, 1, 3, 1, 4), token2->region); 360 | ASSERT_EQ (1, token2->string.size ()); 361 | EXPECT_EQ (U'\U0000004a', token2->string [0]); 362 | auto token3 (lexer.lex ()); 363 | EXPECT_EQ (nullptr, token3.error); 364 | EXPECT_NE (nullptr, token3.token); 365 | auto token4 (dynamic_cast (token3.token)); 366 | ASSERT_NE (nullptr, token4); 367 | EXPECT_EQ (mu::core::region (4, 1, 5, 4, 1, 5), token4->region); 368 | } 369 | 370 | TEST (io_lexer, ascii_lower_letters) 371 | { 372 | std::string text (":a4a"); 373 | mu::io::lexer lexer (text); 374 | auto token1 (lexer.lex ()); 375 | EXPECT_EQ (nullptr, token1.error); 376 | EXPECT_NE (nullptr, token1.token); 377 | auto token2 (dynamic_cast (token1.token)); 378 | ASSERT_NE (nullptr, token2); 379 | EXPECT_EQ (mu::core::region (0, 1, 1, 3, 1, 4), token2->region); 380 | ASSERT_EQ (1, token2->string.size ()); 381 | EXPECT_EQ (U'\U0000004a', token2->string [0]); 382 | auto token3 (lexer.lex ()); 383 | EXPECT_EQ (nullptr, token3.error); 384 | EXPECT_NE (nullptr, token3.token); 385 | auto token4 (dynamic_cast (token3.token)); 386 | ASSERT_NE (nullptr, token4); 387 | EXPECT_EQ (mu::core::region (4, 1, 5, 4, 1, 5), token4->region); 388 | } 389 | 390 | TEST (io_lexer, unicode) 391 | { 392 | std::string text (":uaaaabbbb"); 393 | mu::io::lexer lexer (text); 394 | auto token1 (lexer.lex ()); 395 | EXPECT_EQ (nullptr, token1.error); 396 | EXPECT_NE (nullptr, token1.token); 397 | auto token2 (dynamic_cast (token1.token)); 398 | ASSERT_NE (nullptr, token2); 399 | EXPECT_EQ (mu::core::region (0, 1, 1, 9, 1, 10), token2->region); 400 | ASSERT_EQ (1, token2->string.size ()); 401 | EXPECT_EQ ((char32_t)0xaaaabbbb, token2->string [0]); 402 | auto token3 (lexer.lex ()); 403 | EXPECT_EQ (nullptr, token3.error); 404 | EXPECT_NE (nullptr, token3.token); 405 | auto token4 (dynamic_cast (token3.token)); 406 | ASSERT_NE (nullptr, token4); 407 | EXPECT_EQ (mu::core::region (10, 1, 11, 10, 1, 11), token4->region); 408 | } 409 | 410 | TEST (io_lexer, identifier_inner_comment) 411 | { 412 | std::string text ("a:*junk*:b"); 413 | mu::io::lexer lexer (text); 414 | auto token1 (lexer.lex ()); 415 | EXPECT_EQ (nullptr, token1.error); 416 | EXPECT_NE (nullptr, token1.token); 417 | auto token2 (dynamic_cast (token1.token)); 418 | ASSERT_NE (nullptr, token2); 419 | EXPECT_EQ (mu::core::region (0, 1, 1, 9, 1, 10), token2->region); 420 | ASSERT_EQ (2, token2->string.size ()); 421 | EXPECT_EQ (U'a', token2->string [0]); 422 | EXPECT_EQ (U'b', token2->string [1]); 423 | auto token3 (lexer.lex ()); 424 | EXPECT_EQ (nullptr, token3.error); 425 | EXPECT_NE (nullptr, token3.token); 426 | auto token4 (dynamic_cast (token3.token)); 427 | ASSERT_NE (nullptr, token4); 428 | EXPECT_EQ (mu::core::region (10, 1, 11, 10, 1, 11), token4->region); 429 | } 430 | 431 | TEST (io_lexer, nested_comment) 432 | { 433 | std::string text ("a:*:*junk*:*:b"); 434 | mu::io::lexer lexer (text); 435 | auto token1 (lexer.lex ()); 436 | EXPECT_EQ (nullptr, token1.error); 437 | EXPECT_NE (nullptr, token1.token); 438 | auto token2 (dynamic_cast (token1.token)); 439 | ASSERT_NE (nullptr, token2); 440 | EXPECT_EQ (mu::core::region (0, 1, 1, 13, 1, 14), token2->region); 441 | ASSERT_EQ (2, token2->string.size ()); 442 | EXPECT_EQ (U'a', token2->string [0]); 443 | EXPECT_EQ (U'b', token2->string [1]); 444 | auto token3 (lexer.lex ()); 445 | EXPECT_EQ (nullptr, token3.error); 446 | EXPECT_NE (nullptr, token3.token); 447 | auto token4 (dynamic_cast (token3.token)); 448 | ASSERT_NE (nullptr, token4); 449 | EXPECT_EQ (mu::core::region (14, 1, 15, 14, 1, 15), token4->region); 450 | } 451 | 452 | TEST (io_lexer, empty_complex) 453 | { 454 | std::string text ("{}"); 455 | mu::io::lexer lexer (text); 456 | auto token1 (lexer.lex ()); 457 | EXPECT_EQ (nullptr, token1.error); 458 | EXPECT_NE (nullptr, token1.token); 459 | auto token2 (dynamic_cast (token1.token)); 460 | ASSERT_NE (nullptr, token2); 461 | EXPECT_EQ (mu::core::region (0, 1, 1, 1, 1, 2), token2->region); 462 | ASSERT_EQ (0, token2->string.size ()); 463 | auto token3 (lexer.lex ()); 464 | EXPECT_EQ (nullptr, token3.error); 465 | EXPECT_NE (nullptr, token3.token); 466 | auto token4 (dynamic_cast (token3.token)); 467 | ASSERT_NE (nullptr, token4); 468 | EXPECT_EQ (mu::core::region (2, 1, 3, 2, 1, 3), token4->region); 469 | } 470 | 471 | TEST (io_lexer, complex_with_control) 472 | { 473 | std::stringstream text; 474 | text << "{a}[];: \n\t\r\f"; 475 | text << '\0'; 476 | text << 'a'; 477 | mu::io::lexer lexer (text.str ()); 478 | auto token1 (lexer.lex ()); 479 | EXPECT_EQ (nullptr, token1.error); 480 | EXPECT_NE (nullptr, token1.token); 481 | auto token2 (dynamic_cast (token1.token)); 482 | ASSERT_NE (nullptr, token2); 483 | EXPECT_EQ (mu::core::region (0, 1, 1, 13, 4, 2), token2->region); 484 | ASSERT_EQ (10, token2->string.size ()); 485 | EXPECT_EQ (U'[', token2->string [0]); 486 | EXPECT_EQ (U']', token2->string [1]); 487 | EXPECT_EQ (U';', token2->string [2]); 488 | EXPECT_EQ (U':', token2->string [3]); 489 | EXPECT_EQ (U' ', token2->string [4]); 490 | EXPECT_EQ (U'\n', token2->string [5]); 491 | EXPECT_EQ (U'\t', token2->string [6]); 492 | EXPECT_EQ (U'\r', token2->string [7]); 493 | EXPECT_EQ (U'\f', token2->string [8]); 494 | EXPECT_EQ (U'\0', token2->string [9]); 495 | auto token3 (lexer.lex ()); 496 | EXPECT_EQ (nullptr, token3.error); 497 | EXPECT_NE (nullptr, token3.token); 498 | auto token4 (dynamic_cast (token3.token)); 499 | ASSERT_NE (nullptr, token4); 500 | EXPECT_EQ (mu::core::region (14, 4, 3, 14, 4, 3), token4->region); 501 | } 502 | 503 | TEST (io_lexer, invalid_control) 504 | { 505 | std::string text (":z"); 506 | mu::io::lexer lexer (text); 507 | auto token1 (lexer.lex ()); 508 | EXPECT_NE (nullptr, token1.error); 509 | EXPECT_EQ (nullptr, token1.token); 510 | } 511 | 512 | TEST (io_lexer, invalid_ascii) 513 | { 514 | std::string text (":aqq"); 515 | mu::io::lexer lexer (text); 516 | auto token1 (lexer.lex ()); 517 | EXPECT_NE (nullptr, token1.error); 518 | EXPECT_EQ (nullptr, token1.token); 519 | } 520 | 521 | TEST (io_lexer, invalid_eof_in_region_comment) 522 | { 523 | std::string text (":*"); 524 | mu::io::lexer lexer (text); 525 | auto token1 (lexer.lex ()); 526 | EXPECT_NE (nullptr, token1.error); 527 | EXPECT_EQ (nullptr, token1.token); 528 | } 529 | 530 | TEST (io_lexer, invalid_eof_in_ascii) 531 | { 532 | std::string text (":a"); 533 | mu::io::lexer lexer (text); 534 | auto token1 (lexer.lex ()); 535 | EXPECT_NE (nullptr, token1.error); 536 | EXPECT_EQ (nullptr, token1.token); 537 | } 538 | 539 | TEST (io_lexer, invalid_eof_in_complex_identifier) 540 | { 541 | std::string text ("{a}"); 542 | mu::io::lexer lexer (text); 543 | auto token1 (lexer.lex ()); 544 | EXPECT_NE (nullptr, token1.error); 545 | EXPECT_EQ (nullptr, token1.token); 546 | } 547 | 548 | TEST (io_lexer, hash_empty) 549 | { 550 | mu::string string; 551 | mu::core::string_hash hash (string); 552 | auto text (hash.text()); 553 | ASSERT_EQ (U"5049d74780a3e07d4202ab47d4cef2f4", text); 554 | } 555 | 556 | TEST (io_lexer, hash_sentence) 557 | { 558 | mu::string string (U"The quick brown fox jumps over the lazy dog"); 559 | mu::core::string_hash hash (string); 560 | auto text (hash.text()); 561 | ASSERT_EQ (U"e32e5d57dfbb310c2b90a934f1d30625", text); 562 | } 563 | 564 | TEST (io_lexer, region_comment_containing_control_character) 565 | { 566 | std::string text (":*:a00*:;"); 567 | mu::io::lexer lexer (text); 568 | auto token1 (lexer.lex ()); 569 | EXPECT_EQ (nullptr, token1.error); 570 | EXPECT_NE (nullptr, token1.token); 571 | auto token2 (dynamic_cast (token1.token)); 572 | ASSERT_NE (nullptr, token2); 573 | EXPECT_EQ (mu::core::region (8, 1, 9, 8, 1, 9), token2->region); 574 | auto token3 (lexer.lex ()); 575 | EXPECT_EQ (nullptr, token3.error); 576 | EXPECT_NE (nullptr, token3.token); 577 | auto token4 (dynamic_cast (token3.token)); 578 | ASSERT_NE (nullptr, token4); 579 | EXPECT_EQ (mu::core::region (9, 1, 10, 9, 1, 10), token4->region); 580 | } 581 | -------------------------------------------------------------------------------- /mu/llvmc/ast.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace mu 9 | { 10 | namespace iou 11 | { 12 | template 13 | class stream; 14 | class token; 15 | } 16 | namespace llvmc 17 | { 18 | namespace skeleton 19 | { 20 | class node; 21 | } 22 | class template_context; 23 | class clone_context 24 | { 25 | public: 26 | clone_context (mu::llvmc::template_context * template_a); 27 | mu::llvmc::template_context * template_m; 28 | mu::map generated; 29 | }; 30 | namespace ast 31 | { 32 | class visitor; 33 | class namespace_visitor; 34 | class node 35 | { 36 | public: 37 | node (mu::llvmc::template_context * template_a = nullptr); 38 | node (mu::llvmc::ast::node const & other_a) = delete; 39 | node (mu::llvmc::ast::node const & other_a, mu::llvmc::clone_context & context_a); 40 | virtual ~node (); 41 | mu::llvmc::ast::node * clone (mu::llvmc::clone_context & context_a); 42 | virtual void visit (mu::llvmc::ast::visitor * visitor_a); 43 | virtual bool is_sequenced () const; 44 | mu::llvmc::template_context * template_m; 45 | mu::core::region region; 46 | mu::vector generated; 47 | bool assigned; 48 | private: 49 | virtual mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a); 50 | }; 51 | class value : public mu::llvmc::ast::node 52 | { 53 | public: 54 | value (mu::llvmc::ast::value const & other_a, mu::llvmc::clone_context & context_a); 55 | value (mu::llvmc::skeleton::node * node_a, mu::llvmc::template_context * template_a = nullptr); 56 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 57 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 58 | mu::llvmc::skeleton::node * node_m; 59 | }; 60 | class loop_parameter : public mu::llvmc::ast::node 61 | { 62 | public: 63 | loop_parameter (mu::llvmc::ast::loop_parameter const & other_a); 64 | loop_parameter (mu::string const & name_a, mu::llvmc::template_context * template_a = nullptr); 65 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 66 | mu::string name; 67 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 68 | }; 69 | class unit : public mu::llvmc::ast::node 70 | { 71 | public: 72 | unit (mu::llvmc::template_context * template_a = nullptr); 73 | unit (mu::llvmc::ast::unit const & other_a, mu::llvmc::clone_context & context_a); 74 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 75 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 76 | }; 77 | class parameter : public mu::llvmc::ast::node 78 | { 79 | public: 80 | parameter (mu::llvmc::template_context * template_a = nullptr); 81 | parameter (mu::llvmc::ast::parameter const & other_a, mu::llvmc::clone_context & context_a); 82 | parameter (mu::string const & name_a, mu::llvmc::ast::node * type_a, mu::llvmc::template_context * template_a = nullptr); 83 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 84 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 85 | mu::llvmc::ast::node * type; 86 | mu::string name; 87 | }; 88 | class element : public mu::llvmc::ast::node 89 | { 90 | public: 91 | element (mu::llvmc::ast::node * node_a, size_t index_a, size_t total_a, mu::string const & name_a, mu::core::region const & region_a, mu::llvmc::template_context * template_a = nullptr); 92 | element (mu::llvmc::ast::element const & other_a, mu::llvmc::clone_context & context_a); 93 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 94 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 95 | mu::llvmc::ast::node * node_m; 96 | size_t index; 97 | size_t total; 98 | mu::string name; 99 | }; 100 | class loop_result 101 | { 102 | public: 103 | loop_result () = default; 104 | loop_result (std::initializer_list const &); 105 | loop_result (mu::llvmc::ast::loop_result const &, mu::llvmc::clone_context &); 106 | mu::vector nodes; 107 | }; 108 | class loop : public mu::llvmc::ast::node 109 | { 110 | public: 111 | loop (std::initializer_list const &, mu::llvmc::template_context * = nullptr); 112 | loop (mu::llvmc::template_context * = nullptr); 113 | loop (mu::llvmc::ast::loop const &, mu::llvmc::clone_context &); 114 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context &) override; 115 | void visit (mu::llvmc::ast::visitor *) override; 116 | mu::llvmc::ast::loop_result & add_branch (); 117 | mu::vector arguments; 118 | mu::vector parameters; 119 | mu::vector roots; 120 | mu::vector results; 121 | }; 122 | class expression : public mu::llvmc::ast::node 123 | { 124 | public: 125 | expression (mu::llvmc::template_context * template_a = nullptr); 126 | expression (std::initializer_list arguments, mu::llvmc::template_context * template_a = nullptr); 127 | expression (mu::llvmc::ast::expression const & other_a, mu::llvmc::clone_context & context_a); 128 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 129 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 130 | mu::vector arguments; 131 | }; 132 | class function_branch 133 | { 134 | public: 135 | function_branch () = default; 136 | function_branch (std::initializer_list const &); 137 | function_branch (mu::llvmc::ast::function_branch const &, mu::llvmc::clone_context &); 138 | mu::vector nodes; 139 | }; 140 | class function_result 141 | { 142 | public: 143 | function_result () = default; 144 | function_result (std::initializer_list const &); 145 | function_result (mu::llvmc::ast::function_result const &, mu::llvmc::clone_context &); 146 | mu::llvmc::ast::function_branch & add_branch (); 147 | mu::vector branches; 148 | }; 149 | class function_return 150 | { 151 | public: 152 | function_return () = default; 153 | function_return (std::initializer_list const &); 154 | mu::vector types; 155 | }; 156 | class function : public mu::llvmc::ast::node 157 | { 158 | public: 159 | function (mu::llvmc::template_context * template_a = nullptr); 160 | function (mu::llvmc::ast::function const & other_a, mu::llvmc::clone_context & context_a); 161 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 162 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 163 | mu::vector parameters; 164 | mu::vector returns; 165 | mu::llvmc::ast::function_result results; 166 | mu::vector roots; 167 | }; 168 | class function_family : public mu::llvmc::ast::node 169 | { 170 | public: 171 | function_family (mu::llvmc::template_context * = nullptr); 172 | function_family (mu::llvmc::ast::function_family const &, mu::llvmc::clone_context &); 173 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context &) override; 174 | void visit (mu::llvmc::ast::visitor *) override; 175 | }; 176 | class function_overload : public mu::llvmc::ast::node 177 | { 178 | public: 179 | function_overload (mu::llvmc::template_context * = nullptr); 180 | function_overload (mu::llvmc::ast::function_overload const &, mu::llvmc::clone_context &); 181 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context &) override; 182 | void visit (mu::llvmc::ast::visitor *) override; 183 | mu::llvmc::ast::node * family; 184 | mu::llvmc::ast::node * function; 185 | }; 186 | class integer_type : public mu::llvmc::ast::node 187 | { 188 | public: 189 | integer_type (mu::llvmc::ast::integer_type const & other_a); 190 | integer_type (mu::llvmc::template_context * template_a = nullptr); 191 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 192 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 193 | mu::llvmc::ast::node * bits; 194 | }; 195 | class pointer_type : public mu::llvmc::ast::node 196 | { 197 | public: 198 | pointer_type (mu::llvmc::template_context * template_a = nullptr); 199 | pointer_type (mu::llvmc::ast::pointer_type const & other_a, mu::llvmc::clone_context & context_a); 200 | pointer_type (mu::llvmc::ast::node * pointed_type_a, mu::llvmc::template_context * template_a = nullptr); 201 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 202 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 203 | mu::llvmc::ast::node * pointed_type; 204 | }; 205 | class fixed_array_type : public mu::llvmc::ast::node 206 | { 207 | public: 208 | fixed_array_type (mu::llvmc::template_context * template_a = nullptr); 209 | fixed_array_type (mu::llvmc::ast::fixed_array_type const & other_a, mu::llvmc::clone_context & context_a); 210 | fixed_array_type (mu::llvmc::ast::node * element_type_a, mu::llvmc::ast::node * size_a, mu::llvmc::template_context * template_a = nullptr); 211 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 212 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 213 | mu::llvmc::ast::node * element_type; 214 | mu::llvmc::ast::node * size; 215 | }; 216 | class array_type : public mu::llvmc::ast::node 217 | { 218 | public: 219 | array_type (mu::llvmc::template_context * template_a = nullptr); 220 | array_type (mu::llvmc::ast::array_type const & other_a, mu::llvmc::clone_context & context_a); 221 | array_type (mu::llvmc::ast::node * element_type_a, mu::llvmc::template_context * template_a = nullptr); 222 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 223 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 224 | mu::llvmc::ast::node * element_type; 225 | }; 226 | class unit_type : public mu::llvmc::ast::node 227 | { 228 | public: 229 | unit_type (mu::llvmc::template_context * template_a = nullptr); 230 | unit_type (mu::llvmc::ast::unit_type const & other_a); 231 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 232 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 233 | }; 234 | class module : public mu::llvmc::ast::node 235 | { 236 | public: 237 | module (mu::llvmc::template_context * template_a = nullptr); 238 | module (mu::llvmc::ast::module const & other_a, mu::llvmc::clone_context & context_a); 239 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 240 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 241 | mu::vector globals; 242 | mu::map names; 243 | void dump (); 244 | }; 245 | class constant_int : public mu::llvmc::ast::node 246 | { 247 | public: 248 | constant_int (mu::llvmc::ast::constant_int const & other_a, mu::llvmc::clone_context & context_a); 249 | constant_int (mu::llvmc::template_context * template_a = nullptr); 250 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 251 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 252 | }; 253 | class constant_array : public mu::llvmc::ast::node 254 | { 255 | public: 256 | constant_array (mu::llvmc::template_context * template_a = nullptr); 257 | constant_array (mu::llvmc::ast::constant_array const & other_a, mu::llvmc::clone_context & context_a); 258 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 259 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 260 | mu::llvmc::ast::node * type; 261 | mu::vector initializer; 262 | }; 263 | class constant_pointer_null : public mu::llvmc::ast::node 264 | { 265 | public: 266 | constant_pointer_null (mu::llvmc::template_context * template_a = nullptr); 267 | constant_pointer_null (mu::llvmc::ast::constant_pointer_null const & other_a, mu::llvmc::clone_context & context_a); 268 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 269 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 270 | mu::llvmc::ast::node * type; 271 | }; 272 | class number : public mu::llvmc::ast::node 273 | { 274 | public: 275 | number (mu::string const & number_a, mu::llvmc::template_context * context_a = nullptr); 276 | number (mu::llvmc::ast::number const & other_a, mu::llvmc::clone_context & context_a); 277 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 278 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 279 | mu::string number_m; 280 | }; 281 | class asm_c : public mu::llvmc::ast::node 282 | { 283 | public: 284 | asm_c (mu::llvmc::template_context * template_a = nullptr); 285 | asm_c (mu::llvmc::ast::asm_c const & other_a, mu::llvmc::clone_context & context_a); 286 | asm_c (mu::llvmc::ast::node * type_a, mu::string const & text_a, mu::string const & constraints_a, mu::llvmc::template_context * template_a = nullptr); 287 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 288 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 289 | mu::llvmc::ast::node * type; 290 | mu::string text; 291 | mu::string constraints; 292 | }; 293 | class global_variable : public mu::llvmc::ast::node 294 | { 295 | public: 296 | global_variable (mu::llvmc::template_context * template_a = nullptr); 297 | global_variable (mu::llvmc::ast::global_variable const & other_a, mu::llvmc::clone_context & context_a); 298 | global_variable (mu::llvmc::ast::node * initializer_a, mu::llvmc::template_context * template_a = nullptr); 299 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 300 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 301 | mu::llvmc::ast::node * initializer; 302 | }; 303 | class join_branch 304 | { 305 | public: 306 | mu::vector arguments; 307 | mu::vector predicates; 308 | }; 309 | class join : public mu::llvmc::ast::node 310 | { 311 | public: 312 | join (mu::llvmc::template_context * context_a = nullptr); 313 | join (mu::llvmc::ast::join const & other_a, mu::llvmc::clone_context & context_a); 314 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 315 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 316 | mu::vector branches; 317 | mu::llvmc::ast::join_branch & add_branch (); 318 | }; 319 | class struct_type : public mu::llvmc::ast::node 320 | { 321 | public: 322 | struct_type (mu::llvmc::template_context * context_a = nullptr); 323 | struct_type (mu::llvmc::ast::struct_type const & other_a, mu::llvmc::clone_context & context_a); 324 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 325 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 326 | mu::map names; 327 | mu::vector elements; 328 | }; 329 | class undefined : public mu::llvmc::ast::node 330 | { 331 | public: 332 | undefined (mu::llvmc::template_context * context_a = nullptr); 333 | undefined (mu::llvmc::ast::undefined const & other_a, mu::llvmc::clone_context & context_a); 334 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 335 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 336 | mu::llvmc::ast::node * type; 337 | }; 338 | class template_parameter : public mu::llvmc::ast::node 339 | { 340 | public: 341 | template_parameter (mu::string const & name_a, mu::llvmc::template_context * template_a = nullptr); 342 | template_parameter (mu::llvmc::ast::template_parameter const & other_a, mu::llvmc::clone_context & context_a); 343 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 344 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 345 | size_t argument; 346 | mu::string name; 347 | }; 348 | class template_c : public mu::llvmc::ast::node 349 | { 350 | public: 351 | template_c (mu::llvmc::template_context * base_a, mu::llvmc::template_context * context_a = nullptr); 352 | template_c (mu::llvmc::ast::template_c const & other_a, mu::llvmc::clone_context & context_a); 353 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 354 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 355 | mu::llvmc::template_context * base; 356 | mu::vector parameters; 357 | mu::vector body; 358 | }; 359 | class entry : public mu::llvmc::ast::node 360 | { 361 | public: 362 | entry (mu::llvmc::template_context * context_a = nullptr); 363 | entry (mu::llvmc::ast::entry const & other_a, mu::llvmc::clone_context & context_a); 364 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 365 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 366 | mu::llvmc::ast::node * function; 367 | }; 368 | class set : public mu::llvmc::ast::node 369 | { 370 | public: 371 | set (mu::llvmc::template_context * context_a = nullptr); 372 | set (mu::llvmc::ast::set const & other_a, mu::llvmc::clone_context & context_a); 373 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 374 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 375 | mu::vector nodes; 376 | }; 377 | class namespace_c : public mu::llvmc::ast::node 378 | { 379 | public: 380 | namespace_c (mu::string const & member_a, mu::llvmc::ast::node * node_a, mu::llvmc::template_context * context_a = nullptr); 381 | namespace_c (mu::llvmc::template_context * context_a = nullptr); 382 | namespace_c (mu::llvmc::ast::namespace_c const & other_a, mu::llvmc::clone_context & context_a); 383 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 384 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 385 | mu::string member; 386 | mu::llvmc::ast::node * node_m; 387 | }; 388 | class sequence : public mu::llvmc::ast::node 389 | { 390 | public: 391 | sequence (mu::llvmc::ast::node * = nullptr, mu::llvmc::template_context * context_a = nullptr); 392 | sequence (mu::llvmc::ast::sequence const & other_a, mu::llvmc::clone_context & context_a); 393 | mu::llvmc::ast::node * do_clone (mu::llvmc::clone_context & context_a) override; 394 | void visit (mu::llvmc::ast::visitor * visitor_a) override; 395 | bool is_sequenced () const override; 396 | mu::llvmc::ast::node * node_m; 397 | }; 398 | class visitor 399 | { 400 | public: 401 | void unexpected (mu::llvmc::ast::node *); 402 | virtual void node (mu::llvmc::ast::node *); 403 | virtual void fixed_array_type (mu::llvmc::ast::fixed_array_type *); 404 | virtual void array_type (mu::llvmc::ast::array_type *); 405 | virtual void constant_int (mu::llvmc::ast::constant_int *); 406 | virtual void integer_type (mu::llvmc::ast::integer_type *); 407 | virtual void pointer_type (mu::llvmc::ast::pointer_type *); 408 | virtual void constant_array (mu::llvmc::ast::constant_array *); 409 | virtual void global_variable (mu::llvmc::ast::global_variable *); 410 | virtual void expression (mu::llvmc::ast::expression *); 411 | virtual void constant_pointer_null (mu::llvmc::ast::constant_pointer_null *); 412 | virtual void join (mu::llvmc::ast::join *); 413 | virtual void loop (mu::llvmc::ast::loop *); 414 | virtual void unit (mu::llvmc::ast::unit *); 415 | virtual void asm_c (mu::llvmc::ast::asm_c *); 416 | virtual void value (mu::llvmc::ast::value *); 417 | virtual void module (mu::llvmc::ast::module *); 418 | virtual void number (mu::llvmc::ast::number *); 419 | virtual void element (mu::llvmc::ast::element *); 420 | virtual void function (mu::llvmc::ast::function *); 421 | virtual void unit_type (mu::llvmc::ast::unit_type *); 422 | virtual void loop_parameter (mu::llvmc::ast::loop_parameter *); 423 | virtual void parameter (mu::llvmc::ast::parameter *); 424 | virtual void struct_type (mu::llvmc::ast::struct_type *); 425 | virtual void undefined (mu::llvmc::ast::undefined *); 426 | virtual void template_c (mu::llvmc::ast::template_c *); 427 | virtual void template_parameter (mu::llvmc::ast::template_parameter *); 428 | virtual void entry (mu::llvmc::ast::entry *); 429 | virtual void set (mu::llvmc::ast::set *); 430 | virtual void namespace_c (mu::llvmc::ast::namespace_c *); 431 | virtual void sequence (mu::llvmc::ast::sequence *); 432 | virtual void function_family (mu::llvmc::ast::function_family *); 433 | virtual void function_overload (mu::llvmc::ast::function_overload *); 434 | }; 435 | } 436 | } 437 | } -------------------------------------------------------------------------------- /mu/llvmc/ast.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | mu::llvmc::ast::module::module (mu::llvmc::template_context * template_a) : 7 | node (template_a) 8 | { 9 | } 10 | 11 | mu::llvmc::ast::node::node (mu::llvmc::template_context * template_a) : 12 | template_m (template_a), 13 | assigned (false) 14 | { 15 | } 16 | 17 | mu::llvmc::ast::node::~node () 18 | { 19 | } 20 | 21 | mu::llvmc::ast::value::value (mu::llvmc::skeleton::node * node_a, mu::llvmc::template_context * template_a): 22 | node (template_a), 23 | node_m (node_a) 24 | { 25 | } 26 | 27 | mu::llvmc::ast::element::element (mu::llvmc::ast::node * node_a, size_t index_a, size_t total_a, mu::string const & name_a, mu::core::region const & region_a, mu::llvmc::template_context * template_a) : 28 | node (template_a), 29 | node_m (node_a), 30 | index (index_a), 31 | total (total_a), 32 | name (name_a) 33 | { 34 | region = region_a; 35 | } 36 | 37 | mu::llvmc::ast::parameter::parameter (mu::llvmc::template_context * template_a) : 38 | node (template_a) 39 | { 40 | } 41 | 42 | mu::llvmc::ast::parameter::parameter (mu::string const & name_a, mu::llvmc::ast::node * type_a, mu::llvmc::template_context * template_a) : 43 | node (template_a), 44 | type (type_a), 45 | name (name_a) 46 | { 47 | } 48 | 49 | mu::llvmc::ast::expression::expression (std::initializer_list arguments_a, mu::llvmc::template_context * template_a) : 50 | node (template_a) 51 | { 52 | arguments.insert (arguments.end (), arguments_a.begin (), arguments_a.end ()); 53 | } 54 | 55 | mu::llvmc::ast::integer_type::integer_type (mu::llvmc::template_context * template_a) : 56 | node (template_a), 57 | bits (nullptr) 58 | { 59 | } 60 | 61 | mu::llvmc::ast::pointer_type::pointer_type (mu::llvmc::ast::node * pointed_type_a, mu::llvmc::template_context * template_a) : 62 | node (template_a), 63 | pointed_type (pointed_type_a) 64 | { 65 | } 66 | 67 | mu::llvmc::ast::constant_int::constant_int (mu::llvmc::template_context * template_a) : 68 | node (template_a) 69 | { 70 | } 71 | 72 | mu::llvmc::ast::expression::expression (mu::llvmc::template_context * template_a) : 73 | node (template_a) 74 | { 75 | } 76 | 77 | mu::llvmc::ast::loop::loop (mu::llvmc::template_context * template_a) : 78 | node (template_a) 79 | { 80 | } 81 | 82 | mu::llvmc::ast::asm_c::asm_c (mu::llvmc::ast::node * type_a, mu::string const & text_a, mu::string const & constraints_a, mu::llvmc::template_context * template_a) : 83 | node (template_a), 84 | type (type_a), 85 | text (text_a), 86 | constraints (constraints_a) 87 | { 88 | } 89 | 90 | mu::llvmc::ast::fixed_array_type::fixed_array_type (mu::llvmc::ast::node * element_type_a, mu::llvmc::ast::node * size_a, mu::llvmc::template_context * template_a) : 91 | node (template_a), 92 | element_type (element_type_a), 93 | size (size_a) 94 | { 95 | } 96 | 97 | mu::llvmc::ast::global_variable::global_variable (mu::llvmc::ast::node * initializer_a, mu::llvmc::template_context * template_a) : 98 | node (template_a), 99 | initializer (initializer_a) 100 | { 101 | } 102 | 103 | mu::llvmc::ast::join_branch & mu::llvmc::ast::join::add_branch () 104 | { 105 | branches.push_back (decltype (branches)::value_type ()); 106 | auto & result (branches [branches.size () - 1]); 107 | return result; 108 | } 109 | 110 | void mu::llvmc::ast::visitor::unexpected (mu::llvmc::ast::node * node_a) 111 | { 112 | assert (false); 113 | } 114 | 115 | void mu::llvmc::ast::visitor::node (mu::llvmc::ast::node * node_a) 116 | { 117 | unexpected (node_a); 118 | } 119 | 120 | void mu::llvmc::ast::visitor::fixed_array_type (mu::llvmc::ast::fixed_array_type * node_a) 121 | { 122 | node (node_a); 123 | } 124 | 125 | void mu::llvmc::ast::visitor::constant_int (mu::llvmc::ast::constant_int * node_a) 126 | { 127 | node (node_a); 128 | } 129 | 130 | void mu::llvmc::ast::visitor::integer_type (mu::llvmc::ast::integer_type * node_a) 131 | { 132 | node (node_a); 133 | } 134 | 135 | void mu::llvmc::ast::visitor::pointer_type (mu::llvmc::ast::pointer_type * node_a) 136 | { 137 | node (node_a); 138 | } 139 | 140 | void mu::llvmc::ast::visitor::constant_array (mu::llvmc::ast::constant_array * node_a) 141 | { 142 | node (node_a); 143 | } 144 | 145 | void mu::llvmc::ast::visitor::global_variable (mu::llvmc::ast::global_variable * node_a) 146 | { 147 | node (node_a); 148 | } 149 | 150 | void mu::llvmc::ast::visitor::expression (mu::llvmc::ast::expression * node_a) 151 | { 152 | node (node_a); 153 | } 154 | 155 | void mu::llvmc::ast::visitor::constant_pointer_null (mu::llvmc::ast::constant_pointer_null * node_a) 156 | { 157 | node (node_a); 158 | } 159 | 160 | void mu::llvmc::ast::visitor::join (mu::llvmc::ast::join * node_a) 161 | { 162 | node (node_a); 163 | } 164 | 165 | void mu::llvmc::ast::visitor::loop (mu::llvmc::ast::loop * node_a) 166 | { 167 | node (node_a); 168 | } 169 | 170 | void mu::llvmc::ast::visitor::unit (mu::llvmc::ast::unit * node_a) 171 | { 172 | node (node_a); 173 | } 174 | 175 | void mu::llvmc::ast::visitor::asm_c (mu::llvmc::ast::asm_c * node_a) 176 | { 177 | node (node_a); 178 | } 179 | 180 | void mu::llvmc::ast::visitor::value (mu::llvmc::ast::value * node_a) 181 | { 182 | node (node_a); 183 | } 184 | 185 | void mu::llvmc::ast::visitor::module (mu::llvmc::ast::module * node_a) 186 | { 187 | node (node_a); 188 | } 189 | 190 | void mu::llvmc::ast::visitor::number (mu::llvmc::ast::number * node_a) 191 | { 192 | node (node_a); 193 | } 194 | 195 | void mu::llvmc::ast::visitor::element (mu::llvmc::ast::element * node_a) 196 | { 197 | node (node_a); 198 | } 199 | 200 | void mu::llvmc::ast::visitor::function (mu::llvmc::ast::function * node_a) 201 | { 202 | node (node_a); 203 | } 204 | 205 | void mu::llvmc::ast::visitor::unit_type (mu::llvmc::ast::unit_type * node_a) 206 | { 207 | node (node_a); 208 | } 209 | 210 | void mu::llvmc::ast::visitor::loop_parameter (mu::llvmc::ast::loop_parameter * node_a) 211 | { 212 | node (node_a); 213 | } 214 | 215 | void mu::llvmc::ast::visitor::parameter (mu::llvmc::ast::parameter * node_a) 216 | { 217 | node (node_a); 218 | } 219 | 220 | void mu::llvmc::ast::visitor::struct_type (mu::llvmc::ast::struct_type * node_a) 221 | { 222 | node (node_a); 223 | } 224 | 225 | void mu::llvmc::ast::visitor::undefined (mu::llvmc::ast::undefined * node_a) 226 | { 227 | node (node_a); 228 | } 229 | 230 | void mu::llvmc::ast::node::visit (mu::llvmc::ast::visitor * visitor_a) 231 | { 232 | visitor_a->node (this); 233 | } 234 | 235 | void mu::llvmc::ast::fixed_array_type::visit (mu::llvmc::ast::visitor * visitor_a) 236 | { 237 | visitor_a->fixed_array_type (this); 238 | } 239 | 240 | void mu::llvmc::ast::constant_int::visit (mu::llvmc::ast::visitor * visitor_a) 241 | { 242 | visitor_a->constant_int (this); 243 | } 244 | 245 | void mu::llvmc::ast::integer_type::visit (mu::llvmc::ast::visitor * visitor_a) 246 | { 247 | visitor_a->integer_type (this); 248 | } 249 | 250 | void mu::llvmc::ast::pointer_type::visit (mu::llvmc::ast::visitor * visitor_a) 251 | { 252 | visitor_a->pointer_type (this); 253 | } 254 | 255 | void mu::llvmc::ast::constant_array::visit (mu::llvmc::ast::visitor * visitor_a) 256 | { 257 | visitor_a->constant_array (this); 258 | } 259 | 260 | void mu::llvmc::ast::global_variable::visit (mu::llvmc::ast::visitor * visitor_a) 261 | { 262 | visitor_a->global_variable (this); 263 | } 264 | 265 | void mu::llvmc::ast::expression::visit (mu::llvmc::ast::visitor * visitor_a) 266 | { 267 | visitor_a->expression (this); 268 | } 269 | 270 | void mu::llvmc::ast::constant_pointer_null::visit (mu::llvmc::ast::visitor * visitor_a) 271 | { 272 | visitor_a->constant_pointer_null (this); 273 | } 274 | 275 | void mu::llvmc::ast::join::visit (mu::llvmc::ast::visitor * visitor_a) 276 | { 277 | visitor_a->join (this); 278 | } 279 | 280 | void mu::llvmc::ast::loop::visit (mu::llvmc::ast::visitor * visitor_a) 281 | { 282 | visitor_a->loop (this); 283 | } 284 | 285 | void mu::llvmc::ast::unit::visit (mu::llvmc::ast::visitor * visitor_a) 286 | { 287 | visitor_a->unit (this); 288 | } 289 | 290 | void mu::llvmc::ast::asm_c::visit (mu::llvmc::ast::visitor * visitor_a) 291 | { 292 | visitor_a->asm_c (this); 293 | } 294 | 295 | void mu::llvmc::ast::value::visit (mu::llvmc::ast::visitor * visitor_a) 296 | { 297 | visitor_a->value (this); 298 | } 299 | 300 | void mu::llvmc::ast::module::visit (mu::llvmc::ast::visitor * visitor_a) 301 | { 302 | visitor_a->module (this); 303 | } 304 | 305 | void mu::llvmc::ast::number::visit (mu::llvmc::ast::visitor * visitor_a) 306 | { 307 | visitor_a->number (this); 308 | } 309 | 310 | void mu::llvmc::ast::element::visit (mu::llvmc::ast::visitor * visitor_a) 311 | { 312 | visitor_a->element (this); 313 | } 314 | 315 | void mu::llvmc::ast::function::visit (mu::llvmc::ast::visitor * visitor_a) 316 | { 317 | visitor_a->function (this); 318 | } 319 | 320 | void mu::llvmc::ast::unit_type::visit (mu::llvmc::ast::visitor * visitor_a) 321 | { 322 | visitor_a->unit_type (this); 323 | } 324 | 325 | void mu::llvmc::ast::loop_parameter::visit (mu::llvmc::ast::visitor * visitor_a) 326 | { 327 | visitor_a->loop_parameter (this); 328 | } 329 | 330 | void mu::llvmc::ast::parameter::visit (mu::llvmc::ast::visitor * visitor_a) 331 | { 332 | visitor_a->parameter (this); 333 | } 334 | 335 | void mu::llvmc::ast::struct_type::visit (mu::llvmc::ast::visitor * visitor_a) 336 | { 337 | visitor_a->struct_type (this); 338 | } 339 | 340 | void mu::llvmc::ast::undefined::visit (mu::llvmc::ast::visitor * visitor_a) 341 | { 342 | visitor_a->undefined (this); 343 | } 344 | 345 | mu::llvmc::ast::loop_parameter::loop_parameter (mu::string const & name_a, mu::llvmc::template_context * template_a) : 346 | node (template_a), 347 | name (name_a) 348 | { 349 | } 350 | 351 | mu::llvmc::ast::node * mu::llvmc::ast::loop_parameter::do_clone (mu::llvmc::clone_context & context_a) 352 | { 353 | auto result (new mu::llvmc::ast::loop_parameter (*this)); 354 | return result; 355 | } 356 | 357 | mu::llvmc::ast::node * mu::llvmc::ast::module::do_clone (mu::llvmc::clone_context & context_a) 358 | { 359 | auto result (new mu::llvmc::ast::module (*this, context_a)); 360 | return result; 361 | } 362 | 363 | mu::llvmc::ast::node * mu::llvmc::ast::number::do_clone (mu::llvmc::clone_context & context_a) 364 | { 365 | auto result (new mu::llvmc::ast::number (*this, context_a)); 366 | return result; 367 | } 368 | 369 | mu::llvmc::ast::node * mu::llvmc::ast::function::do_clone (mu::llvmc::clone_context & context_a) 370 | { 371 | auto result (new mu::llvmc::ast::function (*this, context_a)); 372 | return result; 373 | } 374 | 375 | mu::llvmc::ast::node * mu::llvmc::ast::fixed_array_type::do_clone (mu::llvmc::clone_context & context_a) 376 | { 377 | auto result (new mu::llvmc::ast::fixed_array_type (*this, context_a)); 378 | return result; 379 | } 380 | 381 | mu::llvmc::ast::node * mu::llvmc::ast::struct_type::do_clone (mu::llvmc::clone_context & context_a) 382 | { 383 | auto result (new mu::llvmc::ast::struct_type (*this, context_a)); 384 | return result; 385 | } 386 | 387 | mu::llvmc::ast::node * mu::llvmc::ast::constant_int::do_clone (mu::llvmc::clone_context & context_a) 388 | { 389 | auto result (new mu::llvmc::ast::constant_int (*this, context_a)); 390 | return result; 391 | } 392 | 393 | mu::llvmc::ast::node * mu::llvmc::ast::integer_type::do_clone (mu::llvmc::clone_context & context_a) 394 | { 395 | auto result (new mu::llvmc::ast::integer_type (*this)); 396 | return result; 397 | } 398 | 399 | mu::llvmc::ast::node * mu::llvmc::ast::pointer_type::do_clone (mu::llvmc::clone_context & context_a) 400 | { 401 | auto result (new mu::llvmc::ast::pointer_type (*this, context_a)); 402 | return result; 403 | } 404 | 405 | mu::llvmc::ast::node * mu::llvmc::ast::constant_array::do_clone (mu::llvmc::clone_context & context_a) 406 | { 407 | auto result (new mu::llvmc::ast::constant_array (*this, context_a)); 408 | return result; 409 | } 410 | 411 | mu::llvmc::ast::node * mu::llvmc::ast::global_variable::do_clone (mu::llvmc::clone_context & context_a) 412 | { 413 | auto result (new mu::llvmc::ast::global_variable (*this, context_a)); 414 | return result; 415 | } 416 | 417 | mu::llvmc::ast::node * mu::llvmc::ast::expression::do_clone (mu::llvmc::clone_context & context_a) 418 | { 419 | auto result (new mu::llvmc::ast::expression (*this, context_a)); 420 | return result; 421 | } 422 | 423 | mu::llvmc::ast::node * mu::llvmc::ast::constant_pointer_null::do_clone (mu::llvmc::clone_context & context_a) 424 | { 425 | auto result (new mu::llvmc::ast::constant_pointer_null (*this, context_a)); 426 | return result; 427 | } 428 | 429 | mu::llvmc::ast::node * mu::llvmc::ast::join::do_clone (mu::llvmc::clone_context & context_a) 430 | { 431 | auto result (new mu::llvmc::ast::join (*this, context_a)); 432 | return result; 433 | } 434 | 435 | mu::llvmc::ast::node * mu::llvmc::ast::loop::do_clone (mu::llvmc::clone_context & context_a) 436 | { 437 | auto result (new mu::llvmc::ast::loop (*this, context_a)); 438 | return result; 439 | } 440 | 441 | mu::llvmc::ast::node * mu::llvmc::ast::unit::do_clone (mu::llvmc::clone_context & context_a) 442 | { 443 | auto result (new mu::llvmc::ast::unit (*this, context_a)); 444 | return result; 445 | } 446 | 447 | mu::llvmc::ast::node * mu::llvmc::ast::asm_c::do_clone (mu::llvmc::clone_context & context_a) 448 | { 449 | auto result (new mu::llvmc::ast::asm_c (*this, context_a)); 450 | return result; 451 | } 452 | 453 | mu::llvmc::ast::node * mu::llvmc::ast::value::do_clone (mu::llvmc::clone_context & context_a) 454 | { 455 | auto result (new mu::llvmc::ast::value (*this, context_a)); 456 | return result; 457 | } 458 | 459 | mu::llvmc::ast::node * mu::llvmc::ast::element::do_clone (mu::llvmc::clone_context & context_a) 460 | { 461 | auto result (new mu::llvmc::ast::element (*this, context_a)); 462 | return result; 463 | } 464 | 465 | mu::llvmc::ast::node * mu::llvmc::ast::parameter::do_clone (mu::llvmc::clone_context & context_a) 466 | { 467 | auto result (new mu::llvmc::ast::parameter (*this, context_a)); 468 | return result; 469 | } 470 | 471 | mu::llvmc::ast::node * mu::llvmc::ast::undefined::do_clone (mu::llvmc::clone_context & context_a) 472 | { 473 | auto result (new mu::llvmc::ast::undefined (*this, context_a)); 474 | return result; 475 | } 476 | 477 | mu::llvmc::ast::fixed_array_type::fixed_array_type (mu::llvmc::ast::fixed_array_type const & other_a, mu::llvmc::clone_context & context_a) : 478 | node (other_a.template_m), 479 | element_type (other_a.element_type->clone (context_a)), 480 | size (other_a.size->clone (context_a)) 481 | { 482 | } 483 | 484 | mu::llvmc::ast::struct_type::struct_type (mu::llvmc::ast::struct_type const & other_a, mu::llvmc::clone_context & context_a) : 485 | node (other_a.template_m), 486 | names (other_a.names) 487 | { 488 | for (auto i: other_a.elements) 489 | { 490 | elements.push_back (i->clone (context_a)); 491 | } 492 | } 493 | 494 | mu::llvmc::ast::constant_int::constant_int (mu::llvmc::ast::constant_int const & other_a, mu::llvmc::clone_context & context_a) : 495 | node (other_a.template_m) 496 | { 497 | } 498 | 499 | mu::llvmc::ast::integer_type::integer_type (mu::llvmc::ast::integer_type const & other_a) : 500 | node (other_a.template_m), 501 | bits (other_a.bits) 502 | { 503 | } 504 | 505 | mu::llvmc::ast::pointer_type::pointer_type (mu::llvmc::ast::pointer_type const & other_a, mu::llvmc::clone_context & context_a) : 506 | node (other_a.template_m), 507 | pointed_type (other_a.pointed_type->clone (context_a)) 508 | { 509 | } 510 | 511 | mu::llvmc::ast::constant_array::constant_array (mu::llvmc::ast::constant_array const & other_a, mu::llvmc::clone_context & context_a) : 512 | node (other_a.template_m), 513 | type (other_a.type->clone (context_a)) 514 | { 515 | for (auto i: other_a.initializer) 516 | { 517 | initializer.push_back (i->clone (context_a)); 518 | } 519 | } 520 | 521 | mu::llvmc::ast::loop_parameter::loop_parameter (mu::llvmc::ast::loop_parameter const & other_a) : 522 | node (other_a.template_m), 523 | name (other_a.name) 524 | { 525 | } 526 | 527 | mu::llvmc::ast::global_variable::global_variable (mu::llvmc::ast::global_variable const & other_a, mu::llvmc::clone_context & context_a) : 528 | node (other_a.template_m), 529 | initializer (other_a.initializer->clone (context_a)) 530 | { 531 | } 532 | 533 | mu::llvmc::ast::expression::expression (mu::llvmc::ast::expression const & other_a, mu::llvmc::clone_context & context_a) : 534 | node (other_a, context_a) 535 | { 536 | for (auto i: other_a.arguments) 537 | { 538 | arguments.push_back (i->clone (context_a)); 539 | } 540 | } 541 | 542 | mu::llvmc::ast::constant_pointer_null::constant_pointer_null (mu::llvmc::ast::constant_pointer_null const & other_a, mu::llvmc::clone_context & context_a) : 543 | node (other_a.template_m), 544 | type (other_a.type->clone (context_a)) 545 | { 546 | } 547 | 548 | mu::llvmc::ast::join::join (mu::llvmc::ast::join const & other_a, mu::llvmc::clone_context & context_a) : 549 | node (other_a.template_m) 550 | { 551 | for (auto & i: other_a.branches) 552 | { 553 | branches.push_back (mu::llvmc::ast::join_branch ()); 554 | auto & target (branches [branches.size () - 1]); 555 | for (auto j: i.arguments) 556 | { 557 | target.arguments.push_back (j->clone (context_a)); 558 | } 559 | for (auto j: i.predicates) 560 | { 561 | target.predicates.push_back (j->clone (context_a)); 562 | } 563 | } 564 | } 565 | 566 | mu::llvmc::ast::loop_result::loop_result (mu::llvmc::ast::loop_result const & other_a, mu::llvmc::clone_context & context_a) 567 | { 568 | for (auto i: other_a.nodes) 569 | { 570 | nodes.push_back (i->clone (context_a)); 571 | } 572 | } 573 | 574 | mu::llvmc::ast::loop::loop (mu::llvmc::ast::loop const & other_a, mu::llvmc::clone_context & context_a) : 575 | node (other_a.template_m) 576 | { 577 | for (auto i: other_a.arguments) 578 | { 579 | arguments.push_back (i->clone (context_a)); 580 | } 581 | for (auto i: other_a.parameters) 582 | { 583 | parameters.push_back (i->clone (context_a)); 584 | } 585 | for (auto i: other_a.roots) 586 | { 587 | roots.push_back (i->clone (context_a)); 588 | } 589 | for (auto i: other_a.results) 590 | { 591 | results.push_back (loop_result (i, context_a)); 592 | } 593 | } 594 | 595 | mu::llvmc::ast::asm_c::asm_c (mu::llvmc::ast::asm_c const & other_a, mu::llvmc::clone_context & context_a) : 596 | node (other_a.template_m), 597 | type (other_a.type->clone (context_a)), 598 | text (other_a.text), 599 | constraints (other_a.constraints) 600 | { 601 | } 602 | 603 | mu::llvmc::ast::module::module (mu::llvmc::ast::module const & other_a, mu::llvmc::clone_context & context_a) : 604 | node (other_a, context_a) 605 | { 606 | for (auto & i: other_a.globals) 607 | { 608 | globals.push_back (i->clone (context_a)); 609 | } 610 | for (auto & i: other_a.names) 611 | { 612 | names [i.first] = i.second->clone (context_a); 613 | } 614 | } 615 | 616 | mu::llvmc::ast::element::element (mu::llvmc::ast::element const & other_a, mu::llvmc::clone_context & context_a) : 617 | node (other_a, context_a), 618 | node_m (other_a.node_m->clone (context_a)), 619 | index (other_a.index), 620 | total (other_a.total), 621 | name (other_a.name) 622 | { 623 | } 624 | 625 | mu::llvmc::ast::function::function (mu::llvmc::ast::function const & other_a, mu::llvmc::clone_context & context_a) : 626 | node (other_a, context_a), 627 | results (other_a.results, context_a) 628 | { 629 | for (auto i: other_a.parameters) 630 | { 631 | parameters.push_back (i->clone (context_a)); 632 | } 633 | for (auto i: other_a.returns) 634 | { 635 | returns.push_back (decltype (returns)::value_type ()); 636 | for (auto j: i.types) 637 | { 638 | returns.back ().types.push_back (j->clone (context_a)); 639 | } 640 | } 641 | } 642 | 643 | mu::llvmc::ast::parameter::parameter (mu::llvmc::ast::parameter const & other_a, mu::llvmc::clone_context & context_a) : 644 | node (other_a.template_m), 645 | type (other_a.type->clone (context_a)), 646 | name (other_a.name) 647 | { 648 | } 649 | 650 | mu::llvmc::ast::undefined::undefined (mu::llvmc::ast::undefined const & other_a, mu::llvmc::clone_context & context_a) : 651 | node (other_a.template_m), 652 | type (other_a.type->clone (context_a)) 653 | { 654 | } 655 | 656 | mu::llvmc::ast::node * mu::llvmc::ast::node::clone (mu::llvmc::clone_context & context_a) 657 | { 658 | mu::llvmc::ast::node * result; 659 | auto existing (context_a.generated.find (this)); 660 | if (existing != context_a.generated.end ()) 661 | { 662 | result = existing->second; 663 | } 664 | else 665 | { 666 | assert (context_a.template_m != nullptr); 667 | if (context_a.template_m->should_clone (template_m)) 668 | { 669 | result = do_clone (context_a); 670 | context_a.generated [this] = result; 671 | } 672 | else 673 | { 674 | result = this; 675 | } 676 | } 677 | return result; 678 | } 679 | 680 | mu::llvmc::ast::node * mu::llvmc::ast::node::do_clone (mu::llvmc::clone_context & context_a) 681 | { 682 | auto result (new mu::llvmc::ast::node (*this, context_a)); 683 | return result; 684 | } 685 | 686 | mu::llvmc::ast::node::node (mu::llvmc::ast::node const & other_a, mu::llvmc::clone_context & context_a) : 687 | template_m (other_a.template_m), 688 | region (other_a.region) 689 | { 690 | } 691 | 692 | mu::llvmc::ast::unit_type::unit_type (mu::llvmc::ast::unit_type const & other_a) : 693 | node (other_a.template_m) 694 | { 695 | } 696 | 697 | mu::llvmc::ast::node * mu::llvmc::ast::unit_type::do_clone (mu::llvmc::clone_context & context_a) 698 | { 699 | auto result (new mu::llvmc::ast::unit_type (*this)); 700 | return result; 701 | } 702 | 703 | mu::llvmc::ast::unit_type::unit_type (mu::llvmc::template_context * template_a) : 704 | node (template_a) 705 | { 706 | } 707 | 708 | mu::llvmc::ast::template_parameter::template_parameter (mu::string const & name_a, mu::llvmc::template_context * template_a) : 709 | node (template_a), 710 | name (name_a) 711 | { 712 | } 713 | 714 | mu::llvmc::ast::template_c::template_c (mu::llvmc::ast::template_c const & other_a, mu::llvmc::clone_context & context_a) : 715 | node (other_a.template_m), 716 | base (other_a.base) 717 | { 718 | for (auto i: other_a.parameters) 719 | { 720 | parameters.push_back (i->clone (context_a)); 721 | } 722 | for (auto i: other_a.body) 723 | { 724 | body.push_back (i->clone (context_a)); 725 | } 726 | } 727 | 728 | mu::llvmc::ast::template_parameter::template_parameter (mu::llvmc::ast::template_parameter const & other_a, mu::llvmc::clone_context & context_a) : 729 | node (other_a.template_m), 730 | argument (other_a.argument), 731 | name (other_a.name) 732 | { 733 | } 734 | 735 | void mu::llvmc::ast::template_parameter::visit (mu::llvmc::ast::visitor * visitor_a) 736 | { 737 | visitor_a->template_parameter (this); 738 | } 739 | 740 | void mu::llvmc::ast::template_c::visit (mu::llvmc::ast::visitor * visitor_a) 741 | { 742 | visitor_a->template_c (this); 743 | } 744 | 745 | void mu::llvmc::ast::visitor::template_c (mu::llvmc::ast::template_c * node_a) 746 | { 747 | node (node_a); 748 | } 749 | 750 | void mu::llvmc::ast::visitor::template_parameter (mu::llvmc::ast::template_parameter * node_a) 751 | { 752 | node (node_a); 753 | } 754 | 755 | mu::llvmc::ast::node * mu::llvmc::ast::template_parameter::do_clone (mu::llvmc::clone_context & context_a) 756 | { 757 | auto result (new mu::llvmc::ast::template_parameter (*this, context_a)); 758 | return result; 759 | } 760 | 761 | mu::llvmc::ast::node * mu::llvmc::ast::template_c::do_clone (mu::llvmc::clone_context & context_a) 762 | { 763 | auto result (new mu::llvmc::ast::template_c (*this, context_a)); 764 | return result; 765 | } 766 | 767 | mu::llvmc::ast::number::number (mu::llvmc::ast::number const & other_a, mu::llvmc::clone_context & context_a) : 768 | node (other_a.template_m), 769 | number_m (other_a.number_m) 770 | { 771 | } 772 | 773 | mu::llvmc::ast::unit::unit (mu::llvmc::ast::unit const & other_a, mu::llvmc::clone_context & context_a) : 774 | node (other_a.template_m) 775 | { 776 | } 777 | 778 | mu::llvmc::ast::value::value (mu::llvmc::ast::value const & other_a, mu::llvmc::clone_context & context_a) : 779 | node (other_a.template_m), 780 | node_m (other_a.node_m) 781 | { 782 | } 783 | 784 | mu::llvmc::ast::entry::entry (mu::llvmc::ast::entry const & other_a, mu::llvmc::clone_context & context_a) : 785 | node (other_a.template_m), 786 | function (other_a.function->clone (context_a)) 787 | { 788 | } 789 | 790 | mu::llvmc::ast::node * mu::llvmc::ast::entry::do_clone (mu::llvmc::clone_context & context_a) 791 | { 792 | auto result (new mu::llvmc::ast::entry (*this, context_a)); 793 | return result; 794 | } 795 | 796 | void mu::llvmc::ast::entry::visit (mu::llvmc::ast::visitor * visitor_a) 797 | { 798 | visitor_a->entry (this); 799 | } 800 | 801 | void mu::llvmc::ast::visitor::entry (mu::llvmc::ast::entry * node_a) 802 | { 803 | node (node_a); 804 | } 805 | 806 | mu::llvmc::ast::set::set (mu::llvmc::ast::set const & other_a, mu::llvmc::clone_context & context_a) : 807 | node (other_a, context_a) 808 | { 809 | for (auto i: other_a.nodes) 810 | { 811 | nodes.push_back (i->clone (context_a)); 812 | } 813 | } 814 | 815 | mu::llvmc::ast::node * mu::llvmc::ast::set::do_clone (mu::llvmc::clone_context & context_a) 816 | { 817 | auto result (new mu::llvmc::ast::set (*this, context_a)); 818 | return result; 819 | } 820 | 821 | void mu::llvmc::ast::set::visit (mu::llvmc::ast::visitor * visitor_a) 822 | { 823 | visitor_a->set (this); 824 | } 825 | 826 | void mu::llvmc::ast::visitor::set (mu::llvmc::ast::set * node_a) 827 | { 828 | node (node_a); 829 | } 830 | 831 | mu::llvmc::ast::fixed_array_type::fixed_array_type (mu::llvmc::template_context * context_a) : 832 | node (context_a) 833 | { 834 | } 835 | 836 | mu::llvmc::ast::template_c::template_c (mu::llvmc::template_context * base_a, mu::llvmc::template_context * context_a) : 837 | node (context_a), 838 | base (base_a) 839 | { 840 | assert (base_a != nullptr); 841 | } 842 | 843 | mu::llvmc::ast::struct_type::struct_type (mu::llvmc::template_context * context_a) : 844 | node (context_a) 845 | { 846 | } 847 | 848 | mu::llvmc::ast::pointer_type::pointer_type (mu::llvmc::template_context * context_a) : 849 | node (context_a) 850 | { 851 | } 852 | 853 | mu::llvmc::ast::constant_array::constant_array (mu::llvmc::template_context * context_a) : 854 | node (context_a) 855 | { 856 | } 857 | 858 | mu::llvmc::ast::global_variable::global_variable (mu::llvmc::template_context * context_a) : 859 | node (context_a) 860 | { 861 | } 862 | 863 | mu::llvmc::ast::constant_pointer_null::constant_pointer_null (mu::llvmc::template_context * context_a) : 864 | node (context_a) 865 | { 866 | } 867 | 868 | mu::llvmc::ast::set::set (mu::llvmc::template_context * context_a) : 869 | node (context_a) 870 | { 871 | } 872 | 873 | mu::llvmc::ast::join::join (mu::llvmc::template_context * context_a) : 874 | node (context_a) 875 | { 876 | } 877 | 878 | mu::llvmc::ast::unit::unit (mu::llvmc::template_context * context_a) : 879 | node (context_a) 880 | { 881 | } 882 | 883 | mu::llvmc::ast::asm_c::asm_c (mu::llvmc::template_context * context_a) : 884 | node (context_a) 885 | { 886 | } 887 | 888 | mu::llvmc::ast::entry::entry (mu::llvmc::template_context * context_a) : 889 | node (context_a) 890 | { 891 | } 892 | 893 | mu::llvmc::ast::function::function (mu::llvmc::template_context * context_a) : 894 | node (context_a) 895 | { 896 | } 897 | 898 | mu::llvmc::ast::undefined::undefined (mu::llvmc::template_context * context_a) : 899 | node (context_a) 900 | { 901 | } 902 | 903 | mu::llvmc::clone_context::clone_context (mu::llvmc::template_context * template_a) : 904 | template_m (template_a) 905 | { 906 | } 907 | 908 | mu::llvmc::ast::namespace_c::namespace_c (mu::llvmc::template_context * context_a) : 909 | node (context_a) 910 | { 911 | } 912 | 913 | mu::llvmc::ast::namespace_c::namespace_c (mu::llvmc::ast::namespace_c const & other_a, mu::llvmc::clone_context & context_a) : 914 | node (other_a.template_m), 915 | member (other_a.member), 916 | node_m (other_a.node_m->clone (context_a)) 917 | { 918 | } 919 | 920 | mu::llvmc::ast::node * mu::llvmc::ast::namespace_c::do_clone (mu::llvmc::clone_context & context_a) 921 | { 922 | auto result (new mu::llvmc::ast::namespace_c (*this, context_a)); 923 | return result; 924 | } 925 | 926 | void mu::llvmc::ast::namespace_c::visit (mu::llvmc::ast::visitor * visitor_a) 927 | { 928 | visitor_a->namespace_c (this); 929 | } 930 | 931 | void mu::llvmc::ast::visitor::namespace_c (mu::llvmc::ast::namespace_c * node_a) 932 | { 933 | node (node_a); 934 | } 935 | 936 | mu::llvmc::ast::namespace_c::namespace_c (mu::string const & member_a, mu::llvmc::ast::node * node_a, mu::llvmc::template_context * context_a) : 937 | node (context_a), 938 | member (member_a), 939 | node_m (node_a) 940 | { 941 | } 942 | 943 | mu::llvmc::ast::array_type::array_type (mu::llvmc::template_context * template_a) : 944 | node (template_a) 945 | { 946 | } 947 | 948 | mu::llvmc::ast::array_type::array_type (mu::llvmc::ast::array_type const & other_a, mu::llvmc::clone_context & context_a) : 949 | node (other_a.template_m), 950 | element_type (other_a.element_type->clone (context_a)) 951 | { 952 | } 953 | 954 | mu::llvmc::ast::array_type::array_type (mu::llvmc::ast::node * element_type_a, mu::llvmc::template_context * template_a) : 955 | node (template_a), 956 | element_type (element_type_a) 957 | { 958 | 959 | } 960 | 961 | mu::llvmc::ast::node * mu::llvmc::ast::array_type::do_clone (mu::llvmc::clone_context & context_a) 962 | { 963 | auto result (new mu::llvmc::ast::array_type (*this, context_a)); 964 | return result; 965 | } 966 | 967 | void mu::llvmc::ast::array_type::visit (mu::llvmc::ast::visitor * visitor_a) 968 | { 969 | visitor_a->array_type (this); 970 | } 971 | 972 | void mu::llvmc::ast::visitor::array_type (mu::llvmc::ast::array_type * node_a) 973 | { 974 | node (node_a); 975 | } 976 | 977 | mu::llvmc::ast::sequence::sequence (mu::llvmc::ast::node * node_a, mu::llvmc::template_context * context_a) : 978 | node (context_a), 979 | node_m (node_a) 980 | { 981 | } 982 | 983 | mu::llvmc::ast::sequence::sequence (mu::llvmc::ast::sequence const & other_a, mu::llvmc::clone_context & context_a) : 984 | node (other_a.template_m), 985 | node_m (other_a.node_m->clone (context_a)) 986 | { 987 | } 988 | 989 | mu::llvmc::ast::node * mu::llvmc::ast::sequence::do_clone (mu::llvmc::clone_context & context_a) 990 | { 991 | auto result (new mu::llvmc::ast::sequence (*this, context_a)); 992 | return result; 993 | } 994 | 995 | void mu::llvmc::ast::sequence::visit (mu::llvmc::ast::visitor * visitor_a) 996 | { 997 | visitor_a->sequence (this); 998 | } 999 | 1000 | void mu::llvmc::ast::visitor::sequence (mu::llvmc::ast::sequence * node_a) 1001 | { 1002 | node (node_a); 1003 | } 1004 | 1005 | mu::llvmc::ast::function_branch::function_branch (std::initializer_list const & nodes_a) : 1006 | nodes (nodes_a) 1007 | { 1008 | } 1009 | 1010 | mu::llvmc::ast::function_result::function_result (std::initializer_list const & branches_a) : 1011 | branches (branches_a) 1012 | { 1013 | } 1014 | 1015 | mu::llvmc::ast::function_result::function_result (mu::llvmc::ast::function_result const & other_a, mu::llvmc::clone_context & context_a) 1016 | { 1017 | for (auto i: other_a.branches) 1018 | { 1019 | branches.push_back (mu::llvmc::ast::function_branch (i, context_a)); 1020 | } 1021 | } 1022 | 1023 | mu::llvmc::ast::function_branch::function_branch (mu::llvmc::ast::function_branch const & other_a, mu::llvmc::clone_context & context_a) 1024 | { 1025 | for (auto i: other_a.nodes) 1026 | { 1027 | nodes.push_back (i->clone (context_a)); 1028 | } 1029 | } 1030 | 1031 | mu::llvmc::ast::function_branch & mu::llvmc::ast::function_result::add_branch () 1032 | { 1033 | branches.push_back (mu::llvmc::ast::function_branch ()); 1034 | return branches.back (); 1035 | } 1036 | 1037 | bool mu::llvmc::ast::node::is_sequenced () const 1038 | { 1039 | return false; 1040 | } 1041 | 1042 | bool mu::llvmc::ast::sequence::is_sequenced () const 1043 | { 1044 | return true; 1045 | } 1046 | 1047 | mu::llvmc::ast::loop_result & mu::llvmc::ast::loop::add_branch () 1048 | { 1049 | results.push_back (mu::llvmc::ast::loop_result ()); 1050 | return results.back (); 1051 | } 1052 | 1053 | mu::llvmc::ast::loop_result::loop_result (std::initializer_list const & list_a) : 1054 | nodes (list_a) 1055 | { 1056 | } 1057 | 1058 | mu::llvmc::ast::loop::loop (std::initializer_list const & list_a, mu::llvmc::template_context * template_a) : 1059 | node (template_a), 1060 | arguments (list_a) 1061 | { 1062 | } 1063 | 1064 | mu::llvmc::ast::function_family::function_family (mu::llvmc::template_context * template_a) : 1065 | node (template_a) 1066 | { 1067 | } 1068 | 1069 | mu::llvmc::ast::function_family::function_family (mu::llvmc::ast::function_family const & other_a, mu::llvmc::clone_context & context_a) : 1070 | node (other_a.template_m) 1071 | { 1072 | } 1073 | 1074 | mu::llvmc::ast::node * mu::llvmc::ast::function_family::do_clone (mu::llvmc::clone_context & context_a) 1075 | { 1076 | return new mu::llvmc::ast::function_family (*this, context_a); 1077 | } 1078 | 1079 | void mu::llvmc::ast::function_family::visit (mu::llvmc::ast::visitor * visitor_a) 1080 | { 1081 | visitor_a->function_family (this); 1082 | } 1083 | 1084 | void mu::llvmc::ast::visitor::function_family (mu::llvmc::ast::function_family * node_a) 1085 | { 1086 | node (node_a); 1087 | } 1088 | 1089 | mu::llvmc::ast::function_overload::function_overload (mu::llvmc::template_context * template_a) 1090 | { 1091 | } 1092 | 1093 | mu::llvmc::ast::function_overload::function_overload (mu::llvmc::ast::function_overload const & other_a, mu::llvmc::clone_context & context_a) : 1094 | family (other_a.family->clone (context_a)), 1095 | function (other_a.function->clone (context_a)) 1096 | { 1097 | } 1098 | 1099 | mu::llvmc::ast::node * mu::llvmc::ast::function_overload::do_clone (mu::llvmc::clone_context & context_a) 1100 | { 1101 | return new mu::llvmc::ast::function_overload (*this, context_a); 1102 | } 1103 | 1104 | void mu::llvmc::ast::function_overload::visit (mu::llvmc::ast::visitor * visitor_a) 1105 | { 1106 | visitor_a->function_overload (this); 1107 | } 1108 | 1109 | void mu::llvmc::ast::visitor::function_overload (mu::llvmc::ast::function_overload * node_a) 1110 | { 1111 | node (node_a); 1112 | } 1113 | 1114 | mu::llvmc::ast::function_return::function_return (std::initializer_list const & types_a) : 1115 | types (types_a) 1116 | { 1117 | } --------------------------------------------------------------------------------