Skip to content

pragma pack struct + volatile results in an unresolved external "atomic_load" when using the Microsoft Linker #28217

Closed
@llvmbot

Description

@llvmbot
Bugzilla Link 27843
Resolution FIXED
Resolved on May 24, 2016 11:10
Version 3.8
OS Windows NT
Reporter LLVM Bugzilla Contributor
CC @majnemer

Extended Description

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.

Metadata

Metadata

Assignees

Labels

bugzillaIssues migrated from bugzillaclang:codegenIR generation bugs: mangling, exceptions, etc.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions