[LLVMdev] Kaleidoscope toy4 failure seg fault on llvm::ExecutionEngine::getTargetData (this=0x0)
Todd Rovito
rovitotv at gmail.com
Wed Feb 17 10:50:41 PST 2010
On Wed, Feb 17, 2010 at 6:29 AM, Conrado Miranda
<miranda.conrado at gmail.com> wrote:
> First, you have to call llvm-g++ to use the llvm-gcc front end, but it
> doesn't matter here.
I got the compile command from the Kaleidoscope documentation.
> I'd like to suggest that you use pastebin to put your code and the send us
> the link, so that we can download it. The problem is that TheExecutionEngine
> is set to NULL (maybe because of a previous error), but it will be really
> better if you use pastebin.
Here is the pastbin:
http://pastebin.com/m167c96c2
Thanks for the help after some further investigation I realized that
there is a difference between the documentation for example 4 on the
web here:
http://llvm.org/releases/2.6/docs/tutorial/LangImpl4.html
And the same example that comes with the llvm distribution that is
installed during the build process here:
file:///Users/rovitotv/llvm/docs/llvm/html/tutorial/LangImpl4.html
(Of course you have to change your path for your installation).
Thanks for the help.
> On Wed, Feb 17, 2010 at 6:01 AM, Todd Rovito <rovitotv at gmail.com> wrote:
>>
>> I am new to llvm so I might be missing a critical step. My system is
>> Fedora 12 but this also happens in Mac OS X 10.6.2. Here are the
>> steps I used to compile llvm:
>> export TARGETS=x86,x86_64,cpp
>> export INSTALLDIR=/home/rovitotv/llvm
>> ../llvm-2.6/configure --prefix=$INSTALLDIR --enable-bindings=none
>> --enable-targets=$TARGETS --enable-optimized
>> --with-llvmgccdir=$INSTALLDIR --with-llvm-externals=/home/rovitotv/
>> make ENABLE_OPTIMIZED=1
>> make install
>>
>> To compile the llvm-gcc4.2-2.6 front end:
>> ../llvm-gcc4.2-2.6/configure --target=i686-pc-linux-gnu
>> --with-tune=generic --with-arch=pentium4 --prefix=/home/rovitotv/llvm/
>> --enable-llvm=/home/rovitotv/llvm/ --enable-languages=c,c++
>> make
>> make install
>>
>> Then I make sure that /home/rovitotv/llvm/bin is in my path. At this
>> point I copy/paste the example in the tutorial chapter 4, please see
>> code below. I have tried a few different commands to compile, here
>> are the variations:
>> g++ -g toy4_new_copy.cpp `llvm-config --cppflags --ldflags --libs core
>> jit native` -O3 -o toy4
>>
>> g++ -g toy4.cpp `llvm-config --cppflags --ldflags --libs core jit
>> interpreter native` -O2 -o toy4
>>
>> The compile completes with no errors or warnings. When I execute the
>> program then enter the expression 4+5; I get a seg fault :-( Here is
>> sample gdb output from a recent run:
>>
>> (gdb) run
>> Starting program: /home/rovitotv/prog/llvm-tutorial/toy4
>> [Thread debugging using libthread_db enabled]
>> ready> 4+5;
>>
>> Program received signal SIGSEGV, Segmentation fault.
>> 0x080524f0 in llvm::ExecutionEngine::getTargetData (this=0x0)
>> at
>> /home/rovitotv/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h:167
>> 167 const TargetData *getTargetData() const { return TD; }
>> Missing separate debuginfos, use: debuginfo-install glibc-2.11-2.i686
>> libgcc-4.4.2-7.fc12.i686 libstdc++-4.4.2-7.fc12.i686
>> (gdb) bt
>> #0 0x080524f0 in llvm::ExecutionEngine::getTargetData (this=0x0)
>> at
>> /home/rovitotv/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h:167
>> #1 0x0805201a in main () at toy4_new_copy.cpp:577
>> (gdb)
>>
>>
>> Any help you can provide would be much appreciated. Thanks!
>>
>>
>>
>>
>>
>> =======================================================================================
>> #include "llvm/DerivedTypes.h"
>> #include "llvm/ExecutionEngine/ExecutionEngine.h"
>> #include "llvm/LLVMContext.h"
>> #include "llvm/Module.h"
>> #include "llvm/ModuleProvider.h"
>> #include "llvm/PassManager.h"
>> #include "llvm/Analysis/Verifier.h"
>> #include "llvm/Target/TargetData.h"
>> #include "llvm/Transforms/Scalar.h"
>> #include "llvm/Support/IRBuilder.h"
>> #include "llvm/Target/TargetSelect.h" // TVR added this line after
>> mailing list post
>> #include <cstdio>
>> #include <string>
>> #include <map>
>> #include <vector>
>> using namespace llvm;
>>
>>
>> //===----------------------------------------------------------------------===//
>> // Lexer
>>
>> //===----------------------------------------------------------------------===//
>>
>> // The lexer returns tokens [0-255] if it is an unknown character,
>> otherwise one
>> // of these for known things.
>> enum Token {
>> tok_eof = -1,
>>
>> // commands
>> tok_def = -2, tok_extern = -3,
>>
>> // primary
>> tok_identifier = -4, tok_number = -5,
>> };
>>
>> static std::string IdentifierStr; // Filled in if tok_identifier
>> static double NumVal; // Filled in if tok_number
>>
>> /// gettok - Return the next token from standard input.
>> static int gettok() {
>> static int LastChar = ' ';
>>
>> // Skip any whitespace.
>> while (isspace(LastChar))
>> LastChar = getchar();
>>
>> if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
>> IdentifierStr = LastChar;
>> while (isalnum((LastChar = getchar())))
>> IdentifierStr += LastChar;
>>
>> if (IdentifierStr == "def") return tok_def;
>> if (IdentifierStr == "extern") return tok_extern;
>> return tok_identifier;
>> }
>>
>> if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+
>> std::string NumStr;
>> do {
>> NumStr += LastChar;
>> LastChar = getchar();
>> } while (isdigit(LastChar) || LastChar == '.');
>>
>> NumVal = strtod(NumStr.c_str(), 0);
>> return tok_number;
>> }
>>
>> if (LastChar == '#') {
>> // Comment until end of line.
>> do LastChar = getchar();
>> while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
>>
>> if (LastChar != EOF)
>> return gettok();
>> }
>>
>> // Check for end of file. Don't eat the EOF.
>> if (LastChar == EOF)
>> return tok_eof;
>>
>> // Otherwise, just return the character as its ascii value.
>> int ThisChar = LastChar;
>> LastChar = getchar();
>> return ThisChar;
>> }
>>
>>
>> //===----------------------------------------------------------------------===//
>> // Abstract Syntax Tree (aka Parse Tree)
>>
>> //===----------------------------------------------------------------------===//
>>
>> /// ExprAST - Base class for all expression nodes.
>> class ExprAST {
>> public:
>> virtual ~ExprAST() {}
>> virtual Value *Codegen() = 0;
>> };
>>
>> /// NumberExprAST - Expression class for numeric literals like "1.0".
>> class NumberExprAST : public ExprAST {
>> double Val;
>> public:
>> NumberExprAST(double val) : Val(val) {}
>> virtual Value *Codegen();
>> };
>>
>> /// VariableExprAST - Expression class for referencing a variable, like
>> "a".
>> class VariableExprAST : public ExprAST {
>> std::string Name;
>> public:
>> VariableExprAST(const std::string &name) : Name(name) {}
>> virtual Value *Codegen();
>> };
>>
>> /// BinaryExprAST - Expression class for a binary operator.
>> class BinaryExprAST : public ExprAST {
>> char Op;
>> ExprAST *LHS, *RHS;
>> public:
>> BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs)
>> : Op(op), LHS(lhs), RHS(rhs) {}
>> virtual Value *Codegen();
>> };
>>
>> /// CallExprAST - Expression class for function calls.
>> class CallExprAST : public ExprAST {
>> std::string Callee;
>> std::vector<ExprAST*> Args;
>> public:
>> CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
>> : Callee(callee), Args(args) {}
>> virtual Value *Codegen();
>> };
>>
>> /// PrototypeAST - This class represents the "prototype" for a function,
>> /// which captures its argument names as well as if it is an operator.
>> class PrototypeAST {
>> std::string Name;
>> std::vector<std::string> Args;
>> public:
>> PrototypeAST(const std::string &name, const std::vector<std::string>
>> &args)
>> : Name(name), Args(args) {}
>>
>> Function *Codegen();
>> };
>>
>> /// FunctionAST - This class represents a function definition itself.
>> class FunctionAST {
>> PrototypeAST *Proto;
>> ExprAST *Body;
>> public:
>> FunctionAST(PrototypeAST *proto, ExprAST *body)
>> : Proto(proto), Body(body) {}
>>
>> Function *Codegen();
>> };
>>
>>
>> //===----------------------------------------------------------------------===//
>> // Parser
>>
>> //===----------------------------------------------------------------------===//
>>
>> /// CurTok/getNextToken - Provide a simple token buffer. CurTok is the
>> current
>> /// token the parser it looking at. getNextToken reads another token from
>> the
>> /// lexer and updates CurTok with its results.
>> static int CurTok;
>> static int getNextToken() {
>> return CurTok = gettok();
>> }
>>
>> /// BinopPrecedence - This holds the precedence for each binary operator
>> that is
>> /// defined.
>> static std::map<char, int> BinopPrecedence;
>>
>> /// GetTokPrecedence - Get the precedence of the pending binary operator
>> token.
>> static int GetTokPrecedence() {
>> if (!isascii(CurTok))
>> return -1;
>>
>> // Make sure it's a declared binop.
>> int TokPrec = BinopPrecedence[CurTok];
>> if (TokPrec <= 0) return -1;
>> return TokPrec;
>> }
>>
>> /// Error* - These are little helper functions for error handling.
>> ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n",
>> Str);return 0;}
>> PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
>> FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
>>
>> static ExprAST *ParseExpression();
>>
>> /// identifierexpr
>> /// ::= identifier
>> /// ::= identifier '(' expression* ')'
>> static ExprAST *ParseIdentifierExpr() {
>> std::string IdName = IdentifierStr;
>>
>> getNextToken(); // eat identifier.
>>
>> if (CurTok != '(') // Simple variable ref.
>> return new VariableExprAST(IdName);
>>
>> // Call.
>> getNextToken(); // eat (
>> std::vector<ExprAST*> Args;
>> if (CurTok != ')') {
>> while (1) {
>> ExprAST *Arg = ParseExpression();
>> if (!Arg) return 0;
>> Args.push_back(Arg);
>>
>> if (CurTok == ')') break;
>>
>> if (CurTok != ',')
>> return Error("Expected ')' or ',' in argument list");
>> getNextToken();
>> }
>> }
>>
>> // Eat the ')'.
>> getNextToken();
>>
>> return new CallExprAST(IdName, Args);
>> }
>>
>> /// numberexpr ::= number
>> static ExprAST *ParseNumberExpr() {
>> ExprAST *Result = new NumberExprAST(NumVal);
>> getNextToken(); // consume the number
>> return Result;
>> }
>>
>> /// parenexpr ::= '(' expression ')'
>> static ExprAST *ParseParenExpr() {
>> getNextToken(); // eat (.
>> ExprAST *V = ParseExpression();
>> if (!V) return 0;
>>
>> if (CurTok != ')')
>> return Error("expected ')'");
>> getNextToken(); // eat ).
>> return V;
>> }
>>
>> /// primary
>> /// ::= identifierexpr
>> /// ::= numberexpr
>> /// ::= parenexpr
>> static ExprAST *ParsePrimary() {
>> switch (CurTok) {
>> default: return Error("unknown token when expecting an expression");
>> case tok_identifier: return ParseIdentifierExpr();
>> case tok_number: return ParseNumberExpr();
>> case '(': return ParseParenExpr();
>> }
>> }
>>
>> /// binoprhs
>> /// ::= ('+' primary)*
>> static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
>> // If this is a binop, find its precedence.
>> while (1) {
>> int TokPrec = GetTokPrecedence();
>>
>> // If this is a binop that binds at least as tightly as the current
>> binop,
>> // consume it, otherwise we are done.
>> if (TokPrec < ExprPrec)
>> return LHS;
>>
>> // Okay, we know this is a binop.
>> int BinOp = CurTok;
>> getNextToken(); // eat binop
>>
>> // Parse the primary expression after the binary operator.
>> ExprAST *RHS = ParsePrimary();
>> if (!RHS) return 0;
>>
>> // If BinOp binds less tightly with RHS than the operator after RHS,
>> let
>> // the pending operator take RHS as its LHS.
>> int NextPrec = GetTokPrecedence();
>> if (TokPrec < NextPrec) {
>> RHS = ParseBinOpRHS(TokPrec+1, RHS);
>> if (RHS == 0) return 0;
>> }
>>
>> // Merge LHS/RHS.
>> LHS = new BinaryExprAST(BinOp, LHS, RHS);
>> }
>> }
>>
>> /// expression
>> /// ::= primary binoprhs
>> ///
>> static ExprAST *ParseExpression() {
>> ExprAST *LHS = ParsePrimary();
>> if (!LHS) return 0;
>>
>> return ParseBinOpRHS(0, LHS);
>> }
>>
>> /// prototype
>> /// ::= id '(' id* ')'
>> static PrototypeAST *ParsePrototype() {
>> if (CurTok != tok_identifier)
>> return ErrorP("Expected function name in prototype");
>>
>> std::string FnName = IdentifierStr;
>> getNextToken();
>>
>> if (CurTok != '(')
>> return ErrorP("Expected '(' in prototype");
>>
>> std::vector<std::string> ArgNames;
>> while (getNextToken() == tok_identifier)
>> ArgNames.push_back(IdentifierStr);
>> if (CurTok != ')')
>> return ErrorP("Expected ')' in prototype");
>>
>> // success.
>> getNextToken(); // eat ')'.
>>
>> return new PrototypeAST(FnName, ArgNames);
>> }
>>
>> /// definition ::= 'def' prototype expression
>> static FunctionAST *ParseDefinition() {
>> getNextToken(); // eat def.
>> PrototypeAST *Proto = ParsePrototype();
>> if (Proto == 0) return 0;
>>
>> if (ExprAST *E = ParseExpression())
>> return new FunctionAST(Proto, E);
>> return 0;
>> }
>>
>> /// toplevelexpr ::= expression
>> static FunctionAST *ParseTopLevelExpr() {
>> if (ExprAST *E = ParseExpression()) {
>> // Make an anonymous proto.
>> PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
>> return new FunctionAST(Proto, E);
>> }
>> return 0;
>> }
>>
>> /// external ::= 'extern' prototype
>> static PrototypeAST *ParseExtern() {
>> getNextToken(); // eat extern.
>> return ParsePrototype();
>> }
>>
>>
>> //===----------------------------------------------------------------------===//
>> // Code Generation
>>
>> //===----------------------------------------------------------------------===//
>>
>> static Module *TheModule;
>> static IRBuilder<> Builder(getGlobalContext());
>> static std::map<std::string, Value*> NamedValues;
>> static FunctionPassManager *TheFPM;
>>
>> Value *ErrorV(const char *Str) { Error(Str); return 0; }
>>
>> Value *NumberExprAST::Codegen() {
>> return ConstantFP::get(getGlobalContext(), APFloat(Val));
>> }
>>
>> Value *VariableExprAST::Codegen() {
>> // Look this variable up in the function.
>> Value *V = NamedValues[Name];
>> return V ? V : ErrorV("Unknown variable name");
>> }
>>
>> Value *BinaryExprAST::Codegen() {
>> Value *L = LHS->Codegen();
>> Value *R = RHS->Codegen();
>> if (L == 0 || R == 0) return 0;
>>
>> switch (Op) {
>> case '+': return Builder.CreateAdd(L, R, "addtmp");
>> case '-': return Builder.CreateSub(L, R, "subtmp");
>> case '*': return Builder.CreateMul(L, R, "multmp");
>> case '<':
>> L = Builder.CreateFCmpULT(L, R, "cmptmp");
>> // Convert bool 0/1 to double 0.0 or 1.0
>> return Builder.CreateUIToFP(L,
>> Type::getDoubleTy(getGlobalContext()), "booltmp");
>> default: return ErrorV("invalid binary operator");
>> }
>> }
>>
>> Value *CallExprAST::Codegen() {
>> // Look up the name in the global module table.
>> Function *CalleeF = TheModule->getFunction(Callee);
>> if (CalleeF == 0)
>> return ErrorV("Unknown function referenced");
>>
>> // If argument mismatch error.
>> if (CalleeF->arg_size() != Args.size())
>> return ErrorV("Incorrect # arguments passed");
>>
>> std::vector<Value*> ArgsV;
>> for (unsigned i = 0, e = Args.size(); i != e; ++i) {
>> ArgsV.push_back(Args[i]->Codegen());
>> if (ArgsV.back() == 0) return 0;
>> }
>>
>> return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(),
>> "calltmp");
>> }
>>
>> Function *PrototypeAST::Codegen() {
>> // Make the function type: double(double,double) etc.
>> std::vector<const Type*> Doubles(Args.size(),
>> Type::getDoubleTy(getGlobalContext()));
>> FunctionType *FT =
>> FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles,
>> false);
>>
>> Function *F = Function::Create(FT, Function::ExternalLinkage, Name,
>> TheModule);
>>
>> // If F conflicted, there was already something named 'Name'. If it has
>> a
>> // body, don't allow redefinition or reextern.
>> if (F->getName() != Name) {
>> // Delete the one we just made and get the existing one.
>> F->eraseFromParent();
>> F = TheModule->getFunction(Name);
>>
>> // If F already has a body, reject this.
>> if (!F->empty()) {
>> ErrorF("redefinition of function");
>> return 0;
>> }
>>
>> // If F took a different number of args, reject.
>> if (F->arg_size() != Args.size()) {
>> ErrorF("redefinition of function with different # args");
>> return 0;
>> }
>> }
>>
>> // Set names for all arguments.
>> unsigned Idx = 0;
>> for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
>> ++AI, ++Idx) {
>> AI->setName(Args[Idx]);
>>
>> // Add arguments to variable symbol table.
>> NamedValues[Args[Idx]] = AI;
>> }
>>
>> return F;
>> }
>>
>> Function *FunctionAST::Codegen() {
>> NamedValues.clear();
>>
>> Function *TheFunction = Proto->Codegen();
>> if (TheFunction == 0)
>> return 0;
>>
>> // Create a new basic block to start insertion into.
>> BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry",
>> TheFunction);
>> Builder.SetInsertPoint(BB);
>>
>> if (Value *RetVal = Body->Codegen()) {
>> // Finish off the function.
>> Builder.CreateRet(RetVal);
>>
>> // Validate the generated code, checking for consistency.
>> verifyFunction(*TheFunction);
>>
>> // Optimize the function.
>> TheFPM->run(*TheFunction);
>>
>> return TheFunction;
>> }
>>
>> // Error reading body, remove function.
>> TheFunction->eraseFromParent();
>> return 0;
>> }
>>
>>
>> //===----------------------------------------------------------------------===//
>> // Top-Level parsing and JIT Driver
>>
>> //===----------------------------------------------------------------------===//
>>
>> static ExecutionEngine *TheExecutionEngine;
>>
>> static void HandleDefinition() {
>> if (FunctionAST *F = ParseDefinition()) {
>> if (Function *LF = F->Codegen()) {
>> fprintf(stderr, "Read function definition:");
>> LF->dump();
>> }
>> } else {
>> // Skip token for error recovery.
>> getNextToken();
>> }
>> }
>>
>> static void HandleExtern() {
>> if (PrototypeAST *P = ParseExtern()) {
>> if (Function *F = P->Codegen()) {
>> fprintf(stderr, "Read extern: ");
>> F->dump();
>> }
>> } else {
>> // Skip token for error recovery.
>> getNextToken();
>> }
>> }
>>
>> static void HandleTopLevelExpression() {
>> // Evaluate a top level expression into an anonymous function.
>> if (FunctionAST *F = ParseTopLevelExpr()) {
>> if (Function *LF = F->Codegen()) {
>> // JIT the function, returning a function pointer.
>> void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
>>
>> // Cast it to the right type (takes no arguments, returns a double)
>> so we
>> // can call it as a native function.
>> double (*FP)() = (double (*)())FPtr;
>> fprintf(stderr, "Evaluated to %f\n", FP());
>> }
>> } else {
>> // Skip token for error recovery.
>> getNextToken();
>> }
>> }
>>
>> /// top ::= definition | external | expression | ';'
>> static void MainLoop() {
>> while (1) {
>> fprintf(stderr, "ready> ");
>> switch (CurTok) {
>> case tok_eof: return;
>> case ';': getNextToken(); break; // ignore top level
>> semicolons.
>> case tok_def: HandleDefinition(); break;
>> case tok_extern: HandleExtern(); break;
>> default: HandleTopLevelExpression(); break;
>> }
>> }
>> }
>>
>>
>>
>>
>> //===----------------------------------------------------------------------===//
>> // "Library" functions that can be "extern'd" from user code.
>>
>> //===----------------------------------------------------------------------===//
>>
>> /// putchard - putchar that takes a double and returns 0.
>> extern "C"
>> double putchard(double X) {
>> putchar((char)X);
>> return 0;
>> }
>>
>>
>> //===----------------------------------------------------------------------===//
>> // Main driver code.
>>
>> //===----------------------------------------------------------------------===//
>>
>> int main() {
>> InitializeNativeTarget(); // TVR added this code after reading llvm
>> post
>> // Install standard binary operators.
>> // 1 is lowest precedence.
>> BinopPrecedence['<'] = 10;
>> BinopPrecedence['+'] = 20;
>> BinopPrecedence['-'] = 20;
>> BinopPrecedence['*'] = 40; // highest.
>>
>> // Prime the first token.
>> fprintf(stderr, "ready> ");
>> getNextToken();
>>
>> // Make the module, which holds all the code.
>> TheModule = new Module("my cool jit", getGlobalContext());
>>
>> // Create the JIT.
>>
>> TheExecutionEngine = EngineBuilder(TheModule).create();
>>
>> {
>> ExistingModuleProvider OurModuleProvider(TheModule);
>> FunctionPassManager OurFPM(&OurModuleProvider);
>>
>> // Set up the optimizer pipeline. Start with registering info about
>> how the
>> // target lays out data structures.
>> OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
>> // Do simple "peephole" optimizations and bit-twiddling optzns.
>> OurFPM.add(createInstructionCombiningPass());
>> // Reassociate expressions.
>> OurFPM.add(createReassociatePass());
>> // Eliminate Common SubExpressions.
>> OurFPM.add(createGVNPass());
>> // Simplify the control flow graph (deleting unreachable blocks, etc).
>> OurFPM.add(createCFGSimplificationPass());
>>
>> // Set the global so the code gen can use this.
>> TheFPM = &OurFPM;
>>
>> // Run the main "interpreter loop" now.
>> MainLoop();
>>
>> TheFPM = 0;
>>
>> // Print out all of the generated code.
>> TheModule->dump();
>> } // Free module provider (and thus the module) and pass manager.
>>
>> return 0;
>> }
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>
More information about the llvm-dev
mailing list