Andrea Gus před 8 roky
rodič
revize
eff9e1c005
13 změnil soubory, kde provedl 320 přidání a 80 odebrání
  1. 58 4
      source/Ast.cpp
  2. 93 33
      source/Ast.h
  3. 2 2
      source/CMakeLists.txt
  4. 1 1
      source/Chapters/CMakeLists.txt
  5. 39 0
      source/Debug.cpp
  6. 35 0
      source/Debug.h
  7. 1 4
      source/JIT.cpp
  8. 0 1
      source/JIT.h
  9. 14 3
      source/Lexer.cpp
  10. 20 1
      source/Lexer.h
  11. 31 7
      source/Main.cpp
  12. 25 21
      source/Parser.cpp
  13. 1 3
      source/Parser.h

+ 58 - 4
source/Ast.cpp

@@ -8,7 +8,7 @@
 
 using namespace jit;
 
-namespace ast{
+namespace ast {
 // attributes added from chapter 3 of the tutorial
 std::unique_ptr<Module> AstObjects::TheModule =
     std::make_unique<Module>("my cool jit", getGlobalContext());
@@ -21,6 +21,7 @@ Value *ErrorV(const char *Str) {
 }
 
 Value *NumberExprAST::codegen() {
+  KSDbgInfo.emitLocation(this);
   return ConstantFP::get(getGlobalContext(), APFloat(Val));
 }
 
@@ -30,6 +31,7 @@ Value *VariableExprAST::codegen() {
   if (!V)
     return ErrorV("Unknown variable name");
 
+  KSDbgInfo.emitLocation(this);
   // Load the value.
   return AstObjects::Builder.CreateLoad(V, Name.c_str());
 }
@@ -43,10 +45,13 @@ Value *UnaryExprAST::codegen() {
   if (!F)
     return ErrorV("Unknown unary operator");
 
+  KSDbgInfo.emitLocation(this);
   return AstObjects::Builder.CreateCall(F, OperandV, "unop");
 }
 
 Value *BinaryExprAST::codegen() {
+  KSDbgInfo.emitLocation(this);
+
   // Special case '=' because we don't want to emit the LHS as an expression.
   if (Op == '=') {
     // Assignment requires the LHS to be an identifier.
@@ -101,6 +106,8 @@ Value *BinaryExprAST::codegen() {
 }
 
 Value *CallExprAST::codegen() {
+  KSDbgInfo.emitLocation(this);
+
   // Look up the name in the global module table.
   Function *CalleeF = getFunction(Callee);
   if (!CalleeF)
@@ -120,6 +127,7 @@ Value *CallExprAST::codegen() {
 }
 
 Value *IfExprAST::codegen() {
+  KSDbgInfo.emitLocation(this);
   Value *CondV = Cond->codegen();
   if (!CondV)
     return nullptr;
@@ -197,6 +205,8 @@ Value *ForExprAST::codegen() {
   // Create an alloca for the variable in the entry block.
   AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
 
+  KSDbgInfo.emitLocation(this);
+
   // Emit the start code first, without 'variable' in scope.
   Value *StartVal = Start->codegen();
   if (!StartVal)
@@ -308,6 +318,8 @@ Value *VarExprAST::codegen() {
     AstObjects::NamedValues[VarName] = Alloca;
   }
 
+  KSDbgInfo.emitLocation(this);
+
   // Codegen the body, now that all vars are in scope.
   Value *BodyVal = Body->codegen();
   if (!BodyVal)
@@ -356,12 +368,44 @@ Function *FunctionAST::codegen() {
   BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
   AstObjects::Builder.SetInsertPoint(BB);
 
+  // Create a subprogram DIE for this function.
+  DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(),
+                                      KSDbgInfo.TheCU->getDirectory());
+  DIScope *FContext = Unit;
+  unsigned LineNo = P.getLine();
+  unsigned ScopeLine = LineNo;
+  DISubprogram *SP = DBuilder->createFunction(
+      FContext, P.getName(), StringRef(), Unit, LineNo,
+      CreateFunctionType(TheFunction->arg_size(), Unit),
+      false /* internal linkage */, true /* definition */, ScopeLine,
+      DINode::FlagPrototyped, false);
+  TheFunction->setSubprogram(SP);
+
+  // Push the current scope.
+  KSDbgInfo.LexicalBlocks.push_back(SP);
+
+  // Unset the location for the prologue emission (leading instructions with no
+  // location in a function are considered part of the prologue and the debugger
+  // will run past them when breaking on a function)
+  KSDbgInfo.emitLocation(nullptr);
+
   // Record the function arguments in the NamedValues map.
   AstObjects::NamedValues.clear();
+  unsigned ArgIdx = 0;
+
   for (auto &Arg : TheFunction->args()) {
     // Create an alloca for this variable.
     AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName());
 
+    // Create a debug descriptor for the variable.
+    DILocalVariable *D = DBuilder->createParameterVariable(
+        SP, Arg.getName(), ++ArgIdx, Unit, LineNo, KSDbgInfo.getDoubleTy(),
+        true);
+
+    DBuilder->insertDeclare(Alloca, D, DBuilder->createExpression(),
+                            DebugLoc::get(LineNo, 0, SP),
+                            Builder.GetInsertBlock());
+
     // Store the initial value into the alloca.
     AstObjects::Builder.CreateStore(&Arg, Alloca);
 
@@ -369,16 +413,18 @@ Function *FunctionAST::codegen() {
     AstObjects::NamedValues[Arg.getName()] = Alloca;
   }
 
+  KSDbgInfo.emitLocation(Body.get());
+
   if (Value *RetVal = Body->codegen()) {
     // Finish off the function.
     AstObjects::Builder.CreateRet(RetVal);
 
+    // Pop off the lexical block for the function.
+    KSDbgInfo.LexicalBlocks.pop_back();
+
     // Validate the generated code, checking for consistency.
     verifyFunction(*TheFunction);
 
-    // Run the optimizer on the function.
-    JITObjects::TheFPM->run(*TheFunction);
-
     return TheFunction;
   }
 
@@ -387,6 +433,11 @@ Function *FunctionAST::codegen() {
 
   if (P.isBinaryOp())
     parser::BinopPrecedence.erase(Proto->getOperatorName());
+
+  // Pop off the lexical block for the function since we added it
+  // unconditionally.
+  KSDbgInfo.LexicalBlocks.pop_back();
+
   return nullptr;
 }
 
@@ -399,6 +450,9 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
   return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), nullptr,
                            VarName.c_str());
 }
+
+// HACK: Libraries not present in the standard llvm installation, but the
+// is not actually used.
 /*
 /// CreateArgumentAllocas - Create an alloca for each argument and register the
 /// argument in the symbol table so that references to it will succeed.

+ 93 - 33
source/Ast.h

@@ -1,18 +1,22 @@
 #ifndef _AST_H
 #define _AST_H
 
-//LLVM includes
+// LLVM includes
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/DIBuilder.h"
+
+// Local includes
+#include "Lexer.h"
 
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
 // Abstract Syntax Tree (aka Parse Tree)
 //===----------------------------------------------------------------------===//
-namespace ast{
+namespace ast {
 // struct instantiated by the 'main' to access data structures if llvm IR.
 struct AstObjects {
 public:
@@ -21,12 +25,23 @@ public:
   static std::map<std::string, AllocaInst*> NamedValues;
 };
 
-/// ExprAST - Base class for all expression nodes.
+raw_ostream &indent(raw_ostream &O, int size) {
+  return O << std::string(size, ' ');
+}
 
+/// ExprAST - Base class for all expression nodes.
 class ExprAST {
+  lexer::SourceLocation Loc;
+
 public:
+  ExprAST(lexer::SourceLocation Loc = lexer::CurLoc) : Loc(Loc) {}
   virtual ~ExprAST() {}
-  virtual llvm::Value *codegen() = 0;
+  virtual Value *codegen() = 0;
+  int getLine() const { return Loc.Line; }
+  int getCol() const { return Loc.Col; }
+  virtual raw_ostream &dump(raw_ostream &out, int ind) {
+    return out << ':' << getLine() << ':' << getCol() << '\n';
+  }
 };
 
 /// NumberExprAST - Expression class for numeric literals like "1.0".
@@ -35,6 +50,9 @@ class NumberExprAST : public ExprAST {
 
 public:
   NumberExprAST(double Val) : Val(Val) {}
+  raw_ostream &dump(raw_ostream &out, int ind) override {
+    return ExprAST::dump(out << Val, ind);
+  }
   Value *codegen() override;
 };
 
@@ -43,12 +61,15 @@ class VariableExprAST : public ExprAST {
   std::string Name;
 
 public:
-  VariableExprAST(const std::string &Name) : Name(Name) {}
+  VariableExprAST(lexer::SourceLocation Loc, const std::string &Name)
+      : ExprAST(Loc), Name(Name) {}
   const std::string &getName() const { return Name; }
   Value *codegen() override;
+  raw_ostream &dump(raw_ostream &out, int ind) override {
+    return ExprAST::dump(out << Name, ind);
+  }
 };
 
-
 /// UnaryExprAST - Expression class for a unary operator.
 class UnaryExprAST : public ExprAST {
   char Opcode;
@@ -58,6 +79,11 @@ public:
   UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand)
       : Opcode(Opcode), Operand(std::move(Operand)) {}
   Value *codegen() override;
+  raw_ostream &dump(raw_ostream &out, int ind) override {
+    ExprAST::dump(out << "unary" << Opcode, ind);
+    Operand->dump(out, ind + 1);
+    return out;
+  }
 };
 
 /// BinaryExprAST - Expression class for a binary operator.
@@ -66,33 +92,53 @@ class BinaryExprAST : public ExprAST {
   std::unique_ptr<ExprAST> LHS, RHS;
 
 public:
-  BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS,
+  BinaryExprAST(lexer::SourceLocation Loc, char Op, std::unique_ptr<ExprAST> LHS,
                 std::unique_ptr<ExprAST> RHS)
-      : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
+      : ExprAST(Loc), Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
   Value *codegen() override;
+  raw_ostream &dump(raw_ostream &out, int ind) override {
+    ExprAST::dump(out << "binary" << Op, ind);
+    LHS->dump(indent(out, ind) << "LHS:", ind + 1);
+    RHS->dump(indent(out, ind) << "RHS:", ind + 1);
+    return out;
+  }
 };
 
-/// ExprAST - Base class for all expression nodes.
 /// CallExprAST - Expression class for function calls.
 class CallExprAST : public ExprAST {
   std::string Callee;
   std::vector<std::unique_ptr<ExprAST>> Args;
 
 public:
-  CallExprAST(const std::string &Callee,
-      std::vector<std::unique_ptr<ExprAST>> Args) : Callee(Callee), Args(std::move(Args)) {}
-    Value *codegen() override;
+  CallExprAST(lexer::SourceLocation Loc, const std::string &Callee,
+              std::vector<std::unique_ptr<ExprAST>> Args)
+      : ExprAST(Loc), Callee(Callee), Args(std::move(Args)) {}
+  Value *codegen() override;
+  raw_ostream &dump(raw_ostream &out, int ind) override {
+    ExprAST::dump(out << "call " << Callee, ind);
+    for (const auto &Arg : Args)
+      Arg->dump(indent(out, ind + 1), ind + 1);
+    return out;
+  }
 };
 
-  /// IfExprAST - Expression class for if/then/else.
+/// IfExprAST - Expression class for if/then/else.
 class IfExprAST : public ExprAST {
   std::unique_ptr<ExprAST> Cond, Then, Else;
 
 public:
-  IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then,
-            std::unique_ptr<ExprAST> Else)
-    : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {}
-  virtual Value *codegen();
+  IfExprAST(lexer::SourceLocation Loc, std::unique_ptr<ExprAST> Cond,
+            std::unique_ptr<ExprAST> Then, std::unique_ptr<ExprAST> Else)
+      : ExprAST(Loc), Cond(std::move(Cond)), Then(std::move(Then)),
+        Else(std::move(Else)) {}
+  Value *codegen() override;
+  raw_ostream &dump(raw_ostream &out, int ind) override {
+    ExprAST::dump(out << "if", ind);
+    Cond->dump(indent(out, ind) << "Cond:", ind + 1);
+    Then->dump(indent(out, ind) << "Then:", ind + 1);
+    Else->dump(indent(out, ind) << "Else:", ind + 1);
+    return out;
+  }
 };
 
 /// ForExprAST - Expression class for for/in.
@@ -104,9 +150,17 @@ public:
   ForExprAST(const std::string &VarName, std::unique_ptr<ExprAST> Start,
              std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step,
              std::unique_ptr<ExprAST> Body)
-    : VarName(VarName), Start(std::move(Start)), End(std::move(End)),
-      Step(std::move(Step)), Body(std::move(Body)) {}
-  virtual Value *codegen();
+      : VarName(VarName), Start(std::move(Start)), End(std::move(End)),
+        Step(std::move(Step)), Body(std::move(Body)) {}
+  Value *codegen() override;
+  raw_ostream &dump(raw_ostream &out, int ind) override {
+    ExprAST::dump(out << "for", ind);
+    Start->dump(indent(out, ind) << "Cond:", ind + 1);
+    End->dump(indent(out, ind) << "End:", ind + 1);
+    Step->dump(indent(out, ind) << "Step:", ind + 1);
+    Body->dump(indent(out, ind) << "Body:", ind + 1);
+    return out;
+  }
 };
 
 /// VarExprAST - Expression class for var/in
@@ -120,6 +174,13 @@ public:
       std::unique_ptr<ExprAST> Body)
       : VarNames(std::move(VarNames)), Body(std::move(Body)) {}
   Value *codegen() override;
+  raw_ostream &dump(raw_ostream &out, int ind) override {
+    ExprAST::dump(out << "var", ind);
+    for (const auto &NamedVar : VarNames)
+      NamedVar.second->dump(indent(out, ind) << NamedVar.first << ':', ind + 1);
+    Body->dump(indent(out, ind) << "Body:", ind + 1);
+    return out;
+  }
 };
 
 /// PrototypeAST - This class represents the "prototype" for a function,
@@ -130,12 +191,14 @@ class PrototypeAST {
   std::vector<std::string> Args;
   bool IsOperator;
   unsigned Precedence; // Precedence if a binary op.
+  int Line;
 
 public:
-  PrototypeAST(const std::string &Name, std::vector<std::string> Args,
-               bool IsOperator = false, unsigned Prec = 0)
+  PrototypeAST(lexer::SourceLocation Loc, const std::string &Name,
+               std::vector<std::string> Args, bool IsOperator = false,
+               unsigned Prec = 0)
       : Name(Name), Args(std::move(Args)), IsOperator(IsOperator),
-        Precedence(Prec) {}
+        Precedence(Prec), Line(Loc.Line) {}
   Function *codegen();
   const std::string &getName() const { return Name; }
 
@@ -148,7 +211,7 @@ public:
   }
 
   unsigned getBinaryPrecedence() const { return Precedence; }
-  void CreateArgumentAllocas(Function *F);
+  int getLine() const { return Line; }
 };
 
 /// FunctionAST - This class represents a function definition itself.
@@ -161,15 +224,12 @@ public:
               std::unique_ptr<ExprAST> Body)
       : Proto(std::move(Proto)), Body(std::move(Body)) {}
   Function *codegen();
+  raw_ostream &dump(raw_ostream &out, int ind) {
+    indent(out, ind) << "FunctionAST\n";
+    ++ind;
+    indent(out, ind) << "Body:";
+    return Body ? Body->dump(out, ind) : out << "null\n";
+  }
 };
 
-llvm::Value *ErrorV(const char *Str);
-
-static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
-                                          const std::string &VarName);
-
-
-
-}
-
 #endif

+ 2 - 2
source/CMakeLists.txt

@@ -8,7 +8,7 @@ find_package(LLVM REQUIRED CONFIG)
 message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
 message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
 
-set(LLVM_CXX_FLAGS "-fno-rtti")
+#set(LLVM_CXX_FLAGS "-fno-rtti")
 
 # Options to compile correctly the llvm tutorial
 add_compile_options(-std=c++14 -g -O0 -rdynamic)
@@ -17,7 +17,7 @@ set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS})
 include_directories(${LLVM_INCLUDE_DIRS})
 add_definitions(${LLVM_DEFINITIONS})
 
-add_executable(kaleidoscope Main.cpp Lexer.cpp Parser.cpp Ast.cpp JIT.cpp)
+add_executable(kaleidoscope Main.cpp Lexer.cpp Parser.cpp Ast.cpp JIT.cpp Debug.cpp)
 
 # Find the libraries that correspond to the LLVM components
 # that we wish to use

+ 1 - 1
source/Chapters/CMakeLists.txt

@@ -17,7 +17,7 @@ set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS})
 include_directories(${LLVM_INCLUDE_DIRS})
 add_definitions(${LLVM_DEFINITIONS})
 
-add_executable(kaleidoscope Chapter7.cpp)
+add_executable(kaleidoscope Chapter8.cpp)
 
 # Find the libraries that correspond to the LLVM components
 # that we wish to use

+ 39 - 0
source/Debug.cpp

@@ -0,0 +1,39 @@
+// Local includes
+#include "Debug.h"
+
+namespace debugger {
+
+DIType *DebugInfo::getDoubleTy() {
+  if (DblTy)
+    return DblTy;
+
+  DblTy = DBuilder->createBasicType("double", 64, 64, dwarf::DW_ATE_float);
+  return DblTy;
+}
+
+void DebugInfo::emitLocation(ExprAST *AST) {
+  if (!AST)
+    return Builder.SetCurrentDebugLocation(DebugLoc());
+  DIScope *Scope;
+  if (LexicalBlocks.empty())
+    Scope = TheCU;
+  else
+    Scope = LexicalBlocks.back();
+  Builder.SetCurrentDebugLocation(
+      DebugLoc::get(AST->getLine(), AST->getCol(), Scope));
+}
+
+static DISubroutineType *CreateFunctionType(unsigned NumArgs, DIFile *Unit) {
+  SmallVector<Metadata *, 8> EltTys;
+  DIType *DblTy = KSDbgInfo.getDoubleTy();
+
+  // Add the result type.
+  EltTys.push_back(DblTy);
+
+  for (unsigned i = 0, e = NumArgs; i != e; ++i)
+    EltTys.push_back(DblTy);
+
+  return DBuilder->createSubroutineType(DBuilder->getOrCreateTypeArray(EltTys));
+}
+
+}

+ 35 - 0
source/Debug.h

@@ -0,0 +1,35 @@
+#ifndef _DEB_H
+#define _DEB_H
+
+// Local includes
+#include "Ast.h"
+#include "Lexer.h"
+
+using namespace llvm;
+
+namespace debugger {
+
+struct DebugObjects {
+public:
+  static std::unique_ptr<DIBuilder> DBuilder;
+};
+
+namespace {
+class PrototypeAST;
+class ExprAST;
+}
+
+struct DebugInfo {
+  DICompileUnit *TheCU;
+  DIType *DblTy;
+  std::vector<DIScope *> LexicalBlocks;
+
+  void emitLocation(ExprAST *AST);
+  DIType *getDoubleTy();
+} KSDbgInfo;
+
+static DISubroutineType *CreateFunctionType(unsigned NumArgs, DIFile *Unit);
+
+}
+
+#endif

+ 1 - 4
source/JIT.cpp

@@ -4,14 +4,11 @@
 // Local includes
 #include "JIT.h"
 
-using namespace ast;
 using namespace llvm;
 using namespace llvm::orc;
 
-namespace jit{
+namespace jit {
 
-std::unique_ptr<llvm::legacy::FunctionPassManager> JITObjects::TheFPM =
-    std::make_unique<llvm::legacy::FunctionPassManager>(AstObjects::TheModule.get());
 std::unique_ptr<llvm::orc::KaleidoscopeJIT> JITObjects::TheJIT =
     std::unique_ptr<llvm::orc::KaleidoscopeJIT>(nullptr);
 std::map<std::string, std::unique_ptr<ast::PrototypeAST>> JITObjects::FunctionProtos{};

+ 0 - 1
source/JIT.h

@@ -13,7 +13,6 @@ namespace jit {
 
 struct JITObjects {
 public:
-  static std::unique_ptr<llvm::legacy::FunctionPassManager> TheFPM;
   static std::unique_ptr<llvm::orc::KaleidoscopeJIT> TheJIT;
   static std::map<std::string, std::unique_ptr<ast::PrototypeAST>> FunctionProtos;
 };

+ 14 - 3
source/Lexer.cpp

@@ -6,7 +6,7 @@
 #include "Lexer.h"
 
 /// gettok - Return the next token from standard input.
-namespace lexer{
+namespace lexer {
 
 std::string LexerObjects::IdentifierStr; // Filled in if tok_identifier
 double LexerObjects::NumVal;
@@ -43,12 +43,23 @@ std::string getTokName(int Tok) {
   return std::string(1, (char)Tok);
 }
 
+static int advance() {
+  int LastChar = getchar();
+
+  if (LastChar == '\n' || LastChar == '\r') {
+    LexLoc.Line++;
+    LexLoc.Col = 0;
+  } else
+    LexLoc.Col++;
+  return LastChar;
+}
+
 int gettok() {
   static int LastChar = ' ';
 
   // Skip any whitespace.
   while (isspace(LastChar))
-  LastChar = getchar();
+  LastChar = advance();
 
   if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
     LexerObjects::IdentifierStr = LastChar;
@@ -82,7 +93,7 @@ int gettok() {
     std::string NumStr;
     do {
       NumStr += LastChar;
-      LastChar = getchar();
+      LastChar = advance();
     } while (isdigit(LastChar) || LastChar == '.');
 
     LexerObjects::NumVal = strtod(NumStr.c_str(), nullptr);

+ 20 - 1
source/Lexer.h

@@ -4,7 +4,14 @@
 // Standard includes
 #include <string>
 
-namespace lexer{
+// LLVM includes
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/DIBuilder.h"
+
+// Local includes
+//#include "Ast.h"
+
+namespace lexer {
 // The lexer returns tokens [0-255] if it is an unknown character, otherwise one
 // of these for known things.
 enum Token {
@@ -31,6 +38,18 @@ enum Token {
   tok_var = -13
 };
 
+//static llvm::IRBuilder<> ast::AstObjects::Builder(getGlobalContext());
+
+struct SourceLocation {
+  int Line;
+  int Col;
+};
+
+static SourceLocation CurLoc;
+static SourceLocation LexLoc = {1, 0};
+
+static int advance();
+
 struct LexerObjects {
 public:
   static std::string IdentifierStr; // Filled in if tok_identifier

+ 31 - 7
source/Main.cpp

@@ -4,14 +4,14 @@
 //LLVM includes
 #include "llvm/Support/TargetSelect.h"
 #include "KaleidoscopeJIT.h"
+#include "llvm/IR/DIBuilder.h"
 
 // Local includes
+#include "JIT.h"
 #include "Ast.h"
+#include "Lexer.h"
 #include "Parser.h"
-#include "JIT.h"
-
-using namespace parser;
-using namespace jit;
+#include "Debug.h"
 
 namespace helper {
 // Cloning make_unique here until it's standard in C++14.
@@ -40,13 +40,37 @@ int main() {
   InitializeNativeTargetAsmPrinter();
   InitializeNativeTargetAsmParser();
 
-  JITObjects::TheJIT = llvm::make_unique<llvm::orc::KaleidoscopeJIT>();
+  jit::JITObjects::TheJIT = llvm::make_unique<llvm::orc::KaleidoscopeJIT>();
   jit::InitializeModule();
 
   // Prime the first token.
-  getNextToken();
+  parser::getNextToken();
+
+  // Add the current debug info version into the module.
+  AstObjects::TheModule->addModuleFlag(Module::Warning, "Debug Info Version",
+                           DEBUG_METADATA_VERSION);
+
+  // Darwin only supports dwarf2.
+  if (Triple(sys::getProcessTriple()).isOSDarwin()) {
+    AstObjects::TheModule->addModuleFlag(llvm::Module::Warning, "Dwarf Version",
+      2);
+  }
+
+  // Construct the DIBuilder, we do this here because we need the module.
+  debugger::DebugObjects::DBuilder =
+      llvm::make_unique<DIBuilder>(*AstObjects::TheModule);
+
+  // Create the compile unit for the module.
+  // Currently down as "fib.ks" as a filename since we're redirecting stdin
+  // but we'd like actual source locations.
+  debugger::KSDbgInfo.TheCU = debugger::DebugObjects::DBuilder->createCompileUnit(
+      dwarf::DW_LANG_C, "fib.ks", ".", "Kaleidoscope Compiler", 0, "", 0);
+
   // Run the main "interpreter loop" now.
-  MainLoop();
+  parser::MainLoop();
+
+  // Finalize the debug info.
+  debugger::DebugObjects::DBuilder->finalize();
 
   AstObjects::TheModule->dump();
 

+ 25 - 21
source/Parser.cpp

@@ -14,7 +14,7 @@
 using namespace lexer;
 using namespace jit;
 
-namespace parser{
+namespace parser {
 
 /// putchard - putchar that takes a double and returns 0.
 extern "C" double putchard(double X) {
@@ -90,10 +90,12 @@ static std::unique_ptr<ExprAST> ParseParenExpr() {
 static std::unique_ptr<ExprAST> ParseIdentifierExpr() {
   std::string IdName = LexerObjects::IdentifierStr;
 
+  SourceLocation LitLoc = CurLoc;
+
   getNextToken(); // eat identifier.
 
   if (CurTok != '(') // Simple variable ref.
-    return llvm::make_unique<VariableExprAST>(IdName);
+    return llvm::make_unique<VariableExprAST>(LitLoc, IdName);
 
   // Call.
   getNextToken(); // eat (
@@ -117,11 +119,14 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() {
   // Eat the ')'.
   getNextToken();
 
-  return llvm::make_unique<CallExprAST>(IdName, std::move(Args));
+  return llvm::make_unique<CallExprAST>(LitLoc, IdName, std::move(Args));
 }
 
 /// ifexpr ::= 'if' expression 'then' expression 'else' expression
 static std::unique_ptr<ExprAST> ParseIfExpr() {
+
+  SourceLocation IfLoc = CurLoc;
+
   getNextToken();  // eat the if.
 
   // condition.
@@ -300,6 +305,7 @@ static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
 
     // Okay, we know this is a binop.
     int BinOp = CurTok;
+    SourceLocation BinLoc = CurLoc;
     getNextToken(); // eat binop
 
     // Parse the unary expression after the binary operator.
@@ -317,8 +323,8 @@ static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
     }
 
     // Merge LHS/RHS.
-    LHS =
-        llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS));
+    LHS = llvm::make_unique<BinaryExprAST>(BinLoc, BinOp, std::move(LHS),
+                                       std::move(RHS));
   }
 }
 
@@ -340,6 +346,8 @@ static std::unique_ptr<ExprAST> ParseExpression() {
 static std::unique_ptr<PrototypeAST> ParsePrototype() {
   std::string FnName;
 
+  SourceLocation FnLoc = CurLoc;
+
   unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
   unsigned BinaryPrecedence = 30;
 
@@ -395,8 +403,8 @@ static std::unique_ptr<PrototypeAST> ParsePrototype() {
   if (Kind && ArgNames.size() != Kind)
     return ErrorP("Invalid number of operands for operator");
 
-  return llvm::make_unique<PrototypeAST>(FnName, ArgNames, Kind != 0,
-                                         BinaryPrecedence);
+    return llvm::make_unique<PrototypeAST>(FnLoc, FnName, ArgNames, Kind != 0,
+                                           BinaryPrecedence);
 
 }
 /// definition ::= 'def' prototype expression
@@ -413,10 +421,11 @@ static std::unique_ptr<FunctionAST> ParseDefinition() {
 
 /// toplevelexpr ::= expression
 static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
+  SourceLocation FnLoc = CurLoc;
   if (auto E = ParseExpression()) {
     // Make an anonymous proto.
-    auto Proto = llvm::make_unique<PrototypeAST>("main",
-        std::vector<std::string>());
+    auto Proto = llvm::make_unique<PrototypeAST>(FnLoc, "__anon_expr",
+                                                 std::vector<std::string>());
     return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
   }
   return nullptr;
@@ -433,25 +442,20 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
 
 static void HandleDefinition() {
   if (auto FnAST = ParseDefinition()) {
-    if (auto *FnIR = FnAST->codegen()) {
-      fprintf(stderr, "Read function definition:");
-      FnIR->dump();
-      JITObjects::TheJIT->addModule(std::move(AstObjects::TheModule));
-      InitializeModule();
-    }
+    if (!FnAST->codegen())
+      fprintf(stderr, "Error reading function definition:");
   } else {
     // Skip token for error recovery.
-     getNextToken();
+    getNextToken();
   }
 }
 
 static void HandleExtern() {
   if (auto ProtoAST = ParseExtern()) {
-    if (auto *FnIR = ProtoAST->codegen()) {
-      fprintf(stderr, "Read extern: ");
-      FnIR->dump();
-      JITObjects::FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST);
-    }
+    if (!ProtoAST->codegen())
+      fprintf(stderr, "Error reading extern");
+    else
+      FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST);
   } else {
     // Skip token for error recovery.
     getNextToken();

+ 1 - 3
source/Parser.h

@@ -7,9 +7,7 @@
 // Local includes
 #include "Ast.h"
 
-using namespace ast;
-
-namespace parser{
+namespace parser {
 
 static int CurTok;
 static std::map<char, int> BinopPrecedence;