This is probably a stupid question, but I\'ve searched for quite a while now here and on the web and couldn\'t come up with a clear answer (did my due diligence goo
1. The principle
When you write:
int A = myfunction(12);
This is translated to:
int A = @call(myfunction, 12);
where @call
can be seen as a dictionary look-up. And if you think about the dictionary analogy, you can certainly know about a word (smogashboard ?) before knowing its definition. All you need is that, at runtime, the definition be in the dictionary.
2. A point on ABI
How does this @call work ? Because of the ABI. The ABI is a way that describes many things, and among those how to perform a call to a given function (depending on its parameters). The call contract is simple: it simply says where each of the function arguments can be found (some will be in the processor's registers, some others on the stack).
Therefore, @call actually does:
@push 12, reg0
@invoke myfunction
And the function definition knows that its first argument (x) is located in reg0
.
3. But I though dictionaries were for dynamic languages ?
And you are right, to an extent. Dynamic languages are typically implemented with a hash table for symbol lookup that is dynamically populated.
For C++, the compiler will transform a translation unit (roughly speaking, a preprocessed source file) into an object (.o
or .obj
in general). Each object contains a table of the symbols it references but for which the definition is not known:
.undefined
[0]: myfunction
Then the linker will bring together the objects and reconciliate the symbols. There are two kinds of symbols at this point:
Both can be treated in the same fashion.
.dynamic
[0]: myfunction at <undefined-address>
And then the code will reference the look-up entry:
@invoke .dynamic[0]
When the library is loaded (DLL_Open
for example), the runtime will finally know where the symbol is mapped in memory, and overwrite the <undefined-address>
with the real address (for this run).