{"id":13494136,"url":"https://github.com/GetFirefly/firefly","last_synced_at":"2025-03-28T13:32:26.011Z","repository":{"id":40477281,"uuid":"160763382","full_name":"GetFirefly/firefly","owner":"GetFirefly","description":"An alternative BEAM implementation, designed for WebAssembly","archived":true,"fork":false,"pushed_at":"2023-10-18T18:50:02.000Z","size":14293,"stargazers_count":3606,"open_issues_count":49,"forks_count":103,"subscribers_count":86,"default_branch":"develop","last_synced_at":"2024-10-29T15:35:06.579Z","etag":null,"topics":["beam","compiler","erlang","erlang-vm","hacktoberfest","lumen","virtual-machine","web-assembly"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GetFirefly.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-12-07T03:04:29.000Z","updated_at":"2024-10-20T02:34:56.000Z","dependencies_parsed_at":"2024-01-05T22:10:13.293Z","dependency_job_id":null,"html_url":"https://github.com/GetFirefly/firefly","commit_stats":null,"previous_names":["lumen/lumen"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetFirefly%2Ffirefly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetFirefly%2Ffirefly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetFirefly%2Ffirefly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GetFirefly%2Ffirefly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GetFirefly","download_url":"https://codeload.github.com/GetFirefly/firefly/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222382507,"owners_count":16975382,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beam","compiler","erlang","erlang-vm","hacktoberfest","lumen","virtual-machine","web-assembly"],"created_at":"2024-07-31T19:01:22.221Z","updated_at":"2024-10-31T08:31:57.051Z","avatar_url":"https://github.com/GetFirefly.png","language":"Rust","funding_links":[],"categories":["Rust","By Industry","By Language","[🧑‍💻 dev](https://github.com/stars/ketsapiwiq/lists/dev)"],"sub_categories":["Web Development","Rust"],"readme":"# Firefly - A new compiler and runtime for BEAM languages\n\n[![x86_64-apple-darwin](https://github.com/GetFirefly/firefly/workflows/x86_64-apple-darwin%20compiler/badge.svg?branch=develop)](https://github.com/GetFirefly/firefly/actions?query=workflow%3A%22x86_64-apple-darwin+compiler%22+branch%3Adevelop)\n[![x86_64-unknown-linux-gnu](https://github.com/GetFirefly/firefly/workflows/x86_64-unknown-linux-gnu%20compiler/badge.svg?branch=develop)](https://github.com/GetFirefly/firefly/actions?query=workflow%3A%22x86_64-unknown-linux-gnu+compiler%22+branch%3Adevelop)\n\n* [Getting Started](#getting-started)\n  * [Installation](#install)\n  * [Usage](#usage)\n* [Contributing](#contributing)\n  * [Tools](#contrib-tools)\n  * [Building Firefly](#contrib-building-firefly)\n  * [Project Structure](#contrib-project)\n  * [Making Changes](#contrib-changes)\n* [About Firefly](#about)\n* [Goals](#goals)\n* [Non-Goals](#non-goals)\n* [Architecture](#architecture)\n\n\u003ca name=\"getting-started\"/\u003e\n\n## Getting Started\n\n\u003ca name=\"install\"/\u003e\n\n### Installation\n\n**NOTE: This section is a placeholder for the moment until we get our toolchain packaging implemented**\n\nTo use Firefly, you'll need to download our toolchain [here](https://github.com/GetFirefly/firefly/releases/), and install it like so:\n\n    \u003e tar -xzf firefly.tar.gz /usr/local/\n\nThis will install the `firefly` executable to `/usr/local/bin/firefly` and various supporting files to appropriate locations under `/usr/local`.\nIf you install to a different target directory, make sure you add the `bin` folder to your PATH, for example:\n\n    \u003e tar -xzf firefly.tar.gz $HOME/.local/share/firefly\n    \u003e export PATH=$HOME/.local/share/firefly/bin:$PATH\n\n\u003ca name=\"usage\"/\u003e\n\n### Usage\n\n**NOTE:** This section reflects the way Firefly is supposed to work, but the current implementation may \nlack functionality described here. However, if you encounter something broken, feel free to open an issue\nif there isn't one already, and we'll ensure it gets tracked as we continue to improve the project.\n\nYou should now be able to run `firefly`, start by reviewing the output of the `help` command:\n\n    \u003e firefly help\n\nThis will print out the various ways you can use the Firefly compiler. Obviously, the most interesting is the ability\nto compile some code, so let's see how that works.\n\nFirefly can compile executables or static/dynamic libraries. By default an executable is produced\nwhich acts very similar to an OTP release, but this behavior can be customized depending on how\nyou want the executable to be used. For example, when compiling an executable that you wish to use\nas a CLI tool, you might want a specific module/function to always be called with the arguments passed \nto the program when the system has booted. There are options to the `compile` command that allow you to\ndo this, and much more. It is even possible to provide your own init, and handle everything manually,\nincluding management of the core supervision tree.\n\n**NOTE:** Firefly does not do any dependency management itself, and we have not yet provided Rebar/Mix \nshims to integrate Firefly as a compiler with those tools, so compiling an application and all of its \ndependencies is still somewhat of a manual process. This will be addressed in the near future.\n\nFirefly allows you to compile Erlang sources a couple of ways, let's take a look at each:\n\n#### Compiling Files/Directories\n\n**NOTE:** Since Firefly is not compiling for a virtual machine, it does not produce BEAM bytecode like `erlc`\ndoes. Instead, it produces either an executable or a static/dynamic library depending on the type of \napplication being compiled, unless otherwise overridden by compiler options. By default, for\nOTP applications (i.e. apps which define the `mod` key in their application manifest), Firefly will produce \nan executable that runs that application much like an OTP release would. For library applications (i.e. apps \nthat do not define the `mod` key in their manifest), Firefly will produce a static library which can be linked \ninto an executable at another time. You may specify `--bin` to force production of an executable, or `--lib` to \nforce production of a library. If you want to compile a shared library, pass `--lib --dynamic`.\n\nYou can compile one or more Erlang source files by specifying their paths like so:\n\n    \u003e firefly compile src/foo.erl src/bar.erl\n    \n**NOTE:** Since there is no application manifest available, these sources will be treated as modules of an anonymous \nlibrary application with the same name as the current working directory. As such, the output of the above\ncommand will be a static library.\n\nAlternatively, you can compile all the files found in one or more directories, by specifying their path:\n\n    \u003e firefly compile app1/ app2/\n    \nIn this case, each directory will be treated as an application; if no `.app` or `.app.src` manifest is found in\na directory, then a new anonymous library application with the same name as the directory will be used as the\ncontainer for the sources in that directory. Since no root application manifest was provided, an anonymous library\napplication with the same name as the current working directory will be used as the \"root\" of the dependency tree.\nIn other words, if the name of our current directory is `myapp`, then in the example above, `app1` and `app2` will\nbe treated as dependencies of the `myapp` application, and will result in a static library being produced containing\nall three applications.\n\nWhen specifying files individually on the command line, you can control the default app properties using compiler flags,\nand use that to manage what type of output gets produced. For example:\n\n    \u003e firefly compile --app-name myapp --app-module foo src/foo.erl src/bar.erl\n    \nThis is equivalent to:\n\n    \u003e firefly compile --app src/myapp.app src/foo.erl src/bar.erl\n    \nWhere `src/myapp.app` looks like:\n\n    {application, myapp, [{mod, {foo, []}}]}.\n    \nIn both cases, the result is an executable containing the `myapp` application, which consists of two modules: `foo` and `bar`.\n\nLet's assume that `src/foo.erl` contains the following:\n\n    -module(foo).\n    -behaviour(application).\n    -export([start/2]).\n    \n    start(_, _) -\u003e\n        erlang:display(\"hello\"),\n        bar:start_link().\n        \n    stop(_) -\u003e ok.\n   \nThen we should see the following when we run our compiled executable:\n\n    \u003e _build/firefly/arm64-apple-macosx11.0.0/myapp\n    \"hello\"\n\n**NOTE:** The directory under `_build/firefly` contains the target triple the executable was compiled for, and\nsince this example was compiled on an M1, the triple reflects that.\n\n#### Compiling Projects\n\nFirefly also recognizes the conventional Erlang project structure. For example, let's say you have an application called `hello`:\n\n    hello/\n    |-include/\n    |-src/\n      |-hello.app.src\n      |-hello.erl\n      |-hello_sup.erl\n\nWhere `hello.app` contains:\n\n    {application, hello, [{vsn, \"1.0\"}, {mod, {hello, []}}]}.\n\nand `hello.erl` contains:\n\n    -module(hello).\n    -behaviour(application).\n    -export([start/2]).\n\n    start(_, _) -\u003e\n      erlang:display(\u003c\u003c\"hello world!\"\u003e\u003e),\n      hello_sup:start_link().\n\nFrom the root of the `hello/` directory, you can compile this to an executable like so:\n\n    \u003e firefly compile\n\nIf we run it, it should print our greeting:\n\n    \u003e _build/firefly/arm64-apple-macosx11.0.0/hello\n    \u003c\u003c\"hello world!\"\u003e\u003e\n\n**NOTE:** The directory under `_build/firefly` contains the target triple the executable was compiled for, and\nsince this example was compiled on an M1, the triple reflects that.\n\nIf you instead wish to compile `hello` as a library, you can compile with:\n\n    \u003e firefly compile --lib\n\nThis will produce the static archive `_build/firefly/\u003ctarget\u003e/hello.a`.\n\nIf you want to compile an application and link in a previously-compiled library, you can do that like so:\n\n    # Assume we previously compiled an app called `foo` as a static archive and moved it to `_build/firefly/\u003ctarget\u003e/foo.a`\n    \u003e firefly compile -L _build/firefly/\u003ctarget\u003e/ -lfoo\n    \nThis tells the compiler to use `_build/firefly/\u003ctarget\u003e/` as a search path for the linker, and to link the library named `foo`.\n\n#### Replacing Erlc\n\nNow that you've learned how to use Firefly to compile Erlang sources, what's the best approach for compiling a real world Erlang\nproject?\n\nLet's assume you are in a directory containing a standard Erlang project called `myapp`, and all of your dependencies are located \nin the `_build/default/lib` (the default for rebar3), then the following will compile your application and all its declared dependencies \n(based on the app manifest) into an executable:\n\n    \u003e firefly compile --bin\n    \nThis works because Firefly has an application manifest to work from, and can infer the location of the sources for the dependencies.\n\nHowever, if your project is less conventional, then you might want to follow a different approach instead, by compiling\neach application to a library, and then compiling the root application as an executable while linking in all of the dependencies:\n\n    \u003e firefly compile --lib -o foo.a deps/foo\n    \u003e firefly compile --lib -o bar.a deps/bar\n    \u003e firefly compile --bin -L. -lfoo -lbar src/\n    \nThe above assumes that `deps/foo` and `deps/bar` are directories containing application manifests, and compiles both to static libraries\nin the current working directory. The last line will create an executable containing the `foo` and `bar` applications, as well as the application\ncontained in `src`.\n\nThis method is more manual, but provides a lot of flexibility for those who need it.\n\n#### Barebones\n\n**NOTE:** This is primarily for experimentation and development work, but might be of interest to\nthose interested in implementing inits, or even alternative Erlang standard libraries.\n\nTo compile an executable which simply invokes `init:boot/1` and leaves the definition of that function\nup to you, you can use the following:\n\n    \u003e firefly compile -C no_default_init --bin init.erl\n\nThe resulting executable performs none of the default initialization work that the standard runtime normally\ndoes, i.e. there is no init, so no application master/controller, and as a result, none of the normal OTP \nstartup sequence occurs. This does however provide you an opportunity to handle this yourself, however you like;\nalbeit with the major caveat that using any standard library modules without doing the proper initialization\nor providing the things needed by those modules will almost certainly fail. Erlang without the default\ninit is a very interesting environment to play in!\n\nAs an example, consider if `init.erl` above is defined as the following:\n\n```erlang\n-module(init).\n-exports([boot/1]).\n\nboot(Args) -\u003e\n    erlang:display(Args).\n```\n\nRunning the resulting executable will print the default arguments the runtime provides to the init\nand then exit.\n\n\u003ca name=\"contributing\"/\u003e\n\n## Contributing\n\nIn order to build Firefly, or make changes to it, you'll need the following installed:\n\n\u003ca name=\"contrib-tools\"/\u003e\n\n### Tools\n\nFirst, you will need to install [rustup](https://rustup.rs/). Follow the instructions at that link.\n\nOnce you have installed `rustup`, you will need to install the nightly version\nof Rust (currently our CI builds against the 2022-08-08 nightly, specifically). We require\nnightly due to a large number of nightly features we use, as well as some\ndependencies for the WebAssembly targets that we make use of.\n\n    # to use the latest nightly\n    rustup default nightly\n\n    # or, in case of issues, install the specific nightly to match our CI\n    rustup default nightly-2022-11-02\n    export CARGO_MAKE_TOOLCHAIN=nightly-2022-11-02\n\nIn order to run various build tasks in the project, you'll need the [cargo-make](https://github.com/sagiegurari/cargo-make) plugin for Cargo. You can install it with:\n\n    cargo install cargo-make\n\nYou can see what tasks are available with `cargo make --print-steps`.\n\nYou may also want to install the following tools for editor support (`rustfmt` will be required on\nall pull requests!):\n\n    rustup component add rustfmt clippy\n\nNext, for wasm32 support, you will need to install the `wasm32` targets for the Rust toolchain:\n\n    rustup target add wasm32-unknown-unknown --toolchain \u003cname of nightly you chose in the previous step\u003e\n\n#### LLVM\n\nLLVM is used internally for the final code generation stage. In order to build the compiler, \nyou must have our expected version of LLVM (currently LLVM 15) installed somewhere locally.\n\nLLVM releases are posted [here](https://releases.llvm.org).\n\n###### Linux (x86_64)\n\nFollow the install instructions [here](https://apt.llvm.org) for Debian or Ubuntu.\nFor other distros, you are going to have to check whether our required LLVM version is\navailable via your package manager, and either use that, or build LLVM from source. Ideally\nyou won't need to do the latter, but you can also try slightly newer LLVM releases as well,\nif they are available, which may also work, but is not a supported configuration.\n\nOnce installed, make sure you export `LLVM_PREFIX` in your environment when working in the\nFirefly repo, e.g. building the compiler.\n\n###### macOS (arm64 and x86_64)\n\nGo to the releases page mentioned above, and follow the download link to the GitHub releases page.\nFrom here, you'll want to select the `clang+llvm` package which matches your platform, then follow\nthe instructions below. NOTE: The following instructions use the arm64 release for the example:\n\n    mkdir -p $XDG_DATA_HOME/llvm/\n    cd $XDG_DATA_HOME/llvm/\n    wget 'https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.7/clang+llvm-15.0.7-arm64-apple-darwin22.0.tar.xz'\n    tar -xzf clang+llvm-15.0.7-arm64-apple-darwin22.0.tar.xz\n    mv clang+llvm-15.0.7-arm64-apple-darwin22.0.tar.xz firefly\n    rm clang+llvm-15.0.7-arm64-apple-darwin22.0.tar.gz\n    cd -\n    export LLVM_PREFIX=\"${XDG_DATA_HOME}/llvm/firefly\"\n\n\u003ca name=\"contrib-building-firefly\"/\u003e\n\n### Building Firefly\n\nOnce LLVM is installed, you can build the `firefly` executable!\n\nNOTE: Firefly has components that need to be compiled with clang; On Linux, the default compiler is generally gcc. \nYou'll need to make sure to use `clang` instead. The LLVM toolchain should include clang, but you may\nneed to install it separately from your package manager. Then, export the following environment variables\nwhen building Firefly:\n\n    export CC=$XDG_DATA_HOME/llvm/firefly/bin/clang\n    export CXX=$XDG_DATA_HOME/llvm/firefly/bin/clang++\n\nTo build Firefly, run the following:\n\n    LLVM_PREFIX=$XDG_DATA_HOME/llvm/firefly cargo make firefly\n\nNOTE: If you have .direnv installed, run `direnv allow` in the project root, and you can omit all\nof the above environment variables, and instead modify the `.envrc` file if needed.\n\nThis will create the compiler executable and associated toolchain for the host\nmachine under `bin` in the root of the project. You can invoke `firefly` via the\nsymlink `bin/firefly`, e.g.:\n\n    bin/firefly --help\n\nYou can compile an Erlang file to an executable (currently only on x86_64/AArch64):\n\n    bin/firefly compile [\u003cpath/to/file_or_directory\u003e..]\n\nThis will produce an executable with the same name as the source file in the\ncurrent working directory with no extension (except on Windows, where it will\nhave the `.exe` extension).\n\n**NOTE:** Firefly is still in a very experimental stage of development, so stability is not guaranteed.\n\n\u003ca name=\"contrib-project\"/\u003e\n\n### Project Structure\n\nFirefly is currently divided into three major components:\n\n#### Compiler\n\nThe Firefly compiler is composed of many small components, but the few most interesting are:\n\n- `firefly` is the crate for the `firefly` executable itself, but it is largely empty, \nmost of the meat is in other crates\n- `compiler/driver`, handles driving the compiler, i.e. parsing arguments, handling commands, \nand orchestrating tasks; it also defines the compiler pipeline. It currently also contains the\npasses which perform code generation.\n- `compiler/syntax_base`, contains common types and metadata used in many places across the compiler\n- `compiler/syntax_*`, these crates implement the frontend and middle-tier of the compiler.\nEach one provides an intermediate representation, semantic analysis, transforms to other representations,\noutput to a textual format, and in some cases, parsing. \n  * `syntax_erl` is the primary frontend of the compiler, which handles Erlang sources\n  * `syntax_pp`, is a frontend for Abstract Erlang Format, and converts to the AST from `syntax_erl`\n  * `syntax_core` is a high-level intermediate representation to which the AST is lowered after some initial\n  semantic analysis. Core is an extended form of lambda calculus, so is highly normalized, and is where we do\n  the remaining semantic analysis tasks. Core is also where comprehension and receive expressions are transformed\n  into their lower level representations. Core is logically split into two forms, \"internal\" and regular. The\n  internal form is used during initial lowering, before certain transformations have been applied. The regular form\n  of Core has certain properties which must be upheld, and the internal form does not enforce them.\n  * `syntax_kernel` is a specialized intermediate representation to which Core is lowered. It is completely flat,\n  i.e. no nested scopes, variables are unique, all function calls are resolved, dynamic apply is converted\n  to a call to `erlang:apply/2,3`, and all closures have been lifted. During the lowering from Core, pattern matching \n  compilation is performed, and some liveness analysis is performed.\n  * `syntax_ssa` is a low-level SSA IR to which Kernel is lowered. While Kernel is flat, it is still expression based,\n  SSA breaks things down further into blocks, jumps, and instructions for a register-based machine.\n  From here, we can perform code generation either to native code, or bytecode.\n- `compiler/linker`, performs all the work needed to link generated code into objects/libraries/executables.\n\nThe remaining crates under `compiler/` are support crates of some kind.\n\n#### Libraries\n\nThere are a number of core libraries that are used by the runtime, but are also in some cases shared\nwith the compiler. These are designed to either be optional components, or part of a tiered system of \ncrates that build up functionality for the various runtime crates.\n\n- `library/system`, provides abstractions over platform-specific implementation details that most of the runtime\ncode doesn't need to know about. This primarily handles unifying low-level platform APIs.\n- `library/alloc`, provides abstractions for memory management\n- `library/arena`, this is a helper crate that provides an implementation of both typed and untyped arenas\n- `library/rt`, this is the primary core runtime library, hence the name, and provides the implementations of all the\nterm types and their native APIs, as well as establishing things like the calling convention for Erlang functions,\nexceptions and backtraces, and other universal runtime concerns that cannot be delegated to a higher-level runtime crate.\n- `library/binary`, this crate provides all the pieces for implementing binaries/bitstrings, including pattern matching\nprimitives and constructors.\n- `library/number`, this crate provides the internal implementation of numeric types for both the compiler and runtime\n- `library/beam`, this crate provides native APIs for working with BEAM files\n- `library/bytecode`, this crate defines the opcodes for the bytecode emulator, as well as support for the binary bytecode format\n\n#### Runtimes\n\nThe runtime is intended to be pluggable, so it consists of a \"wrapper\" crate that provides the entry point\nfor executables, and a specific runtime implementation. Currently there is only one of the latter.\n\n- `runtimes/crt`, plays the role of crt0 in our system, i.e. it provides the entry point, initializes\nthe function and atom tables, and invokes the `main` function of the linked-in runtime.\n- `runtimes/emulator`, provides a runtime which operates on the output of the bytecode compiler\n\n\u003ca name=\"contrib-changes\"/\u003e\n\n### Making Changes\n\nAt this stage of the project, it is important that any changes you wish to contribute are communicated\nwith us first, as there is a good chance we are working on those areas of the code, or have plans around\nthem that will impact your implementation. Please open an issue tagged appropriately based on the part of\nthe project you are contributing to, with an explanation of the issue/change and how you'd like to approach\nimplementation. If there are no conflicts/everything looks good, we'll make sure to avoid stepping on your\ntoes and provide any help you need.\n\nFor smaller changes/bug fixes, feel free to open an issue first if you are new to the project and\nwant some guidance on working through the fix. Otherwise, it is acceptable to just open a PR\ndirectly with your fix, and let the review happen there.\n\nAlways feel free to open issues for bugs, and even perceived issues or questions, as they can be a\nuseful resource for others; but please do make sure to use the search function to avoid\nduplication!\n\nIf you plan to participate in discussions, or contribute to the project, be aware that this project\nwill not tolerate abuse of any kind against other members of the community; if you feel that someone\nis being abusive or inappropriate, please contact one of the core team members directly (or all of\nus). We want to foster an environment where people both new and experienced feel welcomed, can have\ntheir questions answered, and hopefully work together to make this project better!\n\n\u003ca name=\"about\"/\u003e\n\n## About Firefly\n\nFirefly is not only a compiler, but a runtime as well. It consists of two parts:\n\n* A compiler for Erlang to native code for a given target (x86, ARM, WebAssembly)\n* An Erlang runtime, implemented in Rust, which provides the core functionality\n  needed to implement OTP\n\nThe primary motivator for Firefly's development was the ability to compile Elixir\napplications that could target WebAssembly, enabling use of Elixir as a language\nfor frontend development. It is also possible to use Firefly to target other\nplatforms as well, by producing self-contained executables on platforms such as x86.\n\nFirefly is different than BEAM in the following ways:\n\n* It supports compilation to standalone executables\n* It is designed to support targeting WebAssembly, as well as many other types of targets.\n* It is designed to support both ahead-of-time compilation to machine code, and compilation to bytecode\n* It sacrifices some features to enable additional optimizations, in particular we don't\nhave plans currently to support hot code reloading.\n* It is written as a way to better understand the BEAM itself, and one of its goals\nis to provide a more accessible means of learning how the BEAM works internally, to\nthe degree that we provide the same functionality as the BEAM. By implementing it in\nRust, we also hope to learn how implementing something like the BEAM in a much more restrictive,\nbut safe language impacts its development.\n\n\u003ca name=\"goals\"/\u003e\n\n## Goals\n\n- Support WebAssembly/embedded systems as a first-class platforms\n- Produce easy-to-deploy static executables as build artifacts\n- Integrate with tooling provided by BEAM languages\n- Feature parity with mainline OTP (with exception of the non-goals listed below)\n\n\u003ca name=\"non-goals\"/\u003e\n\n## Non-Goals\n\n- Support for hot upgrades/downgrades\n- Support for dynamic code loading\n\nFirefly _is_ an alternative implementation of Erlang/OTP, so as a result it is not as battle tested, or necessarily\nas performant as the BEAM itself. Until we have a chance to run some benchmarks, it is hard to know\nwhat the difference between the two in terms of performance actually is.\n\nFirefly is _not_ intended to replace BEAM at this point in time. At a minimum, the stated non-goals\nof this project mean that for at least some percentage of projects, some required functionality would\nbe missing. However, it is meant to be a drop-in replacement for applications which are better served\nby its feature set.\n\n\u003ca name=\"architecture\"/\u003e\n\n## Architecture\n\n### Compiler\n\nThe compiler frontend accepts Erlang source files. This is parsed into an\nabstract syntax tree, then lowered through a set of intermediate representations\nwhere different types of analysis, transformation, or optimization are performed:\n\n- Core IR (similar to Core Erlang)\n- Kernel IR (similar to Kernel Erlang)\n- SSA IR (a low-level representation used to prepare for code generation)\n- Bytecode/MLIR (where final optimizations and code generation are performed)\n\nThe final stage of the compiler depends on whether compiling to bytecode or native\ncode, but in both cases the output produces LLVM IR that is then compiled to one\nor more object files, and linked via our linker into an executable.\n\n### Runtime\n\nThe runtime design is mostly the same as OTP, but varies a bit on what type of codegen backend was used.\nIn general though:\n\n- The entry point sets up the environment, and starts the scheduler\n- The scheduler is composed of one scheduler per thread\n- Each scheduler can steal work from other schedulers if it is short on work\n- Processes are spawned on the same scheduler as the process they are spawned from,\n  but a scheduler is able to steal them away to load balance\n- I/O is asynchronous, and integrates with the signal management performed by the schedulers\n\nThe initial version is quite spartan, but should be easy to grow now that we have some of the\nfundamentals built out.\n\n### NIFs\n\nCurrently it is straightforward to extend the runtime with native functions implemented in Rust,\nwithout all of the extra stuff that goes into port drivers and `erl_nif`. Currently we have some\nof the baseline infrastructure in place to support port drivers, but none of the necessary pieces\nto support `erl_nif` as of yet. We'll need to start adding some of that in short order however, so\nit is on our roadmap to support NIFs to at least a minimum degree needed for things required by\nthe standard library.\n\n## History\n\nFirefly previously had the name \"Lumen\". This was intended to be a temporary name and it was\nchanged in 2022, partly due to there being numerous other projects also named Lumen.\n\n## License\n\nApache 2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGetFirefly%2Ffirefly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGetFirefly%2Ffirefly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGetFirefly%2Ffirefly/lists"}