Initial implementation of some source-level debugging stuff
authorChris Lattner <sabre@nondot.org>
Mon, 5 Jan 2004 05:23:38 +0000 (05:23 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 5 Jan 2004 05:23:38 +0000 (05:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10684 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Debugger/Debugger.h [new file with mode: 0644]
include/llvm/Debugger/InferiorProcess.h [new file with mode: 0644]
include/llvm/Debugger/ProgramInfo.h [new file with mode: 0644]
include/llvm/Debugger/RuntimeInfo.h [new file with mode: 0644]
include/llvm/Debugger/SourceFile.h [new file with mode: 0644]
include/llvm/Debugger/SourceLanguage.h [new file with mode: 0644]

diff --git a/include/llvm/Debugger/Debugger.h b/include/llvm/Debugger/Debugger.h
new file mode 100644 (file)
index 0000000..b1115da
--- /dev/null
@@ -0,0 +1,169 @@
+//===- Debugger.h - LLVM debugger library interface -------------*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LLVM source-level debugger library interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGGER_DEBUGGER_H
+#define LLVM_DEBUGGER_DEBUGGER_H
+
+#include <string>
+#include <vector>
+
+namespace llvm {
+  class Module;
+  class InferiorProcess;
+
+  /// Debugger class - This class implements the LLVM source-level debugger.
+  /// This allows clients to handle the user IO processing without having to
+  /// worry about how the debugger itself works.
+  ///
+  class Debugger {
+    // State the debugger needs when starting and stopping the program.
+    std::vector<std::string> ProgramArguments;
+
+    // The environment to run the program with.  This should eventually be
+    // changed to vector of strings when we allow the user to edit the
+    // environment.
+    const char * const *Environment;
+
+    // Program - The currently loaded program, or null if none is loaded.
+    Module *Program;
+
+    // Process - The currently executing inferior process.
+    InferiorProcess *Process;
+
+    Debugger(const Debugger &);         // DO NOT IMPLEMENT
+    void operator=(const Debugger &);   // DO NOT IMPLEMENT
+  public:
+    Debugger();
+    ~Debugger();
+
+    //===------------------------------------------------------------------===//
+    // Methods for manipulating and inspecting the execution environment.
+    //
+
+    /// initializeEnvironment - Specify the environment the program should run
+    /// with.  This is used to initialize the environment of the program to the
+    /// environment of the debugger.
+    void initializeEnvironment(const char *const *envp) {
+      Environment = envp;
+    }
+
+    /// setWorkingDirectory - Specify the working directory for the program to
+    /// be started from.
+    void setWorkingDirectory(const std::string &Dir) {
+      // FIXME: implement
+    }
+
+    template<typename It>
+    void setProgramArguments(It I, It E) {
+      ProgramArguments.assign(I, E);
+    }
+
+
+    //===------------------------------------------------------------------===//
+    // Methods for manipulating and inspecting the program currently loaded.
+    //
+
+    /// isProgramLoaded - Return true if there is a program currently loaded.
+    ///
+    bool isProgramLoaded() const { return Program != 0; }
+
+    /// getProgram - Return the LLVM module corresponding to the program.
+    ///
+    Module *getProgram() const { return Program; }
+
+    /// getProgramPath - Get the path of the currently loaded program, or an
+    /// empty string if none is loaded.
+    std::string getProgramPath() const;
+
+    /// loadProgram - If a program is currently loaded, unload it.  Then search
+    /// the PATH for the specified program, loading it when found.  If the
+    /// specified program cannot be found, an exception is thrown to indicate
+    /// the error.
+    void loadProgram(const std::string &Path);
+
+    /// unloadProgram - If a program is running, kill it, then unload all traces
+    /// of the current program.  If no program is loaded, this method silently
+    /// succeeds.
+    void unloadProgram();
+
+    //===------------------------------------------------------------------===//
+    // Methods for manipulating and inspecting the program currently running.
+    //
+    // If the program is running, and the debugger is active, then we know that
+    // the program has stopped.  This being the case, we can inspect the
+    // program, ask it for its source location, set breakpoints, etc.
+    //
+
+    /// isProgramRunning - Return true if a program is loaded and has a
+    /// currently active instance.
+    bool isProgramRunning() const { return Process != 0; }
+
+    /// getRunningProcess - If there is no program running, throw an exception.
+    /// Otherwise return the running process so that it can be inspected by the
+    /// debugger.
+    const InferiorProcess &getRunningProcess() const {
+      if (Process == 0) throw "No process running.";
+      return *Process;
+    }
+
+    /// createProgram - Create an instance of the currently loaded program,
+    /// killing off any existing one.  This creates the program and stops it at
+    /// the first possible moment.  If there is no program loaded or if there is
+    /// a problem starting the program, this method throws an exception.
+    void createProgram();
+
+    /// killProgram - If the program is currently executing, kill off the
+    /// process and free up any state related to the currently running program.
+    /// If there is no program currently running, this just silently succeeds.
+    /// If something horrible happens when killing the program, an exception
+    /// gets thrown.
+    void killProgram();
+
+
+    //===------------------------------------------------------------------===//
+    // Methods for continuing execution.  These methods continue the execution
+    // of the program by some amount.  If the program is successfully stopped,
+    // execution returns, otherwise an exception is thrown.
+    //
+    // NOTE: These methods should always be used in preference to directly
+    // accessing the Dbg object, because these will delete the Process object if
+    // the process unexpectedly dies.
+    //
+
+    /// stepProgram - Implement the 'step' command, continuing execution until
+    /// the next possible stop point.
+    void stepProgram();
+
+    /// nextProgram - Implement the 'next' command, continuing execution until
+    /// the next possible stop point that is in the current function.
+    void nextProgram();
+
+    /// finishProgram - Implement the 'finish' command, continuing execution
+    /// until the specified frame ID returns.
+    void finishProgram(void *Frame);
+
+    /// contProgram - Implement the 'cont' command, continuing execution until
+    /// the next breakpoint is encountered.
+    void contProgram();
+  };
+
+  class NonErrorException {
+    std::string Message;
+  public:
+    NonErrorException(const std::string &M) : Message(M) {}
+    const std::string &getMessage() const { return Message; }
+  };
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Debugger/InferiorProcess.h b/include/llvm/Debugger/InferiorProcess.h
new file mode 100644 (file)
index 0000000..c3f3886
--- /dev/null
@@ -0,0 +1,138 @@
+//===- InferiorProcess.h - Represent the program being debugged -*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the InferiorProcess class, which is used to represent,
+// inspect, and manipulate a process under the control of the LLVM debugger.
+//
+// This is an abstract class which should allow various different types of
+// implementations.  Initially we implement a unix specific debugger backend
+// that does not require code generator support, but we could eventually use
+// code generator support with ptrace, support windows based targets, supported
+// remote targets, etc.
+//
+// If the inferior process unexpectedly dies, an attempt to communicate with it
+// will cause an InferiorProcessDead exception to be thrown, indicating the exit
+// code of the process.  When this occurs, no methods on the InferiorProcess
+// class should be called except for the destructor.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGGER_INFERIORPROCESS_H
+#define LLVM_DEBUGGER_INFERIORPROCESS_H
+
+#include <string>
+#include <vector>
+
+namespace llvm {
+  class Module;
+  class GlobalVariable;
+
+  /// InferiorProcessDead exception - This class is thrown by methods that
+  /// communicate with the interior process if the process unexpectedly exits or
+  /// dies.  The instance variable indicates what the exit code of the process
+  /// was, or -1 if unknown.
+  class InferiorProcessDead {
+    int ExitCode;
+  public:
+    InferiorProcessDead(int EC) : ExitCode(EC) {}
+    int getExitCode() const { return ExitCode; }
+  };
+
+  /// InferiorProcess class - This class represents the process being debugged
+  /// by the debugger.  Objects of this class should not be stack allocated,
+  /// because the destructor can throw exceptions.
+  ///
+  class InferiorProcess {
+    Module *M;
+  protected:
+    InferiorProcess(Module *m) : M(m) {}
+  public:
+    /// create - Create an inferior process of the specified module, and
+    /// stop it at the first opportunity.  If there is a problem starting the
+    /// program (for example, it has no main), throw an exception.
+    static InferiorProcess *create(Module *M,
+                                   const std::vector<std::string> &Arguments,
+                                   const char * const *envp);
+    
+    // InferiorProcess destructor - Kill the current process.  If something
+    // terrible happens, we throw an exception from the destructor.
+    virtual ~InferiorProcess() {}
+
+    //===------------------------------------------------------------------===//
+    // Status methods - These methods return information about the currently
+    // stopped process.
+    //
+
+    /// getStatus - Return a status message that is specific to the current type
+    /// of inferior process that is created.  This can return things like the
+    /// PID of the inferior or other potentially interesting things.
+    virtual std::string getStatus() const {
+      return "";
+    }
+
+    //===------------------------------------------------------------------===//
+    // Methods for inspecting the call stack.
+    //
+
+    /// getPreviousFrame - Given the descriptor for the current stack frame,
+    /// return the descriptor for the caller frame.  This returns null when it
+    /// runs out of frames.  If Frame is null, the initial frame should be
+    /// returned.
+    virtual void *getPreviousFrame(void *Frame) const = 0;
+
+    /// getSubprogramDesc - Return the subprogram descriptor for the current
+    /// stack frame.
+    virtual const GlobalVariable *getSubprogramDesc(void *Frame) const = 0;
+
+    /// getFrameLocation - This method returns the source location where each
+    /// stack frame is stopped.
+    virtual void getFrameLocation(void *Frame, unsigned &LineNo,
+                                  unsigned &ColNo,
+                                  const GlobalVariable *&SourceDesc) const = 0;
+
+    //===------------------------------------------------------------------===//
+    // Methods for manipulating breakpoints.
+    //
+
+    /// addBreakpoint - This method adds a breakpoint at the specified line,
+    /// column, and source file, and returns a unique identifier for it.
+    ///
+    /// It is up to the debugger to determine whether or not there is actually a
+    /// stop-point that corresponds with the specified location.
+    virtual unsigned addBreakpoint(unsigned LineNo, unsigned ColNo,
+                                   const GlobalVariable *SourceDesc) = 0;
+
+    /// removeBreakpoint - This deletes the breakpoint with the specified ID
+    /// number.
+    virtual void removeBreakpoint(unsigned ID) = 0;
+
+
+    //===------------------------------------------------------------------===//
+    // Execution methods - These methods cause the program to continue execution
+    // by some amount.  If the program successfully stops, this returns.
+    // Otherwise, if the program unexpectedly terminates, an InferiorProcessDead
+    // exception is thrown.
+    //
+
+    /// stepProgram - Implement the 'step' command, continuing execution until
+    /// the next possible stop point.
+    virtual void stepProgram() = 0;
+
+    /// finishProgram - Implement the 'finish' command, continuing execution
+    /// until the current function returns.
+    virtual void finishProgram(void *Frame) = 0;
+
+    /// contProgram - Implement the 'cont' command, continuing execution until
+    /// a breakpoint is encountered.
+    virtual void contProgram() = 0;
+  };
+}  // end namespace llvm
+
+#endif
+
diff --git a/include/llvm/Debugger/ProgramInfo.h b/include/llvm/Debugger/ProgramInfo.h
new file mode 100644 (file)
index 0000000..0807d8c
--- /dev/null
@@ -0,0 +1,245 @@
+//===- ProgramInfo.h - Information about the loaded program -----*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines various pieces of information about the currently loaded
+// program.  One instance of this object is created every time a program is
+// loaded, and destroyed every time it is unloaded.
+//
+// The various pieces of information gathered about the source program are all
+// designed to be extended by various SourceLanguage implementations.  This
+// allows source languages to keep any extended information that they support in
+// the derived class portions of the class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGGER_PROGRAMINFO_H
+#define LLVM_DEBUGGER_PROGRAMINFO_H
+
+#include <string>
+#include <map>
+#include <vector>
+
+namespace llvm {
+  class GlobalVariable;
+  class Module;
+  class SourceFile;
+  class SourceLanguage;
+  class ProgramInfo;
+
+  /// SourceLanguageCache - SourceLanguage implementations are allowed to cache
+  /// stuff in the ProgramInfo object.  The only requirement we have on these
+  /// instances is that they are destroyable.
+  struct SourceLanguageCache {
+    virtual ~SourceLanguageCache() {}
+  };
+
+  /// SourceFileInfo - One instance of this structure is created for each
+  /// source file in the program.
+  ///
+  class SourceFileInfo {
+    /// BaseName - The filename of the source file.
+    std::string BaseName;
+
+    /// Directory - The working directory of this source file when it was
+    /// compiled.
+    std::string Directory;
+
+    /// Version - The version of the LLVM debug information that this file was
+    /// compiled with.
+    unsigned Version;
+
+    /// Language - The source language that the file was compiled with.  This
+    /// pointer is never null.
+    ///
+    const SourceLanguage *Language;
+
+    /// Descriptor - The LLVM Global Variable which describes the source file.
+    ///
+    const GlobalVariable *Descriptor;
+
+    /// SourceText - The body of this source file, or null if it has not yet
+    /// been loaded.
+    mutable SourceFile *SourceText;
+  public:
+    SourceFileInfo(const GlobalVariable *Desc, const SourceLanguage &Lang);
+    ~SourceFileInfo();
+    
+    const std::string &getBaseName() const { return BaseName; }
+    const std::string &getDirectory() const { return Directory; }
+    unsigned getDebugVersion() const { return Version; }
+    const GlobalVariable *getDescriptor() const { return Descriptor; }
+    SourceFile &getSourceText() const;
+
+    const SourceLanguage &getLanguage() const { return *Language; }
+  };
+
+
+  /// SourceFunctionInfo - An instance of this class is used to represent each
+  /// source function in the program.
+  ///
+  class SourceFunctionInfo {
+    /// Name - This contains an abstract name that is potentially useful to the
+    /// end-user.  If there is no explicit support for the current language,
+    /// then this string is used to identify the function.
+    std::string Name;
+
+    /// Descriptor - The descriptor for this function.
+    ///
+    const GlobalVariable *Descriptor;
+
+    /// SourceFile - The file that this function is defined in.
+    ///
+    const SourceFileInfo *SourceFile;
+
+    /// LineNo, ColNo - The location of the first stop-point in the function.
+    /// These are computed on demand.
+    mutable unsigned LineNo, ColNo;
+
+  public:
+    SourceFunctionInfo(ProgramInfo &PI, const GlobalVariable *Desc);
+    virtual ~SourceFunctionInfo() {}
+
+    /// getSymbolicName - Return a human-readable symbolic name to identify the
+    /// function (for example, in stack traces).
+    virtual std::string getSymbolicName() const { return Name; }
+
+    /// getDescriptor - This returns the descriptor for the function.
+    ///
+    const GlobalVariable *getDescriptor() const { return Descriptor; }
+
+    /// getSourceFile - This returns the source file that defines the function.
+    ///
+    const SourceFileInfo &getSourceFile() const { return *SourceFile; }
+
+    /// getSourceLocation - This method returns the location of the first
+    /// stopping point in the function.  If the body of the function cannot be
+    /// found, this returns zeros for both values.
+    void getSourceLocation(unsigned &LineNo, unsigned &ColNo) const;
+  };
+
+
+  /// ProgramInfo - This object contains information about the loaded program.
+  /// When a new program is loaded, an instance of this class is created.  When
+  /// the program is unloaded, the instance is destroyed.  This object basically
+  /// manages the lazy computation of information useful for the debugger.
+  class ProgramInfo {
+    Module *M;
+
+    /// ProgramTimeStamp - This is the timestamp of the executable file that we
+    /// currently have loaded into the debugger.
+    unsigned long long ProgramTimeStamp;
+
+    /// SourceFiles - This map is used to transform source file descriptors into
+    /// their corresponding SourceFileInfo objects.  This mapping owns the
+    /// memory for the SourceFileInfo objects.
+    ///
+    bool SourceFilesIsComplete;
+    std::map<const GlobalVariable*, SourceFileInfo*> SourceFiles;
+
+    /// SourceFileIndex - Mapping from source file basenames to the information
+    /// about the file.  Note that there can be filename collisions, so this is
+    /// a multimap.  This map is populated incrementally as the user interacts
+    /// with the program, through the getSourceFileFromDesc method.  If ALL of
+    /// the source files are needed, the getSourceFiles() method scans the
+    /// entire program looking for them.
+    /// 
+    std::multimap<std::string, SourceFileInfo*> SourceFileIndex;
+
+    /// SourceFunctions - This map contains entries functions in the source
+    /// program.  If SourceFunctionsIsComplete is true, then this is ALL of the
+    /// functions in the program are in this map.
+    bool SourceFunctionsIsComplete;
+    std::map<const GlobalVariable*, SourceFunctionInfo*> SourceFunctions;
+
+    /// LanguageCaches - Each source language is permitted to keep a per-program
+    /// cache of information specific to whatever it needs.  This vector is
+    /// effectively a small map from the languages that are active in the
+    /// program to their caches.  This can be accessed by the language by the
+    /// "getLanguageCache" method.
+    std::vector<std::pair<const SourceLanguage*, 
+                          SourceLanguageCache*> > LanguageCaches;
+  public:
+    ProgramInfo(Module *m);
+    ~ProgramInfo();
+
+    /// getProgramTimeStamp - Return the time-stamp of the program when it was
+    /// loaded.
+    unsigned long long getProgramTimeStamp() const { return ProgramTimeStamp; }
+    
+    //===------------------------------------------------------------------===//
+    // Interfaces to the source code files that make up the program.
+    //
+
+    /// getSourceFile - Return source file information for the specified source
+    /// file descriptor object, adding it to the collection as needed.  This
+    /// method always succeeds (is unambiguous), and is always efficient.
+    ///
+    const SourceFileInfo &getSourceFile(const GlobalVariable *Desc);
+
+    /// getSourceFile - Look up the file with the specified name.  If there is
+    /// more than one match for the specified filename, prompt the user to pick
+    /// one.  If there is no source file that matches the specified name, throw
+    /// an exception indicating that we can't find the file.  Otherwise, return
+    /// the file information for that file.
+    ///
+    /// If the source file hasn't been discovered yet in the program, this
+    /// method might have to index the whole program by calling the
+    /// getSourceFiles() method.
+    ///
+    const SourceFileInfo &getSourceFile(const std::string &Filename);
+
+    /// getSourceFiles - Index all of the source files in the program and return
+    /// them.  This information is lazily computed the first time that it is
+    /// requested.  Since this information can take a long time to compute, the
+    /// user is given a chance to cancel it.  If this occurs, an exception is
+    /// thrown.
+    const std::map<const GlobalVariable*, SourceFileInfo*> &
+    getSourceFiles(bool RequiresCompleteMap = true);
+
+    //===------------------------------------------------------------------===//
+    // Interfaces to the functions that make up the program.
+    //
+
+    /// getFunction - Return source function information for the specified
+    /// function descriptor object, adding it to the collection as needed.  This
+    /// method always succeeds (is unambiguous), and is always efficient.
+    ///
+    const SourceFunctionInfo &getFunction(const GlobalVariable *Desc);
+
+    /// getSourceFunctions - Index all of the functions in the program and
+    /// return them.  This information is lazily computed the first time that it
+    /// is requested.  Since this information can take a long time to compute,
+    /// the user is given a chance to cancel it.  If this occurs, an exception
+    /// is thrown.
+    const std::map<const GlobalVariable*, SourceFunctionInfo*> &
+    getSourceFunctions(bool RequiresCompleteMap = true);
+
+    /// addSourceFunctionsRead - Return true if the source functions map is
+    /// complete: that is, all functions in the program have been read in.
+    bool allSourceFunctionsRead() const { return SourceFunctionsIsComplete; }
+
+    /// getLanguageCache - This method is used to build per-program caches of
+    /// information, such as the functions or types visible to the program.
+    /// This can be used by SourceLanguage implementations because it requires
+    /// an accessible <sl>::CacheType typedef, where <sl> is the C++ type of the
+    /// source-language subclass.
+    template<typename SL>
+    typename SL::CacheType &getLanguageCache(const SL *L) {
+      for (unsigned i = 0, e = LanguageCaches.size(); i != e; ++i)
+        if (LanguageCaches[i].first == L)
+          return *(typename SL::CacheType*)LanguageCaches[i].second;
+      typename SL::CacheType *NewCache = L->createSourceLanguageCache(*this);
+      LanguageCaches.push_back(std::make_pair(L, NewCache));
+      return *NewCache;
+    }
+  };
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Debugger/RuntimeInfo.h b/include/llvm/Debugger/RuntimeInfo.h
new file mode 100644 (file)
index 0000000..360b923
--- /dev/null
@@ -0,0 +1,141 @@
+//===- RuntimeInfo.h - Information about running program --------*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes that capture various pieces of information about
+// the currently executing, but stopped, program.  One instance of this object
+// is created every time a program is stopped, and destroyed every time it
+// starts running again.  This object's main goal is to make access to runtime
+// information easy and efficient, by caching information as requested.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGGER_RUNTIMEINFO_H
+#define LLVM_DEBUGGER_RUNTIMEINFO_H
+
+#include <vector>
+
+namespace llvm {
+  class ProgramInfo;
+  class RuntimeInfo;
+  class InferiorProcess;
+  class GlobalVariable;
+  class SourceFileInfo;
+
+  /// StackFrame - One instance of this structure is created for each stack
+  /// frame that is active in the program.
+  ///
+  class StackFrame {
+    RuntimeInfo &RI;
+    void *FrameID;
+    const GlobalVariable *FunctionDesc;
+
+    /// LineNo, ColNo, FileInfo - This information indicates WHERE in the source
+    /// code for the program the stack frame is located.
+    unsigned LineNo, ColNo;
+    const SourceFileInfo *SourceInfo;
+  public:
+    StackFrame(RuntimeInfo &RI, void *ParentFrameID);
+    
+    StackFrame &operator=(const StackFrame &RHS) {
+      FrameID = RHS.FrameID;
+      FunctionDesc = RHS.FunctionDesc;
+      return *this;
+    }
+
+    /// getFrameID - return the low-level opaque frame ID of this stack frame.
+    ///
+    void *getFrameID() const { return FrameID; }
+
+    /// getFunctionDesc - Return the descriptor for the function that contains
+    /// this stack frame, or null if it is unknown.
+    ///
+    const GlobalVariable *getFunctionDesc();
+
+    /// getSourceLocation - Return the source location that this stack frame is
+    /// sitting at.
+    void getSourceLocation(unsigned &LineNo, unsigned &ColNo,
+                           const SourceFileInfo *&SourceInfo);
+  };
+
+
+  /// RuntimeInfo - This class collects information about the currently running
+  /// process.  It is created whenever the program stops execution for the
+  /// debugger, and destroyed whenver execution continues.
+  class RuntimeInfo {
+    /// ProgInfo - This object contains static information about the program.
+    ///
+    ProgramInfo *ProgInfo;
+
+    /// IP - This object contains information about the actual inferior process
+    /// that we are communicating with and aggregating information from.
+    const InferiorProcess &IP;
+
+    /// CallStack - This caches information about the current stack trace of the
+    /// program.  This is lazily computed as needed.
+    std::vector<StackFrame> CallStack;
+    
+    /// CurrentFrame - The user can traverse the stack frame with the
+    /// up/down/frame family of commands.  This index indicates the current
+    /// stack frame.
+    unsigned CurrentFrame;
+
+  public:
+    RuntimeInfo(ProgramInfo *PI, const InferiorProcess &ip)
+      : ProgInfo(PI), IP(ip), CurrentFrame(0) {
+      // Make sure that the top of stack has been materialized.  If this throws
+      // an exception, something is seriously wrong and the RuntimeInfo object
+      // would be unusable anyway.
+      getStackFrame(0);
+    }
+
+    ProgramInfo &getProgramInfo() { return *ProgInfo; }
+    const InferiorProcess &getInferiorProcess() const { return IP; }
+
+    //===------------------------------------------------------------------===//
+    // Methods for inspecting the call stack of the program.
+    //
+
+    /// getStackFrame - Materialize the specified stack frame and return it.  If
+    /// the specified ID is off of the bottom of the stack, throw an exception
+    /// indicating the problem.
+    StackFrame &getStackFrame(unsigned ID) {
+      if (ID >= CallStack.size())
+        materializeFrame(ID);
+      return CallStack[ID];
+    }
+
+    /// getCurrentFrame - Return the current stack frame object that the user is
+    /// inspecting.
+    StackFrame &getCurrentFrame() {
+      assert(CallStack.size() > CurrentFrame &&
+             "Must have materialized frame before making it current!");
+      return CallStack[CurrentFrame];
+    }
+
+    /// getCurrentFrameIdx - Return the current frame the user is inspecting.
+    ///
+    unsigned getCurrentFrameIdx() const { return CurrentFrame; }
+
+    /// setCurrentFrameIdx - Set the current frame index to the specified value.
+    /// Note that the specified frame must have been materialized with
+    /// getStackFrame before it can be made current.
+    void setCurrentFrameIdx(unsigned Idx) {
+      assert(Idx < CallStack.size() &&
+             "Must materialize frame before making it current!");
+      CurrentFrame = Idx;
+    }
+  private:
+    /// materializeFrame - Create and process all frames up to and including the
+    /// specified frame number.  This throws an exception if the specified frame
+    /// ID is nonexistant.
+    void materializeFrame(unsigned ID);
+  };
+}
+
+#endif
diff --git a/include/llvm/Debugger/SourceFile.h b/include/llvm/Debugger/SourceFile.h
new file mode 100644 (file)
index 0000000..86a7f36
--- /dev/null
@@ -0,0 +1,95 @@
+//===- SourceFile.h - Class to represent a source code file -----*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SourceFile class which is used to represent a single
+// file of source code in the program, caching data from the file to make access
+// efficient.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGGER_SOURCEFILE_H
+#define LLVM_DEBUGGER_SOURCEFILE_H
+
+#include <string>
+#include <vector>
+
+namespace llvm {
+  class GlobalVariable;
+
+  class SourceFile {
+    /// Filename - This is the full path of the file that is loaded.
+    ///
+    std::string Filename;
+
+    /// Descriptor - The debugging descriptor for this source file.  If there
+    /// are multiple descriptors for the same file, this is just the first one
+    /// encountered.
+    ///
+    const GlobalVariable *Descriptor;
+
+    /// FileStart, FileEnd - These pointers point to the start and end of the
+    /// file data for this file.  If there was an error loading the file, these
+    /// pointers will both be null.
+    const char *FileStart, *FileEnd;
+
+    /// LineOffset - This vector contains a mapping from source line numbers to
+    /// their offsets in the file.  This data is computed lazily, the first time
+    /// it is asked for.  If there are zero elements allocated in this vector,
+    /// then it has not yet been computed.
+    mutable std::vector<unsigned> LineOffset;
+
+  public:
+    /// SourceFile constructor - Read in the specified source file if it exists,
+    /// but do not build the LineOffsets table until it is requested.  This will
+    /// NOT throw an exception if the file is not found, if there is an error
+    /// reading it, or if the user cancels the operation.  Instead, it will just
+    /// be an empty source file.
+    SourceFile(const std::string &fn, const GlobalVariable *Desc)
+      : Filename(fn), Descriptor(Desc), FileStart(0), FileEnd(0) {
+      readFile();
+    }
+    ~SourceFile() {
+      delete[] FileStart;
+    }
+
+    /// getDescriptor - Return the debugging decriptor for this source file.
+    ///
+    const GlobalVariable *getDescriptor() const { return Descriptor; }
+    
+    /// getFilename - Return the fully resolved path that this file was loaded
+    /// from.
+    const std::string &getFilename() const { return Filename; }
+    
+    /// getSourceLine - Given a line number, return the start and end of the
+    /// line in the file.  If the line number is invalid, or if the file could
+    /// not be loaded, null pointers are returned for the start and end of the
+    /// file.  Note that line numbers start with 0, not 1.  This also strips off
+    /// any newlines from the end of the line, to ease formatting of the text.
+    void getSourceLine(unsigned LineNo, const char *&LineStart,
+                       const char *&LineEnd) const;
+  
+    /// getNumLines - Return the number of lines the source file contains.
+    ///
+    unsigned getNumLines() const {
+      if (LineOffset.empty()) calculateLineOffsets();
+      return LineOffset.size();
+    }
+
+  private:
+    /// readFile - Load Filename into FileStart and FileEnd.
+    ///
+    void readFile();
+    
+    /// calculateLineOffsets - Compute the LineOffset vector for the current
+    /// file.
+    void calculateLineOffsets() const;
+  };
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Debugger/SourceLanguage.h b/include/llvm/Debugger/SourceLanguage.h
new file mode 100644 (file)
index 0000000..798e0fb
--- /dev/null
@@ -0,0 +1,99 @@
+//===- SourceLanguage.h - Interact with source languages --------*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file defines the abstract SourceLanguage interface, which is used by the
+// LLVM debugger to parse source-language expressions and render program objects
+// into a human readable string.  In general, these classes perform all of the
+// analysis and interpretation of the language-specific debugger information.
+//
+// This interface is designed to be completely stateless, so all methods are
+// const.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGGER_SOURCELANGUAGE_H
+#define LLVM_DEBUGGER_SOURCELANGUAGE_H
+
+#include <string>
+
+namespace llvm {
+  class GlobalVariable;
+  class SourceFileInfo;
+  class SourceFunctionInfo;
+  class ProgramInfo;
+  class RuntimeInfo;
+
+  struct SourceLanguage {
+    virtual ~SourceLanguage() {}
+
+    /// getSourceLanguageName - This method is used to implement the 'show
+    /// language' command in the debugger.
+    virtual const char *getSourceLanguageName() const = 0;
+
+    //===------------------------------------------------------------------===//
+    // Methods used to implement debugger hooks.
+    //
+
+    /// printInfo - Implementing this method allows the debugger to use
+    /// language-specific 'info' extensions, e.g., 'info selectors' for objc.
+    /// This method should return true if the specified string is recognized.
+    ///
+    virtual bool printInfo(const std::string &What) const {
+      return false;
+    }
+
+    /// lookupFunction - Given a textual function name, return the
+    /// SourceFunctionInfo descriptor for that function, or null if it cannot be
+    /// found.  If the program is currently running, the RuntimeInfo object
+    /// provides information about the current evaluation context, otherwise it
+    /// will be null.
+    ///
+    virtual SourceFunctionInfo *lookupFunction(const std::string &FunctionName,
+                                               ProgramInfo &PI,
+                                               RuntimeInfo *RI = 0) const {
+      return 0;
+    }
+
+
+    //===------------------------------------------------------------------===//
+    // Methods used to parse various pieces of program information.
+    //
+
+    /// createSourceFileInfo - This method can be implemented by the front-end
+    /// if it needs to keep track of information beyond what the debugger
+    /// requires.
+    virtual SourceFileInfo *
+    createSourceFileInfo(const GlobalVariable *Desc, ProgramInfo &PI) const;
+
+    /// createSourceFunctionInfo - This method can be implemented by the derived
+    /// SourceLanguage if it needs to keep track of more information than the
+    /// SourceFunctionInfo has.
+    virtual SourceFunctionInfo *
+    createSourceFunctionInfo(const GlobalVariable *Desc, ProgramInfo &PI) const;
+
+
+    //===------------------------------------------------------------------===//
+    // Static methods used to get instances of various source languages.
+    //
+
+    /// get - This method returns a source-language instance for the specified
+    /// Dwarf 3 language identifier.  If the language is unknown, an object is
+    /// returned that can support some minimal operations, but is not terribly
+    /// bright.
+    static const SourceLanguage &get(unsigned ID);
+
+    /// get*Instance() - These methods return specific instances of languages.
+    ///
+    static const SourceLanguage &getCFamilyInstance();
+    static const SourceLanguage &getCPlusPlusInstance();
+    static const SourceLanguage &getUnknownLanguageInstance();
+  };
+}
+
+#endif