https://llvm.org/bugs/show_bug.cgi?id=27843

            Bug ID: 27843
           Summary: pragma pack struct + volatile results in an unresolved
                    external "atomic_load" when using the Microsoft Linker
           Product: clang
           Version: 3.8
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangb...@nondot.org
          Reporter: llvmb...@endgame.com
                CC: llvm-bugs@lists.llvm.org
    Classification: Unclassified

A reference to a struct that uses "volatile" in combination with "#pragma
pack()" will yield optimized IR that uses atomic_load, which yields an
unresolved external when using the Microsoft linker.  We were able to reproduce
this with Visual Studio 2010, 2012, and 2013 with the following sample program:

#pragma pack(push)
#pragma pack(1)
struct A {
   volatile int f0;
};
#pragma pack(pop)

static const struct A g_A = { 0xFECDL };

int main (int argc, char* argv[])
{
    int tmp = g_A.f0;
    return 0;
}

When compiled with "/Od" so the relevant code doesn't get optimized out, here's
the IR with "volatile":

define i32 @main(i32 %argc, i8** %argv) #0 {
entry:
  %retval = alloca i32, align 4
  %argv.addr = alloca i8**, align 8
  %argc.addr = alloca i32, align 4
  %tmp = alloca i32, align 4
  %atomic-temp = alloca i32, align 4
  store i32 0, i32* %retval, align 4
  store i8** %argv, i8*** %argv.addr, align 8
  store i32 %argc, i32* %argc.addr, align 4
  %0 = bitcast i32* %atomic-temp to i8*
  call void @__atomic_load(i64 4, i8* bitcast (%struct.A* @g_A to i8*), i8* %0,
i32 2)
  %atomic-load = load atomic volatile i32, i32* %atomic-temp acquire, align 4
  store i32 %atomic-load, i32* %tmp, align 4
  ret i32 0
}

And without "volatile":


define i32 @main(i32 %argc, i8** %argv) #0 {
entry:
  %retval = alloca i32, align 4
  %argv.addr = alloca i8**, align 8
  %argc.addr = alloca i32, align 4
  %tmp = alloca i32, align 4
  store i32 0, i32* %retval, align 4
  store i8** %argv, i8*** %argv.addr, align 8
  store i32 %argc, i32* %argc.addr, align 4
  %0 = load i32, i32* getelementptr inbounds (%struct.A, %struct.A* @g_A, i32
0, i32 0), align 1
  store i32 %0, i32* %tmp, align 4
  ret i32 0
}


If one removes the volatile keyword from the struct member, or removes the
pragma pack, the linking issue goes away. However, we believe the underlying
issue may be that the calling convention mentioned in
http://llvm.org/docs/Atomics.html#libcalls-atomic doesn't line up with how
Microsoft uses the atomic_load call, thus the linker can't resolve the correct
function.

Unsure if the fix should be to ensure the libcall to atomic_load isn't used, or
whether the convention should be fixed for builds on windows.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to