Forward declaration of function LLVM - llvm

I'm trying to use forward declaration of functions in LLVM, but I'm not able to do it... The reason for doing that is this error:
error: invalid forward reference to function 'f' with wrong type! "
Right now I'm trying to do it with this code:
std::vector<Type *> args_type = f->get_args_type();
Module* mod = get_module();
std::string struct_name("struct.");
struct_name.append(f->get_name());
Type* StructTy = mod->getTypeByName(struct_name);
if (!StructTy) {
StructTy = Type::getVoidTy(getGlobalContext());
}
FunctionType *ftype = FunctionType::get(StructTy, args_type, false);
//Function *func = Function::Create(ftype, GlobalValue::InternalLinkage, f->get_name(), get_module());
Constant* c = mod->getOrInsertFunction(f->get_name(), ftype);
Function *func = cast<Function>(c);
But it does not show in the IR when I generate the code. When I create the function again using this same code shown above, it works. I wonder if it's because I insert a BasicBlock right after when I start insert things within the function.
Right now that's how it is my IR
define internal void #main() {
entry:
...
}
define internal %struct.f #f(i32* %x) {
entry:
...
}
I believe that putting an declare %struct.f #f(i32*) before the #main function would fix this issue, but I can't figure out how to do it...
Summary: I just want to create something with a declare on top of the file, so I can use the define it later and start inserting instructions of the function

Ok, it seems LLVM does that 'automatically'.
I just realized that the functions changed their orders when I ran the code again. So, if you create a function before even though you don't insert any code (body), it will create the prototype and wait for any further declarations to the body, as long as you reference this function with the getOrInsert() method of the Module class.
I don't know if this is the right answer or if it's clear, but it solved my problem...

Related

How to Create a Load Instruction in LLVM, given Pointer to do the Load from?

