[llvm-bugs] [Bug 27843] New: pragma pack struct + volatile results in an unresolved external "atomic_load" when using the Microsoft Linker

via llvm-bugs llvm-bugs at lists.llvm.org
Mon May 23 11:28:33 PDT 2016


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: unassignedclangbugs at nondot.org
          Reporter: llvmbugs at endgame.com
                CC: llvm-bugs at 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160523/4ba0cde7/attachment.html>


More information about the llvm-bugs mailing list