diff --git a/src/Arguments.cpp b/src/Arguments.cpp index 2a3644a..d49428f 100644 --- a/src/Arguments.cpp +++ b/src/Arguments.cpp @@ -1,6 +1,7 @@ #include "Arguments.h" #include "Error.h" #include "tclap/CmdLine.h" +#include "utils.h" #include "llvm/Support/Host.h" std::string Arguments::input_fname; @@ -11,6 +12,7 @@ std::string Arguments::cpu; void Arguments::parse(int argc, char** argv) { + __benchmark_impl::init(); try { TCLAP::CmdLine command_line("The Sapphire compiler.", ' ', "0.1"); @@ -23,9 +25,12 @@ void Arguments::parse(int argc, char** argv) TCLAP::ValueArg msystem_arg("", "msystem", "Operating System to compile for.", false, "native", "string"); + TCLAP::SwitchArg mprofile_arg("", "mprofile", "Show execution times for functions."); + TCLAP::SwitchArg wimport_arg("", "wimport", "Show a warning when trying to import an already imported file."); command_line.add(wimport_arg); + command_line.add(mprofile_arg); command_line.add(input_fname_arg); command_line.add(output_fname_arg); @@ -43,6 +48,8 @@ void Arguments::parse(int argc, char** argv) cpu = mcpu_arg.getValue(); setTriple(march_arg.getValue(), msystem_arg.getValue()); + + if (mprofile_arg.getValue()) __benchmark_impl::enable(); } catch (TCLAP::ArgException& e) { diff --git a/src/Importer.cpp b/src/Importer.cpp index b37e7e8..c332f8c 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -3,6 +3,7 @@ #include "Error.h" #include "FileIO.h" #include "sapphirepch.h" +#include "utils.h" #include #define MAX_IMPORTS 100 @@ -13,6 +14,7 @@ std::vector Importer::imported_files; TokenStream Importer::evaluate(const TokenStream& original) { + benchmark(); int i = 0; auto ret_tk = original; TokenStream new_tokens; diff --git a/src/Lexer.cpp b/src/Lexer.cpp index 4863114..fe4c84b 100644 --- a/src/Lexer.cpp +++ b/src/Lexer.cpp @@ -1,5 +1,6 @@ #include "Lexer.h" #include "Error.h" +#include "utils.h" #define WHITESPACE "\t \n" #define LETTERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ_" @@ -76,6 +77,7 @@ bool Lexer::is_in_string(const std::string& string, const char& character) TokenStream Lexer::lex(const std::string& text) { + benchmark(); TokenStream result; bool comment = false; current_lexed_text = text; diff --git a/src/Normalizer.cpp b/src/Normalizer.cpp index 2b69d27..baa2e25 100644 --- a/src/Normalizer.cpp +++ b/src/Normalizer.cpp @@ -1,81 +1,83 @@ #include "Normalizer.h" +#include "utils.h" TokenStream Normalizer::normalize(const TokenStream& input) { - TokenStream result; - int i = 0; - while (i < input.size()) - { - Token current = input[i]; - if (current.tk_type == TT_Null) - { - i++; - continue; - } - if (current.tk_type == TT_Equal) - { - if (i + 1 != input.size()) - { - if (input[i + 1].tk_type == TT_Equal) - { - i += 2; - result.push_back(current.copy_with_new_type(TT_Equals)); - continue; - } - } - i++; - result.push_back(current); - continue; - } - if (current.tk_type == TT_Exclamation) - { - if (i + 1 != input.size()) - { - if (input[i + 1].tk_type == TT_Equal) - { - i += 2; - result.push_back(current.copy_with_new_type(TT_NEqual)); - continue; - } - } - i++; - result.push_back(current); - continue; - } - if (current.tk_type == TT_GreaterThan) - { - if (i + 1 != input.size()) - { - if (input[i + 1].tk_type == TT_Equal) - { - i += 2; - result.push_back(current.copy_with_new_type(TT_GTE)); - continue; - } - } - i++; - result.push_back(current); - continue; - } - if (current.tk_type == TT_LessThan) - { - if (i + 1 != input.size()) - { - if (input[i + 1].tk_type == TT_Equal) - { - i += 2; - result.push_back(current.copy_with_new_type(TT_LTE)); - continue; - } - } - i++; - result.push_back(current); - continue; - } - i++; - result.push_back(current); - continue; - } + benchmark(); + TokenStream result; + int i = 0; + while (i < input.size()) + { + Token current = input[i]; + if (current.tk_type == TT_Null) + { + i++; + continue; + } + if (current.tk_type == TT_Equal) + { + if (i + 1 != input.size()) + { + if (input[i + 1].tk_type == TT_Equal) + { + i += 2; + result.push_back(current.copy_with_new_type(TT_Equals)); + continue; + } + } + i++; + result.push_back(current); + continue; + } + if (current.tk_type == TT_Exclamation) + { + if (i + 1 != input.size()) + { + if (input[i + 1].tk_type == TT_Equal) + { + i += 2; + result.push_back(current.copy_with_new_type(TT_NEqual)); + continue; + } + } + i++; + result.push_back(current); + continue; + } + if (current.tk_type == TT_GreaterThan) + { + if (i + 1 != input.size()) + { + if (input[i + 1].tk_type == TT_Equal) + { + i += 2; + result.push_back(current.copy_with_new_type(TT_GTE)); + continue; + } + } + i++; + result.push_back(current); + continue; + } + if (current.tk_type == TT_LessThan) + { + if (i + 1 != input.size()) + { + if (input[i + 1].tk_type == TT_Equal) + { + i += 2; + result.push_back(current.copy_with_new_type(TT_LTE)); + continue; + } + } + i++; + result.push_back(current); + continue; + } + i++; + result.push_back(current); + continue; + } - return result; + return result; } \ No newline at end of file diff --git a/src/sapphirepch.h b/src/sapphirepch.h index 847a6db..0b0ebac 100644 --- a/src/sapphirepch.h +++ b/src/sapphirepch.h @@ -3,4 +3,5 @@ #include #include #include +#include #include \ No newline at end of file diff --git a/src/utils.cpp b/src/utils.cpp index 18b5452..55ff7b0 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -21,4 +21,42 @@ std::string to_string(const float& value) std::ostringstream result; result << value; return result.str(); -} \ No newline at end of file +} + +__benchmark_impl::__benchmark_impl(std::string_view __function_name) : m_FunctionName(__function_name) +{ + m_InternalBenchmarkingEnabled = m_BenchmarkingEnabled; + if (!m_BenchmarkingEnabled) return; + m_StartTimePoint = std::chrono::high_resolution_clock::now(); +} + +__benchmark_impl::~__benchmark_impl() +{ + if (!m_InternalBenchmarkingEnabled) return; + auto endTimePoint = std::chrono::high_resolution_clock::now(); + auto start = std::chrono::time_point_cast(m_StartTimePoint).time_since_epoch().count(); + auto end = std::chrono::time_point_cast(endTimePoint).time_since_epoch().count(); + auto duration = end - start; + + double ms = duration * 0.001; + + std::cout << "(profile) " << m_FunctionName << " took " << duration << "us (" << ms << "ms) to execute." + << std::endl; +} + +void __benchmark_impl::init() +{ + disable(); +} + +void __benchmark_impl::disable() +{ + m_BenchmarkingEnabled = false; +} + +void __benchmark_impl::enable() +{ + m_BenchmarkingEnabled = true; +} + +bool __benchmark_impl::m_BenchmarkingEnabled; \ No newline at end of file diff --git a/src/utils.h b/src/utils.h index fd7eec9..6f6cdd3 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,6 +1,7 @@ #pragma once #include "FormatString/FormatString.hpp" #include "sapphirepch.h" +#include /* Simple function to replace a substring in a string. */ bool replace(std::string& str, const std::string& from, const std::string& to); @@ -9,4 +10,26 @@ bool replace(std::string& str, const std::string& from, const std::string& to); std::string to_string(const int& value); /* Easy way of converting a float to a string without writing 5 lines of code every time you want to do it. */ -std::string to_string(const float& value); \ No newline at end of file +std::string to_string(const float& value); + +/* Benchmarking utilities. */ + +class __benchmark_impl +{ + public: + __benchmark_impl(std::string_view __function_name); + ~__benchmark_impl(); + + static void enable(); + static void disable(); + + static void init(); + + private: + std::chrono::time_point m_StartTimePoint; + std::string_view m_FunctionName; + static bool m_BenchmarkingEnabled; + bool m_InternalBenchmarkingEnabled; +}; + +#define benchmark() __benchmark_impl __benchmark_impl_timer(__PRETTY_FUNCTION__) \ No newline at end of file