Initial implementation of some source-level debugging stuff

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10684 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2004-01-05 05:23:38 +00:00
parent bdfb339b8d
commit 4575dcb587
6 changed files with 887 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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