From ea479bee9841e7c5677401660ea3cffceeac86e2 Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Wed, 2 Dec 2020 19:51:42 -0500 Subject: [PATCH] Add enums and some cleanup (#148) * support enums * better compiler warnings * tweaks to build with clang --- CMakeLists.txt | 10 +- decompiler/IR/IR.h | 1 + decompiler/data/tpage.h | 2 +- game/CMakeLists.txt | 16 +-- game/system/SystemThread.h | 2 - goal_src/kernel/gkernel-h.gc | 32 ++++- goalc/CMakeLists.txt | 1 - goalc/compiler/Compiler.cpp | 33 +---- goalc/compiler/Compiler.h | 24 +++- goalc/compiler/Enum.h | 15 +++ goalc/compiler/IR.h | 1 + goalc/compiler/StaticObject.h | 1 + goalc/compiler/Val.h | 1 + goalc/compiler/compilation/Atoms.cpp | 10 +- goalc/compiler/compilation/Define.cpp | 7 +- goalc/compiler/compilation/Function.cpp | 1 - goalc/compiler/compilation/Type.cpp | 121 ++++++++++++++++++ goalc/logger/Logger.cpp | 70 ---------- goalc/logger/Logger.h | 45 ------- test/CMakeLists.txt | 2 +- .../variables/bitfield-enums.gc | 16 +++ .../variables/integer-enums.gc | 19 +++ test/goalc/test_variables.cpp | 5 + third-party/fmt/CMakeLists.txt | 4 +- 24 files changed, 257 insertions(+), 182 deletions(-) create mode 100644 goalc/compiler/Enum.h delete mode 100644 goalc/logger/Logger.cpp delete mode 100644 goalc/logger/Logger.h create mode 100644 test/goalc/source_templates/variables/bitfield-enums.gc create mode 100644 test/goalc/source_templates/variables/integer-enums.gc diff --git a/CMakeLists.txt b/CMakeLists.txt index 724a546ef5..135009f9df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ set(CMAKE_CXX_STANDARD 17) # Set default compile flags for GCC # optimization level can be set here. Note that game/ overwrites this for building game C++ code. -if (CMAKE_COMPILER_IS_GNUCXX) +if (UNIX) message(STATUS "GCC detected, adding compile flags") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \ @@ -17,10 +17,10 @@ if (CMAKE_COMPILER_IS_GNUCXX) -Winit-self \ -ggdb \ -Wextra \ - -Wcast-align \ + -Wno-cast-align \ -Wcast-qual \ -Wdisabled-optimization \ - -Wformat=2 \ + -Wformat \ -Wmissing-include-dirs \ -Woverloaded-virtual \ -Wredundant-decls \ @@ -29,7 +29,7 @@ if (CMAKE_COMPILER_IS_GNUCXX) else () set(CMAKE_CXX_FLAGS "/EHsc") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10000000") -endif (CMAKE_COMPILER_IS_GNUCXX) +endif (UNIX) IF (WIN32) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) @@ -41,7 +41,7 @@ ENDIF () option(CODE_COVERAGE "Enable Code Coverage Compiler Flags" OFF) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/third-party/cmake/modules/) -if(CMAKE_COMPILER_IS_GNUCXX AND CODE_COVERAGE) +if(UNIX AND CODE_COVERAGE) include(CodeCoverage) append_coverage_compiler_flags() message("Code Coverage build is enabled!") diff --git a/decompiler/IR/IR.h b/decompiler/IR/IR.h index 00a5100393..d10a2a2b9b 100644 --- a/decompiler/IR/IR.h +++ b/decompiler/IR/IR.h @@ -27,6 +27,7 @@ class IR { virtual TP_Type get_expression_type(const TypeState& input, const LinkedObjectFile& file, DecompilerTypeSystem& dts); + virtual ~IR() = default; }; class IR_Atomic : public virtual IR { diff --git a/decompiler/data/tpage.h b/decompiler/data/tpage.h index 0af532cbe0..add063b332 100644 --- a/decompiler/data/tpage.h +++ b/decompiler/data/tpage.h @@ -1,6 +1,6 @@ #pragma once -class ObjectFileData; +struct ObjectFileData; struct TPageResultStats { int total_textures = 0; diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index db0f8696fd..09f0d0cb68 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -3,18 +3,18 @@ set(CMAKE_CXX_STANDARD 17) # Set default compile flags for GCC # optimization level can be set here. Note that game/ overwrites this for building game C++ code. -if(CMAKE_COMPILER_IS_GNUCXX) +if(UNIX) message(STATUS "GCC detected, adding compile flags") - set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} \ - -ggdb \ + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} \ -Wall \ - -Winit-self \ + -Winit-self \ + -ggdb \ -Wextra \ - -Wcast-align \ + -Wno-cast-align \ -Wcast-qual \ -Wdisabled-optimization \ - -Wformat=2 \ + -Wformat \ -Wmissing-include-dirs \ -Woverloaded-virtual \ -Wredundant-decls \ @@ -22,7 +22,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) -Wsign-promo") else() set(CMAKE_CXX_FLAGS "/EHsc") -endif(CMAKE_COMPILER_IS_GNUCXX) +endif(UNIX) enable_language(ASM_NASM) set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS} asm) diff --git a/game/system/SystemThread.h b/game/system/SystemThread.h index b05958c111..e48bad3519 100644 --- a/game/system/SystemThread.h +++ b/game/system/SystemThread.h @@ -49,8 +49,6 @@ class SystemThread { Timer stats_timer; Timer stat_diff_timer; double cpu_user = 0, cpu_kernel = 0; - uint64_t last_cpu_user = 0, last_cpu_kernel = 0; - uint64_t last_collection_nanoseconds = 0; int id = -1; bool want_exit = false; bool running = false; diff --git a/goal_src/kernel/gkernel-h.gc b/goal_src/kernel/gkernel-h.gc index 05a74adb27..57508d4a4f 100644 --- a/goal_src/kernel/gkernel-h.gc +++ b/goal_src/kernel/gkernel-h.gc @@ -54,8 +54,38 @@ ;; ENUMS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; todo, processs mask +; bitfield enum to indicate proprties about a process-tree +(defenum process-mask :bitfield #t :type int32 + (execute 0) ; 1 + (draw 1) ; 2 + (pause 2) ; 4 + (menu 3) ; 8 + (progress 4) ; 16 + (actor-pause 5) ; 32 + (sleep 6) ; 64 + (sleep-code 7) ; 128 + (process-tree 8) ; 256 ; not an actual process, just a "tree node" for organization + (heap-shrunk 9) ; 512 + (going 10) ; 1024 + (movie 11) ; 2048 + (movie-subject 12) ; 4096 + (target 13) ; 8192 + (sidekick 14) ; 16384 + (crate 15) ; 32768 + (collectable 16) ; 65536 + (enemy 17) ; 131072 + (camera 18) ; 262144 + (platform 19) ; 524288 + (ambient 20) ; 1048576 + (entity 21) ; 2097152 + (projectile 22) ; 4194304 + (attackable 23) ; 8388608 + (death 24) ; 16777216 + ) +;; -961 +(defconstant PROCESS_CLEAR_MASK + (lognot (process-mask sleep sleep-code process-tree heap-shrunk))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; MACROS diff --git a/goalc/CMakeLists.txt b/goalc/CMakeLists.txt index 2303e585f3..13a96f5ae6 100644 --- a/goalc/CMakeLists.txt +++ b/goalc/CMakeLists.txt @@ -29,7 +29,6 @@ add_library(compiler data_compiler/game_count.cpp debugger/Debugger.cpp debugger/DebugInfo.cpp - logger/Logger.cpp listener/Listener.cpp listener/MemoryMap.cpp regalloc/IRegister.cpp diff --git a/goalc/compiler/Compiler.cpp b/goalc/compiler/Compiler.cpp index d8731a7748..c59cdff22c 100644 --- a/goalc/compiler/Compiler.cpp +++ b/goalc/compiler/Compiler.cpp @@ -1,5 +1,4 @@ #include "Compiler.h" -#include "goalc/logger/Logger.h" #include "common/link_types.h" #include "IR.h" #include "goalc/regalloc/allocate.h" @@ -11,8 +10,6 @@ using namespace goos; Compiler::Compiler() : m_debugger(&m_listener) { - init_logger(); - init_settings(); m_listener.add_debugger(&m_debugger); m_ts.add_builtin_types(); m_global_env = std::make_unique(); @@ -61,36 +58,19 @@ void Compiler::execute_repl() { if (m_listener.is_connected()) { m_listener.send_code(data); if (!m_listener.most_recent_send_was_acked()) { - gLogger.log(MSG_ERR, "Runtime is not responding. Did it crash?\n"); + print_compiler_warning("Runtime is not responding. Did it crash?\n"); } } } } catch (std::exception& e) { - gLogger.log(MSG_WARN, "REPL Error: %s\n", e.what()); + print_compiler_warning("REPL Error: %s\n", e.what()); } } m_listener.disconnect(); } -Compiler::~Compiler() { - gLogger.close(); -} - -void Compiler::init_logger() { - gLogger.set_file("compiler.txt"); // todo, a better file than this... - gLogger.config[MSG_COLOR].kind = LOG_FILE; - gLogger.config[MSG_DEBUG].kind = LOG_IGNORE; - gLogger.config[MSG_TGT].color = COLOR_GREEN; - gLogger.config[MSG_TGT_INFO].color = COLOR_BLUE; - gLogger.config[MSG_WARN].color = COLOR_RED; - gLogger.config[MSG_ICE].color = COLOR_RED; - gLogger.config[MSG_ERR].color = COLOR_RED; -} - -void Compiler::init_settings() {} - FileEnv* Compiler::compile_object_file(const std::string& name, goos::Object code, bool allow_emit) { @@ -169,11 +149,6 @@ Val* Compiler::compile_error_guard(const goos::Object& code, Env* env) { } } -void Compiler::ice(const std::string& error) { - gLogger.log(MSG_ICE, "[ICE] %s\n", error.c_str()); - throw std::runtime_error("ICE"); -} - void Compiler::color_object_file(FileEnv* env) { for (auto& f : env->functions()) { AllocationInput input; @@ -232,7 +207,7 @@ std::vector Compiler::run_test_from_file(const std::string& source_ m_listener.record_messages(ListenerMessageKind::MSG_PRINT); m_listener.send_code(data); if (!m_listener.most_recent_send_was_acked()) { - gLogger.log(MSG_ERR, "Runtime is not responding after sending test code. Did it crash?\n"); + print_compiler_warning("Runtime is not responding after sending test code. Did it crash?\n"); } return m_listener.stop_recording_messages(); } catch (std::exception& e) { @@ -258,7 +233,7 @@ std::vector Compiler::run_test_from_string(const std::string& src, m_listener.record_messages(ListenerMessageKind::MSG_PRINT); m_listener.send_code(data); if (!m_listener.most_recent_send_was_acked()) { - gLogger.log(MSG_ERR, "Runtime is not responding after sending test code. Did it crash?\n"); + print_compiler_warning("Runtime is not responding after sending test code. Did it crash?\n"); } return m_listener.stop_recording_messages(); } catch (std::exception& e) { diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index 0c22835dd5..8674a8427d 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -15,13 +15,13 @@ #include "third-party/fmt/core.h" #include "third-party/fmt/color.h" #include "CompilerException.h" +#include "Enum.h" enum MathMode { MATH_INT, MATH_BINT, MATH_FLOAT, MATH_INVALID }; class Compiler { public: Compiler(); - ~Compiler(); void execute_repl(); goos::Interpreter& get_goos() { return m_goos; } FileEnv* compile_object_file(const std::string& name, goos::Object code, bool allow_emit); @@ -30,9 +30,7 @@ class Compiler { Env* env); Val* compile(const goos::Object& code, Env* env); Val* compile_error_guard(const goos::Object& code, Env* env); - void ice(const std::string& err); None* get_none() { return m_none.get(); } - std::vector run_test_from_file(const std::string& source_code); std::vector run_test_from_string(const std::string& src, const std::string& obj_name = "*listener*"); @@ -42,14 +40,10 @@ class Compiler { void enable_throw_on_redefines() { m_throw_on_define_extern_redefinition = true; } Debugger& get_debugger() { return m_debugger; } listener::Listener& listener() { return m_listener; } - void poke_target() { m_listener.send_poke(); } - bool connect_to_target(); private: - void init_logger(); - void init_settings(); bool try_getting_macro_from_goos(const goos::Object& macro_name, goos::Object* dest); void set_bitfield(const goos::Object& form, BitFieldVal* dst, RegVal* src, Env* env); Val* do_set(const goos::Object& form, Val* dst, RegVal* src, Env* env); @@ -125,6 +119,7 @@ class Compiler { Debugger m_debugger; goos::Interpreter m_goos; std::unordered_map m_symbol_types; + std::unordered_map m_enums; std::unordered_map, goos::Object> m_global_constants; std::unordered_map, LambdaVal*> m_inlineable_functions; CompilerSettings m_settings; @@ -140,6 +135,10 @@ class Compiler { Val* number_to_binteger(const goos::Object& form, Val* in, Env* env); Val* to_math_type(const goos::Object& form, Val* in, MathMode mode, Env* env); bool is_none(Val* in); + Val* compile_enum_lookup(const goos::Object& form, + const GoalEnum& e, + const goos::Object& rest, + Env* env); Val* compile_variable_shift(const goos::Object& form, const RegVal* in, @@ -200,6 +199,16 @@ class Compiler { throw CompilerException("Compilation Error"); } + template + void print_compiler_warning(const std::string& str, Args&&... args) { + fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "[Warning] "); + if (!str.empty() && str.back() == '\n') { + fmt::print(str, std::forward(args)...); + } else { + fmt::print(str + '\n', std::forward(args)...); + } + } + public: // Atoms @@ -295,6 +304,7 @@ class Compiler { Val* compile_addr_of(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_declare_type(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_none(const goos::Object& form, const goos::Object& rest, Env* env); + Val* compile_defenum(const goos::Object& form, const goos::Object& rest, Env* env); }; #endif // JAK_COMPILER_H diff --git a/goalc/compiler/Enum.h b/goalc/compiler/Enum.h new file mode 100644 index 0000000000..f9568082ec --- /dev/null +++ b/goalc/compiler/Enum.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include "common/common_types.h" +#include "common/type_system/TypeSpec.h" + +struct GoalEnum { + TypeSpec base_type; + bool is_bitfield = false; + std::unordered_map entries; + + bool operator==(const GoalEnum& other) const; + bool operator!=(const GoalEnum& other) const; +}; \ No newline at end of file diff --git a/goalc/compiler/IR.h b/goalc/compiler/IR.h index 045746e29b..55ac55a62d 100644 --- a/goalc/compiler/IR.h +++ b/goalc/compiler/IR.h @@ -20,6 +20,7 @@ class IR { (void)constraints; (void)my_id; } + virtual ~IR() = default; }; // class IR_Set : public IR { diff --git a/goalc/compiler/StaticObject.h b/goalc/compiler/StaticObject.h index 0c55a97663..c2fde90edc 100644 --- a/goalc/compiler/StaticObject.h +++ b/goalc/compiler/StaticObject.h @@ -21,6 +21,7 @@ class StaticObject { virtual LoadInfo get_load_info() const = 0; virtual void generate(emitter::ObjectGenerator* gen) = 0; virtual int get_addr_offset() const = 0; + virtual ~StaticObject() = default; emitter::StaticRecord rec; }; diff --git a/goalc/compiler/Val.h b/goalc/compiler/Val.h index e66d07aeb7..74521132c5 100644 --- a/goalc/compiler/Val.h +++ b/goalc/compiler/Val.h @@ -45,6 +45,7 @@ class Val { void set_type(TypeSpec ts) { m_ts = std::move(ts); } bool settable() const { return m_is_settable; } void mark_as_settable() { m_is_settable = true; } + virtual ~Val() = default; protected: TypeSpec m_ts; diff --git a/goalc/compiler/compilation/Atoms.cpp b/goalc/compiler/compilation/Atoms.cpp index 70b85d9c8d..72a330eafb 100644 --- a/goalc/compiler/compilation/Atoms.cpp +++ b/goalc/compiler/compilation/Atoms.cpp @@ -68,7 +68,7 @@ static const std::unordered_map< // TYPE {"deftype", &Compiler::compile_deftype}, {"defmethod", &Compiler::compile_defmethod}, - // {"defenum", &Compiler::compile_defenum}, + {"defenum", &Compiler::compile_defenum}, {"->", &Compiler::compile_deref}, {"&", &Compiler::compile_addr_of}, {"the-as", &Compiler::compile_the_as}, @@ -152,7 +152,7 @@ Val* Compiler::compile(const goos::Object& code, Env* env) { case goos::ObjectType::FLOAT: return compile_float(code, env); default: - ice("Don't know how to compile " + code.print()); + throw_compiler_error(code, "Cannot compile {}.", code.print()); } return get_none(); } @@ -161,7 +161,6 @@ Val* Compiler::compile(const goos::Object& code, Env* env) { * Compile a pair/list. * Can be a compiler form, function call (possibly inlined), method call, immediate application of a * lambda, or a goos macro. - * TODO - enums. */ Val* Compiler::compile_pair(const goos::Object& code, Env* env) { auto pair = code.as_pair(); @@ -182,7 +181,10 @@ Val* Compiler::compile_pair(const goos::Object& code, Env* env) { return compile_goos_macro(code, macro_obj, rest, env); } - // try as an enum (not yet implemented) + auto enum_kv = m_enums.find(head_sym->name); + if (enum_kv != m_enums.end()) { + return compile_enum_lookup(code, enum_kv->second, rest, env); + } } // if none of the above cases worked, then treat it like a function/method call. diff --git a/goalc/compiler/compilation/Define.cpp b/goalc/compiler/compilation/Define.cpp index db1a21596d..02b2dc79a9 100644 --- a/goalc/compiler/compilation/Define.cpp +++ b/goalc/compiler/compilation/Define.cpp @@ -4,7 +4,6 @@ */ #include "goalc/compiler/Compiler.h" -#include "goalc/logger/Logger.h" /*! * Define or set a global value. Has some special magic to store data for functions which may be @@ -73,10 +72,8 @@ Val* Compiler::compile_define_extern(const goos::Object& form, const goos::Objec "define-extern would redefine the type of symbol {} from {} to {}.", symbol_string(sym), existing_type->second.print(), new_type.print()); } else { - // todo nicer warning message. - gLogger.log( - MSG_WARN, - "[Warning] define-extern has redefined the type of symbol %s\npreviously: %s\nnow: %s\n", + print_compiler_warning( + "[Warning] define-extern has redefined the type of symbol {}\npreviously: {}\nnow: {}\n", symbol_string(sym).c_str(), existing_type->second.print().c_str(), new_type.print().c_str()); } diff --git a/goalc/compiler/compilation/Function.cpp b/goalc/compiler/compilation/Function.cpp index 20bdb2c474..cdfd0c1345 100644 --- a/goalc/compiler/compilation/Function.cpp +++ b/goalc/compiler/compilation/Function.cpp @@ -4,7 +4,6 @@ */ #include "goalc/compiler/Compiler.h" -#include "goalc/logger/Logger.h" #include "third-party/fmt/core.h" namespace { diff --git a/goalc/compiler/compilation/Type.cpp b/goalc/compiler/compilation/Type.cpp index 7b71e65264..c3a164ba54 100644 --- a/goalc/compiler/compilation/Type.cpp +++ b/goalc/compiler/compilation/Type.cpp @@ -1,6 +1,7 @@ #include "goalc/compiler/Compiler.h" #include "third-party/fmt/core.h" #include "common/type_system/deftype.h" +#include "goalc/compiler/Enum.h" namespace { @@ -785,4 +786,124 @@ Val* Compiler::compile_none(const goos::Object& form, const goos::Object& rest, auto args = get_va(form, rest); va_check(form, args, {}, {}); return get_none(); +} + +Val* Compiler::compile_defenum(const goos::Object& form, const goos::Object& _rest, Env* env) { + // format is (defenum name [options] [entries]) + (void)env; + auto* rest = &_rest; + + // name + auto enum_name = symbol_string(pair_car(*rest)); + rest = &pair_cdr(*rest); + + // default enum type will be int32. + auto enum_type = m_ts.make_typespec("int32"); + bool is_bitfield = false; + + auto current = pair_car(*rest); + while (current.is_symbol() && symbol_string(current).at(0) == ':') { + auto option_name = symbol_string(current); + rest = &pair_cdr(*rest); + auto option_value = pair_car(*rest); + rest = &pair_cdr(*rest); + current = pair_car(*rest); + + if (option_name == ":type") { + enum_type = parse_typespec(option_value); + } else if (option_name == ":bitfield") { + if (symbol_string(option_value) == "#t") { + is_bitfield = true; + } else if (symbol_string(option_value) == "#f") { + is_bitfield = false; + } else { + throw_compiler_error(form, "Invalid option {} to :bitfield option.", option_value.print()); + } + } else { + throw_compiler_error(form, "Unknown option {} for defenum.", option_name); + } + } + + GoalEnum new_enum; + new_enum.base_type = enum_type; + new_enum.is_bitfield = is_bitfield; + + while (!rest->is_empty_list()) { + auto def = pair_car(*rest); + auto name = symbol_string(pair_car(def)); + def = pair_cdr(def); + auto value = pair_car(def); + if (!value.is_int()) { + throw_compiler_error(def, "Expected integer for enum value, got {}", value.print()); + } + + def = pair_cdr(def); + if (!def.is_empty_list()) { + throw_compiler_error(def, "Got too many items in defenum defintion."); + } + + new_enum.entries[name] = value.integer_obj.value; + rest = &pair_cdr(*rest); + } + + auto existing_kv = m_enums.find(enum_name); + if (existing_kv != m_enums.end() && existing_kv->second != new_enum) { + print_compiler_warning("defenum changes the definition of existing enum {}", enum_name.c_str()); + } + m_enums[enum_name] = new_enum; + + return get_none(); +} + +Val* Compiler::compile_enum_lookup(const goos::Object& form, + const GoalEnum& e, + const goos::Object& rest, + Env* env) { + if (e.is_bitfield) { + int64_t value = 0; + for_each_in_list(rest, [&](const goos::Object& o) { + auto kv = e.entries.find(symbol_string(o)); + if (kv == e.entries.end()) { + throw_compiler_error(form, "The value {} was not found in enum.", o.print()); + } + value |= (1 << kv->second); + }); + + auto result = compile_integer(value, env); + result->set_type(e.base_type); + return result; + } else { + int64_t value = 0; + bool got = false; + for_each_in_list(rest, [&](const goos::Object& o) { + if (got) { + throw_compiler_error(form, "Invalid enum lookup."); + } + auto kv = e.entries.find(symbol_string(o)); + if (kv == e.entries.end()) { + throw_compiler_error(form, "The value {} was not found in enum.", o.print()); + } + value = kv->second; + got = true; + }); + + if (!got) { + throw_compiler_error(form, "Invalid enum lookup."); + } + + auto result = compile_integer(value, env); + result->set_type(e.base_type); + return result; + } + + return get_none(); +} + +bool GoalEnum::operator==(const GoalEnum& other) const { + return base_type == other.base_type && is_bitfield == other.is_bitfield && + entries == other.entries; +} + +bool GoalEnum::operator!=(const GoalEnum& other) const { + return !(*this == other); } \ No newline at end of file diff --git a/goalc/logger/Logger.cpp b/goalc/logger/Logger.cpp deleted file mode 100644 index e49bebf783..0000000000 --- a/goalc/logger/Logger.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include "Logger.h" - -void Logger::close() { - if (fp) { - fclose(fp); - fp = nullptr; - } -} - -void Logger::set_file(std::string filename) { - if (fp) { - fclose(fp); - } - - fp = fopen(filename.c_str(), "w"); - if (!fp) { - throw std::runtime_error("invalid file name " + filename + " in logger"); - } -} - -void Logger::log(LoggerMessageKind kind, const char* format, ...) { - FILE* dest = nullptr; - auto& settings = config[kind]; - switch (settings.kind) { - case LOG_STDERR: - dest = stderr; - break; - case LOG_STDOUT: - dest = stdout; - break; - case LOG_IGNORE: - dest = nullptr; - break; - case LOG_FILE: - dest = fp; - break; - default: - throw std::runtime_error("unknown log destination in log"); - } - - if (!dest) - return; - - if (!settings.prefix.empty()) { - fprintf(dest, "%s", settings.prefix.c_str()); - } - - if (settings.color != COLOR_NORMAL) { - const char* color_codes[] = {"", "[0;31m", "[0;32m", "[0;36m"}; - printf("\033%s", color_codes[settings.color]); - } - - va_list arglist; - va_start(arglist, format); - vfprintf(dest, format, arglist); - va_end(arglist); - - if (settings.color != COLOR_NORMAL) { - printf("\033[0m"); - fflush(stdout); - } - - // todo, does this make things slow? - if (settings.kind == LOG_FILE) { - fflush(fp); - } -} - -Logger gLogger; \ No newline at end of file diff --git a/goalc/logger/Logger.h b/goalc/logger/Logger.h deleted file mode 100644 index d6fe5b0d4e..0000000000 --- a/goalc/logger/Logger.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#ifndef JAK_LOGGER_H -#define JAK_LOGGER_H - -#include -#include -#include - -enum LoggerColor { COLOR_NORMAL, COLOR_RED, COLOR_GREEN, COLOR_BLUE }; - -enum LoggerDestKind { LOG_STDOUT, LOG_STDERR, LOG_FILE, LOG_IGNORE }; - -struct LoggerDest { - LoggerDestKind kind = LOG_STDOUT; - LoggerColor color = COLOR_NORMAL; - std::string prefix; -}; - -enum LoggerMessageKind { - MSG_GOAL, - MSG_ICE, - MSG_ERR, - MSG_COLOR, - MSG_EMIT, - MSG_DEBUG, - MSG_WARN, - MSG_TGT, - MSG_TGT_INFO, -}; - -class Logger { - public: - void set_file(std::string filename); - void log(LoggerMessageKind kind, const char* format, ...); - std::unordered_map config; - void close(); - - private: - FILE* fp = nullptr; -}; - -extern Logger gLogger; - -#endif // JAK_LOGGER_H diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 569b53e41f..4f84573c1a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -30,7 +30,7 @@ ELSE() target_link_libraries(goalc-test cross_sockets goos common_util runtime compiler type_system gtest Zydis) ENDIF() -if(CMAKE_COMPILER_IS_GNUCXX AND CODE_COVERAGE) +if(UNIX AND CODE_COVERAGE) include(CodeCoverage) append_coverage_compiler_flags() setup_target_for_coverage_lcov(NAME goalc-test_coverage diff --git a/test/goalc/source_templates/variables/bitfield-enums.gc b/test/goalc/source_templates/variables/bitfield-enums.gc new file mode 100644 index 0000000000..7453bb6eb0 --- /dev/null +++ b/test/goalc/source_templates/variables/bitfield-enums.gc @@ -0,0 +1,16 @@ +(defenum test-bitfield :bitfield #t + (four 2) + (one 0) + (two 1) + ) + +(deftype type-with-bitfield (basic) + ((name basic) + (thing int32) + ) + ) + +(let ((obj (new 'global 'type-with-bitfield))) + (set! (-> obj thing) (test-bitfield one four)) + (the uint (-> obj thing)) + ) diff --git a/test/goalc/source_templates/variables/integer-enums.gc b/test/goalc/source_templates/variables/integer-enums.gc new file mode 100644 index 0000000000..5d4506888c --- /dev/null +++ b/test/goalc/source_templates/variables/integer-enums.gc @@ -0,0 +1,19 @@ +(defenum test-int-enum :bitfield #f + (four 4) + (one 1) + (seven 7) + (two 2) + ) + +(deftype type-with-bitfield2 (basic) + ((name basic) + (thing1 int32) + (thing2 int32) + ) + ) + +(let ((obj (new 'global 'type-with-bitfield2))) + (set! (-> obj thing1) (test-int-enum four)) + (set! (-> obj thing2) (test-int-enum seven)) + (+ (-> obj thing1) (-> obj thing2)) + ) diff --git a/test/goalc/test_variables.cpp b/test/goalc/test_variables.cpp index 5058fd1153..d1a44287e8 100644 --- a/test/goalc/test_variables.cpp +++ b/test/goalc/test_variables.cpp @@ -72,4 +72,9 @@ TEST_F(VariableTests, Let) { TEST_F(VariableTests, StackVars) { runner.run_static_test(env, testCategory, "stack-ints.gc", {"12\n"}); runner.run_static_test(env, testCategory, "stack-ints-2.gc", {"1\n"}); +} + +TEST_F(VariableTests, Bitfields) { + runner.run_static_test(env, testCategory, "bitfield-enums.gc", {"5\n"}); + runner.run_static_test(env, testCategory, "integer-enums.gc", {"11\n"}); } \ No newline at end of file diff --git a/third-party/fmt/CMakeLists.txt b/third-party/fmt/CMakeLists.txt index 8c9003855f..7c1a01067d 100644 --- a/third-party/fmt/CMakeLists.txt +++ b/third-party/fmt/CMakeLists.txt @@ -1,8 +1,8 @@ -if (CMAKE_COMPILER_IS_GNUCXX) +if (UNIX) set(CMAKE_CXX_FLAGS "-O3") else () set(CMAKE_CXX_FLAGS "/EHsc") -endif (CMAKE_COMPILER_IS_GNUCXX) +endif (UNIX) include_directories(../) add_library(fmt SHARED format.cc) \ No newline at end of file