I am writing a toy compiler for a pascal-like language. Suppose I have a pseudocode like the following:
define main
define foo
define b
writeInteger: 1
call b
define bar
define b
writeInteger: 2
call b
call foo
call bar
where two different b
functions are defined inside of foo
and bar
.
So the corresponding LLVM IR function for b
inside of foo
is
define void @b(%foo_type* %foo_frame) {
...
And for b
inside of bar
is
define void @b.1(%bar_type* %bar_frame) {
...
The problem is that when I try to call the function b
, LLVM automatically assumes that I am calling the void @b
, but I have no way to call void @b.1
.
So, the printed result is 11
but I would like it to be 12
.
I use the TheModule->getFunction("b");
command to access the LLVM function Object.
So, how can I call the b
function defined inside of bar
?
UPDATE:
As AlexDenisov pointed out I could name the first b as main_foo_b
and the second as main_bar_b
.
So I could then call the right function b
, by finding out from which part of the code I am calling b. I will try that by holding a list of all of the function names until now(that have not been closed). Lets call it function_names_list
.
So then when I call the b
function that is inside main
and foo
I would call main_foo_b
because function_names_list=["main","foo"]
. And when I call the b
function that is inside main
and bar
I would call main_bar_b
because function_names_list=["main","bar"]
.
That will probably solve the problem for the current example.
But in an example like the following:
define main
define f
writeInteger: 1
define g
define f
writeInteger: 2
call f
define h
call f
call g # prints 2
call f # prints 1
call h # prints 1
I would also need to check in which nesting level the function is. By nesting level I mean inside of how many enclosing functions I currently am. main
has zero nesting levels, main_f
,main_g
and main_h
have 1 nesting level and main_g_f
has two nesting levels.
I would need to check the nesting level because, I would need to change how I call f
inside of h
.I would have to call it as main_f
and not main_h_f
.By knowing that the f
I am trying to call is at the previous nesting level, I can then use all but one elements from function_names_list
(function_names_list[0:n-1]
) in order to get the name main_f
.
Welcome to the SO, Nik.
Internally, all the global values (such as functions, variables, and aliases) live in hash-table-like storage inside of an LLVM module where the name serves as a key. In order to avoid collisions, LLVM adds suffixes to the function names.
I guess in this case you have to add some sort of namespacing, i.e. name the first b
as main_foo_b
and the second as main_bar_b
. This way you can clearly differentiate between the 'colliding' names.
I hope this helps :)
UPD:
Now it seems I went a bit too far and the suggestion by @arnt sounds more reasonable. Your solution with function_names_list
is the right direction. Usually, this is solved by a so-called Symbol Table: a symbol table is just a key-value data structure that also has a pointer to the parent symbol table. The keys in your case are the function names, and the values are emitted LLVM functions.
You start with a global symbol table (for the whole translation unit), then whenever you enter a new scope you create a new symbol table and set the parent to the "previous" symbol table. Then, when you need to emit a call to the function you look for the named function in the current symbol table, if there is none, then you walk up and look at the parent symbol table. Do it recursively until you reach the global symbol table, in which case a missing function can be reported as an error.
Here is an example for your first code snippet:
global_table:
scope = <whole translation unit>
parent = null
"main" = <main function>
main_table:
scope = <main function>
parent = global_table
"foo" = <foo function>
"bar" = <bar function>
foo_table:
scope = <foo function>
parent = main_table
"b" = <b function>
bar_table:
scope = <bar function>
parent = main_table
"b" = <b.1 function>
(Tables for b
and b.1
are empty, so I skipped them for brevity).
Then, depending on the scope (foo
or bar
) you'll start looking in either foo_table
or bar_table
and should find the right b
function.