#pragma once #include #define CommandF(F) \ F(compile),\ F(test), ENUM(Command, u8, CommandF); #define BuildModeF(F) \ F(debug_none),\ F(debug),\ F(soft_optimize),\ F(optimize_for_speed),\ F(optimize_for_size),\ F(aggressively_optimize_for_speed),\ F(aggressively_optimize_for_size), ENUM(BuildMode, u8, BuildModeF); fn String build_mode_to_string(BuildMode build_mode) { switch (build_mode) { case_to_name(BuildMode, debug_none); case_to_name(BuildMode, debug); case_to_name(BuildMode, soft_optimize); case_to_name(BuildMode, optimize_for_speed); case_to_name(BuildMode, optimize_for_size); case_to_name(BuildMode, aggressively_optimize_for_speed); case_to_name(BuildMode, aggressively_optimize_for_size); } } #define CPUArchitectureF(F) \ F(x86_64) ENUM(CPUArchitecture, u8, CPUArchitectureF); #define OperatingSystemF(F) \ F(linux_) ENUM(OperatingSystem, u8, OperatingSystemF); struct Target { CPUArchitecture cpu; OperatingSystem os; }; struct Compile { String relative_file_path; BuildMode build_mode; bool has_debug_info; bool silent; }; #define base_cache_dir "bb-cache" enum class TypeId { }; struct TypeInteger { u32 bit_count; bool is_signed; }; struct Type { }; struct Value { }; struct Scope { }; struct Variable { }; struct Global { Variable variable; }; struct Local { Variable variable; }; struct MacroDeclaration { }; struct MacroInstantiation { }; struct Module { Arena& arena; String content; u64 offset; u64 line_offset; u64 line_character_offset; Type* first_pointer_type; Type* first_slice_type; Type* first_pair_struct_type; Type* first_array_type; Type* base_type_allocation; Type* va_list_type; Value* void_value; Global* first_global; Global* current_function; MacroDeclaration* current_macro_declaration; MacroInstantiation* current_macro_instantiation; Scope scope; String name; String path; String executable; Sliceobjects; Target target; BuildMode build_mode; bool has_debug_info; bool silent; }; constexpr u64 i128_offset = 64 * 2; constexpr u64 void_offset = i128_offset + 2; fn Type* integer_type(Module& module, TypeInteger integer) { assert(integer.bit_count); assert(integer.bit_count <= 64 || integer.bit_count == 128); auto index = integer.bit_count ? (i128_offset + integer.is_signed) : (integer.bit_count - 1 + (64 * integer.is_signed)); return module.base_type_allocation + index; } fn Type* void_type(Module& module) { return module.base_type_allocation + void_offset; } fn Type* noreturn_type(Module& module) { return void_type(module) + 1; } struct Options { String content; String path; String executable; String name; Slice objects; Target target; BuildMode build_mode; bool has_debug_info; bool silent; }; fn Type* new_type(Module& module) { auto* result = &arena_allocate(module.arena, 1)[0]; return result; } fn Value* new_value(Module& module) { auto* result = &arena_allocate(module.arena, 1)[0]; return result; } void parse(Module& module); void emit(Module& module);