Skip to content

Commit

Permalink
Reduce VM size by supporting compilers from 3 last OTP releases
Browse files Browse the repository at this point in the history
Update few CI tests to optimize VM for the tested OTP version
Fix accordingly conditions for following opcodes:
- OP_BS_MATCH_STRING is generated by at least OTP 21 to 27
- OP_BS_TEST_UNIT is generated by at least OTP 21 to 25

Signed-off-by: Paul Guyot <[email protected]>
  • Loading branch information
pguyot committed Feb 18, 2025
1 parent 7caa566 commit c426504
Show file tree
Hide file tree
Showing 18 changed files with 182 additions and 23 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/build-and-test-macos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ jobs:
os: ["macos-13", "macos-14", "macos-15"]
otp: ["24", "25", "26", "27"]

include:
- otp: "24"
cmake_opts_other: "-DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=24 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=24"

steps:
# Setup
- name: "Checkout repo"
Expand Down Expand Up @@ -83,7 +87,7 @@ jobs:
working-directory: build
run: |
export PATH="/usr/local/opt/erlang@${{ matrix.otp }}/bin:/opt/homebrew/opt/erlang@${{ matrix.otp }}/bin:$PATH"
cmake -DAVM_WARNINGS_ARE_ERRORS=ON -G Ninja ..
cmake -DAVM_WARNINGS_ARE_ERRORS=ON ${{ matrix.cmake_opts_other }} -G Ninja ..
- name: "Build: run ninja"
working-directory: build
Expand Down
18 changes: 16 additions & 2 deletions .github/workflows/build-and-test-other.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,16 @@ jobs:
name: test-modules
path: build_tests

- name: Skip compilation of Erlang code
run: |
sed -e 's|add_subdirectory(libs)|# add_subdirectory(libs)|g' \
-e 's|add_subdirectory(examples)|# add_subdirectory(examples)|g' \
-i CMakeLists.txt
sed -e 's|add_subdirectory(erlang_tests)|# add_subdirectory(erlang_tests)|g' \
-e 's|add_subdirectory(libs/|# add_subdirectory(libs/|g' \
-e 's|add_dependencies(test-erlang erlang_test_modules)|# add_dependencies(test-erlang erlang_test_modules)|g' \
-i tests/CMakeLists.txt
- name: Set up QEMU
uses: docker/setup-qemu-action@v3

