Skip to content

Commit

Permalink
Merge pull request #1238 from bettio/add-raw_raise-opcode
Browse files Browse the repository at this point in the history
opcodesswitch: add support for raw_raise

Add support for `raw_raise` instruction that has been found in some code
compiled with Elixir.

The compiler may replace `erlang:raise/3` with `raw_raise` instruction.

These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).

SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
  • Loading branch information
bettio committed Aug 6, 2024
2 parents 1f06efc + 8bcb57d commit 2c0f5d0
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Implement `gpio:init/1` on esp32 to initialize pins for GPIO usage, which some pins
require depending on default function and bootloader code
- Implement missing opcode 161 (raw_raise), that looks more likely to be generated with Elixir code

## [0.6.3] - 20-07-2024

Expand Down
1 change: 1 addition & 0 deletions src/libAtomVM/opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
#define OP_GET_MAP_ELEMENTS 158
#define OP_IS_TAGGED_TUPLE 159
#define OP_BUILD_STACKTRACE 160
#define OP_RAW_RAISE 161
#define OP_GET_HD 162
#define OP_GET_TL 163
#define OP_PUT_TUPLE2 164
Expand Down
20 changes: 20 additions & 0 deletions src/libAtomVM/opcodesswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -6102,6 +6102,26 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
break;
}

case OP_RAW_RAISE: {

TRACE("raw_raise/0\n");

#ifdef IMPL_EXECUTE_LOOP
// This is an optimization from the compiler where we don't need to call
// stacktrace_create_raw here because the stack trace has already been created
// and set in x[2].
term ex_class = x_regs[0];
if (UNLIKELY(ex_class != ERROR_ATOM &&
ex_class != LOWERCASE_EXIT_ATOM &&
ex_class != THROW_ATOM)) {
x_regs[0] = BADARG_ATOM;
} else {
goto handle_error;
}
#endif
break;
}

case OP_GET_HD: {
term src_value;
DECODE_COMPACT_TERM(src_value, pc)
Expand Down
4 changes: 4 additions & 0 deletions tests/erlang_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,8 @@ compile_erlang(twentyone_param_fun)
compile_erlang(test_fun_to_list)
compile_erlang(maps_nifs)

compile_erlang(test_raw_raise)

add_custom_target(erlang_test_modules DEPENDS
code_load_files

Expand Down Expand Up @@ -968,4 +970,6 @@ add_custom_target(erlang_test_modules DEPENDS

test_fun_to_list.beam
maps_nifs.beam

test_raw_raise.beam
)
68 changes: 68 additions & 0 deletions tests/erlang_tests/test_raw_raise.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
%
% This file is part of AtomVM.
%
% Copyright 2024 Davide Bettio <davide@uninstall.it>
%
% 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
%

-module(test_raw_raise).

-export([start/0, do_raise/0, fail_with_atom/1, do_raise_not_error/0]).

start() ->
do_catch() + do_catch2().

do_catch() ->
try ?MODULE:do_raise() of
_X -> 1
catch
error:{badarith, new_reason}:ST ->
case ST of
L when is_list(L) -> 0;
_ -> 2
end;
_:_ ->
3
end.

do_raise() ->
try ?MODULE:fail_with_atom(ciao) of
X -> X
catch
error:Reason:ST ->
erlang:raise(id(error), {Reason, new_reason}, ST)
end.

do_catch2() ->
try ?MODULE:do_raise_not_error() of
X -> 0
catch
_:_ -> 1
end.

do_raise_not_error() ->
try ?MODULE:fail_with_atom(ciao) of
X -> X
catch
error:Reason:ST ->
erlang:raise(id(not_error), {Reason, new_reason}, ST)
end.

fail_with_atom(Atom) ->
Atom + 1.

id(X) ->
X.
2 changes: 2 additions & 0 deletions tests/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ struct Test tests[] = {
TEST_CASE(test_fun_to_list),
TEST_CASE(maps_nifs),

TEST_CASE(test_raw_raise),

// TEST CRASHES HERE: TEST_CASE(memlimit),

{ NULL, 0, false, false }
Expand Down

0 comments on commit 2c0f5d0

Please sign in to comment.