diff --git a/src/compiler.cpp b/src/compiler.cpp index 95094b3..9b8a9a6 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -5,6 +5,8 @@ global_variable Slice environment; fn void compile(Arena* arena, Options options) { Module module; + save_time(TimeId::start, &module, CounterId::initialization); + auto start_time = module.counters[(u64)CounterId::initialization].start; auto base_allocation_type_count = i128_offset + // 64 * 2 for basic integer types 2 + // u128, s128 2; // void, noreturn @@ -132,7 +134,12 @@ fn void compile(Arena* arena, Options options) }; } + module.counters[(u64)CounterId::initialization].start = start_time; + save_time(TimeId::end, &module, CounterId::initialization); + + save_time(TimeId::start, &module, CounterId::parsing); parse(&module); + save_time(TimeId::end, &module, CounterId::parsing); emit(&module); } diff --git a/src/compiler.hpp b/src/compiler.hpp index 56962e0..7edba17 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #define report_error() trap() @@ -1302,6 +1303,26 @@ struct Definition String value; }; +struct Counter +{ + struct timespec start; + struct timespec end; +}; + +enum class CounterId +{ + initialization, + parsing, + llvm_initialization_global, + llvm_initialization_local, + semantic_analysis, + verification, + optimization, + emit_object, + link, + count, +}; + struct Module { Arena* arena; @@ -1343,12 +1364,25 @@ struct Module bool link_libc = true; bool link_libcpp = false; + Counter counters[(u64)CounterId::count]; + Target target; BuildMode build_mode; bool has_debug_info; bool silent; }; +enum class TimeId +{ + start, + end, +}; + +fn void save_time(TimeId time_id, Module* module, CounterId counter_id) +{ + clock_gettime(CLOCK_MONOTONIC, &module->counters[(u64)counter_id].start + (s64)time_id); +} + constexpr u64 i128_offset = 64 * 2; constexpr u64 void_offset = i128_offset + 2; diff --git a/src/emitter.cpp b/src/emitter.cpp index 48c1448..e3fef83 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -384,7 +384,10 @@ fn LLVMCallConv llvm_calling_convention(CallingConvention calling_convention) fn void llvm_initialize(Module* module) { + save_time(TimeId::start, module, CounterId::llvm_initialization_global); llvm_initialize_all(); + save_time(TimeId::end, module, CounterId::llvm_initialization_global); + save_time(TimeId::start, module, CounterId::llvm_initialization_local); auto context = LLVMContextCreate(); auto m = LLVMModuleCreateWithNameInContext((char*)module->name.pointer, context); @@ -502,6 +505,7 @@ fn void llvm_initialize(Module* module) assert(attribute_id != 0); module->llvm.attribute_table[i].n = attribute_id; } + save_time(TimeId::end, module, CounterId::llvm_initialization_local); } enum class AbiSystemVClass @@ -9168,10 +9172,11 @@ struct ObjectGenerate bool has_debug_info; }; -fn BBLLVMCodeGenerationPipelineResult generate_object(LLVMModuleRef module, LLVMTargetMachineRef target_machine, ObjectGenerate options) +fn BBLLVMCodeGenerationPipelineResult generate_object(Module* module, LLVMTargetMachineRef target_machine, ObjectGenerate options) { if (options.run_optimization_passes) { + save_time(TimeId::start, module, CounterId::optimization); // BBLLVM bool prefer_speed = options.optimization_level == BBLLVMOptimizationLevel::O2 || options.optimization_level == BBLLVMOptimizationLevel::O3; BBLLVMOptimizationPipelineOptions optimization_options = { @@ -9187,16 +9192,20 @@ fn BBLLVMCodeGenerationPipelineResult generate_object(LLVMModuleRef module, LLVM .assignment_tracking = options.has_debug_info, .verify_module = true, }; - llvm_module_run_optimization_pipeline(module, target_machine, optimization_options); + llvm_module_run_optimization_pipeline(module->llvm.module, target_machine, optimization_options); + save_time(TimeId::end, module, CounterId::optimization); + // BBLLVM } + save_time(TimeId::start, module, CounterId::emit_object); BBLLVMCodeGenerationPipelineOptions code_generation_options = { .output_file_path = options.path, .file_type = BBLLVMCodeGenerationFileType::object_file, .optimize_when_possible = options.optimization_level > BBLLVMOptimizationLevel::O0, .verify_module = true, }; - auto result = llvm_module_run_code_generation_pipeline(module, target_machine, &code_generation_options); + auto result = llvm_module_run_code_generation_pipeline(module->llvm.module, target_machine, &code_generation_options); + save_time(TimeId::end, module, CounterId::emit_object); return result; } @@ -9325,8 +9334,11 @@ void emit(Module* module) assert(!module->current_function); assert(!module->current_macro_instantiation); assert(!module->current_macro_declaration); + llvm_initialize(module); + save_time(TimeId::start, module, CounterId::semantic_analysis); + for (auto* global = module->first_global; global; global = global->next) { assert(!module->current_function); @@ -10003,6 +10015,9 @@ void emit(Module* module) LLVMDIBuilderFinalize(module->llvm.di_builder); } + save_time(TimeId::end, module, CounterId::semantic_analysis); + + save_time(TimeId::start, module, CounterId::verification); char* verification_error_message = 0; auto result = LLVMVerifyModule(module->llvm.module, LLVMReturnStatusAction, &verification_error_message) == 0; if (!result) @@ -10012,6 +10027,7 @@ void emit(Module* module) print(c_string_to_slice(verification_error_message)); bb_fail(); } + save_time(TimeId::end, module, CounterId::verification); if (!module->silent) { @@ -10043,7 +10059,7 @@ void emit(Module* module) case BuildMode::count: unreachable(); } - auto object_generation_result = generate_object(module->llvm.module, module->llvm.target_machine, { + auto object_generation_result = generate_object(module, module->llvm.target_machine, { .path = module->objects[0], .optimization_level = optimization_level, .run_optimization_passes = module->build_mode != BuildMode::debug_none, @@ -10054,5 +10070,34 @@ void emit(Module* module) report_error(); } + save_time(TimeId::start, module, CounterId::link); link(module); + save_time(TimeId::end, module, CounterId::link); + + struct timespec res_ts; + clock_getres(CLOCK_MONOTONIC, &res_ts); + + auto res_ns = res_ts.tv_nsec + (res_ts.tv_sec * 1000 * 1000 * 1000); + + u64 times[(u64)CounterId::count]; + for (u64 i = 0; i < (u64)CounterId::count; i += 1) + { + auto& start = module->counters[i].start; + auto& end = module->counters[i].end; + + auto ns = end.tv_nsec - start.tv_nsec; + auto s = end.tv_sec - start.tv_sec; + + if (ns < 0) + { + s -= 1; + ns += 1000 * 1000 * 1000; + } + + ns = ns + (s * 1000 * 1000 * 1000); + + times[i] = ns; + } + + trap(); }