diff --git a/CMakeLists.txt b/CMakeLists.txt index a4719b0e4c..80f850d72f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(jak) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 14) # Set default compile flags for GCC # optimization level can be set here. Note that game/ overwrites this for building game C++ code. @@ -11,8 +11,8 @@ if (CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \ -Wall \ - -Winit-self \ - -ggdb \ + -Winit-self \ + -ggdb \ -Wextra \ -Wcast-align \ -Wcast-qual \ @@ -25,6 +25,7 @@ if (CMAKE_COMPILER_IS_GNUCXX) -Wsign-promo") else () set(CMAKE_CXX_FLAGS "/EHsc") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10000000") endif (CMAKE_COMPILER_IS_GNUCXX) IF (WIN32) diff --git a/common/util/CMakeLists.txt b/common/util/CMakeLists.txt index 23f5a949df..caf551f79c 100644 --- a/common/util/CMakeLists.txt +++ b/common/util/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(common_util SHARED FileUtil.cpp + DgoWriter.cpp Timer.cpp) diff --git a/common/util/DgoWriter.cpp b/common/util/DgoWriter.cpp new file mode 100644 index 0000000000..69adf5e950 --- /dev/null +++ b/common/util/DgoWriter.cpp @@ -0,0 +1,28 @@ +#include "BinaryWriter.h" +#include "FileUtil.h" +#include "DgoWriter.h" + +void build_dgo(const DgoDescription& description) { + BinaryWriter writer; + // dgo header + writer.add(description.entries.size()); + writer.add_cstr_len(description.dgo_name.c_str(), 60); + + for (auto& obj : description.entries) { + auto obj_data = file_util::read_binary_file(file_util::get_file_path({"data", obj.file_name})); + // size + writer.add(obj_data.size()); + // name + writer.add_str_len(obj.name_in_dgo, 60); + // data + writer.add_data(obj_data.data(), obj_data.size()); + // pad + while (writer.get_size() & 0xf) { + writer.add(0); + } + } + + printf("DGO: %15s %.3f MB\n", description.dgo_name.c_str(), + (float)(writer.get_size()) / (1 << 20)); + writer.write_to_file(file_util::get_file_path({"out", description.dgo_name})); +} diff --git a/common/util/DgoWriter.h b/common/util/DgoWriter.h new file mode 100644 index 0000000000..1781694b68 --- /dev/null +++ b/common/util/DgoWriter.h @@ -0,0 +1,17 @@ +#ifndef JAK_DGOWRITER_H +#define JAK_DGOWRITER_H + +#include + +struct DgoDescription { + std::string dgo_name; + struct DgoEntry { + std::string file_name; + std::string name_in_dgo; + }; + std::vector entries; +}; + +void build_dgo(const DgoDescription& description); + +#endif // JAK_DGOWRITER_H diff --git a/common/util/FileUtil.cpp b/common/util/FileUtil.cpp index 01c07c1997..88bd4142eb 100644 --- a/common/util/FileUtil.cpp +++ b/common/util/FileUtil.cpp @@ -9,26 +9,29 @@ #include #else #include +#include #endif std::string file_util::get_project_path() { #ifdef _WIN32 char buffer[FILENAME_MAX]; GetModuleFileNameA(NULL, buffer, FILENAME_MAX); - std::string::size_type pos = std::string(buffer).rfind( - "\\jak-project\\"); // Strip file path down to \jak-project\ directory + printf("using path %s\n", buffer); + std::string::size_type pos = + std::string(buffer).rfind("jak-project"); // Strip file path down to \jak-project\ directory + printf("rfind returned %lld\n", pos); return std::string(buffer).substr( - 0, pos + 12); // + 12 to include "\jak-project" in the returned filepath + 0, pos + 11); // + 12 to include "\jak-project" in the returned filepath #else // do Linux stuff char buffer[FILENAME_MAX]; readlink("/proc/self/exe", buffer, FILENAME_MAX); // /proc/self acts like a "virtual folder" containing information about // the current process - std::string::size_type pos = std::string(buffer).rfind( - "/jak-project/"); // Strip file path down to /jak-project/ directory + std::string::size_type pos = + std::string(buffer).rfind("jak-project"); // Strip file path down to /jak-project/ directory return std::string(buffer).substr( - 0, pos + 12); // + 12 to include "/jak-project" in the returned filepath + 0, pos + 11); // + 12 to include "/jak-project" in the returned filepath #endif } @@ -76,7 +79,8 @@ void file_util::write_text_file(const std::string& file_name, const std::string& std::vector file_util::read_binary_file(const std::string& filename) { auto fp = fopen(filename.c_str(), "rb"); if (!fp) - throw std::runtime_error("File " + filename + " cannot be opened"); + throw std::runtime_error("File " + filename + + " cannot be opened: " + std::string(strerror(errno))); fseek(fp, 0, SEEK_END); auto len = ftell(fp); rewind(fp); @@ -87,6 +91,7 @@ std::vector file_util::read_binary_file(const std::string& filename) { if (fread(data.data(), len, 1, fp) != 1) { throw std::runtime_error("File " + filename + " cannot be read"); } + fclose(fp); return data; } diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 6fb1dacae2..6ded6b6508 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -1,5 +1,5 @@ # We define our own compilation flags here. -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 14) # Set default compile flags for GCC # optimization level can be set here. Note that game/ overwrites this for building game C++ code. diff --git a/game/fake_iso.txt b/game/fake_iso.txt index 28f3185fc3..cca0e660ae 100644 --- a/game/fake_iso.txt +++ b/game/fake_iso.txt @@ -2,8 +2,8 @@ ; Each entry should consist of an ISO name, followed by a file name ; note that tweakval, vagdir, screen1 have dummy data for now. -KERNEL.CGO resources/KERNEL.CGO -GAME.CGO resources/GAME.CGO +KERNEL.CGO out/KERNEL.CGO +GAME.CGO out/GAME.CGO TEST.CGO resources/TEST.CGO TWEAKVAL.MUS resources/TWEAKVAL.MUS VAGDIR.AYB resources/VAGDIR.AYB diff --git a/game/kernel/klisten.cpp b/game/kernel/klisten.cpp index 322d049e33..22f9aad10b 100644 --- a/game/kernel/klisten.cpp +++ b/game/kernel/klisten.cpp @@ -149,6 +149,7 @@ void ProcessListenerMessage(Ptr msg) { // this setup allows listener function execution to clean up after itself. ListenerFunction->value = link_and_exec(buffer, "*listener*", 0, kdebugheap, LINK_FLAG_FORCE_DEBUG).offset; + fprintf(stderr, "ListenerFunction is now 0x%x\n", ListenerFunction->value); return; // don't ack yet, this will happen after the function runs. } break; default: diff --git a/goal_src/build/all_files.gc b/goal_src/build/all_files.gc new file mode 100644 index 0000000000..438da9a6b7 --- /dev/null +++ b/goal_src/build/all_files.gc @@ -0,0 +1,511 @@ +(defglobalconstant all-goal-files + ( + "goal_src/kernel/gcommon.gc" + "goal_src/kernel/gstring-h.gc" + "goal_src/kernel/gkernel-h.gc" + "goal_src/kernel/gkernel.gc" + "goal_src/kernel/pskernel.gc" + "goal_src/kernel/gstring.gc" + "goal_src/kernel/dgo-h.gc" + "goal_src/kernel/gstate.gc" + "goal_src/engine/util/types-h.gc" + "goal_src/engine/ps2/vu1-macros.gc" + "goal_src/engine/math/math.gc" + "goal_src/engine/math/vector-h.gc" + "goal_src/engine/physics/gravity-h.gc" + "goal_src/engine/geometry/bounding-box-h.gc" + "goal_src/engine/math/matrix-h.gc" + "goal_src/engine/math/quaternion-h.gc" + "goal_src/engine/math/euler-h.gc" + "goal_src/engine/math/transform-h.gc" + "goal_src/engine/geometry/geometry-h.gc" + "goal_src/engine/math/trigonometry-h.gc" + "goal_src/engine/math/transformq-h.gc" + "goal_src/engine/geometry/bounding-box.gc" + "goal_src/engine/math/matrix.gc" + "goal_src/engine/math/transform.gc" + "goal_src/engine/math/quaternion.gc" + "goal_src/engine/math/euler.gc" + "goal_src/engine/geometry/geometry.gc" + "goal_src/engine/math/trigonometry.gc" + "goal_src/engine/sound/gsound-h.gc" + "goal_src/engine/ps2/timer-h.gc" + "goal_src/engine/ps2/timer.gc" + "goal_src/engine/ps2/vif-h.gc" + "goal_src/engine/dma/dma-h.gc" + "goal_src/engine/gfx/hw/video-h.gc" + "goal_src/engine/gfx/hw/vu1-user-h.gc" + "goal_src/engine/dma/dma.gc" + "goal_src/engine/dma/dma-buffer.gc" + "goal_src/engine/dma/dma-bucket.gc" + "goal_src/engine/dma/dma-disasm.gc" + "goal_src/engine/ps2/pad.gc" + "goal_src/engine/gfx/hw/gs.gc" + "goal_src/engine/gfx/hw/display-h.gc" + "goal_src/engine/math/vector.gc" + "goal_src/engine/load/file-io.gc" + "goal_src/engine/load/loader-h.gc" + "goal_src/engine/gfx/texture-h.gc" + "goal_src/engine/level/level-h.gc" + "goal_src/engine/camera/math-camera-h.gc" + "goal_src/engine/camera/math-camera.gc" + "goal_src/engine/gfx/font-h.gc" + "goal_src/engine/gfx/decomp-h.gc" + "goal_src/engine/gfx/hw/display.gc" + "goal_src/engine/engine/connect.gc" + "goal_src/engine/ui/text-h.gc" + "goal_src/engine/game/settings-h.gc" + "goal_src/engine/gfx/capture.gc" + "goal_src/engine/debug/memory-usage-h.gc" + "goal_src/engine/gfx/texture.gc" + "goal_src/engine/game/main-h.gc" + "goal_src/engine/anim/mspace-h.gc" + "goal_src/engine/draw/drawable-h.gc" + "goal_src/engine/draw/drawable-group-h.gc" + "goal_src/engine/draw/drawable-inline-array-h.gc" + "goal_src/engine/draw/draw-node-h.gc" + "goal_src/engine/draw/drawable-tree-h.gc" + "goal_src/engine/draw/drawable-actor-h.gc" + "goal_src/engine/draw/drawable-ambient-h.gc" + "goal_src/engine/game/task/game-task-h.gc" + "goal_src/engine/game/task/hint-control-h.gc" + "goal_src/engine/gfx/generic/generic-h.gc" + "goal_src/engine/gfx/lights-h.gc" + "goal_src/engine/gfx/ocean/ocean-h.gc" + "goal_src/engine/gfx/ocean/ocean-trans-tables.gc" + "goal_src/engine/gfx/ocean/ocean-tables.gc" + "goal_src/engine/gfx/ocean/ocean-frames.gc" + "goal_src/engine/gfx/sky/sky-h.gc" + "goal_src/engine/gfx/mood-h.gc" + "goal_src/engine/gfx/time-of-day-h.gc" + "goal_src/engine/data/art-h.gc" + "goal_src/engine/gfx/generic/generic-vu1-h.gc" + "goal_src/engine/gfx/merc/merc-h.gc" + "goal_src/engine/gfx/merc/generic-merc-h.gc" + "goal_src/engine/gfx/tie/generic-tie-h.gc" + "goal_src/engine/gfx/generic/generic-work-h.gc" + "goal_src/engine/gfx/shadow/shadow-cpu-h.gc" + "goal_src/engine/gfx/shadow/shadow-vu1-h.gc" + "goal_src/engine/ps2/memcard-h.gc" + "goal_src/engine/game/game-info-h.gc" + "goal_src/engine/gfx/wind-h.gc" + "goal_src/engine/gfx/tie/prototype-h.gc" + "goal_src/engine/anim/joint-h.gc" + "goal_src/engine/anim/bones-h.gc" + "goal_src/engine/engine/engines.gc" + "goal_src/engine/data/res-h.gc" + "goal_src/engine/data/res.gc" + "goal_src/engine/gfx/lights.gc" + "goal_src/engine/physics/dynamics-h.gc" + "goal_src/engine/target/surface-h.gc" + "goal_src/engine/target/pat-h.gc" + "goal_src/engine/game/fact-h.gc" + "goal_src/engine/anim/aligner-h.gc" + "goal_src/engine/game/game-h.gc" + "goal_src/engine/game/generic-obs-h.gc" + "goal_src/engine/camera/pov-camera-h.gc" + "goal_src/engine/util/sync-info-h.gc" + "goal_src/engine/util/smush-control-h.gc" + "goal_src/engine/physics/trajectory-h.gc" + "goal_src/engine/debug/debug-h.gc" + "goal_src/engine/target/joint-mod-h.gc" + "goal_src/engine/collide/collide-func-h.gc" + "goal_src/engine/collide/collide-mesh-h.gc" + "goal_src/engine/collide/collide-shape-h.gc" + "goal_src/engine/collide/collide-target-h.gc" + "goal_src/engine/collide/collide-touch-h.gc" + "goal_src/engine/collide/collide-edge-grab-h.gc" + "goal_src/engine/draw/process-drawable-h.gc" + "goal_src/engine/game/effect-control-h.gc" + "goal_src/engine/collide/collide-frag-h.gc" + "goal_src/engine/game/projectiles-h.gc" + "goal_src/engine/target/target-h.gc" + "goal_src/engine/gfx/depth-cue-h.gc" + "goal_src/engine/debug/stats-h.gc" + "goal_src/engine/gfx/vis/bsp-h.gc" + "goal_src/engine/collide/collide-cache-h.gc" + "goal_src/engine/collide/collide-h.gc" + "goal_src/engine/gfx/shrub/shrubbery-h.gc" + "goal_src/engine/gfx/tie/tie-h.gc" + "goal_src/engine/gfx/tfrag/tfrag-h.gc" + "goal_src/engine/gfx/background-h.gc" + "goal_src/engine/gfx/tfrag/subdivide-h.gc" + "goal_src/engine/entity/entity-h.gc" + "goal_src/engine/gfx/sprite/sprite-h.gc" + "goal_src/engine/gfx/shadow/shadow-h.gc" + "goal_src/engine/gfx/eye-h.gc" + "goal_src/engine/sparticle/sparticle-launcher-h.gc" + "goal_src/engine/sparticle/sparticle-h.gc" + "goal_src/engine/entity/actor-link-h.gc" + "goal_src/engine/camera/camera-h.gc" + "goal_src/engine/camera/cam-debug-h.gc" + "goal_src/engine/camera/cam-interface-h.gc" + "goal_src/engine/camera/cam-update-h.gc" + "goal_src/engine/debug/assert-h.gc" + "goal_src/engine/ui/hud-h.gc" + "goal_src/engine/ui/progress-h.gc" + "goal_src/engine/ps2/rpc-h.gc" + "goal_src/engine/nav/path-h.gc" + "goal_src/engine/nav/navigate-h.gc" + "goal_src/engine/load/load-dgo.gc" + "goal_src/engine/load/ramdisk.gc" + "goal_src/engine/sound/gsound.gc" + "goal_src/engine/math/transformq.gc" + "goal_src/engine/collide/collide-func.gc" + "goal_src/engine/anim/joint.gc" + "goal_src/engine/geometry/cylinder.gc" + "goal_src/engine/gfx/wind.gc" + "goal_src/engine/gfx/vis/bsp.gc" + "goal_src/engine/gfx/tfrag/subdivide.gc" + "goal_src/engine/gfx/sprite/sprite.gc" + "goal_src/engine/gfx/sprite/sprite-distort.gc" + "goal_src/engine/debug/debug-sphere.gc" + "goal_src/engine/debug/debug.gc" + "goal_src/engine/gfx/merc/merc-vu1.gc" + "goal_src/engine/gfx/merc/merc-blend-shape.gc" + "goal_src/engine/gfx/merc/merc.gc" + "goal_src/engine/gfx/ripple.gc" + "goal_src/engine/anim/bones.gc" + "goal_src/engine/gfx/generic/generic-vu0.gc" + "goal_src/engine/gfx/generic/generic.gc" + "goal_src/engine/gfx/generic/generic-vu1.gc" + "goal_src/engine/gfx/generic/generic-effect.gc" + "goal_src/engine/gfx/generic/generic-merc.gc" + "goal_src/engine/gfx/generic/generic-tie.gc" + "goal_src/engine/gfx/shadow/shadow-cpu.gc" + "goal_src/engine/gfx/shadow/shadow-vu1.gc" + "goal_src/engine/gfx/depth-cue.gc" + "goal_src/engine/gfx/font.gc" + "goal_src/engine/load/decomp.gc" + "goal_src/engine/gfx/background.gc" + "goal_src/engine/draw/draw-node.gc" + "goal_src/engine/gfx/shrub/shrubbery.gc" + "goal_src/engine/gfx/shrub/shrub-work.gc" + "goal_src/engine/gfx/tfrag/tfrag-near.gc" + "goal_src/engine/gfx/tfrag/tfrag.gc" + "goal_src/engine/gfx/tfrag/tfrag-methods.gc" + "goal_src/engine/gfx/tfrag/tfrag-work.gc" + "goal_src/engine/gfx/tie/tie.gc" + "goal_src/engine/gfx/tie/tie-near.gc" + "goal_src/engine/gfx/tie/tie-work.gc" + "goal_src/engine/gfx/tie/tie-methods.gc" + "goal_src/engine/util/sync-info.gc" + "goal_src/engine/physics/trajectory.gc" + "goal_src/engine/sparticle/sparticle-launcher.gc" + "goal_src/engine/sparticle/sparticle.gc" + "goal_src/engine/entity/entity-table.gc" + "goal_src/engine/load/loader.gc" + "goal_src/engine/game/task/task-control-h.gc" + "goal_src/engine/game/game-info.gc" + "goal_src/engine/game/game-save.gc" + "goal_src/engine/game/settings.gc" + "goal_src/engine/ambient/mood-tables.gc" + "goal_src/engine/ambient/mood.gc" + "goal_src/engine/ambient/weather-part.gc" + "goal_src/engine/gfx/time-of-day.gc" + "goal_src/engine/gfx/sky/sky-utils.gc" + "goal_src/engine/gfx/sky/sky.gc" + "goal_src/engine/gfx/sky/sky-tng.gc" + "goal_src/engine/level/load-boundary-h.gc" + "goal_src/engine/level/load-boundary.gc" + "goal_src/engine/level/load-boundary-data.gc" + "goal_src/engine/level/level-info.gc" + "goal_src/engine/level/level.gc" + "goal_src/engine/ui/text.gc" + "goal_src/engine/collide/collide-probe.gc" + "goal_src/engine/collide/collide-frag.gc" + "goal_src/engine/collide/collide-mesh.gc" + "goal_src/engine/collide/collide-touch.gc" + "goal_src/engine/collide/collide-edge-grab.gc" + "goal_src/engine/collide/collide-shape.gc" + "goal_src/engine/collide/collide-shape-rider.gc" + "goal_src/engine/collide/collide.gc" + "goal_src/engine/collide/collide-planes.gc" + "goal_src/engine/gfx/merc/merc-death.gc" + "goal_src/engine/gfx/water/water-h.gc" + "goal_src/engine/camera/camera.gc" + "goal_src/engine/camera/cam-interface.gc" + "goal_src/engine/camera/cam-master.gc" + "goal_src/engine/camera/cam-states.gc" + "goal_src/engine/camera/cam-states-dbg.gc" + "goal_src/engine/camera/cam-combiner.gc" + "goal_src/engine/camera/cam-update.gc" + "goal_src/engine/geometry/vol-h.gc" + "goal_src/engine/camera/cam-layout.gc" + "goal_src/engine/camera/cam-debug.gc" + "goal_src/engine/camera/cam-start.gc" + "goal_src/engine/draw/process-drawable.gc" + "goal_src/engine/game/task/hint-control.gc" + "goal_src/engine/ambient/ambient.gc" + "goal_src/engine/debug/assert.gc" + "goal_src/engine/game/generic-obs.gc" + "goal_src/engine/target/target-util.gc" + "goal_src/engine/target/target-part.gc" + "goal_src/engine/collide/collide-reaction-target.gc" + "goal_src/engine/target/logic-target.gc" + "goal_src/engine/target/sidekick.gc" + "goal_src/engine/game/voicebox.gc" + "goal_src/engine/target/target-handler.gc" + "goal_src/engine/target/target.gc" + "goal_src/engine/target/target2.gc" + "goal_src/engine/target/target-death.gc" + "goal_src/engine/debug/menu.gc" + "goal_src/engine/draw/drawable.gc" + "goal_src/engine/draw/drawable-group.gc" + "goal_src/engine/draw/drawable-inline-array.gc" + "goal_src/engine/draw/drawable-tree.gc" + "goal_src/engine/gfx/tie/prototype.gc" + "goal_src/engine/collide/main-collide.gc" + "goal_src/engine/game/video.gc" + "goal_src/engine/game/main.gc" + "goal_src/engine/collide/collide-cache.gc" + "goal_src/engine/entity/relocate.gc" + "goal_src/engine/debug/memory-usage.gc" + "goal_src/engine/entity/entity.gc" + "goal_src/engine/nav/path.gc" + "goal_src/engine/geometry/vol.gc" + "goal_src/engine/nav/navigate.gc" + "goal_src/engine/anim/aligner.gc" + "goal_src/engine/game/effect-control.gc" + "goal_src/engine/gfx/water/water.gc" + "goal_src/engine/game/collectables-part.gc" + "goal_src/engine/game/collectables.gc" + "goal_src/engine/game/task/task-control.gc" + "goal_src/engine/game/task/process-taskable.gc" + "goal_src/engine/camera/pov-camera.gc" + "goal_src/engine/game/powerups.gc" + "goal_src/engine/game/crates.gc" + "goal_src/engine/ui/hud.gc" + "goal_src/engine/ui/hud-classes.gc" + "goal_src/engine/ui/progress/progress-static.gc" + "goal_src/engine/ui/progress/progress-part.gc" + "goal_src/engine/ui/progress/progress-draw.gc" + "goal_src/engine/ui/progress/progress.gc" + "goal_src/engine/ui/credits.gc" + "goal_src/engine/game/projectiles.gc" + "goal_src/engine/gfx/ocean/ocean.gc" + "goal_src/engine/gfx/ocean/ocean-vu0.gc" + "goal_src/engine/gfx/ocean/ocean-texture.gc" + "goal_src/engine/gfx/ocean/ocean-mid.gc" + "goal_src/engine/gfx/ocean/ocean-transition.gc" + "goal_src/engine/gfx/ocean/ocean-near.gc" + "goal_src/engine/gfx/shadow/shadow.gc" + "goal_src/engine/gfx/eye.gc" + "goal_src/engine/util/glist-h.gc" + "goal_src/engine/util/glist.gc" + "goal_src/engine/debug/anim-tester.gc" + "goal_src/engine/debug/viewer.gc" + "goal_src/engine/debug/part-tester.gc" + "goal_src/engine/debug/default-menu.gc" + "goal_src/levels/common/texture-upload.gc" + "goal_src/levels/common/rigid-body-h.gc" + "goal_src/levels/common/water-anim.gc" + "goal_src/levels/common/dark-eco-pool.gc" + "goal_src/levels/common/rigid-body.gc" + "goal_src/levels/common/nav-enemy-h.gc" + "goal_src/levels/common/nav-enemy.gc" + "goal_src/levels/common/baseplat.gc" + "goal_src/levels/common/basebutton.gc" + "goal_src/levels/common/tippy.gc" + "goal_src/levels/common/joint-exploder.gc" + "goal_src/levels/common/babak.gc" + "goal_src/levels/common/sharkey.gc" + "goal_src/levels/common/orb-cache.gc" + "goal_src/levels/common/plat.gc" + "goal_src/levels/common/plat-button.gc" + "goal_src/levels/common/plat-eco.gc" + "goal_src/levels/common/ropebridge.gc" + "goal_src/levels/common/ticky.gc" + "goal_src/levels/common/mistycannon.gc" + "goal_src/levels/common/babak-with-cannon.gc" + "goal_src/levels/beach/air-h.gc" + "goal_src/levels/beach/air.gc" + "goal_src/levels/beach/wobbler.gc" + "goal_src/levels/beach/twister.gc" + "goal_src/levels/beach/beach-obs.gc" + "goal_src/levels/beach/bird-lady.gc" + "goal_src/levels/beach/bird-lady-beach.gc" + "goal_src/levels/beach/mayor.gc" + "goal_src/levels/beach/sculptor.gc" + "goal_src/levels/beach/pelican.gc" + "goal_src/levels/beach/lurkerworm.gc" + "goal_src/levels/beach/lurkercrab.gc" + "goal_src/levels/beach/lurkerpuppy.gc" + "goal_src/levels/beach/beach-rocks.gc" + "goal_src/levels/beach/seagull.gc" + "goal_src/levels/beach/beach-part.gc" + "goal_src/levels/village_common/villagep-obs.gc" + "goal_src/levels/village_common/oracle.gc" + "goal_src/levels/common/battlecontroller.gc" + "goal_src/levels/citadel/citadel-part.gc" + "goal_src/levels/citadel/citadel-obs.gc" + "goal_src/levels/citadel/citb-plat.gc" + "goal_src/levels/citadel/citadel-sages.gc" + "goal_src/levels/common/snow-bunny.gc" + "goal_src/levels/citadel/citb-bunny.gc" + "goal_src/levels/citadel/citb-drop-plat-CIT.gc" + "goal_src/levels/l1_only/citb-drop-plat-L1.gc" + "goal_src/levels/citadel/assistant-citadel.gc" + "goal_src/levels/darkcave/darkcave-obs.gc" + "goal_src/levels/demo/demo-obs.gc" + "goal_src/levels/common/static-screen.gc" + "goal_src/levels/finalboss/robotboss-h.gc" + "goal_src/levels/finalboss/robotboss-part.gc" + "goal_src/levels/finalboss/sage-finalboss-part.gc" + "goal_src/levels/finalboss/light-eco.gc" + "goal_src/levels/finalboss/robotboss-weapon.gc" + "goal_src/levels/finalboss/robotboss-misc.gc" + "goal_src/levels/finalboss/green-eco-lurker.gc" + "goal_src/levels/finalboss/robotboss.gc" + "goal_src/levels/finalboss/final-door.gc" + "goal_src/levels/finalboss/sage-finalboss-FIN.gc" + "goal_src/levels/l1_only/sage-finalboss-L1.gc" + "goal_src/levels/intro/evilbro.gc" + "goal_src/levels/jungleb/jungleb-obs.gc" + "goal_src/levels/jungleb/plat-flip.gc" + "goal_src/levels/jungleb/aphid.gc" + "goal_src/levels/jungleb/plant-boss.gc" + "goal_src/levels/jungle/jungle-elevator.gc" + "goal_src/levels/jungle/bouncer.gc" + "goal_src/levels/jungle/hopper.gc" + "goal_src/levels/jungle/junglesnake.gc" + "goal_src/levels/jungle/darkvine.gc" + "goal_src/levels/jungle/jungle-obs.gc" + "goal_src/levels/jungle/jungle-mirrors.gc" + "goal_src/levels/jungle/junglefish.gc" + "goal_src/levels/jungle/fisher-JUN.gc" + "goal_src/levels/jungle/fisher-JUNGLE-L1.gc" + "goal_src/levels/jungle/jungle-part.gc" + "goal_src/levels/common/launcherdoor.gc" + "goal_src/levels/l1_only/target-racer-h-L1-RACERP.gc" + "goal_src/levels/racer_common/target-racer-h-FIC-LAV-MIS-OGR-ROL.gc" + "goal_src/levels/racer_common/racer-part.gc" + "goal_src/levels/racer_common/racer.gc" + "goal_src/levels/l1_only/target-racer-L1-RACERP.gc" + "goal_src/levels/racer_common/target-racer-FIC-LAV-MIS-OGR-ROL.gc" + "goal_src/levels/l1_only/racer-states-L1-RACERP.gc" + "goal_src/levels/racer_common/racer-states-FIC-LAV-MIS-OGR-ROL.gc" + "goal_src/levels/racer_common/collide-reaction-racer.gc" + "goal_src/levels/common/blocking-plane.gc" + "goal_src/levels/flut_common/flut-part.gc" + "goal_src/levels/flut_common/flutflut.gc" + "goal_src/levels/flut_common/target-flut.gc" + "goal_src/levels/village1/farmer.gc" + "goal_src/levels/village1/explorer.gc" + "goal_src/levels/village1/assistant.gc" + "goal_src/levels/village1/sage.gc" + "goal_src/levels/village1/yakow.gc" + "goal_src/levels/l1_only/village-obs-L1.gc" + "goal_src/levels/village1/village-obs-VI1.gc" + "goal_src/levels/village1/fishermans-boat.gc" + "goal_src/levels/village1/village1-part.gc" + "goal_src/levels/village1/village1-part2.gc" + "goal_src/levels/village1/sequence-a-village1.gc" + "goal_src/levels/training/training-obs.gc" + "goal_src/levels/training/training-part.gc" + "goal_src/levels/misty/misty-obs.gc" + "goal_src/levels/misty/misty-warehouse.gc" + "goal_src/levels/misty/misty-conveyor.gc" + "goal_src/levels/misty/mud.gc" + "goal_src/levels/misty/muse.gc" + "goal_src/levels/misty/bonelurker.gc" + "goal_src/levels/misty/quicksandlurker.gc" + "goal_src/levels/misty/misty-teetertotter.gc" + "goal_src/levels/misty/balloonlurker.gc" + "goal_src/levels/misty/misty-part.gc" + "goal_src/levels/misty/sidekick-human.gc" + "goal_src/levels/firecanyon/firecanyon-part.gc" + "goal_src/levels/firecanyon/assistant-firecanyon.gc" + "goal_src/levels/village2/village2-part.gc" + "goal_src/levels/village2/village2-obs.gc" + "goal_src/levels/village2/village2-part2.gc" + "goal_src/levels/village2/gambler.gc" + "goal_src/levels/village2/warrior.gc" + "goal_src/levels/village2/geologist.gc" + "goal_src/levels/village2/swamp-blimp.gc" + "goal_src/levels/village2/sage-bluehut.gc" + "goal_src/levels/village2/flutflut-bluehut.gc" + "goal_src/levels/village2/assistant-village2.gc" + "goal_src/levels/village2/sunken-elevator.gc" + "goal_src/levels/swamp/swamp-obs.gc" + "goal_src/levels/swamp/swamp-bat.gc" + "goal_src/levels/swamp/swamp-rat.gc" + "goal_src/levels/swamp/swamp-rat-nest.gc" + "goal_src/levels/swamp/kermit.gc" + "goal_src/levels/swamp/swamp-part.gc" + "goal_src/levels/swamp/billy.gc" + "goal_src/levels/maincave/cavecrystal-light.gc" + "goal_src/levels/maincave/maincave-obs.gc" + "goal_src/levels/maincave/maincave-part.gc" + "goal_src/levels/maincave/spiderwebs.gc" + "goal_src/levels/maincave/dark-crystal.gc" + "goal_src/levels/maincave/baby-spider.gc" + "goal_src/levels/maincave/mother-spider-h.gc" + "goal_src/levels/maincave/mother-spider-egg.gc" + "goal_src/levels/maincave/mother-spider-proj.gc" + "goal_src/levels/maincave/mother-spider.gc" + "goal_src/levels/maincave/gnawer.gc" + "goal_src/levels/maincave/driller-lurker.gc" + "goal_src/levels/sunken/sunken-part.gc" + "goal_src/levels/sunken/sunken-part2.gc" + "goal_src/levels/sunken/sunken-part3.gc" + "goal_src/levels/sunken/sunken-part4.gc" + "goal_src/levels/sunken/sunken-part5.gc" + "goal_src/levels/sunken/target-tube.gc" + "goal_src/levels/sunken/sunken-obs.gc" + "goal_src/levels/sunken/shover.gc" + "goal_src/levels/sunken/square-platform.gc" + "goal_src/levels/sunken/sun-iris-door.gc" + "goal_src/levels/sunken/orbit-plat.gc" + "goal_src/levels/sunken/wedge-plats.gc" + "goal_src/levels/sunken/wall-plat.gc" + "goal_src/levels/sunken/qbert-plat.gc" + "goal_src/levels/sunken/steam-cap.gc" + "goal_src/levels/sunken/sun-exit-chamber.gc" + "goal_src/levels/sunken/floating-launcher.gc" + "goal_src/levels/sunken/sunken-water.gc" + "goal_src/levels/sunken/whirlpool.gc" + "goal_src/levels/sunken/sunken-pipegame.gc" + "goal_src/levels/sunken/bully.gc" + "goal_src/levels/sunken/double-lurker.gc" + "goal_src/levels/sunken/helix-water.gc" + "goal_src/levels/sunken/puffer.gc" + "goal_src/levels/sunken/sunken-fish.gc" + "goal_src/levels/rolling/rolling-obs.gc" + "goal_src/levels/rolling/rolling-lightning-mole.gc" + "goal_src/levels/rolling/rolling-robber.gc" + "goal_src/levels/rolling/rolling-race-ring.gc" + "goal_src/levels/firecanyon/firecanyon-obs.gc" + "goal_src/levels/ogre/ogre-part.gc" + "goal_src/levels/ogre/ogreboss.gc" + "goal_src/levels/ogre/ogre-obs.gc" + "goal_src/levels/ogre/flying-lurker.gc" + "goal_src/levels/village3/village3-part.gc" + "goal_src/levels/village3/village3-obs.gc" + "goal_src/levels/village3/minecart.gc" + "goal_src/levels/village3/miners.gc" + "goal_src/levels/village3/assistant-village3.gc" + "goal_src/levels/village3/sage-village3.gc" + "goal_src/levels/robocave/cave-trap.gc" + "goal_src/levels/robocave/spider-egg.gc" + "goal_src/levels/robocave/robocave-part.gc" + "goal_src/levels/snow/target-snowball.gc" + "goal_src/levels/snow/target-ice.gc" + "goal_src/levels/snow/ice-cube.gc" + "goal_src/levels/snow/snow-ball.gc" + "goal_src/levels/snow/snow-obs.gc" + "goal_src/levels/snow/snow-flutflut-obs.gc" + "goal_src/levels/snow/snow-bumper.gc" + "goal_src/levels/snow/snow-ram-h.gc" + "goal_src/levels/snow/snow-ram-boss.gc" + "goal_src/levels/snow/snow-ram.gc" + "goal_src/levels/snow/snow-part.gc" + "goal_src/levels/snow/yeti.gc" + "goal_src/levels/lavatube/lavatube-obs.gc" + "goal_src/levels/lavatube/lavatube-energy.gc" + "goal_src/levels/lavatube/lavatube-part.gc" + "goal_src/levels/lavatube/assistant-lavatube.gc" + "goal_src/levels/title/title-obs.gc" + "goal_src/old/lava/lava.gc" + ) + ) \ No newline at end of file diff --git a/goal_src/goal-lib.gc b/goal_src/goal-lib.gc index da2e5bf547..2c746a53fb 100644 --- a/goal_src/goal-lib.gc +++ b/goal_src/goal-lib.gc @@ -1,3 +1,7 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; BUILD SYSTEM +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; compile, color, and save a file (defmacro m (file) `(asm-file ,file :color :write) @@ -8,6 +12,20 @@ `(asm-file ,file :color :load :write) ) +(desfun make-build-command (file) + `(asm-file ,file :color :write) + ) + +(defmacro build-game () + `(begin + ,@(apply make-build-command all-goal-files) + (build-dgos "goal_src/build/dgos.txt") + ) + ) + +;; load list of all goal files +(asm-file "goal_src/build/all_files.gc") + (defmacro e () `(:exit) ) diff --git a/goal_src/test/test-add-function-returns.gc b/goal_src/test/test-add-function-returns.gc new file mode 100644 index 0000000000..85989a928d --- /dev/null +++ b/goal_src/test/test-add-function-returns.gc @@ -0,0 +1,16 @@ +(defun return-one () + 1) + +(defun return-sum ((a integer) (b integer)) + (+ a b) + ) + +(defun return-plus-two ((in integer)) + (+ in 2) + ) + +(defun return-plus-three ((in integer)) + (+ 3 in) + ) + +(+ 2 (return-one) (return-plus-three 2) (return-plus-two 3) (return-sum 1 2) (return-plus-two 3)) \ No newline at end of file diff --git a/goal_src/test/test-add-int-constants.gc b/goal_src/test/test-add-int-constants.gc new file mode 100644 index 0000000000..422b5923f5 --- /dev/null +++ b/goal_src/test/test-add-int-constants.gc @@ -0,0 +1 @@ +(+ 15 -2) \ No newline at end of file diff --git a/goal_src/test/test-add-int-multiple-2.gc b/goal_src/test/test-add-int-multiple-2.gc new file mode 100644 index 0000000000..82a3684b08 --- /dev/null +++ b/goal_src/test/test-add-int-multiple-2.gc @@ -0,0 +1,11 @@ +(defun add-five-v2 ((a int32) (b int32) (c int32) (d int32) (e int32)) + (let* ((total-1 a) + (also-d d) + (total-2 (+ total-1 b)) + (total-3 (+ c total-2)) + ) + (+ total-3 e also-d) + ) + ) + +(add-five 1 2 3 4 5) diff --git a/goal_src/test/test-add-int-multiple.gc b/goal_src/test/test-add-int-multiple.gc new file mode 100644 index 0000000000..5e13e42805 --- /dev/null +++ b/goal_src/test/test-add-int-multiple.gc @@ -0,0 +1,5 @@ +(defun add-five ((a integer) (b integer) (c integer) (d integer) (e integer)) + (+ c d (+ e a) b) + ) + +(add-five 1 2 3 4 5) \ No newline at end of file diff --git a/goal_src/test/test-add-int-vars.gc b/goal_src/test/test-add-int-vars.gc new file mode 100644 index 0000000000..3de3bff655 --- /dev/null +++ b/goal_src/test/test-add-int-vars.gc @@ -0,0 +1,5 @@ +(defun add-two ((x integer) (y integer)) + (+ x y) + ) + +(add-two 3 4) \ No newline at end of file diff --git a/goal_src/test/test-build-game.gc b/goal_src/test/test-build-game.gc new file mode 100644 index 0000000000..83f28a46fb --- /dev/null +++ b/goal_src/test/test-build-game.gc @@ -0,0 +1,6 @@ +(build-game) +;(define-extern global kheap) +;(define-extern dgo-load (function string kheap int int int)) +;(dgo-load "kernel" global #xf #x200000) ; todo, remove once kernel loads itself. +;(dgo-load "game" global #xf #x200000) +1 \ No newline at end of file diff --git a/goal_src/test/test-mul-1.gc b/goal_src/test/test-mul-1.gc new file mode 100644 index 0000000000..40a27765ad --- /dev/null +++ b/goal_src/test/test-mul-1.gc @@ -0,0 +1,5 @@ +(defun product ((a integer) (b integer)) + (* b a) + ) + +(product 4 -3) \ No newline at end of file diff --git a/goal_src/test/test-sub-1.gc b/goal_src/test/test-sub-1.gc new file mode 100644 index 0000000000..a0556c9610 --- /dev/null +++ b/goal_src/test/test-sub-1.gc @@ -0,0 +1,16 @@ +(defun negative ((a integer)) + (- a) + ) + +(defun minus-two ((a integer)) + (- a 2) + ) + + +(defun sub-test ((a integer) (b integer)) + (- 1 a b) + ) + +(let ((x (sub-test 1 (minus-two 7)))) + (- 1 x (- -2)) + ) diff --git a/goal_src/test/test-sub-2.gc b/goal_src/test/test-sub-2.gc new file mode 100644 index 0000000000..321c930931 --- /dev/null +++ b/goal_src/test/test-sub-2.gc @@ -0,0 +1,17 @@ +(defun negative ((a integer)) + (- a) + ) + +(defun minus-two ((a integer)) + (- a 2) + ) + + +(defun sub-test ((a integer) (b integer)) + (- 1 a b) + ) + +(let ((x (sub-test 1 (minus-two 7)))) + (- 1 (negative -2) x) + ) + diff --git a/goalc/CMakeLists.txt b/goalc/CMakeLists.txt index 50a6ae967f..0c9ba1f0f4 100644 --- a/goalc/CMakeLists.txt +++ b/goalc/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(compiler compiler/compilation/CompilerControl.cpp compiler/compilation/Block.cpp compiler/compilation/Macro.cpp + compiler/compilation/Math.cpp compiler/compilation/Define.cpp compiler/compilation/Function.cpp compiler/Util.cpp diff --git a/goalc/compiler/CodeGenerator.cpp b/goalc/compiler/CodeGenerator.cpp index 8864d52939..c7513e21cf 100644 --- a/goalc/compiler/CodeGenerator.cpp +++ b/goalc/compiler/CodeGenerator.cpp @@ -86,13 +86,21 @@ void CodeGenerator::do_function(FunctionEnv* env, int f_idx) { auto& bonus = allocs.stack_ops.at(ir_idx); for (auto& op : bonus.ops) { if (op.load) { - assert(false); + if (op.reg.is_gpr()) { + m_gen.add_instr(IGen::load64_gpr64_plus_s32(op.reg, op.slot * GPR_SIZE, RSP), i_rec); + } else { + assert(false); + } } } ir->do_codegen(&m_gen, allocs, i_rec); for (auto& op : bonus.ops) { if (op.store) { - assert(false); + if (op.reg.is_gpr()) { + m_gen.add_instr(IGen::store64_gpr64_plus_s32(RSP, op.slot * GPR_SIZE, op.reg), i_rec); + } else { + assert(false); + } } } } diff --git a/goalc/compiler/Compiler.cpp b/goalc/compiler/Compiler.cpp index b03bdaa400..f50a2826a9 100644 --- a/goalc/compiler/Compiler.cpp +++ b/goalc/compiler/Compiler.cpp @@ -158,6 +158,7 @@ void Compiler::color_object_file(FileEnv* env) { input.debug_settings.print_input = true; input.debug_settings.print_result = true; input.debug_settings.print_analysis = true; + input.debug_settings.allocate_log_level = 2; } f->set_allocations(allocate_registers(input)); @@ -186,6 +187,9 @@ std::vector Compiler::run_test(const std::string& source_code) { auto code = m_goos.reader.read_from_file({source_code}); auto compiled = compile_object_file("test-code", code, true); + if (compiled->is_empty()) { + return {}; + } color_object_file(compiled); auto data = codegen_object_file(compiled); m_listener.record_messages(ListenerMessageKind::MSG_PRINT); @@ -200,6 +204,12 @@ std::vector Compiler::run_test(const std::string& source_code) { } } +std::vector Compiler::run_test_no_load(const std::string& source_code) { + auto code = m_goos.reader.read_from_file({source_code}); + auto compiled = compile_object_file("test-code", code, true); + return {}; +} + void Compiler::shutdown_target() { if (m_listener.is_connected()) { m_listener.send_reset(true); diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index aa00e90137..af93e5325b 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -8,6 +8,8 @@ #include "goalc/compiler/IR.h" #include "CompilerSettings.h" +enum MathMode { MATH_INT, MATH_BINT, MATH_FLOAT, MATH_INVALID }; + class Compiler { public: Compiler(); @@ -24,6 +26,7 @@ class Compiler { None* get_none() { return m_none.get(); } std::vector run_test(const std::string& source_code); + std::vector run_test_no_load(const std::string& source_code); void shutdown_target(); private: @@ -83,6 +86,16 @@ class Compiler { std::unordered_map, goos::Object> m_global_constants; std::unordered_map, LambdaVal*> m_inlineable_functions; CompilerSettings m_settings; + MathMode get_math_mode(const TypeSpec& ts); + bool is_number(const TypeSpec& ts); + bool is_float(const TypeSpec& ts); + bool is_integer(const TypeSpec& ts); + bool is_binteger(const TypeSpec& ts); + bool is_singed_integer_or_binteger(const TypeSpec& ts); + Val* number_to_integer(Val* in, Env* env); + Val* number_to_float(Val* in, Env* env); + Val* number_to_binteger(Val* in, Env* env); + Val* to_math_type(Val* in, MathMode mode, Env* env); public: // Atoms @@ -104,6 +117,8 @@ class Compiler { Val* compile_poke(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_gs(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_set_config(const goos::Object& form, const goos::Object& rest, Env* env); + Val* compile_in_package(const goos::Object& form, const goos::Object& rest, Env* env); + Val* compile_build_dgo(const goos::Object& form, const goos::Object& rest, Env* env); // Define Val* compile_define(const goos::Object& form, const goos::Object& rest, Env* env); @@ -114,6 +129,11 @@ class Compiler { Val* compile_quote(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_defglobalconstant(const goos::Object& form, const goos::Object& rest, Env* env); + // Math + Val* compile_add(const goos::Object& form, const goos::Object& rest, Env* env); + Val* compile_sub(const goos::Object& form, const goos::Object& rest, Env* env); + Val* compile_mul(const goos::Object& form, const goos::Object& rest, Env* env); + // Function Val* compile_lambda(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_inline(const goos::Object& form, const goos::Object& rest, Env* env); diff --git a/goalc/compiler/CompilerSettings.cpp b/goalc/compiler/CompilerSettings.cpp index 81463587f0..eec56ac010 100644 --- a/goalc/compiler/CompilerSettings.cpp +++ b/goalc/compiler/CompilerSettings.cpp @@ -6,6 +6,9 @@ CompilerSettings::CompilerSettings() { m_settings["print-regalloc"].kind = SettingKind::BOOL; m_settings["print-regalloc"].boolp = &debug_print_regalloc; + + m_settings["disable-math-const-prop"].kind = SettingKind::BOOL; + m_settings["disable-math-const-prop"].boolp = &disable_math_const_prop; } void CompilerSettings::set(const std::string& name, const goos::Object& value) { diff --git a/goalc/compiler/CompilerSettings.h b/goalc/compiler/CompilerSettings.h index fa6d9b56b4..6bf4badd45 100644 --- a/goalc/compiler/CompilerSettings.h +++ b/goalc/compiler/CompilerSettings.h @@ -10,6 +10,9 @@ class CompilerSettings { CompilerSettings(); bool debug_print_ir = false; bool debug_print_regalloc = false; + bool disable_math_const_prop = false; + bool emit_move_after_return = true; + void set(const std::string& name, const goos::Object& value); private: diff --git a/goalc/compiler/IR.cpp b/goalc/compiler/IR.cpp index 8d046af51b..5c8ccb8146 100644 --- a/goalc/compiler/IR.cpp +++ b/goalc/compiler/IR.cpp @@ -350,4 +350,56 @@ void IR_FunctionAddr::do_codegen(emitter::ObjectGenerator* gen, auto instr = gen->add_instr(IGen::static_addr(dr, 0), irec); gen->link_instruction_to_function(instr, gen->get_existing_function_record(m_src->idx_in_file)); gen->add_instr(IGen::sub_gpr64_gpr64(dr, emitter::gRegInfo.get_offset_reg()), irec); +} + +///////////////////// +// IntegerMath +/////////////////// + +IR_IntegerMath::IR_IntegerMath(IntegerMathKind kind, RegVal* dest, RegVal* arg) + : m_kind(kind), m_dest(dest), m_arg(arg) {} + +std::string IR_IntegerMath::print() { + switch (m_kind) { + case IntegerMathKind::ADD_64: + return fmt::format("addi {}, {}", m_dest->print(), m_arg->print()); + case IntegerMathKind::SUB_64: + return fmt::format("subi {}, {}", m_dest->print(), m_arg->print()); + case IntegerMathKind::IMUL_32: + return fmt::format("imul {}, {}", m_dest->print(), m_arg->print()); + default: + assert(false); + } +} + +RegAllocInstr IR_IntegerMath::to_rai() { + RegAllocInstr rai; + rai.write.push_back(m_dest->ireg()); + rai.read.push_back(m_dest->ireg()); + rai.read.push_back(m_arg->ireg()); + return rai; +} + +void IR_IntegerMath::do_codegen(emitter::ObjectGenerator* gen, + const AllocationResult& allocs, + emitter::IR_Record irec) { + switch (m_kind) { + case IntegerMathKind::ADD_64: + gen->add_instr( + IGen::add_gpr64_gpr64(get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec); + break; + case IntegerMathKind::SUB_64: + gen->add_instr( + IGen::sub_gpr64_gpr64(get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec); + break; + case IntegerMathKind::IMUL_32: { + auto dr = get_reg(m_dest, allocs, irec); + gen->add_instr(IGen::imul_gpr32_gpr32(dr, get_reg(m_arg, allocs, irec)), irec); + gen->add_instr(IGen::movsx_r64_r32(dr, dr), irec); + } + + break; + default: + assert(false); + } } \ No newline at end of file diff --git a/goalc/compiler/IR.h b/goalc/compiler/IR.h index d7cfa70f85..0443eb4279 100644 --- a/goalc/compiler/IR.h +++ b/goalc/compiler/IR.h @@ -173,4 +173,37 @@ class IR_FunctionAddr : public IR { FunctionEnv* m_src = nullptr; }; +enum class IntegerMathKind { + ADD_64, + SUB_64, + IMUL_32, + IDIV_32, + SHLV_64, + SARV_64, + SHRV_64, + SHL_64, + SAR_64, + SHR_64, + IMOD_32, + OR_64, + AND_64, + XOR_64, + NOT_64 +}; + +class IR_IntegerMath : public IR { + public: + IR_IntegerMath(IntegerMathKind kind, RegVal* dest, RegVal* arg); + std::string print() override; + RegAllocInstr to_rai() override; + void do_codegen(emitter::ObjectGenerator* gen, + const AllocationResult& allocs, + emitter::IR_Record irec) override; + + protected: + IntegerMathKind m_kind; + RegVal* m_dest; + RegVal* m_arg; +}; + #endif // JAK_IR_H diff --git a/goalc/compiler/Val.h b/goalc/compiler/Val.h index 21e4015c72..239ee59fe0 100644 --- a/goalc/compiler/Val.h +++ b/goalc/compiler/Val.h @@ -131,13 +131,23 @@ class StaticVal : public Val { class IntegerConstantVal : public Val { public: - IntegerConstantVal(TypeSpec ts, s64 value) : Val(ts), m_value(value) {} + IntegerConstantVal(TypeSpec ts, s64 value) : Val(std::move(ts)), m_value(value) {} std::string print() const override { return "integer-constant-" + std::to_string(m_value); } RegVal* to_reg(Env* fe) override; protected: s64 m_value = -1; }; + +class FloatConstantVal : public Val { + public: + FloatConstantVal(TypeSpec ts, float value) : Val(std::move(ts)), m_value(value) {} + std::string print() const override { return "float-constant-" + std::to_string(m_value); } + RegVal* to_reg(Env* fe) override; + + protected: + float m_value = -1.f; +}; // IntegerConstant // FloatConstant // Bitfield diff --git a/goalc/compiler/compilation/Atoms.cpp b/goalc/compiler/compilation/Atoms.cpp index 60e2303aba..e1ade2fb5f 100644 --- a/goalc/compiler/compilation/Atoms.cpp +++ b/goalc/compiler/compilation/Atoms.cpp @@ -37,7 +37,7 @@ static const std::unordered_map< {"reset-target", &Compiler::compile_reset_target}, {":status", &Compiler::compile_poke}, // {"test", &Compiler::compile_test}, - // {"in-package", &Compiler::compile_in_package}, + {"in-package", &Compiler::compile_in_package}, // // // CONDITIONAL COMPILATION {"#cond", &Compiler::compile_gscond}, @@ -102,9 +102,9 @@ static const std::unordered_map< // {"cdr", &Compiler::compile_cdr}, // // // IT IS MATH - // {"+", &Compiler::compile_add}, - // {"-", &Compiler::compile_sub}, - // {"*", &Compiler::compile_mult}, + {"+", &Compiler::compile_add}, + {"-", &Compiler::compile_sub}, + {"*", &Compiler::compile_mul}, // {"/", &Compiler::compile_divide}, // {"shlv", &Compiler::compile_shlv}, // {"shrv", &Compiler::compile_shrv}, @@ -127,7 +127,7 @@ static const std::unordered_map< // {">", &Compiler::compile_condition_as_bool}, // // // BUILDER (build-dgo/build-cgo?) - // {"builder", &Compiler::compile_builder}, + {"build-dgos", &Compiler::compile_build_dgo}, // // // UTIL {"set-config!", &Compiler::compile_set_config}, diff --git a/goalc/compiler/compilation/CompilerControl.cpp b/goalc/compiler/compilation/CompilerControl.cpp index 7ece53faba..48113cb4a6 100644 --- a/goalc/compiler/compilation/CompilerControl.cpp +++ b/goalc/compiler/compilation/CompilerControl.cpp @@ -1,6 +1,7 @@ #include "goalc/compiler/Compiler.h" #include "goalc/compiler/IR.h" #include "common/util/Timer.h" +#include "common/util/DgoWriter.h" #include "common/util/FileUtil.h" Val* Compiler::compile_exit(const goos::Object& form, const goos::Object& rest, Env* env) { @@ -67,6 +68,7 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re for (int idx = int(filename.size()) - 1; idx-- > 0;) { if (filename.at(idx) == '\\' || filename.at(idx) == '/') { obj_file_name = filename.substr(idx + 1); + break; } } @@ -94,7 +96,7 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re if (write) { // auto output_dir = as_string(get_constant_or_error(form, "*compiler-output-path*")); // todo, change extension based on v3/v4 - auto output_name = m_goos.reader.get_source_dir() + "/out/" + obj_file_name + ".o"; + auto output_name = m_goos.reader.get_source_dir() + "/data/" + obj_file_name + ".o"; file_util::write_binary_file(output_name, (void*)data.data(), data.size()); } } else { @@ -108,9 +110,11 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re } // if(truthy(get_config("print-asm-file-time"))) { + printf("F: %36s ", obj_file_name.c_str()); for (auto& e : timing) { - printf(" %12s %4.2f\n", e.first.c_str(), e.second); + printf(" %12s %4.2f", e.first.c_str(), e.second); } + printf("\n"); // } return get_none(); @@ -181,5 +185,41 @@ Val* Compiler::compile_set_config(const goos::Object& form, const goos::Object& auto args = get_va(form, rest); va_check(form, args, {goos::ObjectType::SYMBOL, {}}, {}); m_settings.set(symbol_string(args.unnamed.at(0)), args.unnamed.at(1)); + return get_none(); +} + +Val* Compiler::compile_in_package(const goos::Object& form, const goos::Object& rest, Env* env) { + (void)form; + (void)rest; + (void)env; + return get_none(); +} + +Val* Compiler::compile_build_dgo(const goos::Object& form, const goos::Object& rest, Env* env) { + (void)env; + auto args = get_va(form, rest); + va_check(form, args, {goos::ObjectType::STRING}, {}); + auto dgo_desc = pair_cdr(m_goos.reader.read_from_file({args.unnamed.at(0).as_string()->data})); + + for_each_in_list(dgo_desc, [&](const goos::Object& dgo) { + DgoDescription desc; + auto first = pair_car(dgo); + desc.dgo_name = as_string(first); + auto dgo_rest = pair_cdr(dgo); + + for_each_in_list(dgo_rest, [&](const goos::Object& entry) { + auto e_arg = get_va(dgo, entry); + va_check(dgo, e_arg, {goos::ObjectType::STRING, goos::ObjectType::STRING}, {}); + DgoDescription::DgoEntry o; + o.file_name = as_string(e_arg.unnamed.at(0)); + o.name_in_dgo = as_string(e_arg.unnamed.at(1)); + if (o.file_name.substr(o.file_name.length() - 3) != ".go") { // kill v2's for now. + desc.entries.push_back(o); + } + }); + + build_dgo(desc); + }); + return get_none(); } \ No newline at end of file diff --git a/goalc/compiler/compilation/Function.cpp b/goalc/compiler/compilation/Function.cpp index aea6a32228..48f33ef192 100644 --- a/goalc/compiler/compilation/Function.cpp +++ b/goalc/compiler/compilation/Function.cpp @@ -351,5 +351,12 @@ Val* Compiler::compile_real_function_call(const goos::Object& form, } env->emit(std::make_unique(function, return_reg, arg_outs)); - return return_reg; + + if (m_settings.emit_move_after_return) { + auto result_reg = env->make_gpr(return_reg->type()); + env->emit(std::make_unique(result_reg, return_reg)); + return result_reg; + } else { + return return_reg; + } } \ No newline at end of file diff --git a/goalc/compiler/compilation/Math.cpp b/goalc/compiler/compilation/Math.cpp new file mode 100644 index 0000000000..8a9f16689a --- /dev/null +++ b/goalc/compiler/compilation/Math.cpp @@ -0,0 +1,203 @@ +#include "goalc/compiler/Compiler.h" + +MathMode Compiler::get_math_mode(const TypeSpec& ts) { + if (m_ts.typecheck(m_ts.make_typespec("binteger"), ts, "", false, false)) { + return MATH_BINT; + } + + if (m_ts.typecheck(m_ts.make_typespec("integer"), ts, "", false, false)) { + return MATH_INT; + } + + if (m_ts.typecheck(m_ts.make_typespec("float"), ts, "", false, false)) { + return MATH_FLOAT; + } + + return MATH_INVALID; +} + +bool Compiler::is_number(const TypeSpec& ts) { + return m_ts.typecheck(m_ts.make_typespec("number"), ts, "", false, false); +} + +bool Compiler::is_float(const TypeSpec& ts) { + return m_ts.typecheck(m_ts.make_typespec("float"), ts, "", false, false); +} + +bool Compiler::is_integer(const TypeSpec& ts) { + return m_ts.typecheck(m_ts.make_typespec("integer"), ts, "", false, false) && + !m_ts.typecheck(m_ts.make_typespec("binteger"), ts, "", false, false); +} + +bool Compiler::is_binteger(const TypeSpec& ts) { + return m_ts.typecheck(m_ts.make_typespec("binteger"), ts, "", false, false); +} + +bool Compiler::is_singed_integer_or_binteger(const TypeSpec& ts) { + return m_ts.typecheck(m_ts.make_typespec("integer"), ts, "", false, false) && + !m_ts.typecheck(m_ts.make_typespec("uinteger"), ts, "", false, false); +} + +Val* Compiler::number_to_integer(Val* in, Env* env) { + auto ts = in->type(); + if (is_binteger(ts)) { + assert(false); + } else if (is_float(ts)) { + assert(false); + } else if (is_integer(ts)) { + return in; + } else { + assert(false); + } +} + +Val* Compiler::number_to_binteger(Val* in, Env* env) { + auto ts = in->type(); + if (is_binteger(ts)) { + return in; + } else if (is_float(ts)) { + assert(false); + } else if (is_integer(ts)) { + assert(false); + } else { + assert(false); + } +} + +Val* Compiler::number_to_float(Val* in, Env* env) { + auto ts = in->type(); + if (is_binteger(ts)) { + assert(false); + } else if (is_float(ts)) { + return in; + } else if (is_integer(ts)) { + assert(false); + } else { + assert(false); + } +} + +Val* Compiler::to_math_type(Val* in, MathMode mode, Env* env) { + switch (mode) { + case MATH_BINT: + return number_to_binteger(in, env); + case MATH_INT: + return number_to_integer(in, env); + case MATH_FLOAT: + return number_to_float(in, env); + default: + assert(false); + } +} + +Val* Compiler::compile_add(const goos::Object& form, const goos::Object& rest, Env* env) { + auto args = get_va(form, rest); + if (!args.named.empty() || args.unnamed.empty()) { + throw_compile_error(form, "Invalid + form"); + } + + // look at the first value to determine the math mode + auto first_val = compile_error_guard(args.unnamed.at(0), env); + auto first_type = first_val->type(); + auto math_type = get_math_mode(first_type); + switch (math_type) { + case MATH_INT: { + auto result = env->make_gpr(first_type); + env->emit(std::make_unique(result, first_val->to_gpr(env))); + + for (size_t i = 1; i < args.unnamed.size(); i++) { + env->emit(std::make_unique( + IntegerMathKind::ADD_64, result, + to_math_type(compile_error_guard(args.unnamed.at(i), env), math_type, env) + ->to_gpr(env))); + } + return result; + } + case MATH_INVALID: + throw_compile_error( + form, "Cannot determine the math mode for object of type " + first_type.print()); + break; + default: + assert(false); + } + assert(false); + return get_none(); +} + +Val* Compiler::compile_mul(const goos::Object& form, const goos::Object& rest, Env* env) { + auto args = get_va(form, rest); + if (!args.named.empty() || args.unnamed.empty()) { + throw_compile_error(form, "Invalid * form"); + } + + // look at the first value to determine the math mode + auto first_val = compile_error_guard(args.unnamed.at(0), env); + auto first_type = first_val->type(); + auto math_type = get_math_mode(first_type); + switch (math_type) { + case MATH_INT: { + auto result = env->make_gpr(first_type); + env->emit(std::make_unique(result, first_val->to_gpr(env))); + + for (size_t i = 1; i < args.unnamed.size(); i++) { + env->emit(std::make_unique( + IntegerMathKind::IMUL_32, result, + to_math_type(compile_error_guard(args.unnamed.at(i), env), math_type, env) + ->to_gpr(env))); + } + return result; + } + case MATH_INVALID: + throw_compile_error( + form, "Cannot determine the math mode for object of type " + first_type.print()); + break; + default: + assert(false); + } + assert(false); + return get_none(); +} + +Val* Compiler::compile_sub(const goos::Object& form, const goos::Object& rest, Env* env) { + auto args = get_va(form, rest); + if (!args.named.empty() || args.unnamed.empty()) { + throw_compile_error(form, "Invalid - form"); + } + + auto first_val = compile_error_guard(args.unnamed.at(0), env); + auto first_type = first_val->type(); + auto math_type = get_math_mode(first_type); + switch (math_type) { + case MATH_INT: + if (args.unnamed.size() == 1) { + auto result = compile_integer(0, env)->to_gpr(env); + env->emit(std::make_unique( + IntegerMathKind::SUB_64, result, + to_math_type(compile_error_guard(args.unnamed.at(0), env), math_type, env) + ->to_gpr(env))); + return result; + } else { + auto result = env->make_gpr(first_type); + env->emit(std::make_unique( + result, to_math_type(compile_error_guard(args.unnamed.at(0), env), math_type, env) + ->to_gpr(env))); + + for (size_t i = 1; i < args.unnamed.size(); i++) { + env->emit(std::make_unique( + IntegerMathKind::SUB_64, result, + to_math_type(compile_error_guard(args.unnamed.at(i), env), math_type, env) + ->to_gpr(env))); + } + return result; + } + + case MATH_INVALID: + throw_compile_error( + form, "Cannot determine the math mode for object of type " + first_type.print()); + break; + default: + assert(false); + } + assert(false); + return get_none(); +} \ No newline at end of file diff --git a/goalc/emitter/IGen.h b/goalc/emitter/IGen.h index fca3273d1b..481e19f7b7 100644 --- a/goalc/emitter/IGen.h +++ b/goalc/emitter/IGen.h @@ -1199,6 +1199,26 @@ class IGen { // TODO, special load/stores of 128 bit values. // TODO, consider specialized stack loads and stores? + static Instruction load64_gpr64_plus_s32(Register dst_reg, int32_t offset, Register src_reg) { + assert(dst_reg.is_gpr()); + assert(src_reg.is_gpr()); + Instruction instr(0x8b); + instr.set_modrm_rex_sib_for_reg_reg_disp32(dst_reg.hw_id(), 2, src_reg.hw_id(), true); + instr.set_disp(Imm(4, offset)); + return instr; + } + + /*! + * Store 64-bits from gpr into memory located at 64-bit reg + 32-bit signed offset. + */ + static Instruction store64_gpr64_plus_s32(Register addr, int32_t offset, Register value) { + assert(addr.is_gpr()); + assert(value.is_gpr()); + Instruction instr(0x89); + instr.set_modrm_rex_sib_for_reg_reg_disp32(value.hw_id(), 2, addr.hw_id(), true); + instr.set_disp(Imm(4, offset)); + return instr; + } //;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; // FUNCTION STUFF diff --git a/goalc/regalloc/Allocator.cpp b/goalc/regalloc/Allocator.cpp index 10e928146f..bbf70f2ad5 100644 --- a/goalc/regalloc/Allocator.cpp +++ b/goalc/regalloc/Allocator.cpp @@ -485,7 +485,8 @@ bool can_var_be_assigned(int var, if (lr.has_constraint && lr.assignment.at(instr - lr.min).is_assigned()) { if (!(ass.occupies_same_reg(lr.assignment.at(instr - lr.min)))) { if (debug_trace >= 2) { - printf("at idx %d self bad\n", instr); + printf("at idx %d self bad (%s) (%s)\n", instr, + lr.assignment.at(instr - lr.min).to_string().c_str(), ass.to_string().c_str()); } return false; diff --git a/goalc/regalloc/Assignment.h b/goalc/regalloc/Assignment.h index 9752d6b073..fea9994a5b 100644 --- a/goalc/regalloc/Assignment.h +++ b/goalc/regalloc/Assignment.h @@ -21,7 +21,7 @@ struct Assignment { } switch (kind) { case Kind::STACK: - result += fmt::format("stack[{:2d}]", stack_slot); + result += fmt::format("s[{:2d}]", stack_slot); break; case Kind::REGISTER: result += emitter::gRegInfo.get_info(reg).name; diff --git a/test/test_compiler_and_runtime.cpp b/test/test_compiler_and_runtime.cpp index f165e020f6..0a731e9488 100644 --- a/test/test_compiler_and_runtime.cpp +++ b/test/test_compiler_and_runtime.cpp @@ -113,6 +113,26 @@ struct CompilerTestRunner { } // namespace +TEST(CompilerAndRuntime, BuildGame) { + std::thread runtime_thread([]() { exec_runtime(0, nullptr); }); + Compiler compiler; + + fprintf(stderr, "about to run test\n"); + + try { + compiler.run_test("goal_src/test/test-build-game.gc"); + } catch (std::exception& e) { + fprintf(stderr, "caught exception %s\n", e.what()); + EXPECT_TRUE(false); + } + fprintf(stderr, "DONE!\n"); + + // todo, tests after loading the game. + + compiler.shutdown_target(); + runtime_thread.join(); +} + TEST(CompilerAndRuntime, CompilerTests) { std::thread runtime_thread([]() { exec_runtime(0, nullptr); }); Compiler compiler; @@ -153,7 +173,18 @@ TEST(CompilerAndRuntime, CompilerTests) { runner.run_test("test-defun-return-symbol.gc", {"42\n"}); runner.run_test("test-function-return-arg.gc", {"23\n"}); runner.run_test("test-nested-function-call.gc", {"2\n"}); + + // math + runner.run_test("test-add-int-constants.gc", {"13\n"}); + runner.run_test("test-add-int-vars.gc", {"7\n"}); + runner.run_test("test-add-int-multiple.gc", {"15\n"}); + runner.run_test("test-add-int-multiple-2.gc", {"15\n"}); + runner.run_test("test-add-function-returns.gc", {"21\n"}); + runner.run_test("test-sub-1.gc", {"4\n"}); + runner.run_test("test-sub-2.gc", {"4\n"}); + runner.run_test("test-mul-1.gc", {"-12\n"}); + compiler.shutdown_target(); runtime_thread.join(); runner.print_summary(); -} \ No newline at end of file +}