Age | Commit message (Collapse) | Author |
|
A map key in a pattern would be incorrectly pretty-printed.
As an example, the pattern in:
x() ->
#{ #{ a => 3 } := 42 } = X.
would be pretty-printed as:
<~{~<~{~<'a',3>}~,42>}~
instead of:
<~{~<~{::<'a',3>}~,42>}~
When this problem has been corrected, the workaround for it in
cerl:ann_c_map/3 can be removed. The workaround was not harmless,
as it would cause the following map update to incorrectly succeed:
(#{})#{a:=1}
|
|
When we compile from Core Erlang, do it with and without
Core Erlang optimizations to ensure that we are not dependent
on the optimizations always being run.
|
|
v3_core is careful to always create literals whenever possible.
Correct core_parse so it, too, always creates literals out
of literal conses. With that correction, we can remove the
workaround in sys_core_fold (introduced in 26a5dea3cb5e101)
that handles non-literal flags in a binary.
|
|
Maps have certain invariants that must be preserved:
(1) A map as a pattern must be represented as #c_map{} record,
never as a literal. The reason is that the pattern '#{}' will
match any map, not just the empty map. The literal '#{}' will
only match the empty map.
(2) In a map pattern, the key must be a literal, a variable, or
data (list or tuple). Keys that are binaries or maps *must* be
represented as literals.
(3) Maps in expressions should be represented as literals if possible.
Nothing is broken if this invariant is broken, but the generated
code will be less efficient.
To preserve invariant (1), cerl:update_c_map/3 must never collapse
a map to a literal. To preserve invariant (3), cerl:update_c_map/3
must collapse a map to a literal if possible.
To preserve both invariants, we need a way for cerl:update_c_map/3 to
know whether the map is used as a pattern or as an expression. The
simplest way is to have an 'is_pat' boolean in the #c_map{} record
which is set when a #c_map{} record is initially created.
We also need to update core_parse.yrl to establish the invariants
in the same way as v3_core, to ensure that compiling from a
.core file will work even if all optimizations on Core Erlang are
disabled.
|
|
|
|
We used to evaluate the body of a 'letrec' in value context, even
if the 'letrec' was being evaluated in effect context. In most
cases, the context does not matter because the body is usually
just an 'apply' which will never be optimized away.
However, in the case of incorrect code described in the previous
commit, it does matter. We can find such bad code by evaluating
the body in effect context. For example, if we have the following
incorrect code:
letrec
f/1 = fun(A) -> ... <use of Var> ...
in let Var = <<2:301>>
in apply(Arg)
If the letrec is evaluated in effect context, the code will be
reduced to:
letrec
f/1 = fun(A) -> ... <use of Var> ...
in seq Var = <<2:301>> do apply(Arg)
Now Var will be unbound and a later compiler pass will crash to
ensure that the bad Core Erlang code is noticed.
Also add a test case to ensure that the compiler crashes if the
bug fixed in the previous commit re-surfaces.
|
|
The translation of list comprehension with a map pattern
with a big literal binary as key such as:
lc(L) ->
[V || #{<<2:301>> := V} <- L].
would generate Core Erlang code where an unbound variable
were referenced:
'lc'/1 =
fun (L) ->
letrec
'lc$^0'/1 = fun (_cor4) ->
case _cor4 of
<[~{~<_cor1,V>}~|_cor3]> when 'true' ->
let <_cor5> = apply 'lc$^0'/1(_cor3)
in [V|_cor5]
<[_cor2|_cor3]> when 'true' ->
apply 'lc$^0'/1(_cor3)
<[]> when 'true' ->
[]
end
in let <_cor1> = #{#<2>(301,1,'integer',['unsigned'|['big']])}#
in apply 'lc$^0'/1(L)
In the map pattern in the 'case' in the 'letrec', the key is the
variable '_cor1' which should be bound in the enclosing environment.
It is not.
There is binding of '_cor1', but in the wrong place (at the end of
the function). Because of the way v3_kernel translates letrecs,
the code *happens* to work.
The code will break if Core Erlang optimizations were strengthened
to more aggressively eliminate variable bindings that are not used,
or if the translation from Core Erlang to Kernel Erlang were changed.
Correct the translation so that '_cor1' is bound in the environment
enclosing the 'letrec':
'lc'/1 =
fun (L) ->
let <_cor1> = #{#<2>(301,1,'integer',['unsigned'|['big']])}#
in letrec
'lc$^0'/1 = fun (_cor4) ->
case _cor4 of
<[~{~<_cor1,V>}~|_cor3]> when 'true' ->
let <_cor5> = apply 'lc$^0'/1(_cor3)
in [V|_cor5]
<[_cor2|_cor3]> when 'true' ->
apply 'lc$^0'/1(_cor3)
<[]> when 'true' ->
[]
end
in apply 'lc$^0'/1(L)
Unfortunately I was not able to come up with a test case that
demonstrates the bug.
|
|
is_var_used/2 did not notice that variable keys in map patterns
were used, which could cause sys_core_fold to do unsafe
optimizations.
|
|
|
|
|
|
Remove ?line macros. Run test cases in parallel.
|
|
|
|
* ia/ssh/sftp-v3-flags:
ssh: Add some more flags
ssh: Correct Sftp flag handling
ssh: Add handling of sftp v3 flags
|
|
* ia/ssl/poddle/OTP-12390:
ssl: Remove default support for RC4 ciphers
ssl: Reenable padding check for TLS-1.0 and provide backwards compatible disable option
ssl: Remove sslv3 from the default supported protocol versions
|
|
* ia/ssl/maint/poddle/OTP-12420:
ssl: Reenable padding check for TLS-1.0 and provide backwards compatible disable option
|
|
* egil/fix-maps-compiler-coverage/OTP-12425:
compiler: Rename util function to adhere to name policy
compiler: Remove get_map_elements label check in blocks
compiler: Remove unnecassary guard for get_map_elements
compiler: Remove dead code in beam_flatten
compiler: Increase Maps code coverage
|
|
|
|
* egil/fix-lcnt/OTP-12364:
tools: Fix lcnt printout of histograms
tools: Fix lcnt sort of inspected locks
|
|
|
|
* nox/standard_error/OTP-12424:
Test standard_error
Properly handle broken input in standard_error
Fix io:getopts(standard_error)
|
|
|
|
* marcus/rabbe-doc-typos2/OTP-12399:
fix spelling
|
|
|
|
disable option
|
|
|
|
disable option
Conflicts:
lib/ssl/src/ssl_cipher.erl
lib/ssl/src/ssl_record.erl
lib/ssl/src/tls_record.erl
lib/ssl/test/ssl_cipher_SUITE.erl
|
|
|
|
Function name was somewhat confusing and when trying to find a better
name for it we realised it did not work as intended.
|
|
|
|
* bjorn/compiler/coverage:
map_SUITE: Ensure recompilation when running cover
Add beam_utils_SUITE to cover more lines in beam_utils
beam_utils: Remove unreachable clauses in live_opt/4
receive_SUITE: Cover handling of recv_mark & recv_set in beam_utils
beam_validator_SUITE: Mend the compiler_bug/1 test case
beam_clean: Remove handling of forgotten instructions
compile_SUITE: Test the 'dialyzer' option
|
|
* maint:
Update primary bootstrap
core_lib: Handle patterns in map values
|
|
* bjorn/compiler/map-pattern/OTP-12414:
core_lib: Handle patterns in map values
|
|
|
|
|
|
beam_utils:live_opt() is only invoked on code that has been
blockified by beam_block. Therefore the allocate/3 and
allocate_heap/4 instructions only occur in their transformed
form inside a block.
While we are it, correct a comment. 'asm' has been replaced
by 'from_asm'.
|
|
While we are it, also remove ?line macros in ref_opt_1/1 and correct
the indentation in do_ref_opt/2.
|
|
The compiler_bug/1 test case succeeded for the wrong reason. The
'asm' option is no longer supported (was ignored) and the compiler
looked for a .erl file.
Make sure that we don't fall for this trick again by making sure
that the error is reported from beam_validator.
|
|
|
|
io:put_chars(standard_error, [oops]) could previously crash the
standard_error process.
Reported-by: Alexei Sholik
|
|
core_lib:is_var_used/2 would not consider a variable used in the
value of a map pattern such as:
case Map of
#{key := <<42:N>>} -> ok
end
Here the variable 'N' would not be considered used.
It was assumed that there was no need to check map patterns at
all, since maps currently don't support variables in keys.
|
|
|
|
* mikpe/hipe-fconv-fmove-fixes/OTP-12413:
hipe: rtl: fix phi_remove_pred/2 FP moves
hipe: backends: correct #fconv{} translation
|
|
|
|
* oliv3/math_log2/OTP-12411:
Add math:log2/1
|
|
Commits b44f86b7 and 97953704 introduced translations of instructions
in beam_a and beam_z, but forgot to remove the handling of them in
beam_clean.
|
|
Cover more code in v3_core.
|
|
* origin/hb/parsetools/suppress_dialyzer_warnings/OTP-12271:
Let Leex use the new -dialyzer attribute
Let Yecc use the new -dialyzer attribute
|
|
* maint:
Update primary bootstrap
beam_bool: Correct live calculation for GC BIFs
beam_bool: Correct indentation for try...catch
sys_core_fold: Correct optimization of 'case'
Conflicts:
bootstrap/bin/start.boot
bootstrap/bin/start_clean.boot
bootstrap/lib/compiler/ebin/beam_asm.beam
bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
|
|
* bjorn/compiler/map-in-record-bug/OTP-12402:
sys_core_fold: Correct optimization of 'case'
|
|
* bjorn/compiler/beam_bool/OTP-12410:
beam_bool: Correct live calculation for GC BIFs
beam_bool: Correct indentation for try...catch
|