Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

incorrect parsing of floating point literals #4813

Closed
vicuna opened this issue Jun 4, 2009 · 6 comments
Closed

incorrect parsing of floating point literals #4813

vicuna opened this issue Jun 4, 2009 · 6 comments
Assignees
Labels

Comments

@vicuna
Copy link

vicuna commented Jun 4, 2009

Original bug ID: 4813
Reporter: @mshinwell
Assigned to: @xavierleroy
Status: closed (set by @xavierleroy on 2011-05-29T10:14:07Z)
Resolution: fixed
Priority: normal
Severity: major
Version: 3.11.1+rc0
Fixed in version: 3.11.2+dev
Category: ~DO NOT USE (was: OCaml general)
Monitored by: letaris pzimmer @mmottl

Bug description

The GNU assembler contains a nasty bug in its parsing of floating point literals (http://sourceware.org/bugzilla/show_bug.cgi?id=10241). Create test.s thus:

.data
.double 0e0e-4
    .double 0
.double 0e-4
.double 0
    .double -4.0
.double 0

Assemble with the equivalent of the following on your favourite target:
$ ./install/bin/x86_64-pc-linux-gnu-as -o test.o test.s && ./install/bin/x86_64-pc-linux-gnu-objdump -Dr test.o

Note that, most seriously, 0e-4 has been assembled as -4 (!) and even 0e0e-4 is accepted. This still exists in the latest released version of binutils (2.19.1), and has probably been around for some time.

Since the O'Caml compiler passes the string representation of floating point literals directly to the assembler, we are exposed in O'Caml to the bug where 0e-4 parses as -4. (The 0e0e-4 case should be prevented by O'Caml's lexical analysis, as will be any of the other potential failure cases in the assembler when the second character of the literal is a letter of the alphabet but not 'e'.) As a consequence, the following program produces the surprising result of "a = -4.000000" under native code compilation:

type foo = Foo of float
let a = Foo 0e-4
let _ =
match a with
| Foo a ->
Printf.printf "a = %f" a

I suggest that the O'Caml compiler should be modified such that it never emits a string literal starting with "0e"; instead it should just emit a zero literal. This is safe even if the assembler concerned is not the GNU assembler. Unfortunately, this will necessitate a lot of tedious little changes throughout the asmcomp/ directory.

@vicuna
Copy link
Author

vicuna commented Jun 4, 2009

Comment author: @mmottl

The link seems to include a superfluous ')'. It should be:

http://sourceware.org/bugzilla/show_bug.cgi?id=10241

@vicuna
Copy link
Author

vicuna commented Jun 5, 2009

Comment author: @mshinwell

So it turns out that this is expected assembler behaviour (see the node Flonums in the info documentation for gas). It seems pretty crazy to me. Anyway, I still suggest a compiler patch is in order. It occurs to me that one other option is to alter the O'Caml lexer so it doesn't permit literals starting with "0e", although personally I think it would be better to accept such literals.

@vicuna
Copy link
Author

vicuna commented Jun 5, 2009

Comment author: pzimmer

If I understand correctly, one easy way to fix it would be for the OCaml compiler to output 0Ex instead of x for every float (or any letter other than E). This would lead to strange output like "0E1e-4" but should be correct in all cases. I agree the gas convention is very confusing...

@vicuna
Copy link
Author

vicuna commented Jun 5, 2009

Comment author: @mshinwell

I think the problem with pzimmer's suggestion is that it would result in having to determine whether a GNU assembler was being used, which it might not be on some targets.

@vicuna
Copy link
Author

vicuna commented Jun 23, 2009

Comment author: @xavierleroy

What a mess in the GNU assembler :-) Thanks for reporting it. I guess the simplest portable workaround is to emit float literals in the generated .s files as 64-bit integers, doing the string -> binary IEEE float conversion within Caml. Some ports already do this; it's a "small matter of programming" to do it systematically.

@vicuna
Copy link
Author

vicuna commented Jul 15, 2009

Comment author: @xavierleroy

Tentative fix in 3.11 release branch. Float literals are converted to IEEE representation by OCaml, then emitted as 32- or 64-bit integers. Tested on amd64/linux. Needs testing on other platforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants