Reputation: 882
I'm looking at this: Importing Function Calls Using __declspec(dllimport) and I do not understand why __declspec(dllimport) is really needed? Why can't linker patch call func1 into call DWORD PTR __imp_func1 (IAT table address) during linking phase therefore avoiding the need for separate declaration in source?
Upvotes: 4
Views: 351
Reputation: 16207
In VS 2022 (and probably long, long before that), the compiler (not the linker) is indeed able to optimize the thunk away with or without __declspec(dllimport)
. It is completely redundant today, hopefully the docs would reflect it one day.
Upvotes: 0
Reputation: 21674
Insuffcient space for patching instruction might be a reason, but not the major reason. Even if there is enough space, the linker still would not patch it for better performance. The reason is linker doesn't do or modify the code generated by the compiler back-end, it just patches the places with relocation information. Below example is not in good coding style, but explain the issue clearly. The generated instruction for bar()
is call dword[_imp__bar]
, which is 6 bytes long, even if the linker has the knowledge that bar()
is defined in the final image, it doesn't patch it with call OffsetOfBar
which only requires 5 bytes. Delay the code gen to link time (pass /GL to cl.exe) can solve this issue because linker will invoke the compiler back-end during link time, and the back-end will generate optimized call
instruction because it knows the call
target is in the same module.
// main.c
// compile it with 'cl.exe /Zi /O2 main.c bar.c'
__declspec(dllimport) void bar();
int main() {
bar();
}
// bar.c
void __declspec(noinline) bar() {}
Upvotes: 2
Reputation: 882
Quoting Raymond Chen: call func is 5 bytes long, but call dword ptr [_imp_func] is 6 bytes long. The patch does not fit. It's one byte too big. Adding a nop after every single call instruction (just in case it happens to be imported) sounds pretty excessive.
Upvotes: 1