Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v27
- run: nix build -L
- run: nix build -L .#ml
- run: nix build -L .#ocaml
- run: nix build -L .#legacy
- run: nix flake check -L
125 changes: 78 additions & 47 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,26 +1,59 @@
cmake_minimum_required(VERSION 3.28)
project(haven C CXX ASM)
project(haven LANGUAGES NONE)

cmake_policy(SET CMP0171 NEW)

include("CMakeDependentOption")
include(CheckCCompilerFlag)

include(build-etc/config.cmake)
include(build-etc/macros.cmake)
option(WITH_LEGACY_COMPILER "build the legacy C bootstrap compiler" OFF)

find_program(DUNE_EXECUTABLE dune)
if (NOT DUNE_EXECUTABLE AND NOT WITH_LEGACY_COMPILER)
message(FATAL_ERROR "Dune is required to build the mainline OCaml Haven compiler")
endif ()

set(HAVEN_OCAML_BUILD_DIR "${CMAKE_SOURCE_DIR}/src/_build/default")
if (DUNE_EXECUTABLE)
if (WITH_LEGACY_COMPILER)
add_custom_target(haven_ml_cli
COMMAND ${DUNE_EXECUTABLE} build bin/haven.exe bin/hvfmt.exe bin/hvast.exe bin/lsp/hvlsp.exe
BYPRODUCTS
${HAVEN_OCAML_BUILD_DIR}/bin/haven.exe
${HAVEN_OCAML_BUILD_DIR}/bin/hvfmt.exe
${HAVEN_OCAML_BUILD_DIR}/bin/hvast.exe
${HAVEN_OCAML_BUILD_DIR}/bin/lsp/hvlsp.exe
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src
COMMENT "Building mainline OCaml Haven compiler")
else ()
add_custom_target(haven_ml_cli ALL
COMMAND ${DUNE_EXECUTABLE} build bin/haven.exe bin/hvfmt.exe bin/hvast.exe bin/lsp/hvlsp.exe
BYPRODUCTS
${HAVEN_OCAML_BUILD_DIR}/bin/haven.exe
${HAVEN_OCAML_BUILD_DIR}/bin/hvfmt.exe
${HAVEN_OCAML_BUILD_DIR}/bin/hvast.exe
${HAVEN_OCAML_BUILD_DIR}/bin/lsp/hvlsp.exe
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src
COMMENT "Building mainline OCaml Haven compiler")
endif ()
endif ()

if (WITH_LEGACY_COMPILER)
enable_language(C CXX ASM)

find_library(MALLOC NAMES jemalloc tcmalloc)
include(CheckCCompilerFlag)
include(build-etc/macros.cmake)

find_package(LLVM REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)
find_package(GTest REQUIRED)
find_package(benchmark REQUIRED)
find_package(Doxygen)
find_library(MALLOC NAMES jemalloc tcmalloc)

include_directories(${LLVM_INCLUDE_DIRS})
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS_LIST})
link_directories(${LLVM_LIBRARY_DIRS})
find_package(LLVM REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)
find_package(GTest REQUIRED)
find_package(benchmark REQUIRED)
find_package(Doxygen)

include_directories(${LLVM_INCLUDE_DIRS})
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS_LIST})
link_directories(${LLVM_LIBRARY_DIRS})

# Possibly enable ASAN/TSAN/etc
option(ASAN "address sanitizer" OFF)
Expand Down Expand Up @@ -81,43 +114,41 @@ set(HAVEN_C_FLAGS "${HAVEN_DEFAULT_C_FLAGS}" CACHE STRING "C flags to pass to Ha
string(REPLACE ";" " " HAVEN_C_FLAGS "${HAVEN_C_FLAGS}")

# Flags for compiling Haven code
set(HAVEN_BOOTSTRAP_COMPILE_FLAGS "${HAVEN_C_FLAGS} --O2" CACHE STRING "flags to use when compiling Haven code with the bootstrap compiler")
set(HAVEN_COMPILE_FLAGS "${HAVEN_C_FLAGS} --O2" CACHE STRING "flags to use when compiling Haven code with the main compiler")
set(HAVEN_BOOTSTRAP_COMPILE_FLAGS "${HAVEN_C_FLAGS} --O2" CACHE STRING "flags to use when compiling Haven code with the bootstrap compiler")
set(HAVEN_COMPILE_FLAGS "${HAVEN_C_FLAGS} --O2" CACHE STRING "flags to use when compiling Haven code with the main compiler")

include(build-etc/compiler.cmake)
include(build-etc/compiler.cmake)

find_program(DUNE_EXECUTABLE dune)
if (DUNE_EXECUTABLE)
add_custom_target(haven_ml_cli
COMMAND ${DUNE_EXECUTABLE} build bin/haven.exe
BYPRODUCTS ${CMAKE_SOURCE_DIR}/src-ml/_build/default/bin/haven.exe
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src-ml
COMMENT "Building OCaml Haven compiler")
endif ()
# Use jemalloc?
if (OTHER_MALLOC AND MALLOC)
set (CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} ${MALLOC}")
set (CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} ${MALLOC}")
endif ()

# Use jemalloc?
if (OTHER_MALLOC AND MALLOC)
set (CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} ${MALLOC}")
set (CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} ${MALLOC}")
endif ()
include_directories(legacy/include legacy/src)

include_directories(include src)
enable_testing()

enable_testing()
add_subdirectory(legacy/src legacy-src)
add_subdirectory(src-new)
add_subdirectory(tests)
add_subdirectory(bench)

add_subdirectory(src)
add_subdirectory(src-new)
add_subdirectory(tests)
add_subdirectory(bench)
if (DOXYGEN_FOUND)
doxygen_add_docs(doxygen legacy/src legacy/include)
endif ()

if (DOXYGEN_FOUND)
doxygen_add_docs(doxygen src include)
include(CTest)
install(TARGETS haven havenfmt hvast hdr2haven runtime
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
INCLUDES DESTINATION include)
else ()
install(PROGRAMS
${HAVEN_OCAML_BUILD_DIR}/bin/haven.exe
${HAVEN_OCAML_BUILD_DIR}/bin/hvfmt.exe
DESTINATION bin)
install(PROGRAMS ${HAVEN_OCAML_BUILD_DIR}/bin/hvast.exe DESTINATION bin RENAME hvast-ml)
install(PROGRAMS ${HAVEN_OCAML_BUILD_DIR}/bin/lsp/hvlsp.exe DESTINATION bin RENAME haven-lsp)
endif ()

include(CTest)

install(TARGETS haven havenfmt runtime
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
INCLUDES DESTINATION include)
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@ And, all else aside, I really just wanted to build a language that's optimized f

## The Compilers

This repository is split into two compilers:
This repository currently contains three compiler implementations:

1. The initial compiler, built in C, in `src` and `include`, and
2. The self-hosted compiler, written in Haven, currently in `src-new`.
1. The mainline compiler, written in OCaml, in `src`.
2. The original compiler, written in C, in `legacy/src` and `legacy/include`.
3. The experimental self-hosted compiler, written in Haven, in `src-new`.

The initial compiler in C is hardly production quality, and I'm trying to minimize how much additional effort
I invest into it outside of necessary additions or fixes to support the self-hosting effort.
The OCaml compiler is the maintained implementation and the default build target throughout the repository.
The C compiler is deprecated and retained as a historical bootstrap artifact.
It can still be built through CMake with `-DWITH_LEGACY_COMPILER=ON`.
`nix build` and plain CMake now both target the OCaml compiler by default; use `nix build .#legacy`
when you explicitly want the deprecated C compiler path.

## Fractal Example

Expand Down
2 changes: 1 addition & 1 deletion build-etc/macros.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ macro(add_ocaml_haven_library name source)

add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
COMMAND ${CMAKE_SOURCE_DIR}/src-ml/_build/default/bin/haven.exe ${HAVEN_SANITIZER_FLAGS} --trace --debug-ir -c ${HAVEN_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
COMMAND ${CMAKE_SOURCE_DIR}/src/_build/default/bin/haven.exe ${HAVEN_SANITIZER_FLAGS} --trace --debug-ir -c ${HAVEN_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${source}
DEPENDS haven_ml_cli ${ARGN}
COMMENT "Building ${name} from ${source} [ocaml]"
Expand Down
1 change: 1 addition & 0 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ stdenv.mkDerivation {
cmakeFlags = [
"-DLLVM_DIR=${llvmCmakeDir}"
"-DHAVEN_C_FLAGS=${lib.escapeShellArg haven_c_flags}"
"-DWITH_LEGACY_COMPILER=ON"
];

postPatch = ''
Expand Down
2 changes: 1 addition & 1 deletion examples/syscall.hv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ./build/bin/haven examples/syscall.hv --asan --Xl -lruntime --Xl -Lbuild/lib
// ./src/_build/default/bin/haven.exe examples/syscall.hv --asan --Xl -lruntime --Xl -Lbuild/lib

pub impure fn SYS_write(u32 fd, str buf, u64 count) -> i64;

Expand Down
38 changes: 31 additions & 7 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,53 @@
(old: {
patches = (old.patches or [ ]) ++ [ ./nix/ocaml-llvm-macos-ext-dll.patch ];
});
haven = pkgs.callPackage ./default.nix { inherit llvmPkgs llvmCmakeDir self; stdenv = llvmPkgs.stdenv; };
havenMl = pkgs.callPackage ./src-ml/default.nix {
havenLegacy = pkgs.callPackage ./default.nix { inherit llvmPkgs llvmCmakeDir self; stdenv = llvmPkgs.stdenv; };
havenOcaml = pkgs.callPackage ./src/default.nix {
inherit llvmOcaml;
llvmPackages = llvmPkgs;
repoSrc = ./.;
};
in {
apps.default = {
type = "app";
program = "${haven}/bin/haven";
program = "${havenOcaml}/bin/haven";
meta = with pkgs.lib; {
description = "The Haven programming language";
license = licenses.mit;
};
};

packages.default = haven;
packages.ml = havenMl;
packages.default = havenOcaml;
packages.ocaml = havenOcaml;
packages.ml = havenOcaml;
packages.legacy = havenLegacy;

checks.ml = havenMl;
checks.default = havenOcaml;
checks.ocaml = havenOcaml;
checks.legacy = havenLegacy;

devShells.default = pkgs.mkShell {
nativeBuildInputs = with pkgs; [ cmake ninja pkg-config llvmPkgs.clang llvmPkgs.libllvm llvmPkgs.lld gtest gbenchmark doxygen ];
nativeBuildInputs = with pkgs; [
cmake
ninja
pkg-config
dune_3
ocamlPackages.ocaml
ocamlPackages.cmdliner
ocamlPackages.fmt
ocamlPackages.linol-lwt
ocamlPackages.logs
ocamlPackages.menhir
ocamlPackages.sedlex
ocamlPackages.yojson
llvmPkgs.clang
llvmPkgs.libllvm
llvmPkgs.lld
llvmOcaml
gtest
gbenchmark
doxygen
];
CMAKE_PREFIX_PATH = llvmCmakeDir;
};
});
Expand Down
6 changes: 6 additions & 0 deletions legacy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Legacy compiler

This directory contains the original C implementation of the Haven compiler.
It is deprecated and kept primarily as a historical bootstrap artifact.

Use `-DWITH_LEGACY_COMPILER=ON` when you explicitly want to build it through CMake.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ set -o pipefail
FILENAME=$1
shift

COMPILER="./build/bin/haven"
# COMPILER="./build/bin/haven_bootstrap"
COMPILER="./src/_build/default/bin/haven.exe"
# LEGACY_COMPILER="./build/bin/haven"

OPT="O2"
ASAN="--asan"
Expand Down
11 changes: 7 additions & 4 deletions scripts/verify-examples-compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ set -eu
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
REPO_DIR=$(dirname "${SCRIPT_DIR}")

COMPILER=${REPO_DIR}/build/bin/haven
COMPILER=${REPO_DIR}/src/_build/default/bin/haven.exe

if [ ! -x ${COMPILER} ]; then
COMPILER=bin/haven
COMPILER=${REPO_DIR}/build/bin/haven
if [ ! -x ${COMPILER} ]; then
echo "Expected a built Haven compiler in build/bin/ or bin/ - build the compiler first."
exit 1
COMPILER=bin/haven
if [ ! -x ${COMPILER} ]; then
echo "Expected a built Haven compiler in src/_build/default/bin/, build/bin/, or bin/ - build the compiler first."
exit 1
fi
fi
fi

Expand Down
4 changes: 0 additions & 4 deletions src-ml/README.md

This file was deleted.

File renamed without changes.
File renamed without changes.
5 changes: 5 additions & 0 deletions src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# src: OCaml compiler

This is the mainline Haven compiler implementation.
The older C compiler now lives in `../legacy/` as a deprecated historical bootstrap artifact,
while the experimental self-hosted compiler remains in `../src-new/`.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
14 changes: 11 additions & 3 deletions src-ml/default.nix → src/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ocamlPackages.buildDunePackage {
ocamlPackages.menhir
];
propagatedBuildInputs = [
ocamlPackages.cmdliner
ocamlPackages.fmt
ocamlPackages.linol-lwt
llvmOcaml
Expand All @@ -29,11 +30,18 @@ ocamlPackages.buildDunePackage {
];

buildPhase = ''
# Keep the Nix build focused on the OCaml build/test entrypoint.
dune build @runtest
runHook preBuild
dune build @runtest bin/haven.exe bin/hvfmt.exe bin/hvast.exe bin/lsp/hvlsp.exe
runHook postBuild
'';

installPhase = ''
mkdir -p $out
runHook preInstall
mkdir -p $out/bin
cp _build/default/bin/haven.exe $out/bin/haven
cp _build/default/bin/hvfmt.exe $out/bin/hvfmt
cp _build/default/bin/hvast.exe $out/bin/hvast-ml
cp _build/default/bin/lsp/hvlsp.exe $out/bin/haven-lsp
runHook postInstall
'';
}
2 changes: 1 addition & 1 deletion src-ml/dune-project → src/dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
(name haven)
(synopsis "The Haven compiler")
(description "The Haven compiler")
(depends ocaml sedlex menhir unix yojson llvm)
(depends ocaml cmdliner fmt linol-lwt logs menhir menhirLib sedlex unix yojson llvm)
(tags (compiler)))

(using menhir 3.0)
9 changes: 7 additions & 2 deletions src-ml/haven.opam → src/haven.opam
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ bug-reports: "https://github.com/username/reponame/issues"
depends: [
"dune" {>= "3.19"}
"ocaml"
"llvm"
"sedlex"
"cmdliner"
"fmt"
"linol-lwt"
"logs"
"menhir"
"menhirLib"
"sedlex"
"unix"
"yojson"
"llvm"
"odoc" {with-doc}
]
build: [
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading