Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0006594OCamlback end (clambda to assembly)public2014-10-03 13:442016-12-08 16:57
Assigned Toshinwell 
Platformamd64OSWin64OS VersionWin7
Product Version4.02.0+beta1 / +rc1 
Target VersionlaterFixed in Version 
Summary0006594: options -nodynlink and -fno-PIC together produce assembler errors for MSVC64
DescriptionI tried compiling with MSVC11 (Visual 2012) 64 bits, either option works fine but the two together seem to produce assembler errors as soon as the .ml file is large enough.
Steps To Reproduce1. edit stdlib/Makefile.shared to add `-nodynlink -fno-PIC -verbose` to COMPFLAGS
2. touch stdlib/
3. make libraryopt

? I get Assembler error: error A2084: constant value too large
TagsNo tags attached.
Attached Files

- Relationships

-  Notes
oandrieu (reporter)
2014-10-06 10:32

Apparently it's the Istore_symbol instruction that causes the issue (in asmcomp/amd64/emit_nt.mlp):

    | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
        assert (not !pic_code);
    add_used_symbol s;
        ` mov QWORD PTR {emit_addressing addr i.arg 0}, OFFSET {emit_symbol s}\n`

vs. the non-windows version:

    | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
        assert (not !pic_code && not !Clflags.dlcode);
        ` movq ${emit_symbol s}, {emit_addressing addr i.arg 0}\n`
frisch (developer)
2015-03-11 17:04

Hi Olivier,

Commit 15900 on trunk changes how symbols are addressed on Win64. This was mostly done to support loading .cmxs at arbitrary location in the memory space (otherwise, flexdll would fail at load time to relocate symbols which end up too far). But I suspect this could fix since the movabsq instruction is now used. Can you try?
oandrieu (reporter)
2015-03-11 18:51

Hi Alain,

thanks for looking into this.

Well no it doesn't seem to fix it since only X86_gas uses movabsq, X86_masm still emits a plain mov :)

Now from what I understand movabs is a GAS mnemonic (rather than a Intel-documented one), I'm not sure what the ml64 equivalent is ...
frisch (developer)
2015-03-11 19:40

The mnemonic is simply "MOV". Normally ml64 picks the right instruction if the operand is large enough. In that case, the operand is a symbol. I will need to have a closer look at how to fix this...

(FWIW, LexiFi uses a binary code emitter, which means we choose our instructions precisely and don't rely on external assemblers.)
frisch (developer)
2015-03-12 13:27

Out of curiosity:
 1. why do you compile with -nodynlink and -fno-PIC?
 2. How big is the .ml file?
oandrieu (reporter)
2015-03-12 14:51

1. Well, first I'm not 100% clear on the difference between these two options. It's just that I don't need/use dynlink and I thought that using these options would yield the plainest, simplest assembler output.

2. size of the .ml doesn't appear to be a factor ... There's the issue with stdlib
frisch (developer)
2015-03-12 15:09

1. -nodynlink means that the code is not intended to be linked into a .cmxs file and then dynamically loaded; and -fno-PIC that we don't require it to be position-independant. Some systems require dynamically loaded code to be position-independant (so none of -nodynlink and -fno-PIC can be used if we want to use Dynlink), but not always. Under Windows, this is rather the opposite:
flexdll needs to patch the loaded code, so it doesn't really matter that it is position-independant or not (position-independant is useful to allow physically sharing of pages, which is not possible under Windows anyway). So without -nodynlink and without -fno-PIC, the generated code is not position-independant.

I'm wondering whether we should just ignore -nodynlink and -fno-PIC under Windows. Can you confirm you don't have any problem when you don't use these options?

2. Ah, I missed the fact about pervasives and I was confused by "as soon as the .ml file is large enough".
oandrieu (reporter)
2015-03-12 15:42

Yes, no problem with no option, or either of the option alone. Only when they are both present.

The problematic asm then looks like this:
mov QWORD PTR [rbx], DWORD OFFSET camlPervasives__loop_1150

As for MOV variants, there is:
MOV r64, imm64
MOV r/m64, imm32

So I guess the error there is about the attempted "MOV r/m64, imm64" that doesn't exist ?
frisch (developer)
2015-11-27 18:10

A simple workaround exists, so no hurry here. Pushing to "later".
xleroy (administrator)
2015-11-28 10:22

@oandrieu's analysis is spot on: x86-64 has no "move imm64 to mem64" instruction, only "move imm32 to mem64". ocamlopt uses the latter instruction for the Ispecific(Istore_symbol) operation, which initializes a 64-bit memory location with the address of a symbol.

This works only if the symbol is in the low 4 Gb of the addressing space, and the assembler and linker know about this fact.

It is the case under Linux and MacOS X when producing static code (position-dependent and not in a DLL). Clearly it is not the case under Win64: either the symbol is not guaranteed to be in the low 4 Gb, or the assembler and linker don't support relocations of the "low 32 bits of a symbol address" kind.

Solution 1: turn off the recognition of Istore_symbol for Win64. The code to change is in asmcomp/amd64/, method select_store.

Solution 2: suppress the Istore_symbol operation entirely. Even under Linux and MacOS X, it is rarely recognized because the default is to produce PIC code. So, it would not be a big loss.
frisch (developer)
2016-07-13 18:35

There is an IMAGE_REL_AMD64_ADDR32 kind of relocation in COFF for x64 processors, although it's hard to tell exactly what it is supposed to do exactly ("The 32-bit VA of the relocation target" -- I guess it means the image loader is supposed to fail if the target is not in the low 4Gb, or perhaps that it would store its low 32 bits). But:

  - The assembler has no way to know that the symbol will indeed be in the low 4 Gb (even if Windows guaranteed that property for static code -- I don't know if this is the case or not).

  - Even it is produced the relocation kind above, flexdll does not support it (on x64, it supports only ADDR64 and REL32, REL32_1, REL32_2, REL32_4, and actually only ADDR64 in its no_rel_relocs mode).
shinwell (developer)
2016-12-08 16:57

Superceded by [^] where there is also a proposed patch.

- Issue History
Date Modified Username Field Change
2014-10-03 13:44 oandrieu New Issue
2014-10-04 10:09 doligez Status new => acknowledged
2014-10-04 10:09 doligez Target Version => 4.02.2+dev / +rc1
2014-10-06 10:32 oandrieu Note Added: 0012298
2015-03-11 17:04 frisch Note Added: 0013447
2015-03-11 18:51 oandrieu Note Added: 0013449
2015-03-11 19:40 frisch Note Added: 0013450
2015-03-12 13:27 frisch Note Added: 0013460
2015-03-12 14:51 oandrieu Note Added: 0013462
2015-03-12 15:09 frisch Note Added: 0013465
2015-03-12 15:42 oandrieu Note Added: 0013468
2015-03-18 17:55 frisch Target Version 4.02.2+dev / +rc1 => 4.02.3+dev
2015-07-10 18:04 doligez Target Version 4.02.3+dev => 4.03.0+dev / +beta1
2015-11-27 18:10 frisch Note Added: 0014868
2015-11-27 18:10 frisch Target Version 4.03.0+dev / +beta1 => later
2015-11-28 10:22 xleroy Note Added: 0014875
2016-07-13 18:35 frisch Note Added: 0016074
2016-12-08 16:57 shinwell Note Added: 0016910
2016-12-08 16:57 shinwell Status acknowledged => closed
2016-12-08 16:57 shinwell Assigned To => shinwell
2016-12-08 16:57 shinwell Resolution open => duplicate
2017-02-23 16:35 doligez Category OCaml backend (code generation) => Back end (clambda to assembly)
2017-02-23 16:44 doligez Category Back end (clambda to assembly) => back end (clambda to assembly)

Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker