Issue 171855
Summary Global object alignment diverges from MSVC
Labels backend:X86, diverges-from:msvc
Assignees
Reporter e-kud
    Let's consider the following code
```
template<unsigned SIZE, typename T>
class Obj {
public:
  Obj() = default;
  T mm[SIZE];
  static const Obj<SIZE, T>& g() {
    static const Obj<SIZE, T> _g = Obj<SIZE, T>();
    return _g;
  }
};
template<unsigned SIZE>
__declspec(noinline) const Obj<SIZE, char> &foo() {
        return Obj<SIZE, char>::g();
}
int main() {
 return foo<128>().mm[0];
}
```

Here we introduce a global object with an array inside.
When compiled with `cl test.cpp` we see the following in `llvm-readobj --all test.obj`
```
...
  Section {
    Number: 12
 Name: .bss (2E 62 73 73 00 00 00 00)
    VirtualSize: 0x0
 VirtualAddress: 0x0
    RawDataSize: 128
    PointerToRawData: 0x0
 PointerToRelocations: 0x0
    PointerToLineNumbers: 0x0
 RelocationCount: 0
    LineNumberCount: 0
    Characteristics [ (0xC0501080)
      IMAGE_SCN_ALIGN_16BYTES (0x500000)
 IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_READ (0x40000000)
      IMAGE_SCN_MEM_WRITE (0x80000000)
    ]
  }
...
  Symbol {
    Name: ?_g@?1??g@?$Obj@$0IA@D@@SAAEBV2@XZ@4V2@B
    Value: 0
    Section: .bss (12)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
 StorageClass: External (0x2)
    AuxSymbolCount: 0
  }
...
```
So the symbol is 16 bytes aligned.
However, when compiled with `clang++ -fms-extensions -O3 -target x86_64-pc-windows-msvc test.cpp -c` we see no alignment
```
...
  Section {
    Number: 6
    Name: .rdata (2E 72 64 61 74 61 00 00)
    VirtualSize: 0x0
    VirtualAddress: 0x0
 RawDataSize: 128
    PointerToRawData: 0x1B1
    PointerToRelocations: 0x0
    PointerToLineNumbers: 0x0
    RelocationCount: 0
 LineNumberCount: 0
    Characteristics [ (0x40101040)
 IMAGE_SCN_ALIGN_1BYTES (0x100000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
...
  Symbol {
    Name: ?_g@?1??g@?$Obj@$0IA@D@@SAAEBV2@XZ@4V2@B
    Value: 0
    Section: .rdata (6)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: External (0x2)
    AuxSymbolCount: 0
  }
...
```
The problem here is that the code compiled with MSVC cannot work with Clang compiled binaries due to misalignment as MSVC generates instructions for aligned memory access, when in reality it is not aligned if it is in Clang compiled binaries. (Sorry, I don't have a small reproducer for runtime failure).

MSVC doesn't have any align attributes in assembly. Through a set of experiments I figured out that MSVC aligns objects by following rules:
1) Size `>=64` align to 16 bytes
2) Size `>=8` align to 8 bytes
3) Size `>=2` align to 4 bytes
4) Otherwise align to 1 byte.

I'm not sure what is the better place to fix it. I'll submit a PR to fix it in assembly emission:
1) It allows to save compatibility between binaries of earlier and future versions compiled by clang
2) Provides MSVC-Clang compatibility.

If we change it in the FE, binaries will be incompatible between clang version, i.e. breaking change.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to