Skip to content

Commit

Permalink
Add a table of pseudo-guard BIFs
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorng committed Nov 14, 2024
1 parent 621c5c7 commit 9d985f5
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 5 deletions.
55 changes: 53 additions & 2 deletions erts/emulator/utils/beam_makeops
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,13 @@ foreach my $makes_no_sense ('f', 'j', 'o', 'q') {
delete $construction_type{$makes_no_sense};
}

#
# Pseudo-guard BIFs.
#
my $in_pbifs_section = 0;
my @pbifs;
my %known_bifs; # Known BIFs based on bif.tab.

#
# Generate bits.
#
Expand Down Expand Up @@ -532,13 +539,50 @@ while (<>) {
next;
}

#
# Handle %pbifs start and %pbifs end.
#
if (/^\%pbifs\s+(\S+)/) {
if ($1 eq 'start') {
$in_pbifs_section = 1;
} elsif ($1 eq 'end') {
$in_pbifs_section = 0;
} else {
error("pbifs: Illegal sub-directive '$1'");
}
next;
}

#
# Handle unrecognized % directives.
#
if (/^\%(\S+)/) {
error("Unrecognized directive '%$1'");
}

#
# Handle pseudo-guard BIFs.
#
if ($in_pbifs_section && m@^([\w\d_]+):([\w\d_]+)/(\d+)@) {
my $pbif = "$1:$2:$3";
unless (defined $known_bifs{$pbif}) {
error("BIF $1:$2/$3 is not defined as a 'bif' in bif.tab\n");
}
push @pbifs, "$1:$2:$3";
next;
} elsif (m@^bif\s+([\w\d_]+):([\w\d_]+)/(\d+)@) {
# This is a `bif` directive in bif.tab.
my $pbif = "$1:$2:$3";
$known_bifs{$pbif} = 1;
next;
} elsif (m@^[hu]bif\s+[\w\d_']+:@) {
# Ignore `hbif and `ubif` directives in bif.tab.
next;
} elsif (m@^bif\s+[\w\d_']+:@) {
# Ignore `bif` directives with quoted names in bif.tab.
next;
}

#
# Handle transformations.
#
Expand Down Expand Up @@ -1220,7 +1264,7 @@ sub compiler_output {
comment('erlang');

print "-export([format_number/0]).\n";
print "-export([opcode/2,opname/1]).\n";
print "-export([opcode/2,opname/1,is_pbif/3]).\n";
print "\n";
print "-spec format_number() -> $BEAM_FORMAT_NUMBER.\n";
print "format_number() -> $BEAM_FORMAT_NUMBER.\n\n";
Expand All @@ -1239,7 +1283,14 @@ sub compiler_output {
print "opname($i) -> {",
quote($gen_opname[$i]), ",$gen_arity[$i]};\n";
}
print "opname(Number) -> erlang:error(badarg, [Number]).\n";
print "opname(Number) -> erlang:error(badarg, [Number]).\n\n";

print "-spec is_pbif(module(), atom(), non_neg_integer()) -> boolean().\n";
foreach my $pbif (@pbifs) {
my($mod,$name,$arity) = split(':', $pbif);
print "is_pbif($mod, $name, $arity) -> true;\n";
}
print "is_pbif(_, _, _) -> false.\n";

#
# Generate .hrl file.
Expand Down
4 changes: 2 additions & 2 deletions lib/compiler/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk

$(EGEN)/beam_opcodes.erl $(EGEN)/beam_opcodes.hrl: $(EGEN)/OPCODES-GENERATED

$(EGEN)/OPCODES-GENERATED: genop.tab
$(gen_verbose)$(PERL) $(ERL_TOP)/erts/emulator/utils/beam_makeops -compiler -outdir $(EGEN) $< && echo $? >$(EGEN)/OPCODES-GENERATED
$(EGEN)/OPCODES-GENERATED: genop.tab $(ERL_TOP)/erts/emulator/beam/bif.tab pbif.tab
$(gen_verbose)$(PERL) $(ERL_TOP)/erts/emulator/utils/beam_makeops -compiler -outdir $(EGEN) $^ && echo $^ >$(EGEN)/OPCODES-GENERATED

$(EBIN)/beam_asm.beam: $(ESRC)/beam_asm.erl $(EGEN)/beam_opcodes.hrl
$(V_ERLC) $(ERL_COMPILE_FLAGS) -DCOMPILER_VSN='"$(VSN)"' -o$(EBIN) $<
Expand Down
2 changes: 1 addition & 1 deletion lib/compiler/src/beam_ssa_opt.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1910,7 +1910,7 @@ reduce_try_is([#b_set{anno=Anno,op=call,args=[#b_remote{mod=#b_literal{val=M},
I = I1#b_set{op={bif,F},args=Args1},
reduce_try_is(Is, [I|Acc]);
false ->
case erl_bifs:is_pure(M, F, A) of
case beam_opcodes:is_pbif(M, F, A) of
true ->
I = I0#b_set{anno=Anno#{pseudo_bif => true}},
reduce_try_is(Is, [I|Acc]);
Expand Down
76 changes: 76 additions & 0 deletions lib/compiler/src/pbif.tab
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#
# %CopyrightBegin%
#
# Copyright Ericsson AB 2024. All Rights Reserved.
#
# 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.
#
# %CopyrightEnd%
#

%pbifs start

erlang:atom_to_binary/2
erlang:atom_to_list/1
erlang:binary_to_float/1
erlang:binary_to_list/1
erlang:binary_to_list/3
erlang:float_to_list/1
erlang:float_to_binary/1
erlang:integer_to_binary/1
erlang:integer_to_binary/2
erlang:integer_to_list/1
erlang:integer_to_list/2
erlang:iolist_size/1
erlang:iolist_to_binary/1
erlang:list_to_binary/1
erlang:list_to_float/1
erlang:list_to_pid/1
erlang:list_to_tuple/1
erlang:make_fun/3
erlang:phash/2
erlang:pid_to_list/1
erlang:setelement/3
erlang:split_binary/2
erlang:tuple_to_list/1

ets:lookup_element/3
ets:update_counter/3
ets:update_element/3

math:acos/1
math:acosh/1
math:asin/1
math:asinh/1
math:atan/1
math:atan2/2
math:atanh/1
math:ceil/1
math:cos/1
math:cosh/1
math:erf/1
math:erfc/1
math:exp/1
math:floor/1
math:fmod/2
math:log/1
math:log2/1
math:log10/1
math:pow/2
math:sin/1
math:sinh/1
math:sqrt/1
math:tan/1
math:tanh/1

%pbifs end

0 comments on commit 9d985f5

Please sign in to comment.