Expand Down Expand Up @@ -159,13 +169,17 @@ jobs:
mkdir -p build &&
cd build &&
cmake .. ${{ matrix.cmake_opts }} &&
mkdir -p tests/erlang_tests/code_load/beams/ &&
cp ../build_tests/tests/erlang_tests/*.beam tests/erlang_tests/ &&
cp ../build_tests/tests/erlang_tests/code_load/*.{avm,beam,hrl} tests/erlang_tests/code_load/ &&
mkdir -p tests/erlang_tests/code_load/beams/ &&
cp ../build_tests/tests/erlang_tests/code_load/beams/*.beam tests/erlang_tests/code_load/beams/ &&
mkdir -p tests/libs/etest/ &&
cp ../build_tests/tests/libs/etest/*.avm tests/libs/etest/ &&
cp ../build_tests/tests/libs/estdlib/*.avm tests/libs/estdlib/ &&
mkdir -p tests/libs/estdlib/ &&
cp ../build_tests/tests/libs/estdlib/*.avm tests/libs/estdlib/ &&
mkdir -p tests/libs/eavmlib/ &&
cp ../build_tests/tests/libs/eavmlib/*.avm tests/libs/eavmlib/ &&
mkdir -p tests/libs/alisp/ &&
cp ../build_tests/tests/libs/alisp/*.avm tests/libs/alisp/ &&
make AtomVM &&
make test-erlang &&
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ jobs:
otp: "21"
elixir_version: "1.7"
rebar3_version: "3.15.2"
cmake_opts_other: "-DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=21 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=21"

- os: "ubuntu-20.04"
cc: "cc"
Expand All @@ -210,6 +211,7 @@ jobs:
otp: "22"
elixir_version: "1.8"
rebar3_version: "3.18.0"
cmake_opts_other: "-DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=22 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=22"

- os: "ubuntu-20.04"
cc: "cc"
Expand All @@ -218,6 +220,7 @@ jobs:
otp: "23"
elixir_version: "1.11"
rebar3_version: "3.20.0"
cmake_opts_other: "-DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=23 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=23"

- os: "ubuntu-22.04"
cc: "cc"
Expand All @@ -226,6 +229,7 @@ jobs:
otp: "24"
elixir_version: "1.14"
rebar3_version: "3.23.0"
cmake_opts_other: "-DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=24 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=24"

- os: "ubuntu-24.04"
cc: "cc"
Expand Down Expand Up @@ -275,9 +279,9 @@ jobs:
cc: "gcc-10"
cxx: "g++-10"
cflags: "-m32 -O3"
otp: "23"
elixir_version: "1.11"
rebar3_version: "3.20.0"
otp: "27"
elixir_version: "1.17"
rebar3_version: "3.24.0"
# Use Werror so we get an error with 32 bit specific warnings
cmake_opts_other: "-DAVM_CREATE_STACKTRACES=off -DAVM_WARNINGS_ARE_ERRORS=ON"
arch: "i386"
Expand Down
21 changes: 17 additions & 4 deletions .github/workflows/esp32-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ jobs:
idf-version: 'v5.0.7'
- esp-idf-target: "esp32c3"
idf-version: 'v5.1.5'

# ESP-IDF 5.0.7 and 5.1.5 containers are based on Ubuntu focal which has Erlang/OTP 22
# ESP-IDF 5.2.3 and 5.3.2 containers are based on Ubuntu jammy which has Erlang/OTP 24
include:
- idf-version: 'v5.0.7'
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=22 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=22
- idf-version: 'v5.1.5'
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=22 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=22
- idf-version: 'v5.2.3'
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=24 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=24
- idf-version: 'v5.3.2'
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=24 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=24

steps:
- name: Checkout repo
uses: actions/checkout@v4
Expand Down Expand Up @@ -152,8 +165,8 @@ jobs:
echo "CONFIG_ESP_WIFI_RX_IRAM_OPT=n" >> sdkconfig.defaults
. $IDF_PATH/export.sh
export IDF_TARGET=${{matrix.esp-idf-target}}
idf.py set-target ${{matrix.esp-idf-target}}
idf.py build
idf.py ${{matrix.cmake_opts}} set-target ${{matrix.esp-idf-target}}
idf.py ${{matrix.cmake_opts}} build
- name: Run ESP32 tests using qemu with memory checks build
working-directory: ./src/platforms/esp32/test/
Expand All @@ -173,8 +186,8 @@ jobs:
. $IDF_PATH/export.sh
export IDF_TARGET=${{matrix.esp-idf-target}}
export PATH=${PATH}:${HOME}/.cache/rebar3/bin
idf.py set-target ${{matrix.esp-idf-target}}
idf.py build
idf.py ${{matrix.cmake_opts}} set-target ${{matrix.esp-idf-target}}
idf.py ${{matrix.cmake_opts}} build
- name: Run ESP32 tests using qemu
working-directory: ./src/platforms/esp32/test/
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/run-tests-with-beam.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,45 +43,55 @@ jobs:
- os: "ubuntu-24.04"
test_erlang_opts: "-s prime_smp"
container: erlang:21
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=21 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=21

- os: "ubuntu-24.04"
test_erlang_opts: "-s prime_smp"
container: erlang:22
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=22 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=22

- os: "ubuntu-24.04"
test_erlang_opts: "-s prime_smp"
container: erlang:23
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=23 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=23

- os: "ubuntu-24.04"
test_erlang_opts: "-s prime_smp"
container: erlang:24
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=24 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=24

- os: "ubuntu-24.04"
test_erlang_opts: "-s prime_smp"
container: erlang:25
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=25 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=25

- os: "ubuntu-24.04"
test_erlang_opts: "-s prime_smp"
otp: "26"
container: erlang:26
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=26 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=26

- os: "ubuntu-24.04"
test_erlang_opts: "-s prime_smp"
otp: "27"
container: erlang:27
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=27 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=27

# This is ARM64
- os: "macos-14"
otp: "25"
path_prefix: "/opt/homebrew/opt/erlang@25/bin:"
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=25 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=25

- os: "macos-14"
otp: "26"
path_prefix: "/opt/homebrew/opt/erlang@26/bin:"
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=26 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=26

- os: "macos-14"
otp: "27"
path_prefix: "/opt/homebrew/opt/erlang@27/bin:"
cmake_opts: -DAVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION=27 -DAVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION=27
steps:
# Setup
- name: "Checkout repo"
Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ option(AVM_RELEASE "Build an AtomVM release" OFF)
option(AVM_CREATE_STACKTRACES "Create stacktraces" ON)
option(AVM_BUILD_RUNTIME_ONLY "Only build the AtomVM runtime" OFF)
option(COVERAGE "Build for code coverage" OFF)
set(AVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION "25" CACHE STRING "Minimum supported OTP Release for Erlang compiler")
set(AVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION "28" CACHE STRING "Maximum supported OTP Release for Erlang compiler")

if((${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") OR
(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") OR
Expand Down
13 changes: 6 additions & 7 deletions CMakeModules/FindElixir.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
#

find_program(ELIXIRC_PATH elixirc)
find_program(ELIXIRC_EXECUTABLE elixirc)

if (ELIXIRC_PATH)
message("Found Elixir")
set(Elixir_FOUND TRUE)
elseif(Elixir_FIND_REQUIRED)
message(FATAL_ERROR "Elixir compiler not found")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Elixir
FOUND_VAR Elixir_FOUND
REQUIRED_VARS ELIXIRC_EXECUTABLE
)
72 changes: 72 additions & 0 deletions CMakeModules/FindErlang.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#
# This file is part of AtomVM.
#
# Copyright 2025 Paul Guyot <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
#

cmake_minimum_required(VERSION 3.13)

find_program(ERLC_EXECUTABLE erlc)
find_program(ERL_EXECUTABLE erl)

if (ERLC_EXECUTABLE AND ERL_EXECUTABLE)
execute_process(COMMAND erl -eval "io:put_chars(erlang:system_info(otp_release))." -s init stop -noshell OUTPUT_VARIABLE Erlang_VERSION)
endif()

include(FindPackageHandleStandardArgs)

if (CMAKE_VERSION VERSION_LESS 3.19)
# Handle version range ourselves
if (Erlang_FIND_VERSION AND ERL_EXECUTABLE)
string(REPLACE "..." ";" Erlang_FIND_VERSION_LIST ${Erlang_FIND_VERSION})
list(LENGTH Erlang_FIND_VERSION_LIST Erlang_FIND_VERSION_LIST_LEN)
if (Erlang_FIND_VERSION_LIST_LEN EQUAL 1)
find_package_handle_standard_args(Erlang
FOUND_VAR Erlang_FOUND
REQUIRED_VARS ERLC_EXECUTABLE ERL_EXECUTABLE
VERSION_VAR Erlang_VERSION
)
elseif(${Erlang_FIND_VERSION_LIST_LEN} EQUAL 2)
list(GET Erlang_FIND_VERSION_LIST 0 Erlang_FIND_VERSION_MIN)
list(GET Erlang_FIND_VERSION_LIST 1 Erlang_FIND_VERSION_MAX)
if (${Erlang_VERSION} LESS Erlang_FIND_VERSION_MIN)
message(FATAL_ERROR "-- Found Erlang: ${ERL_EXECUTABLE} but OTP Release ${Erlang_VERSION} is less than required ${Erlang_FIND_VERSION_MIN}")
endif()
if (${Erlang_VERSION} GREATER Erlang_FIND_VERSION_MAX)
message(FATAL_ERROR "-- Found Erlang: ${ERL_EXECUTABLE} but OTP Release ${Erlang_VERSION} is greater than supported ${Erlang_FIND_VERSION_MAX}")
endif()
find_package_handle_standard_args(Erlang
FOUND_VAR Erlang_FOUND
REQUIRED_VARS ERLC_EXECUTABLE ERL_EXECUTABLE
)
else()
message(FATAL_ERROR "-- Found Erlang: ${ERL_EXECUTABLE} but version range syntax is incorrect ${Erlang_FIND_VERSION}")
endif()
else()
find_package_handle_standard_args(Erlang
FOUND_VAR Erlang_FOUND
REQUIRED_VARS ERLC_EXECUTABLE ERL_EXECUTABLE
)
endif()
else()
find_package_handle_standard_args(Erlang
FOUND_VAR Erlang_FOUND
HANDLE_VERSION_RANGE
REQUIRED_VARS ERLC_EXECUTABLE ERL_EXECUTABLE
VERSION_VAR Erlang_VERSION
)
endif()
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ if (Gleam_FOUND)
else()
message(WARNING "-- gleam not found, skipping Gleam examples")
endif()

# Ensure erlang version is compatible with VM
find_package(Erlang ${AVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION}...${AVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION} REQUIRED)
5 changes: 4 additions & 1 deletion libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
#

cmake_minimum_required (VERSION 3.12)
cmake_minimum_required (VERSION 3.13)
project(libs)

add_subdirectory(estdlib/src)
Expand Down Expand Up @@ -65,6 +65,9 @@ else()
message("Dialyzer was not found -- skipping PLT build")
endif()

# Ensure erlang version is compatible with VM
find_package(Erlang ${AVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION}...${AVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION} REQUIRED)

install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/atomvmlib.avm
DESTINATION lib/atomvm
Expand Down
6 changes: 6 additions & 0 deletions src/libAtomVM/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ endif()
if (ADVANCED_TRACING)
target_compile_definitions(libAtomVM PUBLIC ENABLE_ADVANCED_TRACE)
endif()
if (AVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION)
target_compile_definitions(libAtomVM PUBLIC MINIMUM_OTP_COMPILER_VERSION=${AVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION})
endif()
if (AVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION)
target_compile_definitions(libAtomVM PUBLIC MAXIMUM_OTP_COMPILER_VERSION=${AVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION})
endif()

target_link_libraries(libAtomVM PUBLIC m)
include(CheckCSourceCompiles)
Expand Down
12 changes: 7 additions & 5 deletions src/libAtomVM/opcodesswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@

// These constants can be used to reduce the size of the VM for a specific
// range of compiler versions
#define MINIMUM_OTP_COMPILER_VERSION 21
#define MAXIMUM_OTP_COMPILER_VERSION 26
#ifndef MINIMUM_OTP_COMPILER_VERSION
#define MINIMUM_OTP_COMPILER_VERSION 25
#endif
#ifndef MAXIMUM_OTP_COMPILER_VERSION
#define MAXIMUM_OTP_COMPILER_VERSION 28
#endif

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -4815,7 +4819,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
}
#endif

#if MINIMUM_OTP_COMPILER_VERSION <= 25
case OP_BS_MATCH_STRING: {
uint32_t fail;
DECODE_LABEL(fail, pc)
Expand Down Expand Up @@ -4887,7 +4890,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
#endif
break;
}
#endif

#if MINIMUM_OTP_COMPILER_VERSION <= 21
case OP_BS_SAVE2: {
Expand Down Expand Up @@ -4989,7 +4991,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
break;
}

#if MINIMUM_OTP_COMPILER_VERSION <= 24
#if MINIMUM_OTP_COMPILER_VERSION <= 25
case OP_BS_TEST_UNIT: {
uint32_t fail;
DECODE_LABEL(fail, pc)
Expand Down
2 changes: 2 additions & 0 deletions src/platforms/emscripten/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ endif ()
option(AVM_DISABLE_SMP "Disable SMP." OFF)
option(AVM_USE_32BIT_FLOAT "Use 32 bit floats." OFF)
option(AVM_VERBOSE_ABORT "Print module and line number on VM abort" OFF)
set(AVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION "25" CACHE STRING "Minimum supported OTP Release for Erlang compiler")
set(AVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION "28" CACHE STRING "Maximum supported OTP Release for Erlang compiler")

set(
PLATFORM_LIB_SUFFIX
Expand Down
5 changes: 5 additions & 0 deletions src/platforms/esp32/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ set(AVM_SELECT_IN_TASK ON)

project(atomvm-esp32-test)

# Ensure erlang version is compatible with VM
set(AVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION "25" CACHE STRING "Minimum supported OTP Release for Erlang compiler")
set(AVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION "28" CACHE STRING "Maximum supported OTP Release for Erlang compiler")
find_package(Erlang ${AVM_MINIMUM_OTP_RELEASE_COMPILER_VERSION}...${AVM_MAXIMUM_OTP_RELEASE_COMPILER_VERSION} REQUIRED)

# esp-idf does not use compile_feature but instead sets version in
# c_compile_options
# Ensure project is compiled with at least C11
Expand Down
Loading

0 comments on commit c426504

Please sign in to comment.