I'm writing a LLVM pass where I create a function with integer pointer arguments. I need to implement the body of the function as well, and in order to do so, I need the integer values that are being pointed to. I am trying to create a load instruction that I can insert at the end of the basic block that contains the function body, but I am getting an error when doing so. Things compile fine, but when I run the pass, I get a generic error.
From what I've found about LLVM, there are usually ways to create instructions that don't involve using constructors, but I couldn't find a way to do that for load instructions, so I just used one of the constructors instead. After creating the function with arguments of the integer pointer type, this is the code that I'm using to do the load:
llvm::LoadInst operandLoad(llvm::Type::getInt32Ty(ctx), argList[0], "test", basicBlock);
If I comment the above line out, my pass runs fine. I'm unsure whether this is enough to diagnose the issue, so I'll include all the code to create the function (it's slightly simplified):
void createFunction(std::string functionName, llvm::LLVMContext &ctx, llvm::Module *module) {
std::vector<llvm::Type*> typeList = {llvm::Type::getInt32PtrTy(ctx)};
// Create function type
llvm::FunctionType *functionType = llvm::FunctionType::get(llvm::Type::getVoidTy(ctx), typeList, false);
// Create function
llvm::Function *function = llvm::Function::Create(functionType, llvm::Function::ExternalLinkage, functionName, module);
std::vector<llvm::Value*> argList;
for (llvm::Function::arg_iterator it = function->arg_begin(); it != function->arg_end(); ++it) {
argList.push_back(it);
}
llvm::BasicBlock *basicBlock = llvm::BasicBlock::Create(ctx, "entry", function);
llvm::LoadInst operandLoad(llvm::Type::getInt32Ty(ctx), argList[0], "test", basicBlock);
llvm::IRBuilder<> builder(ctx);
builder.SetInsertPoint(basicBlock);
builder.CreateRet(nullptr);
}
I'm sure this is a stupid question, so sorry about that. And thanks in advance!

Passing NSString* to a C++ reference parameter

Have an Objective-C++ function. (The file has the correct .mm extension).
int SPGetNumericAttribute(NSMutableString* line, NSString* &attr) {...}
Some code calls as follows:
NSString* queryAttr = nil;
int res = SPGetNameAttribute(line, queryAttr); <-- error
Compiler complains:
No matching function call for 'SPGetNameAttribute'.
Is there a technical reason why you can't pass an Objective-C object to a C++ reference parameter?
My guess is something to do with ARC.
ARC needs to know how to handle the reference counting of the second parameter inside of the function. By default the parameter has autoreleasing type. Thus your variable queryAttr must have the autoreleasing ARC type
__autoreleasing NSString* queryAttr = nil;
or alternatively you can declare your function as
int SPGetNumericAttribute(NSMutableString* line, NSString* __strong &attr) { ... }
and the error disappears for strong variables. Tests with Instruments show that ARC seems to be handling this right, too. But then you may only use strong variables for this parameter.
I think it should be better, if you use a pointer instead:
int SPGetNumericAttribute(NSMutableString* line, NSString** attr) { ... }

How to get a member function pointer in MSVC?

I'm not going to get into too much of the details on the Excel side of things, I essentially took code from this example:
C++ app automates Excel (CppAutomateExcel)
solution1.cpp
So I've tried this code in MSVC and it compiles:
class foo { public: virtual void bar(){} };
int main()
{
void (foo::*p)() = &foo::bar;
}
But similar code to capture the address of the move function in Excel does not work:
int main()
{
Excel::_ApplicationPtr spXlApp;
HRESULT hr = spXlApp.CreateInstance(__uuidof(Excel::Application));
Excel::WorkbooksPtr spXlBooks = spXlApp->Workbooks;
Excel::_WorkbookPtr spXlBook = spXlBooks->Add();
Excel::_WorksheetPtr spXlSheet = spXlBook->ActiveSheet;
HRESULT(Excel::_Worksheet::*pMove)(...) = &spXlSheet->Excel::_Worksheet::Move;
<... irrelevant code ...>
return 0;
}
This has the following compiler error:
error C2276: '&': illegal operation on bound member function expression
If I remove the &, it says I should add it back:
error C3867: 'Excel::_Worksheet::Move': non-standard syntax; use '&' to create a pointer to member
Any help on what to do here would be greatly appreciated.
You say in your question "but similar code..." and then you show code in which you do not do the same thing. Try using the same syntax for setting pMove as you used for setting p in your smaller example. Try something like &Excel::_Worksheet::Move; (without the "spXlSheet->").
If you can specify the specific instance of the object for which to call the function pointer at the time that you set the function pointer as you have there, I'm not aware of such a capability. After dropping spXlSheet-> from where you set the variable, use it instead where you want to call the function pointer.
You need to declare the method pointer like this instead:
// or whatever parameter type Move() actually uses...
void (Excel::_Worksheet::*pMove)(tagVARIANT, tagVARIANT) = &Excel::_Worksheet::Move;
Then, to actually call pMove(), you would have to do something like this:
Excel::_WorksheetPtr spXlSheet = ...;
(spXlSheet.Get()->*pMove)(...);

*Value is not being generated into the LLVM code

I am attempting to write some compiler and use LLVM to generate intermediate code. Unfortunately, LLVM documentation is not very great and even somewhat confusing.
At the moment I have lexer,grammar and AST implemented. I was also following some examples found on Internet. My current AST works as follows: it has the abstract base class Tree*, from which other trees inherit (so, like one for variable definition, one for statement list, one for binary expression etc.).
I am trying to implement the variable definition, so for the input
class Test{
int main()
{
int x;
}
}
I want LLVM output to be:
; ModuleID = "Test"
define i32 #main() {
entry:
%x = alloca i32
return i32 0
}
However, right now I can get %x = alloca i32 part to the part where main function is created, but the actual output is missing the %x = alloca i32. So, the output I'm getting is as follows:
; ModuleID = "Test"
define i32 #main() {
entry:
return i32 0
}
my Codegen() for variable declaration is shown bellow (symbol table for now is just a list, I am trying to keep things as simple as possible at the moment):
llvm::Value *decafStmtList::Codegen() {
string name = SyandTy.back(); // Just a name of a variable
string type = SyandTy.front(); // and its type in string format
Type* typeVal = getLLVMType(decafType(str2DecafType(type))); // get LLVM::*Type representation
llvm::AllocaInst *Alloca = Builder.CreateAlloca(typeVal, 0, name.c_str());
Value *V = Alloca;
return Alloca;//Builder.CreateLoad(V, name.c_str());
}
The part where I am generating my #main is as follows:
Note: I have commented out the print_int function (this is the function I will use later to print things, but for now I don't need it). If I'll uncomment the print_int function, TheFunction will not pass verifier(TheFunction) -> complains about module being broken and parameters not matching the signature.
Function *gen_main_def(llvm::Value *RetVal, Function *print_int) {
if (RetVal == 0) {
throw runtime_error("something went horribly wrong\n");
}
// create the top-level definition for main
FunctionType *FT = FunctionType::get(IntegerType::get(getGlobalContext(), 32), false);
Function *TheFunction = Function::Create(FT, Function::ExternalLinkage, "main", TheModule);
if (TheFunction == 0) {
throw runtime_error("empty function block");
}
// Create a new basic block which contains a sequence of LLVM instructions
BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
// All subsequent calls to IRBuilder will place instructions in this location
Builder.SetInsertPoint(BB);
/*
Function *CalleeF = TheModule->getFunction(print_int->getName());
if (CalleeF == 0) {
throw runtime_error("could not find the function print_int\n");
}*/
// print the value of the expression and we are done
// Value *CallF = Builder.CreateCall(CalleeF, RetVal, "calltmp");
// Finish off the function.
// return 0 from main, which is EXIT_SUCCESS
Builder.CreateRet(ConstantInt::get(getGlobalContext(), APInt(32, 0)));
return TheFunction;
}
If someone knows why my Alloca object is not being generated, please help me out - any hints will be greatly appreciated.
Thank you
EDIT:
Codegen is called from the grammar:
start: program
program: extern_list decafclass
{
ProgramAST *prog = new ProgramAST((decafStmtList *)$1, (ClassAST *)$2);
if (printAST) {
cout << getString(prog) << endl;
}
Value *RetVal = prog->Codegen();
delete $1; // get rid of abstract syntax tree
delete $2; // get rid of abstract syntax tree
// we create an implicit print_int function call to print
// out the value of the expression.
Function *print_int = gen_print_int_def();
Function *TheFunction = gen_main_def(RetVal, print_int);
verifyFunction(*TheFunction);
}
EDIT: I figured it out, basically the createAlloca has to be called after the basicblock when generating main;
There are two weird things here:
All you do is call Builder.CreateRet... I don't see how there could be any code in main unless you call something that creates the corresponding instructions. In particular, you never seem to call the CodeGen part.
You pass a size of zero to CreateAlloc. I think the size should be one for a single variable.
Also, make sure that you don't call any LLVM optimization passes after generating your code. Those passes would optimize the value away (it's never used, thus dead code).

