I have the following problem with llvm and c++: Given an array, I want to shift every entry of that array by one to the right, i.e., I want to implement the following c code:
int arr[5];
for(int i=1;i<5;++i){
arr[i] = arr[i-1];
}
I tried the following c++ code:
IntegerType *Int32Ty = IntegerType::getInt32Ty(M.getContext(););
GlobalVariable *arrVariable;
arrVariable = new GlobalVariable(M, PointerType::get(Int32Ty, 0), false,
GlobalValue::ExternalLinkage, 0, "__arr");
for(int i=0;i<ARRAY_LENGTH;++i){
Constant* fromIdx = Constant::getIntegerValue(Int32Ty, llvm::APInt(32, i-1));
Value *fromLocPtrIdx = IRB.CreateGEP(arrVariable, fromIdx);
Constant* toIdx = Constant::getIntegerValue(Int32Ty, llvm::APInt(32, i));
Value *toLocPtrIdx = IRB.CreateGEP(arrVariable, toIdx);
StoreInst *MoveStoreInst = IRB.CreateStore(fromLocPtrIdx,toLocPtrIdx);
}
where __arr is defined as:
__thread u32 __arr[ARRAY_LENGTH];
However, when compiling, this yields the following error message:
/usr/bin/ld: __arr: TLS definition in ../inject.o section .tbss mismatches non-TLS reference in /tmp/test-inject.o
What is the right way to move values in an arrays using the llvm c++ api?
You need to specify that your global variable is thread_local.
The way to do that is to add the thread-local mode to your global creation:
arrVariable = new GlobalVariable(M, PointerType::get(Int32Ty, 0), false,
GlobalValue::ExternalLinkage, 0, "__arr", nullptr, InitialExecTLSModel);
The exact mode depends on what your target is, but I think InitialExecTLSModel is a generally "good starting point".
Related
I build 2 functions using the LLVM C API. Each returns a different pointer to global string ("first" and "second"). However when I run each with LLVMRunFunction using the LLVM interpreter, they both return a pointer to the string "first".
The problem does not occur when I return integers or function pointers.
I tried looking at the produced llvm code and it is correct, each function returns a different pointer.
Here's a sample that will reproduce the problem (on LLVM 7.0.1)
#include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h>
#include <stdio.h>
int main() {
auto module = LLVMModuleCreateWithName("test");
LLVMExecutionEngineRef interpreter;
LLVMCreateInterpreterForModule(&interpreter, module, nullptr);
auto funType = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0), nullptr, 0, 0);
auto fun = LLVMAddFunction(module, "fun1", funType);
auto builder = LLVMCreateBuilder();
auto entry = LLVMAppendBasicBlock(fun, "entry");
LLVMPositionBuilderAtEnd(builder, entry);
LLVMBuildRet(builder, LLVMBuildGlobalStringPtr(builder, "first", ""));
auto generic = LLVMRunFunction(interpreter, fun, 0, nullptr);
printf("%s\n", (const char*)LLVMGenericValueToPointer(generic));
fun = LLVMAddFunction(module, "fun2", funType);
entry = LLVMAppendBasicBlock(fun, "entry");
LLVMPositionBuilderAtEnd(builder, entry);
LLVMBuildRet(builder, LLVMBuildGlobalStringPtr(builder, "second", ""));
generic = LLVMRunFunction(interpreter, fun, 0, nullptr);
printf("%s\n", (const char*)LLVMGenericValueToPointer(generic));
return 0;
}
I would expect the output
first
second
Instead it outputs
first
first
After having a closer look at the generated LLVM, I noticed that the global strings built with LLVMBuildGlobalStringPtr had the unnamed_addr modifier. When building the global string manually instead of using LLVMBuildGlobalStringPtr, the interpreter actually returns the correct string pointers and the output becomes as expected:
auto glbstr = LLVMAddGlobal(mBuilder.module_, llvmType, "glbstr");
LLVMSetInitializer(glbstr, LLVMConstString(toStringz(arg.value), cast(uint) arg.value.length, 0));
auto firstCharPtr = LLVMBuildGEP(builder, glbstr, [LLVMConstInt(LLVMInt8Type(), 0, 0), LLVMConstInt(LLVMInt8Type(), 0, 0)].ptr, 2, "");
In the following code, I am trying to insertnew global variables in .ll file using Module Pass:
Module::FunctionListType &FList= M.getFunctionList();
LLVMContext &Ctx= M.getContext();
int x=0;
std::string Cbb="BB";
GlobalVariable *bbcounter;
for (Module::FunctionListType::iterator fit=FList.begin();fit!=FList.end();fit++){
for (Function::iterator b = (*fit).begin(), be = (*fit).end(); b != be; ++b){
Cbb= "BB"+std::to_string(x);
const Twine &tw(Cbb);
b->setName (tw);
bbcounter=new GlobalVariable(M,Type::getInt64Ty(b->getContext()),false,GlobalValue::ExternalLinkage,0,Cbb);
assert(bbcounter&&"Error: unable to get basicblock counter");
x++;
}}
The following one is for inserting load/store if the new global variables:
for (Module::FunctionListType::iterator fit=FList.begin();fit!=FList.end();fit++)
{
Function::iterator b = (*fit).begin();
Function::iterator be = (*fit).end();
for ( ; b != be; ++b, git++){ //git is global variable
Instruction *InsertPos=b->getTerminator();
LoadInst* OldVal=new LoadInst( &(*git), Cbb);
OldVal->insertBefore (InsertPos);
Instruction * NewVal= BinaryOperator::Create(Instruction::Add, OldVal, ConstantInt::get(Type::getInt64Ty(b->getContext()), 1), Cbb);
NewVal->insertBefore (InsertPos);
StoreInst *SI=new StoreInst(NewVal, &*git);
SI->insertBefore (InsertPos);
}
This code after make and call opt command does not edit anything in .ll file. I there a problem in it? or should I write new file ?
Note: I tried to write a new file using removeFromParent() function, but it gives me errors. Also, cloning does not set right predecessors.
I'm trying to use the LLVM C++ bindings to write a pass which generates the following IR
%1 = call i64 #time(i64* null) #3
#time here is the C standard library time() function.
Here's the code I've written
void Pass::Insert(BasicBlock *bb, Type *timety, Module *m) {
Type *timetype[1];
timetype[0] = timety;
ArrayRef<Type *> timeTypeAref(timetype, 1);
Value *args[1];
args[0] = ConstantInt::get(timety, 0, false);
ArrayRef<Value *> argsRef(args, 1);
FunctionType *signature = FunctionType::get(timety, false);
Function *timeFunc =
Function::Create(signature, Function::ExternalLinkage, "time", m);
IRBuilder<> Builder(&*(bb->getFirstInsertionPt()));
AllocaInst *a1 = Builder.CreateAlloca(timety, nullptr, Twine("a1"));
CallInst *c1 = Builder.CreateCall(timeFunc, args, Twine("time"));
}
This compiles, but results in the following error when run
Incorrect number of arguments passed to called function!
%time = call i64 #time(i64 0)
As I understand this, I need to pass an int64 pointer which deferences to nullptr, but I'm unable to figure out how to do that.
LLVM provides a ConstantPointerNull class which does exactly what I want - it returns a null pointer of the required type.
All that needs to be changed is the line beginning with args[0] = ... to
args[0] = ConstantPointerNull::get(PointerType::get(timety, 0));.
I am trying to write a simple interpreter.
I am trying to generate LLVM IR for assignment operation. The code for the generation part looks like this
llvm::Value* codeGenSymTab(llvm::LLVMContext& context) {
printf("\n CodeGen SymTab \n");
Value *num = ConstantInt::get(Type::getInt64Ty(context), aTable.value, true);
Value *alloc = new AllocaInst(IntegerType::get(context, 32), aTable.variableName,entry);
StoreInst *ptr = new StoreInst(num,alloc,false,entry);
}
Here goes the SymTab definition:
struct SymTab {
char* variableName;
int value;
llvm::Value* (*codeGen)(llvm::LLVMContext& context);
};
When I try to execute the output file,I get the following error:
Assertion failed: (getOperand(0)->getType() == cast<PointerType>(getOperand(1)->getType())->getElementType() && "Ptr must be a pointer to Val type!"), function AssertOK, file Instructions.cpp, line 1084.
Abort trap: 6
Can you help me resolve it ?
Thanks
You try to store a value of type i64 into an address of type i32*, and these don't match.
You can fix this by using the same type - or preferably, the actual same object:
IntegerType *int_type = Type::getInt64Ty(context);
Value *num = ConstantInt::get(int_type, aTable.value, true);
Value *alloc = new AllocaInst(int_type, aTable.variableName, entry);
StoreInst *ptr = new StoreInst(num,alloc,false,entry);
How can I get the value of a primitive literal using libclang?
For example, if I have a CXCursor of cursor kind CXCursor_IntegerLiteral, how can I extract the literal value.
UPDATE:
I've run into so many problems using libclang. I highly recommend avoiding it entirely and instead use the C++ interface clang provides. The C++ interface is highly useable and very well documented: http://clang.llvm.org/doxygen/annotated.html
The only purpose I see of libclang now is to generate the ASTUnit object for you as with the following code (it's not exactly easy otherwise):
ASTUnit * astUnit;
{
index = clang_createIndex(0, 0);
tu = clang_parseTranslationUnit(
index, 0,
clangArgs, nClangArgs,
0, 0, CXTranslationUnit_None
);
astUnit = static_cast<ASTUnit *>(tu->TUData);
}
Now you might say that libclang is stable and the C++ interface isn't. That hardly matters, as the time you spend figuring out the AST with libclang and creating kludges with it wastes so much of your time anyway. I'd just as soon spend a few hours fixing up code that does not compile after a version upgrade (if even needed).
Instead of reparsing the original, you already have all the information you need inside the translation unit :
if (kind == CXCursor_IntegerLiteral)
{
CXSourceRange range = clang_getCursorExtent(cursor);
CXToken *tokens = 0;
unsigned int nTokens = 0;
clang_tokenize(tu, range, &tokens, &nTokens);
for (unsigned int i = 0; i < nTokens; i++)
{
CXString spelling = clang_getTokenSpelling(tu, tokens[i]);
printf("token = %s\n", clang_getCString(spelling));
clang_disposeString(spelling);
}
clang_disposeTokens(tu, tokens, nTokens);
}
You will see that the first token is the integer itself, the next one is not relevant (eg. it's ; for int i = 42;.
If you have access to a CXCursor, you can make use of the clang_Cursor_Evaluate function, for example:
CXChildVisitResult var_decl_visitor(
CXCursor cursor, CXCursor parent, CXClientData data) {
auto kind = clang_getCursorKind(cursor);
switch (kind) {
case CXCursor_IntegerLiteral: {
auto res = clang_Cursor_Evaluate(cursor);
auto value = clang_EvalResult_getAsInt(res);
clang_EvalResult_dispose(res);
std::cout << "IntegerLiteral " << value << std::endl;
break;
}
default:
break;
}
return CXChildVisit_Recurse;
}
Outputs:
IntegerLiteral 42
I found a way to do this by referring to the original files:
std::string getCursorText (CXCursor cur) {
CXSourceRange range = clang_getCursorExtent(cur);
CXSourceLocation begin = clang_getRangeStart(range);
CXSourceLocation end = clang_getRangeEnd(range);
CXFile cxFile;
unsigned int beginOff;
unsigned int endOff;
clang_getExpansionLocation(begin, &cxFile, 0, 0, &beginOff);
clang_getExpansionLocation(end, 0, 0, 0, &endOff);
ClangString filename = clang_getFileName(cxFile);
unsigned int textSize = endOff - beginOff;
FILE * file = fopen(filename.c_str(), "r");
if (file == 0) {
exit(ExitCode::CANT_OPEN_FILE);
}
fseek(file, beginOff, SEEK_SET);
char buff[4096];
char * pBuff = buff;
if (textSize + 1 > sizeof(buff)) {
pBuff = new char[textSize + 1];
}
pBuff[textSize] = '\0';
fread(pBuff, 1, textSize, file);
std::string res(pBuff);
if (pBuff != buff) {
delete [] pBuff;
}
fclose(file);
return res;
}
You can actually use a combination of libclang and the C++ interface.
The libclang CXCursor type contains a data field which contains references to the underlying AST nodes.
I was able to successfully access the IntegerLiteral value by casting data[1] to the IntegerLiteral type.
I'm implementing this in Nim so I will provide Nim code, but you can likely do the same in C++.
let literal = cast[clang.IntegerLiteral](cursor.data[1])
echo literal.getValue().getLimitedValue()
The IntegerLiteral type is wrapped like so:
type
APIntObj* {.importcpp: "llvm::APInt", header: "llvm/ADT/APInt.h".} = object
# https://github.com/llvm-mirror/llvm/blob/master/include/llvm/ADT/APInt.h
APInt* = ptr APIntObj
IntegerLiteralObj* {.importcpp: "clang::IntegerLiteral", header: "clang/AST/Expr.h".} = object
IntegerLiteral* = ptr IntegerLiteralObj
proc getValue*(i: IntegerLiteral): APIntObj {.importcpp: "#.getValue()".}
# This is implemented by the superclass: https://clang.llvm.org/doxygen/classclang_1_1APIntStorage.html
proc getLimitedValue*(a: APInt | APIntObj): culonglong {.importcpp: "#.getLimitedValue()".}
Hope this helps someone :)