[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