C++11 Lambda Functions inside member methods inherit scope

I've written a function foreach that accepts a lambda function ala:
void foreach(void (*p)(pNode))
{ /* ... */ }
Which works as intended if I pass a lambda function from the main loop:
int a = 5;
env.N().foreach
(
[&](pNode n)->void
{
n->tps(a);
}
);
However, if I try to call the same function from within a member method, the lambda function "inherits" the scope of the member function and generates a compiler error. For example, if I try to include it inside the member method of class Object named method(), I get the following error:
error: no matching function for call to ‘IDSet<Node>::foreach(Object::method()::<lambda(pNode)>)’
note: candidate is: void IDSet<T>::foreach(void (*)(IDSet<T>::pT)) [with T = Node, IDSet<T>::pT = pNode]
I realize this is the compiler being safe, since I could include instance-specific variables inside the lambda function, in which case the lambda would need to be scoped, however I'm wondering if it's possible to make this lambda "static".
I've tried a reinterpret_cast, however that gives me this error:
error: invalid cast from type ‘Object::method()::<lambda(pNode)>’ to type ‘void (*)(pNode)’
Specifying static before [&](pNode ... doesn't seem like valid syntax either.
Desperately, I also tried changing [&] to [=], [], [a], none of which worked.
Does anyone know if there is a way to do accomplish my goal of creating a "static" lambda function, or at any sort of lambda function that will be accepted for that matter?
Thanks!
Answer:
With help from Cat Plus Plus, I was able to turn my incorrect code:
void foreach(void (*p)(pT))
{
for(pTiter i = _map.begin(); i != _map.end(); i++)
{
(*p)(i->second);
}
}
into fully functional code:
void foreach(std::function<void(pT)>(p))
{
for(pTiter i = _map.begin(); i != _map.end(); i++)
{
p(i->second);
}
}
that does what I was looking for perfectly.
Well, you can not use pointers.
void foreach(std::function<void(pNode)>);