Delete all stale files.

This commit is contained in:
rdivacky 2009-10-15 16:26:17 +00:00
parent 5effb5c6a1
commit 1adacceba9
368 changed files with 0 additions and 37434 deletions

View File

@ -1,51 +0,0 @@
Date: Sun, 8 Jul 2001 09:37:22 -0500
From: Vikram S. Adve <vadve@cs.uiuc.edu>
To: Ruchira Sasanka <sasanka@students.uiuc.edu>
Cc: Chris Lattner <lattner@cs.uiuc.edu>
Subject: machine instruction operands
Ruchira,
When generating machine instructions, I have to make several choices about
operands. For cases were a register is required, there are 3 cases:
1. The register is for a Value* that is already in the VM code.
2. The register is for a value that is not in the VM code, usually because 2
machine instructions get generated for a single VM instruction (and the
register holds the result of the first m/c instruction and is used by the
second m/c instruction).
3. The register is a pre-determined machine register.
E.g, for this VM instruction:
ptr = alloca type, numElements
I have to generate 2 machine instructions:
reg = mul constant, numElements
ptr = add %sp, reg
Each machine instruction is of class MachineInstr.
It has a vector of operands. All register operands have type MO_REGISTER.
The 3 types of register operands are marked using this enum:
enum VirtualRegisterType {
MO_VMVirtualReg, // virtual register for *value
MO_MInstrVirtualReg, // virtual register for result of *minstr
MO_MachineReg // pre-assigned machine register `regNum'
} vregType;
Here's how this affects register allocation:
1. MO_VMVirtualReg is the standard case: you just do the register
allocation.
2. MO_MInstrVirtualReg is the case where there is a hidden register being
used. You should decide how you want to handle it, e.g., do you want do
create a Value object during the preprocessing phase to make the value
explicit (like for address register for the RETURN instruction).
3. For case MO_MachineReg, you don't need to do anything, at least for
SPARC. The only machine regs I am using so far are %g0 and %sp.
--Vikram

View File

@ -1,25 +0,0 @@
Date: Sun, 8 Jul 2001 10:02:20 -0500
From: Vikram S. Adve <vadve@cs.uiuc.edu>
To: vadve@cs.uiuc.edu, Ruchira Sasanka <sasanka@students.uiuc.edu>
Cc: Chris Lattner <lattner@cs.uiuc.edu>
Subject: RE: machine instruction operands
I got interrupted and forgot to explain the example. In that case:
reg will be the 3rd operand of MUL and it will be of type
MO_MInstrVirtualReg. The field MachineInstr* minstr will point to the
instruction that computes reg.
numElements will be an immediate constant, not a register.
%sp will be operand 1 of ADD and it will be of type MO_MachineReg. The
field regNum identifies the register.
numElements will be operand 2 of ADD and it will be of type
MO_VMVirtualReg. The field Value* value identifies the value.
ptr will be operand 3 of ADD will also be %sp, i.e., of
type MO_MachineReg. regNum identifies the register.
--Vikram

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
//===-- llvm/ADT/HashExtras.h - Useful functions for STL hash ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains some templates that are useful if you are working with the
// STL Hashed containers.
//
// No library is required when using these functions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_HASHEXTRAS_H
#define LLVM_ADT_HASHEXTRAS_H
#include <string>
// Cannot specialize hash template from outside of the std namespace.
namespace HASH_NAMESPACE {
// Provide a hash function for arbitrary pointers...
template <class T> struct hash<T *> {
inline size_t operator()(const T *Val) const {
return reinterpret_cast<size_t>(Val);
}
};
template <> struct hash<std::string> {
size_t operator()(std::string const &str) const {
return hash<char const *>()(str.c_str());
}
};
} // End namespace std
#endif

View File

@ -1,62 +0,0 @@
//===- llvm/ADT/Tree.h - Generic n-way tree structure -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class defines a generic N-way tree node structure. The tree structure
// is immutable after creation, but the payload contained within it is not.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_TREE_H
#define LLVM_ADT_TREE_H
#include <vector>
namespace llvm {
template<class ConcreteTreeNode, class Payload>
class Tree {
std::vector<ConcreteTreeNode*> Children; // This node's children, if any.
ConcreteTreeNode *Parent; // Parent of this node.
Payload Data; // Data held in this node.
protected:
void setChildren(const std::vector<ConcreteTreeNode*> &children) {
Children = children;
}
public:
inline Tree(ConcreteTreeNode *parent) : Parent(parent) {}
inline Tree(const std::vector<ConcreteTreeNode*> &children,
ConcreteTreeNode *par) : Children(children), Parent(par) {}
inline Tree(const std::vector<ConcreteTreeNode*> &children,
ConcreteTreeNode *par, const Payload &data)
: Children(children), Parent(par), Data(data) {}
// Tree dtor - Free all children
inline ~Tree() {
for (unsigned i = Children.size(); i > 0; --i)
delete Children[i-1];
}
// Tree manipulation/walking routines...
inline ConcreteTreeNode *getParent() const { return Parent; }
inline unsigned getNumChildren() const { return Children.size(); }
inline ConcreteTreeNode *getChild(unsigned i) const {
assert(i < Children.size() && "Tree::getChild with index out of range!");
return Children[i];
}
// Payload access...
inline Payload &getTreeData() { return Data; }
inline const Payload &getTreeData() const { return Data; }
};
} // End llvm namespace
#endif

View File

@ -1,90 +0,0 @@
//===- LoopVR.cpp - Value Range analysis driven by loop information -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface for the loop-driven value range pass.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LOOPVR_H
#define LLVM_ANALYSIS_LOOPVR_H
#include "llvm/Pass.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Support/ConstantRange.h"
#include <iosfwd>
#include <map>
namespace llvm {
/// LoopVR - This class maintains a mapping of Values to ConstantRanges.
/// There are interfaces to look up and update ranges by value, and for
/// accessing all values with range information.
///
class LoopVR : public FunctionPass {
public:
static char ID; // Class identification, replacement for typeinfo
LoopVR() : FunctionPass(&ID) {}
bool runOnFunction(Function &F);
virtual void print(std::ostream &os, const Module *) const;
void releaseMemory();
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequiredTransitive<LoopInfo>();
AU.addRequiredTransitive<ScalarEvolution>();
AU.setPreservesAll();
}
//===---------------------------------------------------------------------
// Methods that are used to look up and update particular values.
/// get - return the ConstantRange for a given Value of IntegerType.
ConstantRange get(Value *V);
/// remove - remove a value from this analysis.
void remove(Value *V);
/// narrow - improve our unterstanding of a Value by pointing out that it
/// must fall within ConstantRange. To replace a range, remove it first.
void narrow(Value *V, const ConstantRange &CR);
//===---------------------------------------------------------------------
// Methods that are used to iterate across all values with information.
/// size - returns the number of Values with information
unsigned size() const { return Map.size(); }
typedef std::map<Value *, ConstantRange *>::iterator iterator;
/// begin - return an iterator to the first Value, ConstantRange pair
iterator begin() { return Map.begin(); }
/// end - return an iterator one past the last Value, ConstantRange pair
iterator end() { return Map.end(); }
/// getValue - return the Value referenced by an iterator
Value *getValue(iterator I) { return I->first; }
/// getConstantRange - return the ConstantRange referenced by an iterator
ConstantRange getConstantRange(iterator I) { return *I->second; }
private:
ConstantRange compute(Value *V);
ConstantRange getRange(const SCEV* S, Loop *L, ScalarEvolution &SE);
ConstantRange getRange(const SCEV* S, const SCEV* T, ScalarEvolution &SE);
std::map<Value *, ConstantRange *> Map;
};
} // end llvm namespace
#endif

View File

@ -1,63 +0,0 @@
//===- LazyLiveness.h - Lazy, CFG-invariant liveness information ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass implements a lazy liveness analysis as per "Fast Liveness Checking
// for SSA-form Programs," by Boissinot, et al.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_LAZYLIVENESS_H
#define LLVM_CODEGEN_LAZYLIVENESS_H
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SparseBitVector.h"
#include <vector>
namespace llvm {
class MachineRegisterInfo;
class LazyLiveness : public MachineFunctionPass {
public:
static char ID; // Pass identification, replacement for typeid
LazyLiveness() : MachineFunctionPass(&ID) { }
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<MachineDominatorTree>();
}
bool runOnMachineFunction(MachineFunction &mf);
bool vregLiveIntoMBB(unsigned vreg, MachineBasicBlock* MBB);
private:
void computeBackedgeChain(MachineFunction& mf, MachineBasicBlock* MBB);
typedef std::pair<MachineBasicBlock*, MachineBasicBlock*> edge_t;
MachineRegisterInfo* MRI;
DenseMap<MachineBasicBlock*, unsigned> preorder;
std::vector<MachineBasicBlock*> rev_preorder;
DenseMap<MachineBasicBlock*, SparseBitVector<128> > rv;
DenseMap<MachineBasicBlock*, SparseBitVector<128> > tv;
DenseSet<edge_t> backedges;
SparseBitVector<128> backedge_source;
SparseBitVector<128> backedge_target;
SparseBitVector<128> calculated;
};
}
#endif

View File

@ -1,49 +0,0 @@
/*
* The LLVM Compiler Infrastructure
*
* This file is distributed under the University of Illinois Open Source
* License. See LICENSE.TXT for details.
*
******************************************************************************
*
* Description:
* This header file includes the infamous alloc.h header file if the
* autoconf system has found it. It hides all of the autoconf details
* from the rest of the application source code.
*/
#ifndef _CONFIG_ALLOC_H
#define _CONFIG_ALLOC_H
#include "llvm/Config/config.h"
/*
* This is a modified version of that suggested by the Autoconf manual.
* 1) The #pragma is indented so that pre-ANSI C compilers ignore it.
* 2) If alloca.h cannot be found, then try stdlib.h. Some platforms
* (notably FreeBSD) defined alloca() there.
*/
#ifdef _MSC_VER
#include <malloc.h>
#define alloca _alloca
#elif defined(HAVE_ALLOCA_H)
#include <alloca.h>
#elif defined(__MINGW32__) && defined(HAVE_MALLOC_H)
#include <malloc.h>
#elif !defined(__GNUC__)
# ifdef _AIX
# pragma alloca
# else
# ifndef alloca
char * alloca ();
# endif
# endif
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# else
# error "The function alloca() is required but not found!"
# endif
#endif
#endif

View File

@ -1,176 +0,0 @@
//===- Debugger.h - LLVM debugger library interface -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file 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;
class LLVMContext;
/// 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);
}
unsigned getNumProgramArguments() const {
return static_cast<unsigned>(ProgramArguments.size());
}
const std::string &getProgramArgument(unsigned i) const {
return ProgramArguments[i];
}
//===------------------------------------------------------------------===//
// 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, LLVMContext& Context);
/// 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

@ -1,137 +0,0 @@
//===- InferiorProcess.h - Represent the program being debugged -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file 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

@ -1,246 +0,0 @@
//===- ProgramInfo.h - Information about the loaded program -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file 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 "llvm/System/TimeValue.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.
sys::TimeValue 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.
sys::TimeValue 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

@ -1,142 +0,0 @@
//===- RuntimeInfo.h - Information about running program --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file 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>
#include <cassert>
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

@ -1,87 +0,0 @@
//===- SourceFile.h - Class to represent a source code file -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file 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 "llvm/System/Path.h"
#include "llvm/ADT/OwningPtr.h"
#include <vector>
namespace llvm {
class GlobalVariable;
class MemoryBuffer;
class SourceFile {
/// Filename - This is the full path of the file that is loaded.
///
sys::Path 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;
/// This is the memory mapping for the file so we can gain access to it.
OwningPtr<MemoryBuffer> File;
/// 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);
~SourceFile();
/// 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.toString(); }
/// 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 static_cast<unsigned>(LineOffset.size());
}
private:
/// calculateLineOffsets - Compute the LineOffset vector for the current
/// file.
void calculateLineOffsets() const;
};
} // end namespace llvm
#endif

View File

@ -1,99 +0,0 @@
//===- SourceLanguage.h - Interact with source languages --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file 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

View File

@ -1,135 +0,0 @@
//===-- llvm/Metadata.h - Constant class subclass definitions ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// @file
/// This file contains the declarations for the subclasses of Constant,
/// which represent the different flavors of constant values that live in LLVM.
/// Note that Constants are immutable (once created they never change) and are
/// fully shared by structural equivalence. This means that two structurally
/// equivalent constants will always have the same address. Constant's are
/// created on demand as needed and never deleted: thus clients don't have to
/// worry about the lifetime of the objects.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_MDNODE_H
#define LLVM_MDNODE_H
#include "llvm/Constant.h"
#include "llvm/Type.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ValueHandle.h"
namespace llvm {
//===----------------------------------------------------------------------===//
/// MDNode - a tuple of other values.
/// These contain a list of the Constants that represent the metadata. The
/// operand list is always empty, query the element list instead.
///
/// This class will attempt to keep track of values as they are modified. When
/// a value is replaced the element will be replaced with it, and when the
/// value is deleted the element is set to a null pointer. In order to preserve
/// structural equivalence while the elements mutate, the MDNode may call
/// replaceAllUsesWith on itself. Because of this, users of MDNode must use a
/// WeakVH or CallbackVH to hold the node pointer if there is a chance that one
/// of the elements held by the node may change.
///
class MDNode : public Constant, public FoldingSetNode {
MDNode(const MDNode &); // DO NOT IMPLEMENT
friend class ElementVH;
struct ElementVH : public CallbackVH {
MDNode *OwningNode;
ElementVH(Value *V, MDNode *Parent)
: CallbackVH(V), OwningNode(Parent) {}
~ElementVH() {}
/// deleted - Set this entry in the MDNode to 'null'. This will reallocate
/// the MDNode.
virtual void deleted() {
OwningNode->replaceElement(this->operator Value*(), 0);
}
/// allUsesReplacedWith - Modify the MDNode by replacing this entry with
/// new_value. This will reallocate the MDNode.
virtual void allUsesReplacedWith(Value *new_value) {
OwningNode->replaceElement(this->operator Value*(), new_value);
}
};
void replaceElement(Value *From, Value *To);
SmallVector<ElementVH, 4> Node;
typedef SmallVectorImpl<ElementVH>::iterator elem_iterator;
protected:
explicit MDNode(Value*const* Vals, unsigned NumVals);
public:
typedef SmallVectorImpl<ElementVH>::const_iterator const_elem_iterator;
/// get() - Static factory methods - Return objects of the specified value.
///
static MDNode *get(Value*const* Vals, unsigned NumVals);
Value *getElement(unsigned i) const {
return Node[i];
}
unsigned getNumElements() const {
return Node.size();
}
bool elem_empty() const {
return Node.empty();
}
const_elem_iterator elem_begin() const {
return Node.begin();
}
const_elem_iterator elem_end() const {
return Node.end();
}
/// getType() specialization - Type is always MetadataTy.
///
inline const Type *getType() const {
return Type::MetadataTy;
}
/// isNullValue - Return true if this is the value that would be returned by
/// getNullValue. This always returns false because getNullValue will never
/// produce metadata.
virtual bool isNullValue() const {
return false;
}
/// Profile - calculate a unique identifier for this MDNode to collapse
/// duplicates
void Profile(FoldingSetNodeID &ID) const;
virtual void destroyConstant();
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
assert(0 && "This should never be called because MDNodes have no ops");
abort();
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const MDNode *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == MDNodeVal;
}
};
} // end llvm namespace
#endif

View File

@ -1,216 +0,0 @@
//===-- llvm/Support/Annotation.h - Annotation classes ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations for two classes: Annotation & Annotable.
// Using these two simple classes, anything that derives from Annotable can have
// Annotation subclasses attached to them, ready for easy retrieval.
//
// Annotations are designed to be easily attachable to various classes.
//
// The AnnotationManager class is essential for using these classes. It is
// responsible for turning Annotation name strings into tokens [unique id #'s]
// that may be used to search for and create annotations.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_ANNOTATION_H
#define LLVM_SUPPORT_ANNOTATION_H
#include <cassert>
namespace llvm {
class AnnotationID;
class Annotation;
class Annotable;
struct AnnotationManager;
//===----------------------------------------------------------------------===//
//
// AnnotationID - This class is a thin wrapper around an unsigned integer that
// is used to hopefully prevent errors using AnnotationID's. They may be copied
// freely around and passed byvalue with little or no overhead.
//
class AnnotationID {
friend struct AnnotationManager;
unsigned ID;
AnnotationID(); // Default ctor is disabled
// AnnotationID is only creatable from AnnMgr.
explicit inline AnnotationID(unsigned i) : ID(i) {}
public:
inline AnnotationID(const AnnotationID &A) : ID(A.ID) {}
inline bool operator==(const AnnotationID &A) const {
return A.ID == ID;
}
inline bool operator<(const AnnotationID &A) const {
return ID < A.ID;
}
};
//===----------------------------------------------------------------------===//
//
// Annotation Class - This class serves as a base class for any specific
// annotations that you might need. Simply subclass this to add extra
// information to the annotations.
//
class Annotation {
friend class Annotable; // Annotable manipulates Next list
AnnotationID ID; // ID number, as obtained from AnnotationManager
Annotation *Next; // The next annotation in the linked list
public:
explicit inline Annotation(AnnotationID id) : ID(id), Next(0) {}
virtual ~Annotation(); // Designed to be subclassed
// getID - Return the unique ID# of this annotation
inline AnnotationID getID() const { return ID; }
// getNext - Return the next annotation in the list...
inline Annotation *getNext() const { return Next; }
};
//===----------------------------------------------------------------------===//
//
// Annotable - This class is used as a base class for all objects that would
// like to have annotation capability.
//
// Annotable objects keep their annotation list sorted as annotations are
// inserted and deleted. This is used to ensure that annotations with identical
// ID#'s are stored sequentially.
//
class Annotable {
mutable Annotation *AnnotationList;
Annotable(const Annotable &); // Do not implement
void operator=(const Annotable &); // Do not implement
public:
Annotable() : AnnotationList(0) {}
~Annotable();
// getAnnotation - Search the list for annotations of the specified ID. The
// pointer returned is either null (if no annotations of the specified ID
// exist), or it points to the first element of a potentially list of elements
// with identical ID #'s.
//
Annotation *getAnnotation(AnnotationID ID) const {
for (Annotation *A = AnnotationList; A; A = A->getNext())
if (A->getID() == ID) return A;
return 0;
}
// getOrCreateAnnotation - Search through the annotation list, if there is
// no annotation with the specified ID, then use the AnnotationManager to
// create one.
//
inline Annotation *getOrCreateAnnotation(AnnotationID ID) const;
// addAnnotation - Insert the annotation into the list in a sorted location.
//
void addAnnotation(Annotation *A) const {
assert(A->Next == 0 && "Annotation already in list?!?");
Annotation **AL = &AnnotationList;
while (*AL && (*AL)->ID < A->getID()) // Find where to insert annotation
AL = &((*AL)->Next);
A->Next = *AL; // Link the annotation in
*AL = A;
}
// unlinkAnnotation - Remove the first annotation of the specified ID... and
// then return the unlinked annotation. The annotation object is not deleted.
//
inline Annotation *unlinkAnnotation(AnnotationID ID) const {
for (Annotation **A = &AnnotationList; *A; A = &((*A)->Next))
if ((*A)->getID() == ID) {
Annotation *Ret = *A;
*A = Ret->Next;
Ret->Next = 0;
return Ret;
}
return 0;
}
// deleteAnnotation - Delete the first annotation of the specified ID in the
// list. Unlink unlinkAnnotation, this actually deletes the annotation object
//
bool deleteAnnotation(AnnotationID ID) const {
Annotation *A = unlinkAnnotation(ID);
delete A;
return A != 0;
}
};
//===----------------------------------------------------------------------===//
//
// AnnotationManager - This class is primarily responsible for maintaining a
// one-to-one mapping between string Annotation names and Annotation ID numbers.
//
// Compared to the rest of the Annotation system, these mapping methods are
// relatively slow, so they should be avoided by locally caching Annotation
// ID #'s. These methods are safe to call at any time, even by static ctors, so
// they should be used by static ctors most of the time.
//
// This class also provides support for annotations that are created on demand
// by the Annotable::getOrCreateAnnotation method. To get this to work, simply
// register an annotation handler
//
struct AnnotationManager {
typedef Annotation *(*Factory)(AnnotationID, const Annotable *, void*);
//===--------------------------------------------------------------------===//
// Basic ID <-> Name map functionality
static AnnotationID getID(const char *Name); // Name -> ID
static const char *getName(AnnotationID ID); // ID -> Name
// getID - Name -> ID + registration of a factory function for demand driven
// annotation support.
static AnnotationID getID(const char *Name, Factory Fact, void *Data = 0);
//===--------------------------------------------------------------------===//
// Annotation creation on demand support...
// registerAnnotationFactory - This method is used to register a callback
// function used to create an annotation on demand if it is needed by the
// Annotable::getOrCreateAnnotation method.
//
static void registerAnnotationFactory(AnnotationID ID, Factory Func,
void *ExtraData = 0);
// createAnnotation - Create an annotation of the specified ID for the
// specified object, using a register annotation creation function.
//
static Annotation *createAnnotation(AnnotationID ID, const Annotable *Obj);
};
// getOrCreateAnnotation - Search through the annotation list, if there is
// no annotation with the specified ID, then use the AnnotationManager to
// create one.
//
inline Annotation *Annotable::getOrCreateAnnotation(AnnotationID ID) const {
Annotation *A = getAnnotation(ID); // Fast path, check for preexisting ann
if (A) return A;
// No annotation found, ask the annotation manager to create an annotation...
A = AnnotationManager::createAnnotation(ID, this);
assert(A && "AnnotationManager could not create annotation!");
addAnnotation(A);
return A;
}
} // End namespace llvm
#endif

View File

@ -1,91 +0,0 @@
//===- llvm/Support/Streams.h - Wrappers for iostreams ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a wrapper for the STL I/O streams. It prevents the need
// to include <iostream> in a file just to get I/O.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_STREAMS_H
#define LLVM_SUPPORT_STREAMS_H
#include <iosfwd>
namespace llvm {
/// FlushStream - Function called by BaseStream to flush an ostream.
void FlushStream(std::ostream &S);
/// BaseStream - Acts like the STL streams. It's a wrapper for the std::cerr,
/// std::cout, std::cin, etc. streams. However, it doesn't require #including
/// @verbatim <iostream> @endverbatm in every file (doing so increases static
/// c'tors & d'tors in the object code).
///
template <typename StreamTy>
class BaseStream {
StreamTy *Stream;
public:
BaseStream() : Stream(0) {}
BaseStream(StreamTy &S) : Stream(&S) {}
BaseStream(StreamTy *S) : Stream(S) {}
StreamTy *stream() const { return Stream; }
inline BaseStream &operator << (std::ios_base &(*Func)(std::ios_base&)) {
if (Stream) *Stream << Func;
return *this;
}
inline BaseStream &operator << (StreamTy &(*Func)(StreamTy&)) {
if (Stream) *Stream << Func;
return *this;
}
void flush() {
if (Stream)
FlushStream(*Stream);
}
template <typename Ty>
BaseStream &operator << (const Ty &Thing) {
if (Stream) *Stream << Thing;
return *this;
}
template <typename Ty>
BaseStream &operator >> (Ty &Thing) {
if (Stream) *Stream >> Thing;
return *this;
}
template <typename Ty>
BaseStream &write(const Ty &A, unsigned N) {
if (Stream) Stream->write(A, N);
return *this;
}
operator StreamTy* () { return Stream; }
bool operator == (const StreamTy &S) { return &S == Stream; }
bool operator != (const StreamTy &S) { return !(*this == S); }
bool operator == (const BaseStream &S) { return S.Stream == Stream; }
bool operator != (const BaseStream &S) { return !(*this == S); }
};
typedef BaseStream<std::ostream> OStream;
typedef BaseStream<std::istream> IStream;
typedef BaseStream<std::stringstream> StringStream;
extern OStream cout;
extern OStream cerr;
extern IStream cin;
} // End llvm namespace
#endif

View File

@ -1,50 +0,0 @@
//===---- DarwinTargetAsmInfo.h - Darwin asm properties ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target asm properties related what form asm statements
// should take in general on Darwin-based targets
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DARWIN_TARGET_ASM_INFO_H
#define LLVM_DARWIN_TARGET_ASM_INFO_H
#include "llvm/Target/TargetAsmInfo.h"
namespace llvm {
class GlobalValue;
class GlobalVariable;
class Type;
class Mangler;
struct DarwinTargetAsmInfo : public TargetAsmInfo {
const Section* TextCoalSection;
const Section* ConstTextCoalSection;
const Section* ConstDataCoalSection;
const Section* ConstDataSection;
const Section* DataCoalSection;
const Section* FourByteConstantSection;
const Section* EightByteConstantSection;
const Section* SixteenByteConstantSection;
explicit DarwinTargetAsmInfo(const TargetMachine &TM);
virtual const Section* SelectSectionForGlobal(const GlobalValue *GV) const;
virtual std::string UniqueSectionForGlobal(const GlobalValue* GV,
SectionKind::Kind kind) const;
virtual bool emitUsedDirectiveFor(const GlobalValue *GV,
Mangler *Mang) const;
const Section* MergeableConstSection(const GlobalVariable *GV) const;
const Section* MergeableConstSection(const Type *Ty) const;
const Section* MergeableStringSection(const GlobalVariable *GV) const;
const Section* SelectSectionForMachineConst(const Type *Ty) const;
};
}
#endif // LLVM_DARWIN_TARGET_ASM_INFO_H

View File

@ -1,45 +0,0 @@
//===---- ELFTargetAsmInfo.h - ELF asm properties ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target asm properties related what form asm statements
// should take in general on ELF-based targets
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ELF_TARGET_ASM_INFO_H
#define LLVM_ELF_TARGET_ASM_INFO_H
#include "llvm/Target/TargetAsmInfo.h"
namespace llvm {
class GlobalValue;
class GlobalVariable;
class Type;
struct ELFTargetAsmInfo: public TargetAsmInfo {
explicit ELFTargetAsmInfo(const TargetMachine &TM);
SectionKind::Kind SectionKindForGlobal(const GlobalValue *GV) const;
virtual const Section* SelectSectionForGlobal(const GlobalValue *GV) const;
virtual std::string printSectionFlags(unsigned flags) const;
const Section* MergeableConstSection(const GlobalVariable *GV) const;
inline const Section* MergeableConstSection(const Type *Ty) const;
const Section* MergeableStringSection(const GlobalVariable *GV) const;
virtual const Section*
SelectSectionForMachineConst(const Type *Ty) const;
const Section* DataRelSection;
const Section* DataRelLocalSection;
const Section* DataRelROSection;
const Section* DataRelROLocalSection;
};
}
#endif // LLVM_ELF_TARGET_ASM_INFO_H

View File

@ -1,930 +0,0 @@
//===-- llvm/Target/TargetAsmInfo.h - Asm info ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a class to be used as the basis for target specific
// asm writers. This class primarily takes care of global printing constants,
// which are used in very similar ways across all targets.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TARGET_ASM_INFO_H
#define LLVM_TARGET_ASM_INFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/DataTypes.h"
#include <string>
namespace llvm {
// DWARF encoding query type
namespace DwarfEncoding {
enum Target {
Data = 0,
CodeLabels = 1,
Functions = 2
};
}
namespace SectionKind {
enum Kind {
Unknown = 0, ///< Custom section
Text, ///< Text section
Data, ///< Data section
DataRel, ///< Contains data that has relocations
DataRelLocal, ///< Contains data that has only local relocations
BSS, ///< BSS section
ROData, ///< Readonly data section
DataRelRO, ///< Contains data that is otherwise readonly
DataRelROLocal, ///< Contains r/o data with only local relocations
RODataMergeStr, ///< Readonly data section (mergeable strings)
RODataMergeConst, ///< Readonly data section (mergeable constants)
SmallData, ///< Small data section
SmallBSS, ///< Small bss section
SmallROData, ///< Small readonly section
ThreadData, ///< Initialized TLS data objects
ThreadBSS ///< Uninitialized TLS data objects
};
static inline bool isReadOnly(Kind K) {
return (K == SectionKind::ROData ||
K == SectionKind::RODataMergeConst ||
K == SectionKind::RODataMergeStr ||
K == SectionKind::SmallROData);
}
static inline bool isBSS(Kind K) {
return (K == SectionKind::BSS ||
K == SectionKind::SmallBSS);
}
}
namespace SectionFlags {
const unsigned Invalid = -1U;
const unsigned None = 0;
const unsigned Code = 1 << 0; ///< Section contains code
const unsigned Writeable = 1 << 1; ///< Section is writeable
const unsigned BSS = 1 << 2; ///< Section contains only zeroes
const unsigned Mergeable = 1 << 3; ///< Section contains mergeable data
const unsigned Strings = 1 << 4; ///< Section contains C-type strings
const unsigned TLS = 1 << 5; ///< Section contains thread-local data
const unsigned Debug = 1 << 6; ///< Section contains debug data
const unsigned Linkonce = 1 << 7; ///< Section is linkonce
const unsigned Small = 1 << 8; ///< Section is small
const unsigned TypeFlags = 0xFF;
// Some gap for future flags
const unsigned Named = 1 << 23; ///< Section is named
const unsigned EntitySize = 0xFF << 24; ///< Entity size for mergeable stuff
static inline unsigned getEntitySize(unsigned Flags) {
return (Flags >> 24) & 0xFF;
}
static inline unsigned setEntitySize(unsigned Flags, unsigned Size) {
return ((Flags & ~EntitySize) | ((Size & 0xFF) << 24));
}
struct KeyInfo {
static inline unsigned getEmptyKey() { return Invalid; }
static inline unsigned getTombstoneKey() { return Invalid - 1; }
static unsigned getHashValue(const unsigned &Key) { return Key; }
static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; }
static bool isPod() { return true; }
};
typedef DenseMap<unsigned, std::string, KeyInfo> FlagsStringsMapType;
}
class TargetMachine;
class CallInst;
class GlobalValue;
class Type;
class Mangler;
class Section {
friend class TargetAsmInfo;
friend class StringMapEntry<Section>;
friend class StringMap<Section>;
std::string Name;
unsigned Flags;
explicit Section(unsigned F = SectionFlags::Invalid):Flags(F) { }
public:
bool isNamed() const { return Flags & SectionFlags::Named; }
unsigned getEntitySize() const { return (Flags >> 24) & 0xFF; }
const std::string& getName() const { return Name; }
unsigned getFlags() const { return Flags; }
};
/// TargetAsmInfo - This class is intended to be used as a base class for asm
/// properties and features specific to the target.
class TargetAsmInfo {
private:
mutable StringMap<Section> Sections;
mutable SectionFlags::FlagsStringsMapType FlagsStrings;
protected:
/// TM - The current TargetMachine.
const TargetMachine &TM;
//===------------------------------------------------------------------===//
// Properties to be set by the target writer, used to configure asm printer.
//
/// TextSection - Section directive for standard text.
///
const Section *TextSection; // Defaults to ".text".
/// DataSection - Section directive for standard data.
///
const Section *DataSection; // Defaults to ".data".
/// BSSSection - Section directive for uninitialized data. Null if this
/// target doesn't support a BSS section.
///
const char *BSSSection; // Default to ".bss".
const Section *BSSSection_;
/// ReadOnlySection - This is the directive that is emitted to switch to a
/// read-only section for constant data (e.g. data declared const,
/// jump tables).
const Section *ReadOnlySection; // Defaults to NULL
/// SmallDataSection - This is the directive that is emitted to switch to a
/// small data section.
///
const Section *SmallDataSection; // Defaults to NULL
/// SmallBSSSection - This is the directive that is emitted to switch to a
/// small bss section.
///
const Section *SmallBSSSection; // Defaults to NULL
/// SmallRODataSection - This is the directive that is emitted to switch to
/// a small read-only data section.
///
const Section *SmallRODataSection; // Defaults to NULL
/// TLSDataSection - Section directive for Thread Local data.
///
const Section *TLSDataSection; // Defaults to ".tdata".
/// TLSBSSSection - Section directive for Thread Local uninitialized data.
/// Null if this target doesn't support a BSS section.
///
const Section *TLSBSSSection; // Defaults to ".tbss".
/// ZeroFillDirective - Directive for emitting a global to the ZeroFill
/// section on this target. Null if this target doesn't support zerofill.
const char *ZeroFillDirective; // Default is null.
/// NonexecutableStackDirective - Directive for declaring to the
/// linker and beyond that the emitted code does not require stack
/// memory to be executable.
const char *NonexecutableStackDirective; // Default is null.
/// NeedsSet - True if target asm treats expressions in data directives
/// as linktime-relocatable. For assembly-time computation, we need to
/// use a .set. Thus:
/// .set w, x-y
/// .long w
/// is computed at assembly time, while
/// .long x-y
/// is relocated if the relative locations of x and y change at linktime.
/// We want both these things in different places.
bool NeedsSet; // Defaults to false.
/// MaxInstLength - This is the maximum possible length of an instruction,
/// which is needed to compute the size of an inline asm.
unsigned MaxInstLength; // Defaults to 4.
/// PCSymbol - The symbol used to represent the current PC. Used in PC
/// relative expressions.
const char *PCSymbol; // Defaults to "$".
/// SeparatorChar - This character, if specified, is used to separate
/// instructions from each other when on the same line. This is used to
/// measure inline asm instructions.
char SeparatorChar; // Defaults to ';'
/// CommentString - This indicates the comment character used by the
/// assembler.
const char *CommentString; // Defaults to "#"
/// GlobalPrefix - If this is set to a non-empty string, it is prepended
/// onto all global symbols. This is often used for "_" or ".".
const char *GlobalPrefix; // Defaults to ""
/// PrivateGlobalPrefix - This prefix is used for globals like constant
/// pool entries that are completely private to the .s file and should not
/// have names in the .o file. This is often "." or "L".
const char *PrivateGlobalPrefix; // Defaults to "."
/// LessPrivateGlobalPrefix - This prefix is used for symbols that should
/// be passed through the assembler but be removed by the linker. This
/// is "l" on Darwin, currently used for some ObjC metadata.
const char *LessPrivateGlobalPrefix; // Defaults to ""
/// JumpTableSpecialLabelPrefix - If not null, a extra (dead) label is
/// emitted before jump tables with the specified prefix.
const char *JumpTableSpecialLabelPrefix; // Default to null.
/// GlobalVarAddrPrefix/Suffix - If these are nonempty, these strings
/// will enclose any GlobalVariable (that isn't a function)
///
const char *GlobalVarAddrPrefix; // Defaults to ""
const char *GlobalVarAddrSuffix; // Defaults to ""
/// FunctionAddrPrefix/Suffix - If these are nonempty, these strings
/// will enclose any GlobalVariable that points to a function.
/// For example, this is used by the IA64 backend to materialize
/// function descriptors, by decorating the ".data8" object with the
/// @verbatim @fptr( ) @endverbatim
/// link-relocation operator.
///
const char *FunctionAddrPrefix; // Defaults to ""
const char *FunctionAddrSuffix; // Defaults to ""
/// PersonalityPrefix/Suffix - If these are nonempty, these strings will
/// enclose any personality function in the common frame section.
///
const char *PersonalityPrefix; // Defaults to ""
const char *PersonalitySuffix; // Defaults to ""
/// NeedsIndirectEncoding - If set, we need to set the indirect encoding bit
/// for EH in Dwarf.
///
bool NeedsIndirectEncoding; // Defaults to false
/// InlineAsmStart/End - If these are nonempty, they contain a directive to
/// emit before and after an inline assembly statement.
const char *InlineAsmStart; // Defaults to "#APP\n"
const char *InlineAsmEnd; // Defaults to "#NO_APP\n"
/// AssemblerDialect - Which dialect of an assembler variant to use.
unsigned AssemblerDialect; // Defaults to 0
/// StringConstantPrefix - Prefix for FEs to use when generating unnamed
/// constant strings. These names get run through the Mangler later; if
/// you want the Mangler not to add the GlobalPrefix as well,
/// use '\1' as the first character.
const char *StringConstantPrefix; // Defaults to ".str"
/// AllowQuotesInName - This is true if the assembler allows for complex
/// symbol names to be surrounded in quotes. This defaults to false.
bool AllowQuotesInName;
//===--- Data Emission Directives -------------------------------------===//
/// ZeroDirective - this should be set to the directive used to get some
/// number of zero bytes emitted to the current section. Common cases are
/// "\t.zero\t" and "\t.space\t". If this is set to null, the
/// Data*bitsDirective's will be used to emit zero bytes.
const char *ZeroDirective; // Defaults to "\t.zero\t"
const char *ZeroDirectiveSuffix; // Defaults to ""
/// AsciiDirective - This directive allows emission of an ascii string with
/// the standard C escape characters embedded into it.
const char *AsciiDirective; // Defaults to "\t.ascii\t"
/// AscizDirective - If not null, this allows for special handling of
/// zero terminated strings on this target. This is commonly supported as
/// ".asciz". If a target doesn't support this, it can be set to null.
const char *AscizDirective; // Defaults to "\t.asciz\t"
/// DataDirectives - These directives are used to output some unit of
/// integer data to the current section. If a data directive is set to
/// null, smaller data directives will be used to emit the large sizes.
const char *Data8bitsDirective; // Defaults to "\t.byte\t"
const char *Data16bitsDirective; // Defaults to "\t.short\t"
const char *Data32bitsDirective; // Defaults to "\t.long\t"
const char *Data64bitsDirective; // Defaults to "\t.quad\t"
/// getASDirective - Targets can override it to provide different data
/// directives for various sizes and non-default address spaces.
virtual const char *getASDirective(unsigned size,
unsigned AS) const {
assert(AS > 0 && "Dont know the directives for default addr space");
return NULL;
}
//===--- Alignment Information ----------------------------------------===//
/// AlignDirective - The directive used to emit round up to an alignment
/// boundary.
///
const char *AlignDirective; // Defaults to "\t.align\t"
/// AlignmentIsInBytes - If this is true (the default) then the asmprinter
/// emits ".align N" directives, where N is the number of bytes to align to.
/// Otherwise, it emits ".align log2(N)", e.g. 3 to align to an 8 byte
/// boundary.
bool AlignmentIsInBytes; // Defaults to true
/// TextAlignFillValue - If non-zero, this is used to fill the executable
/// space created as the result of a alignment directive.
unsigned TextAlignFillValue;
//===--- Section Switching Directives ---------------------------------===//
/// SwitchToSectionDirective - This is the directive used when we want to
/// emit a global to an arbitrary section. The section name is emited after
/// this.
const char *SwitchToSectionDirective; // Defaults to "\t.section\t"
/// TextSectionStartSuffix - This is printed after each start of section
/// directive for text sections.
const char *TextSectionStartSuffix; // Defaults to "".
/// DataSectionStartSuffix - This is printed after each start of section
/// directive for data sections.
const char *DataSectionStartSuffix; // Defaults to "".
/// SectionEndDirectiveSuffix - If non-null, the asm printer will close each
/// section with the section name and this suffix printed.
const char *SectionEndDirectiveSuffix;// Defaults to null.
/// ConstantPoolSection - This is the section that we SwitchToSection right
/// before emitting the constant pool for a function.
const char *ConstantPoolSection; // Defaults to "\t.section .rodata"
/// JumpTableDataSection - This is the section that we SwitchToSection right
/// before emitting the jump tables for a function when the relocation model
/// is not PIC.
const char *JumpTableDataSection; // Defaults to "\t.section .rodata"
/// JumpTableDirective - if non-null, the directive to emit before a jump
/// table.
const char *JumpTableDirective;
/// CStringSection - If not null, this allows for special handling of
/// cstring constants (null terminated string that does not contain any
/// other null bytes) on this target. This is commonly supported as
/// ".cstring".
const char *CStringSection; // Defaults to NULL
const Section *CStringSection_;
/// StaticCtorsSection - This is the directive that is emitted to switch to
/// a section to emit the static constructor list.
/// Defaults to "\t.section .ctors,\"aw\",@progbits".
const char *StaticCtorsSection;
/// StaticDtorsSection - This is the directive that is emitted to switch to
/// a section to emit the static destructor list.
/// Defaults to "\t.section .dtors,\"aw\",@progbits".
const char *StaticDtorsSection;
//===--- Global Variable Emission Directives --------------------------===//
/// GlobalDirective - This is the directive used to declare a global entity.
///
const char *GlobalDirective; // Defaults to NULL.
/// ExternDirective - This is the directive used to declare external
/// globals.
///
const char *ExternDirective; // Defaults to NULL.
/// SetDirective - This is the name of a directive that can be used to tell
/// the assembler to set the value of a variable to some expression.
const char *SetDirective; // Defaults to null.
/// LCOMMDirective - This is the name of a directive (if supported) that can
/// be used to efficiently declare a local (internal) block of zero
/// initialized data in the .bss/.data section. The syntax expected is:
/// @verbatim <LCOMMDirective> SYMBOLNAME LENGTHINBYTES, ALIGNMENT
/// @endverbatim
const char *LCOMMDirective; // Defaults to null.
const char *COMMDirective; // Defaults to "\t.comm\t".
/// COMMDirectiveTakesAlignment - True if COMMDirective take a third
/// argument that specifies the alignment of the declaration.
bool COMMDirectiveTakesAlignment; // Defaults to true.
/// HasDotTypeDotSizeDirective - True if the target has .type and .size
/// directives, this is true for most ELF targets.
bool HasDotTypeDotSizeDirective; // Defaults to true.
/// HasSingleParameterDotFile - True if the target has a single parameter
/// .file directive, this is true for ELF targets.
bool HasSingleParameterDotFile; // Defaults to true.
/// UsedDirective - This directive, if non-null, is used to declare a global
/// as being used somehow that the assembler can't see. This prevents dead
/// code elimination on some targets.
const char *UsedDirective; // Defaults to null.
/// WeakRefDirective - This directive, if non-null, is used to declare a
/// global as being a weak undefined symbol.
const char *WeakRefDirective; // Defaults to null.
/// WeakDefDirective - This directive, if non-null, is used to declare a
/// global as being a weak defined symbol.
const char *WeakDefDirective; // Defaults to null.
/// HiddenDirective - This directive, if non-null, is used to declare a
/// global or function as having hidden visibility.
const char *HiddenDirective; // Defaults to "\t.hidden\t".
/// ProtectedDirective - This directive, if non-null, is used to declare a
/// global or function as having protected visibility.
const char *ProtectedDirective; // Defaults to "\t.protected\t".
//===--- Dwarf Emission Directives -----------------------------------===//
/// AbsoluteDebugSectionOffsets - True if we should emit abolute section
/// offsets for debug information. Defaults to false.
bool AbsoluteDebugSectionOffsets;
/// AbsoluteEHSectionOffsets - True if we should emit abolute section
/// offsets for EH information. Defaults to false.
bool AbsoluteEHSectionOffsets;
/// HasLEB128 - True if target asm supports leb128 directives.
///
bool HasLEB128; // Defaults to false.
/// hasDotLocAndDotFile - True if target asm supports .loc and .file
/// directives for emitting debugging information.
///
bool HasDotLocAndDotFile; // Defaults to false.
/// SupportsDebugInformation - True if target supports emission of debugging
/// information.
bool SupportsDebugInformation;
/// SupportsExceptionHandling - True if target supports
/// exception handling.
///
bool SupportsExceptionHandling; // Defaults to false.
/// RequiresFrameSection - true if the Dwarf2 output needs a frame section
///
bool DwarfRequiresFrameSection; // Defaults to true.
/// DwarfUsesInlineInfoSection - True if DwarfDebugInlineSection is used to
/// encode inline subroutine information.
bool DwarfUsesInlineInfoSection; // Defaults to false.
/// NonLocalEHFrameLabel - If set, the EH_frame label needs to be non-local.
///
bool NonLocalEHFrameLabel; // Defaults to false.
/// GlobalEHDirective - This is the directive used to make exception frame
/// tables globally visible.
///
const char *GlobalEHDirective; // Defaults to NULL.
/// SupportsWeakEmptyEHFrame - True if target assembler and linker will
/// handle a weak_definition of constant 0 for an omitted EH frame.
bool SupportsWeakOmittedEHFrame; // Defaults to true.
/// DwarfSectionOffsetDirective - Special section offset directive.
const char* DwarfSectionOffsetDirective; // Defaults to NULL
/// DwarfAbbrevSection - Section directive for Dwarf abbrev.
///
const char *DwarfAbbrevSection; // Defaults to ".debug_abbrev".
/// DwarfInfoSection - Section directive for Dwarf info.
///
const char *DwarfInfoSection; // Defaults to ".debug_info".
/// DwarfLineSection - Section directive for Dwarf info.
///
const char *DwarfLineSection; // Defaults to ".debug_line".
/// DwarfFrameSection - Section directive for Dwarf info.
///
const char *DwarfFrameSection; // Defaults to ".debug_frame".
/// DwarfPubNamesSection - Section directive for Dwarf info.
///
const char *DwarfPubNamesSection; // Defaults to ".debug_pubnames".
/// DwarfPubTypesSection - Section directive for Dwarf info.
///
const char *DwarfPubTypesSection; // Defaults to ".debug_pubtypes".
/// DwarfDebugInlineSection - Section directive for inline info.
///
const char *DwarfDebugInlineSection; // Defaults to ".debug_inlined"
/// DwarfStrSection - Section directive for Dwarf info.
///
const char *DwarfStrSection; // Defaults to ".debug_str".
/// DwarfLocSection - Section directive for Dwarf info.
///
const char *DwarfLocSection; // Defaults to ".debug_loc".
/// DwarfARangesSection - Section directive for Dwarf info.
///
const char *DwarfARangesSection; // Defaults to ".debug_aranges".
/// DwarfRangesSection - Section directive for Dwarf info.
///
const char *DwarfRangesSection; // Defaults to ".debug_ranges".
/// DwarfMacroInfoSection - Section directive for DWARF macro info.
///
const char *DwarfMacroInfoSection; // Defaults to ".debug_macinfo".
/// DwarfEHFrameSection - Section directive for Exception frames.
///
const char *DwarfEHFrameSection; // Defaults to ".eh_frame".
/// DwarfExceptionSection - Section directive for Exception table.
///
const char *DwarfExceptionSection; // Defaults to ".gcc_except_table".
//===--- CBE Asm Translation Table -----------------------------------===//
const char *const *AsmTransCBE; // Defaults to empty
public:
explicit TargetAsmInfo(const TargetMachine &TM);
virtual ~TargetAsmInfo();
const Section* getNamedSection(const char *Name,
unsigned Flags = SectionFlags::None,
bool Override = false) const;
const Section* getUnnamedSection(const char *Directive,
unsigned Flags = SectionFlags::None,
bool Override = false) const;
/// Measure the specified inline asm to determine an approximation of its
/// length.
virtual unsigned getInlineAsmLength(const char *Str) const;
/// ExpandInlineAsm - This hook allows the target to expand an inline asm
/// call to be explicit llvm code if it wants to. This is useful for
/// turning simple inline asms into LLVM intrinsics, which gives the
/// compiler more information about the behavior of the code.
virtual bool ExpandInlineAsm(CallInst *CI) const {
return false;
}
/// emitUsedDirectiveFor - This hook allows targets to selectively decide
/// not to emit the UsedDirective for some symbols in llvm.used.
virtual bool emitUsedDirectiveFor(const GlobalValue *GV,
Mangler *Mang) const {
return (GV!=0);
}
/// PreferredEHDataFormat - This hook allows the target to select data
/// format used for encoding pointers in exception handling data. Reason is
/// 0 for data, 1 for code labels, 2 for function pointers. Global is true
/// if the symbol can be relocated.
virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const;
/// SectionKindForGlobal - This hook allows the target to select proper
/// section kind used for global emission.
virtual SectionKind::Kind
SectionKindForGlobal(const GlobalValue *GV) const;
/// RelocBehaviour - Describes how relocations should be treated when
/// selecting sections. Reloc::Global bit should be set if global
/// relocations should force object to be placed in read-write
/// sections. Reloc::Local bit should be set if local relocations should
/// force object to be placed in read-write sections.
virtual unsigned RelocBehaviour() const;
/// SectionFlagsForGlobal - This hook allows the target to select proper
/// section flags either for given global or for section.
virtual unsigned
SectionFlagsForGlobal(const GlobalValue *GV = NULL,
const char* name = NULL) const;
/// SectionForGlobal - This hooks returns proper section name for given
/// global with all necessary flags and marks.
virtual const Section* SectionForGlobal(const GlobalValue *GV) const;
// Helper methods for SectionForGlobal
virtual std::string UniqueSectionForGlobal(const GlobalValue* GV,
SectionKind::Kind kind) const;
const std::string& getSectionFlags(unsigned Flags) const;
virtual std::string printSectionFlags(unsigned flags) const { return ""; }
virtual const Section* SelectSectionForGlobal(const GlobalValue *GV) const;
virtual const Section* SelectSectionForMachineConst(const Type *Ty) const;
/// getSLEB128Size - Compute the number of bytes required for a signed
/// leb128 value.
static unsigned getSLEB128Size(int Value);
/// getULEB128Size - Compute the number of bytes required for an unsigned
/// leb128 value.
static unsigned getULEB128Size(unsigned Value);
// Data directive accessors
//
const char *getData8bitsDirective(unsigned AS = 0) const {
return AS == 0 ? Data8bitsDirective : getASDirective(8, AS);
}
const char *getData16bitsDirective(unsigned AS = 0) const {
return AS == 0 ? Data16bitsDirective : getASDirective(16, AS);
}
const char *getData32bitsDirective(unsigned AS = 0) const {
return AS == 0 ? Data32bitsDirective : getASDirective(32, AS);
}
const char *getData64bitsDirective(unsigned AS = 0) const {
return AS == 0 ? Data64bitsDirective : getASDirective(64, AS);
}
// Accessors.
//
const Section *getTextSection() const {
return TextSection;
}
const Section *getDataSection() const {
return DataSection;
}
const char *getBSSSection() const {
return BSSSection;
}
const Section *getBSSSection_() const {
return BSSSection_;
}
const Section *getReadOnlySection() const {
return ReadOnlySection;
}
const Section *getSmallDataSection() const {
return SmallDataSection;
}
const Section *getSmallBSSSection() const {
return SmallBSSSection;
}
const Section *getSmallRODataSection() const {
return SmallRODataSection;
}
const Section *getTLSDataSection() const {
return TLSDataSection;
}
const Section *getTLSBSSSection() const {
return TLSBSSSection;
}
const char *getZeroFillDirective() const {
return ZeroFillDirective;
}
const char *getNonexecutableStackDirective() const {
return NonexecutableStackDirective;
}
bool needsSet() const {
return NeedsSet;
}
const char *getPCSymbol() const {
return PCSymbol;
}
char getSeparatorChar() const {
return SeparatorChar;
}
const char *getCommentString() const {
return CommentString;
}
const char *getGlobalPrefix() const {
return GlobalPrefix;
}
const char *getPrivateGlobalPrefix() const {
return PrivateGlobalPrefix;
}
/// EHGlobalPrefix - Prefix for EH_frame and the .eh symbols.
/// This is normally PrivateGlobalPrefix, but some targets want
/// these symbols to be visible.
virtual const char *getEHGlobalPrefix() const {
return PrivateGlobalPrefix;
}
const char *getLessPrivateGlobalPrefix() const {
return LessPrivateGlobalPrefix;
}
const char *getJumpTableSpecialLabelPrefix() const {
return JumpTableSpecialLabelPrefix;
}
const char *getGlobalVarAddrPrefix() const {
return GlobalVarAddrPrefix;
}
const char *getGlobalVarAddrSuffix() const {
return GlobalVarAddrSuffix;
}
const char *getFunctionAddrPrefix() const {
return FunctionAddrPrefix;
}
const char *getFunctionAddrSuffix() const {
return FunctionAddrSuffix;
}
const char *getPersonalityPrefix() const {
return PersonalityPrefix;
}
const char *getPersonalitySuffix() const {
return PersonalitySuffix;
}
bool getNeedsIndirectEncoding() const {
return NeedsIndirectEncoding;
}
const char *getInlineAsmStart() const {
return InlineAsmStart;
}
const char *getInlineAsmEnd() const {
return InlineAsmEnd;
}
unsigned getAssemblerDialect() const {
return AssemblerDialect;
}
const char *getStringConstantPrefix() const {
return StringConstantPrefix;
}
bool doesAllowQuotesInName() const {
return AllowQuotesInName;
}
const char *getZeroDirective() const {
return ZeroDirective;
}
const char *getZeroDirectiveSuffix() const {
return ZeroDirectiveSuffix;
}
const char *getAsciiDirective() const {
return AsciiDirective;
}
const char *getAscizDirective() const {
return AscizDirective;
}
const char *getJumpTableDirective() const {
return JumpTableDirective;
}
const char *getAlignDirective() const {
return AlignDirective;
}
bool getAlignmentIsInBytes() const {
return AlignmentIsInBytes;
}
unsigned getTextAlignFillValue() const {
return TextAlignFillValue;
}
const char *getSwitchToSectionDirective() const {
return SwitchToSectionDirective;
}
const char *getTextSectionStartSuffix() const {
return TextSectionStartSuffix;
}
const char *getDataSectionStartSuffix() const {
return DataSectionStartSuffix;
}
const char *getSectionEndDirectiveSuffix() const {
return SectionEndDirectiveSuffix;
}
const char *getConstantPoolSection() const {
return ConstantPoolSection;
}
const char *getJumpTableDataSection() const {
return JumpTableDataSection;
}
const char *getCStringSection() const {
return CStringSection;
}
const Section *getCStringSection_() const {
return CStringSection_;
}
const char *getStaticCtorsSection() const {
return StaticCtorsSection;
}
const char *getStaticDtorsSection() const {
return StaticDtorsSection;
}
const char *getGlobalDirective() const {
return GlobalDirective;
}
const char *getExternDirective() const {
return ExternDirective;
}
const char *getSetDirective() const {
return SetDirective;
}
const char *getLCOMMDirective() const {
return LCOMMDirective;
}
const char *getCOMMDirective() const {
return COMMDirective;
}
bool getCOMMDirectiveTakesAlignment() const {
return COMMDirectiveTakesAlignment;
}
bool hasDotTypeDotSizeDirective() const {
return HasDotTypeDotSizeDirective;
}
bool hasSingleParameterDotFile() const {
return HasSingleParameterDotFile;
}
const char *getUsedDirective() const {
return UsedDirective;
}
const char *getWeakRefDirective() const {
return WeakRefDirective;
}
const char *getWeakDefDirective() const {
return WeakDefDirective;
}
const char *getHiddenDirective() const {
return HiddenDirective;
}
const char *getProtectedDirective() const {
return ProtectedDirective;
}
bool isAbsoluteDebugSectionOffsets() const {
return AbsoluteDebugSectionOffsets;
}
bool isAbsoluteEHSectionOffsets() const {
return AbsoluteEHSectionOffsets;
}
bool hasLEB128() const {
return HasLEB128;
}
bool hasDotLocAndDotFile() const {
return HasDotLocAndDotFile;
}
bool doesSupportDebugInformation() const {
return SupportsDebugInformation;
}
bool doesSupportExceptionHandling() const {
return SupportsExceptionHandling;
}
bool doesDwarfRequireFrameSection() const {
return DwarfRequiresFrameSection;
}
bool doesDwarfUsesInlineInfoSection() const {
return DwarfUsesInlineInfoSection;
}
bool doesRequireNonLocalEHFrameLabel() const {
return NonLocalEHFrameLabel;
}
const char *getGlobalEHDirective() const {
return GlobalEHDirective;
}
bool getSupportsWeakOmittedEHFrame() const {
return SupportsWeakOmittedEHFrame;
}
const char *getDwarfSectionOffsetDirective() const {
return DwarfSectionOffsetDirective;
}
const char *getDwarfAbbrevSection() const {
return DwarfAbbrevSection;
}
const char *getDwarfInfoSection() const {
return DwarfInfoSection;
}
const char *getDwarfLineSection() const {
return DwarfLineSection;
}
const char *getDwarfFrameSection() const {
return DwarfFrameSection;
}
const char *getDwarfPubNamesSection() const {
return DwarfPubNamesSection;
}
const char *getDwarfPubTypesSection() const {
return DwarfPubTypesSection;
}
const char *getDwarfDebugInlineSection() const {
return DwarfDebugInlineSection;
}
const char *getDwarfStrSection() const {
return DwarfStrSection;
}
const char *getDwarfLocSection() const {
return DwarfLocSection;
}
const char *getDwarfARangesSection() const {
return DwarfARangesSection;
}
const char *getDwarfRangesSection() const {
return DwarfRangesSection;
}
const char *getDwarfMacroInfoSection() const {
return DwarfMacroInfoSection;
}
const char *getDwarfEHFrameSection() const {
return DwarfEHFrameSection;
}
const char *getDwarfExceptionSection() const {
return DwarfExceptionSection;
}
const char *const *getAsmCBE() const {
return AsmTransCBE;
}
};
}
#endif

View File

@ -1,97 +0,0 @@
//===-- Target/TargetMachineRegistry.h - Target Registration ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file exposes two classes: the TargetMachineRegistry class, which allows
// tools to inspect all of registered targets, and the RegisterTarget class,
// which TargetMachine implementations should use to register themselves with
// the system.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TARGET_TARGETMACHINEREGISTRY_H
#define LLVM_TARGET_TARGETMACHINEREGISTRY_H
#include "llvm/Module.h"
#include "llvm/Support/Registry.h"
namespace llvm {
class Module;
class TargetMachine;
struct TargetMachineRegistryEntry {
const char *Name;
const char *ShortDesc;
TargetMachine *(*CtorFn)(const Module &, const std::string &);
unsigned (*ModuleMatchQualityFn)(const Module &M);
unsigned (*JITMatchQualityFn)();
public:
TargetMachineRegistryEntry(const char *N, const char *SD,
TargetMachine *(*CF)(const Module &, const std::string &),
unsigned (*MMF)(const Module &M),
unsigned (*JMF)())
: Name(N), ShortDesc(SD), CtorFn(CF), ModuleMatchQualityFn(MMF),
JITMatchQualityFn(JMF) {}
};
template<>
class RegistryTraits<TargetMachine> {
public:
typedef TargetMachineRegistryEntry entry;
static const char *nameof(const entry &Entry) { return Entry.Name; }
static const char *descof(const entry &Entry) { return Entry.ShortDesc; }
};
struct TargetMachineRegistry : public Registry<TargetMachine> {
/// getClosestStaticTargetForModule - Given an LLVM module, pick the best
/// target that is compatible with the module. If no close target can be
/// found, this returns null and sets the Error string to a reason.
static const entry *getClosestStaticTargetForModule(const Module &M,
std::string &Error);
/// getClosestTargetForJIT - Pick the best target that is compatible with
/// the current host. If no close target can be found, this returns null
/// and sets the Error string to a reason.
static const entry *getClosestTargetForJIT(std::string &Error);
};
//===--------------------------------------------------------------------===//
/// RegisterTarget - This class is used to make targets automatically register
/// themselves with the tool they are linked. Targets should define an
/// instance of this and implement the static methods described in the
/// TargetMachine comments.
/// The type 'TargetMachineImpl' should provide a constructor with two
/// parameters:
/// - const Module& M: the module that is being compiled:
/// - const std::string& FS: target-specific string describing target
/// flavour.
template<class TargetMachineImpl>
struct RegisterTarget {
RegisterTarget(const char *Name, const char *ShortDesc)
: Entry(Name, ShortDesc, &Allocator,
&TargetMachineImpl::getModuleMatchQuality,
&TargetMachineImpl::getJITMatchQuality),
Node(Entry)
{}
private:
TargetMachineRegistry::entry Entry;
TargetMachineRegistry::node Node;
static TargetMachine *Allocator(const Module &M, const std::string &FS) {
return new TargetMachineImpl(M, FS);
}
};
}
#endif

View File

@ -1,155 +0,0 @@
//===- InlineCost.cpp - Cost analysis for inliner ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements heuristics for inlining decisions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_UTILS_INLINECOST_H
#define LLVM_TRANSFORMS_UTILS_INLINECOST_H
#include "llvm/ADT/SmallPtrSet.h"
#include <cassert>
#include <climits>
#include <map>
#include <vector>
namespace llvm {
class Value;
class Function;
class CallSite;
/// InlineCost - Represent the cost of inlining a function. This
/// supports special values for functions which should "always" or
/// "never" be inlined. Otherwise, the cost represents a unitless
/// amount; smaller values increase the likelyhood of the function
/// being inlined.
class InlineCost {
enum Kind {
Value,
Always,
Never
};
// This is a do-it-yourself implementation of
// int Cost : 30;
// unsigned Type : 2;
// We used to use bitfields, but they were sometimes miscompiled (PR3822).
enum { TYPE_BITS = 2 };
enum { COST_BITS = unsigned(sizeof(unsigned)) * CHAR_BIT - TYPE_BITS };
unsigned TypedCost; // int Cost : COST_BITS; unsigned Type : TYPE_BITS;
Kind getType() const {
return Kind(TypedCost >> COST_BITS);
}
int getCost() const {
// Sign-extend the bottom COST_BITS bits.
return (int(TypedCost << TYPE_BITS)) >> TYPE_BITS;
}
InlineCost(int C, int T) {
TypedCost = (unsigned(C << TYPE_BITS) >> TYPE_BITS) | (T << COST_BITS);
assert(getCost() == C && "Cost exceeds InlineCost precision");
}
public:
static InlineCost get(int Cost) { return InlineCost(Cost, Value); }
static InlineCost getAlways() { return InlineCost(0, Always); }
static InlineCost getNever() { return InlineCost(0, Never); }
bool isVariable() const { return getType() == Value; }
bool isAlways() const { return getType() == Always; }
bool isNever() const { return getType() == Never; }
/// getValue() - Return a "variable" inline cost's amount. It is
/// an error to call this on an "always" or "never" InlineCost.
int getValue() const {
assert(getType() == Value && "Invalid access of InlineCost");
return getCost();
}
};
/// InlineCostAnalyzer - Cost analyzer used by inliner.
class InlineCostAnalyzer {
struct ArgInfo {
public:
unsigned ConstantWeight;
unsigned AllocaWeight;
ArgInfo(unsigned CWeight, unsigned AWeight)
: ConstantWeight(CWeight), AllocaWeight(AWeight) {}
};
// FunctionInfo - For each function, calculate the size of it in blocks and
// instructions.
struct FunctionInfo {
/// NeverInline - True if this callee should never be inlined into a
/// caller.
bool NeverInline;
/// usesDynamicAlloca - True if this function calls alloca (in the C sense).
bool usesDynamicAlloca;
/// NumInsts, NumBlocks - Keep track of how large each function is, which
/// is used to estimate the code size cost of inlining it.
unsigned NumInsts, NumBlocks;
/// NumVectorInsts - Keep track of how many instructions produce vector
/// values. The inliner is being more aggressive with inlining vector
/// kernels.
unsigned NumVectorInsts;
/// ArgumentWeights - Each formal argument of the function is inspected to
/// see if it is used in any contexts where making it a constant or alloca
/// would reduce the code size. If so, we add some value to the argument
/// entry here.
std::vector<ArgInfo> ArgumentWeights;
FunctionInfo() : NeverInline(false), usesDynamicAlloca(false), NumInsts(0),
NumBlocks(0), NumVectorInsts(0) {}
/// analyzeFunction - Fill in the current structure with information
/// gleaned from the specified function.
void analyzeFunction(Function *F);
/// CountCodeReductionForConstant - Figure out an approximation for how
/// many instructions will be constant folded if the specified value is
/// constant.
unsigned CountCodeReductionForConstant(Value *V);
/// CountCodeReductionForAlloca - Figure out an approximation of how much
/// smaller the function will be if it is inlined into a context where an
/// argument becomes an alloca.
///
unsigned CountCodeReductionForAlloca(Value *V);
};
std::map<const Function *, FunctionInfo> CachedFunctionInfo;
public:
/// getInlineCost - The heuristic used to determine if we should inline the
/// function call or not.
///
InlineCost getInlineCost(CallSite CS,
SmallPtrSet<const Function *, 16> &NeverInline);
/// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a
/// higher threshold to determine if the function call should be inlined.
float getInlineFudgeFactor(CallSite CS);
/// resetCachedFunctionInfo - erase any cached cost info for this function.
void resetCachedCostInfo(Function* Caller) {
CachedFunctionInfo[Caller].NumBlocks = 0;
}
};
}
#endif

View File

@ -1,291 +0,0 @@
//===- LoopVR.cpp - Value Range analysis driven by loop information -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// FIXME: What does this do?
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "loopvr"
#include "llvm/Analysis/LoopVR.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
char LoopVR::ID = 0;
static RegisterPass<LoopVR> X("loopvr", "Loop Value Ranges", false, true);
/// getRange - determine the range for a particular SCEV within a given Loop
ConstantRange LoopVR::getRange(const SCEV* S, Loop *L, ScalarEvolution &SE) {
const SCEV* T = SE.getBackedgeTakenCount(L);
if (isa<SCEVCouldNotCompute>(T))
return ConstantRange(cast<IntegerType>(S->getType())->getBitWidth(), true);
T = SE.getTruncateOrZeroExtend(T, S->getType());
return getRange(S, T, SE);
}
/// getRange - determine the range for a particular SCEV with a given trip count
ConstantRange LoopVR::getRange(const SCEV* S, const SCEV* T, ScalarEvolution &SE){
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S))
return ConstantRange(C->getValue()->getValue());
ConstantRange FullSet(cast<IntegerType>(S->getType())->getBitWidth(), true);
// {x,+,y,+,...z}. We detect overflow by checking the size of the set after
// summing the upper and lower.
if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
ConstantRange X = getRange(Add->getOperand(0), T, SE);
if (X.isFullSet()) return FullSet;
for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i) {
ConstantRange Y = getRange(Add->getOperand(i), T, SE);
if (Y.isFullSet()) return FullSet;
APInt Spread_X = X.getSetSize(), Spread_Y = Y.getSetSize();
APInt NewLower = X.getLower() + Y.getLower();
APInt NewUpper = X.getUpper() + Y.getUpper() - 1;
if (NewLower == NewUpper)
return FullSet;
X = ConstantRange(NewLower, NewUpper);
if (X.getSetSize().ult(Spread_X) || X.getSetSize().ult(Spread_Y))
return FullSet; // we've wrapped, therefore, full set.
}
return X;
}
// {x,*,y,*,...,z}. In order to detect overflow, we use k*bitwidth where
// k is the number of terms being multiplied.
if (const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(S)) {
ConstantRange X = getRange(Mul->getOperand(0), T, SE);
if (X.isFullSet()) return FullSet;
const IntegerType *Ty = IntegerType::get(X.getBitWidth());
const IntegerType *ExTy = IntegerType::get(X.getBitWidth() *
Mul->getNumOperands());
ConstantRange XExt = X.zeroExtend(ExTy->getBitWidth());
for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i) {
ConstantRange Y = getRange(Mul->getOperand(i), T, SE);
if (Y.isFullSet()) return FullSet;
ConstantRange YExt = Y.zeroExtend(ExTy->getBitWidth());
XExt = ConstantRange(XExt.getLower() * YExt.getLower(),
((XExt.getUpper()-1) * (YExt.getUpper()-1)) + 1);
}
return XExt.truncate(Ty->getBitWidth());
}
// X smax Y smax ... Z is: range(smax(X_smin, Y_smin, ..., Z_smin),
// smax(X_smax, Y_smax, ..., Z_smax))
// It doesn't matter if one of the SCEVs has FullSet because we're taking
// a maximum of the minimums across all of them.
if (const SCEVSMaxExpr *SMax = dyn_cast<SCEVSMaxExpr>(S)) {
ConstantRange X = getRange(SMax->getOperand(0), T, SE);
if (X.isFullSet()) return FullSet;
APInt smin = X.getSignedMin(), smax = X.getSignedMax();
for (unsigned i = 1, e = SMax->getNumOperands(); i != e; ++i) {
ConstantRange Y = getRange(SMax->getOperand(i), T, SE);
smin = APIntOps::smax(smin, Y.getSignedMin());
smax = APIntOps::smax(smax, Y.getSignedMax());
}
if (smax + 1 == smin) return FullSet;
return ConstantRange(smin, smax + 1);
}
// X umax Y umax ... Z is: range(umax(X_umin, Y_umin, ..., Z_umin),
// umax(X_umax, Y_umax, ..., Z_umax))
// It doesn't matter if one of the SCEVs has FullSet because we're taking
// a maximum of the minimums across all of them.
if (const SCEVUMaxExpr *UMax = dyn_cast<SCEVUMaxExpr>(S)) {
ConstantRange X = getRange(UMax->getOperand(0), T, SE);
if (X.isFullSet()) return FullSet;
APInt umin = X.getUnsignedMin(), umax = X.getUnsignedMax();
for (unsigned i = 1, e = UMax->getNumOperands(); i != e; ++i) {
ConstantRange Y = getRange(UMax->getOperand(i), T, SE);
umin = APIntOps::umax(umin, Y.getUnsignedMin());
umax = APIntOps::umax(umax, Y.getUnsignedMax());
}
if (umax + 1 == umin) return FullSet;
return ConstantRange(umin, umax + 1);
}
// L udiv R. Luckily, there's only ever 2 sides to a udiv.
if (const SCEVUDivExpr *UDiv = dyn_cast<SCEVUDivExpr>(S)) {
ConstantRange L = getRange(UDiv->getLHS(), T, SE);
ConstantRange R = getRange(UDiv->getRHS(), T, SE);
if (L.isFullSet() && R.isFullSet()) return FullSet;
if (R.getUnsignedMax() == 0) {
// RHS must be single-element zero. Return an empty set.
return ConstantRange(R.getBitWidth(), false);
}
APInt Lower = L.getUnsignedMin().udiv(R.getUnsignedMax());
APInt Upper;
if (R.getUnsignedMin() == 0) {
// Just because it contains zero, doesn't mean it will also contain one.
// Use maximalIntersectWith to get the right behaviour.
ConstantRange NotZero(APInt(L.getBitWidth(), 1),
APInt::getNullValue(L.getBitWidth()));
R = R.maximalIntersectWith(NotZero);
}
// But, the maximal intersection might still include zero. If it does, then
// we know it also included one.
if (R.contains(APInt::getNullValue(L.getBitWidth())))
Upper = L.getUnsignedMax();
else
Upper = L.getUnsignedMax().udiv(R.getUnsignedMin());
return ConstantRange(Lower, Upper);
}
// ConstantRange already implements the cast operators.
if (const SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(S)) {
T = SE.getTruncateOrZeroExtend(T, ZExt->getOperand()->getType());
ConstantRange X = getRange(ZExt->getOperand(), T, SE);
return X.zeroExtend(cast<IntegerType>(ZExt->getType())->getBitWidth());
}
if (const SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(S)) {
T = SE.getTruncateOrZeroExtend(T, SExt->getOperand()->getType());
ConstantRange X = getRange(SExt->getOperand(), T, SE);
return X.signExtend(cast<IntegerType>(SExt->getType())->getBitWidth());
}
if (const SCEVTruncateExpr *Trunc = dyn_cast<SCEVTruncateExpr>(S)) {
T = SE.getTruncateOrZeroExtend(T, Trunc->getOperand()->getType());
ConstantRange X = getRange(Trunc->getOperand(), T, SE);
if (X.isFullSet()) return FullSet;
return X.truncate(cast<IntegerType>(Trunc->getType())->getBitWidth());
}
if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
const SCEVConstant *Trip = dyn_cast<SCEVConstant>(T);
if (!Trip) return FullSet;
if (AddRec->isAffine()) {
const SCEV* StartHandle = AddRec->getStart();
const SCEV* StepHandle = AddRec->getOperand(1);
const SCEVConstant *Step = dyn_cast<SCEVConstant>(StepHandle);
if (!Step) return FullSet;
uint32_t ExWidth = 2 * Trip->getValue()->getBitWidth();
APInt TripExt = Trip->getValue()->getValue(); TripExt.zext(ExWidth);
APInt StepExt = Step->getValue()->getValue(); StepExt.zext(ExWidth);
if ((TripExt * StepExt).ugt(APInt::getLowBitsSet(ExWidth, ExWidth >> 1)))
return FullSet;
const SCEV* EndHandle = SE.getAddExpr(StartHandle,
SE.getMulExpr(T, StepHandle));
const SCEVConstant *Start = dyn_cast<SCEVConstant>(StartHandle);
const SCEVConstant *End = dyn_cast<SCEVConstant>(EndHandle);
if (!Start || !End) return FullSet;
const APInt &StartInt = Start->getValue()->getValue();
const APInt &EndInt = End->getValue()->getValue();
const APInt &StepInt = Step->getValue()->getValue();
if (StepInt.isNegative()) {
if (EndInt == StartInt + 1) return FullSet;
return ConstantRange(EndInt, StartInt + 1);
} else {
if (StartInt == EndInt + 1) return FullSet;
return ConstantRange(StartInt, EndInt + 1);
}
}
}
// TODO: non-affine addrec, udiv, SCEVUnknown (narrowed from elsewhere)?
return FullSet;
}
bool LoopVR::runOnFunction(Function &F) { Map.clear(); return false; }
void LoopVR::print(std::ostream &os, const Module *) const {
raw_os_ostream OS(os);
for (std::map<Value *, ConstantRange *>::const_iterator I = Map.begin(),
E = Map.end(); I != E; ++I) {
OS << *I->first << ": " << *I->second << '\n';
}
}
void LoopVR::releaseMemory() {
for (std::map<Value *, ConstantRange *>::iterator I = Map.begin(),
E = Map.end(); I != E; ++I) {
delete I->second;
}
Map.clear();
}
ConstantRange LoopVR::compute(Value *V) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
return ConstantRange(CI->getValue());
Instruction *I = dyn_cast<Instruction>(V);
if (!I)
return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);
LoopInfo &LI = getAnalysis<LoopInfo>();
Loop *L = LI.getLoopFor(I->getParent());
if (!L || L->isLoopInvariant(I))
return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);
ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
const SCEV* S = SE.getSCEV(I);
if (isa<SCEVUnknown>(S) || isa<SCEVCouldNotCompute>(S))
return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);
return ConstantRange(getRange(S, L, SE));
}
ConstantRange LoopVR::get(Value *V) {
std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
if (I == Map.end()) {
ConstantRange *CR = new ConstantRange(compute(V));
Map[V] = CR;
return *CR;
}
return *I->second;
}
void LoopVR::remove(Value *V) {
std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
if (I != Map.end()) {
delete I->second;
Map.erase(I);
}
}
void LoopVR::narrow(Value *V, const ConstantRange &CR) {
if (CR.isFullSet()) return;
std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
if (I == Map.end())
Map[V] = new ConstantRange(CR);
else
Map[V] = new ConstantRange(Map[V]->maximalIntersectWith(CR));
}

View File

@ -1,167 +0,0 @@
//===- LazyLiveness.cpp - Lazy, CFG-invariant liveness information --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass implements a lazy liveness analysis as per "Fast Liveness Checking
// for SSA-form Programs," by Boissinot, et al.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "lazyliveness"
#include "llvm/CodeGen/LazyLiveness.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/PostOrderIterator.h"
using namespace llvm;
char LazyLiveness::ID = 0;
static RegisterPass<LazyLiveness> X("lazy-liveness", "Lazy Liveness Analysis");
void LazyLiveness::computeBackedgeChain(MachineFunction& mf,
MachineBasicBlock* MBB) {
SparseBitVector<128> tmp = rv[MBB];
tmp.set(preorder[MBB]);
tmp &= backedge_source;
calculated.set(preorder[MBB]);
for (SparseBitVector<128>::iterator I = tmp.begin(); I != tmp.end(); ++I) {
assert(rev_preorder.size() > *I && "Unknown block!");
MachineBasicBlock* SrcMBB = rev_preorder[*I];
for (MachineBasicBlock::succ_iterator SI = SrcMBB->succ_begin(),
SE = SrcMBB->succ_end(); SI != SE; ++SI) {
MachineBasicBlock* TgtMBB = *SI;
if (backedges.count(std::make_pair(SrcMBB, TgtMBB)) &&
!rv[MBB].test(preorder[TgtMBB])) {
if (!calculated.test(preorder[TgtMBB]))
computeBackedgeChain(mf, TgtMBB);
tv[MBB].set(preorder[TgtMBB]);
SparseBitVector<128> right = tv[TgtMBB];
tv[MBB] |= right;
}
}
tv[MBB].reset(preorder[MBB]);
}
}
bool LazyLiveness::runOnMachineFunction(MachineFunction &mf) {
rv.clear();
tv.clear();
backedges.clear();
backedge_source.clear();
backedge_target.clear();
calculated.clear();
preorder.clear();
rev_preorder.clear();
rv.resize(mf.size());
tv.resize(mf.size());
preorder.resize(mf.size());
rev_preorder.reserve(mf.size());
MRI = &mf.getRegInfo();
MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>();
// Step 0: Compute preorder numbering for all MBBs.
unsigned num = 0;
for (df_iterator<MachineDomTreeNode*> DI = df_begin(MDT.getRootNode()),
DE = df_end(MDT.getRootNode()); DI != DE; ++DI) {
preorder[(*DI)->getBlock()] = num++;
rev_preorder.push_back((*DI)->getBlock());
}
// Step 1: Compute the transitive closure of the CFG, ignoring backedges.
for (po_iterator<MachineBasicBlock*> POI = po_begin(&*mf.begin()),
POE = po_end(&*mf.begin()); POI != POE; ++POI) {
MachineBasicBlock* MBB = *POI;
SparseBitVector<128>& entry = rv[MBB];
entry.set(preorder[MBB]);
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
SE = MBB->succ_end(); SI != SE; ++SI) {
DenseMap<MachineBasicBlock*, SparseBitVector<128> >::iterator SII =
rv.find(*SI);
// Because we're iterating in postorder, any successor that does not yet
// have an rv entry must be on a backedge.
if (SII != rv.end()) {
entry |= SII->second;
} else {
backedges.insert(std::make_pair(MBB, *SI));
backedge_source.set(preorder[MBB]);
backedge_target.set(preorder[*SI]);
}
}
}
for (SparseBitVector<128>::iterator I = backedge_source.begin();
I != backedge_source.end(); ++I)
computeBackedgeChain(mf, rev_preorder[*I]);
for (po_iterator<MachineBasicBlock*> POI = po_begin(&*mf.begin()),
POE = po_end(&*mf.begin()); POI != POE; ++POI)
if (!backedge_target.test(preorder[*POI]))
for (MachineBasicBlock::succ_iterator SI = (*POI)->succ_begin(),
SE = (*POI)->succ_end(); SI != SE; ++SI)
if (!backedges.count(std::make_pair(*POI, *SI)) && tv.count(*SI)) {
SparseBitVector<128> right = tv[*SI];
tv[*POI] |= right;
}
for (po_iterator<MachineBasicBlock*> POI = po_begin(&*mf.begin()),
POE = po_end(&*mf.begin()); POI != POE; ++POI)
tv[*POI].set(preorder[*POI]);
return false;
}
bool LazyLiveness::vregLiveIntoMBB(unsigned vreg, MachineBasicBlock* MBB) {
MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>();
MachineBasicBlock* DefMBB = MRI->def_begin(vreg)->getParent();
unsigned def = preorder[DefMBB];
unsigned max_dom = 0;
for (df_iterator<MachineDomTreeNode*> DI = df_begin(MDT[DefMBB]),
DE = df_end(MDT[DefMBB]); DI != DE; ++DI) {
if (preorder[DI->getBlock()] > max_dom) {
max_dom = preorder[(*DI)->getBlock()];
}
}
if (preorder[MBB] <= def || max_dom < preorder[MBB])
return false;
SparseBitVector<128>::iterator I = tv[MBB].begin();
while (I != tv[MBB].end() && *I <= def) ++I;
while (I != tv[MBB].end() && *I < max_dom) {
for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(vreg),
UE = MachineRegisterInfo::use_end(); UI != UE; ++UI) {
MachineBasicBlock* UseMBB = UI->getParent();
if (rv[rev_preorder[*I]].test(preorder[UseMBB]))
return true;
unsigned t_dom = 0;
for (df_iterator<MachineDomTreeNode*> DI =
df_begin(MDT[rev_preorder[*I]]), DE = df_end(MDT[rev_preorder[*I]]);
DI != DE; ++DI)
if (preorder[DI->getBlock()] > t_dom) {
max_dom = preorder[(*DI)->getBlock()];
}
I = tv[MBB].begin();
while (I != tv[MBB].end() && *I < t_dom) ++I;
}
}
return false;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,284 +0,0 @@
//===---------------- PBQP.cpp --------- PBQP Solver ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Developed by: Bernhard Scholz
// The University of Sydney
// http://www.it.usyd.edu.au/~scholz
//===----------------------------------------------------------------------===//
// TODO:
//
// * Default to null costs on vector initialisation?
// * C++-ify the rest of the solver.
#ifndef LLVM_CODEGEN_PBQPSOLVER_H
#define LLVM_CODEGEN_PBQPSOLVER_H
#include <cassert>
#include <algorithm>
#include <functional>
namespace llvm {
//! \brief Floating point type to use in PBQP solver.
typedef double PBQPNum;
//! \brief PBQP Vector class.
class PBQPVector {
public:
//! \brief Construct a PBQP vector of the given size.
explicit PBQPVector(unsigned length) :
length(length), data(new PBQPNum[length]) {
std::fill(data, data + length, 0);
}
//! \brief Copy construct a PBQP vector.
PBQPVector(const PBQPVector &v) :
length(v.length), data(new PBQPNum[length]) {
std::copy(v.data, v.data + length, data);
}
~PBQPVector() { delete[] data; }
//! \brief Assignment operator.
PBQPVector& operator=(const PBQPVector &v) {
delete[] data;
length = v.length;
data = new PBQPNum[length];
std::copy(v.data, v.data + length, data);
return *this;
}
//! \brief Return the length of the vector
unsigned getLength() const throw () {
return length;
}
//! \brief Element access.
PBQPNum& operator[](unsigned index) {
assert(index < length && "PBQPVector element access out of bounds.");
return data[index];
}
//! \brief Const element access.
const PBQPNum& operator[](unsigned index) const {
assert(index < length && "PBQPVector element access out of bounds.");
return data[index];
}
//! \brief Add another vector to this one.
PBQPVector& operator+=(const PBQPVector &v) {
assert(length == v.length && "PBQPVector length mismatch.");
std::transform(data, data + length, v.data, data, std::plus<PBQPNum>());
return *this;
}
//! \brief Subtract another vector from this one.
PBQPVector& operator-=(const PBQPVector &v) {
assert(length == v.length && "PBQPVector length mismatch.");
std::transform(data, data + length, v.data, data, std::minus<PBQPNum>());
return *this;
}
//! \brief Returns the index of the minimum value in this vector
unsigned minIndex() const {
return std::min_element(data, data + length) - data;
}
private:
unsigned length;
PBQPNum *data;
};
//! \brief PBQP Matrix class
class PBQPMatrix {
public:
//! \brief Construct a PBQP Matrix with the given dimensions.
PBQPMatrix(unsigned rows, unsigned cols) :
rows(rows), cols(cols), data(new PBQPNum[rows * cols]) {
std::fill(data, data + (rows * cols), 0);
}
//! \brief Copy construct a PBQP matrix.
PBQPMatrix(const PBQPMatrix &m) :
rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) {
std::copy(m.data, m.data + (rows * cols), data);
}
~PBQPMatrix() { delete[] data; }
//! \brief Assignment operator.
PBQPMatrix& operator=(const PBQPMatrix &m) {
delete[] data;
rows = m.rows; cols = m.cols;
data = new PBQPNum[rows * cols];
std::copy(m.data, m.data + (rows * cols), data);
return *this;
}
//! \brief Return the number of rows in this matrix.
unsigned getRows() const throw () { return rows; }
//! \brief Return the number of cols in this matrix.
unsigned getCols() const throw () { return cols; }
//! \brief Matrix element access.
PBQPNum* operator[](unsigned r) {
assert(r < rows && "Row out of bounds.");
return data + (r * cols);
}
//! \brief Matrix element access.
const PBQPNum* operator[](unsigned r) const {
assert(r < rows && "Row out of bounds.");
return data + (r * cols);
}
//! \brief Returns the given row as a vector.
PBQPVector getRowAsVector(unsigned r) const {
PBQPVector v(cols);
for (unsigned c = 0; c < cols; ++c)
v[c] = (*this)[r][c];
return v;
}
//! \brief Reset the matrix to the given value.
PBQPMatrix& reset(PBQPNum val = 0) {
std::fill(data, data + (rows * cols), val);
return *this;
}
//! \brief Set a single row of this matrix to the given value.
PBQPMatrix& setRow(unsigned r, PBQPNum val) {
assert(r < rows && "Row out of bounds.");
std::fill(data + (r * cols), data + ((r + 1) * cols), val);
return *this;
}
//! \brief Set a single column of this matrix to the given value.
PBQPMatrix& setCol(unsigned c, PBQPNum val) {
assert(c < cols && "Column out of bounds.");
for (unsigned r = 0; r < rows; ++r)
(*this)[r][c] = val;
return *this;
}
//! \brief Matrix transpose.
PBQPMatrix transpose() const {
PBQPMatrix m(cols, rows);
for (unsigned r = 0; r < rows; ++r)
for (unsigned c = 0; c < cols; ++c)
m[c][r] = (*this)[r][c];
return m;
}
//! \brief Returns the diagonal of the matrix as a vector.
//!
//! Matrix must be square.
PBQPVector diagonalize() const {
assert(rows == cols && "Attempt to diagonalize non-square matrix.");
PBQPVector v(rows);
for (unsigned r = 0; r < rows; ++r)
v[r] = (*this)[r][r];
return v;
}
//! \brief Add the given matrix to this one.
PBQPMatrix& operator+=(const PBQPMatrix &m) {
assert(rows == m.rows && cols == m.cols &&
"Matrix dimensions mismatch.");
std::transform(data, data + (rows * cols), m.data, data,
std::plus<PBQPNum>());
return *this;
}
//! \brief Returns the minimum of the given row
PBQPNum getRowMin(unsigned r) const {
assert(r < rows && "Row out of bounds");
return *std::min_element(data + (r * cols), data + ((r + 1) * cols));
}
//! \brief Returns the minimum of the given column
PBQPNum getColMin(unsigned c) const {
PBQPNum minElem = (*this)[0][c];
for (unsigned r = 1; r < rows; ++r)
if ((*this)[r][c] < minElem) minElem = (*this)[r][c];
return minElem;
}
//! \brief Subtracts the given scalar from the elements of the given row.
PBQPMatrix& subFromRow(unsigned r, PBQPNum val) {
assert(r < rows && "Row out of bounds");
std::transform(data + (r * cols), data + ((r + 1) * cols),
data + (r * cols),
std::bind2nd(std::minus<PBQPNum>(), val));
return *this;
}
//! \brief Subtracts the given scalar from the elements of the given column.
PBQPMatrix& subFromCol(unsigned c, PBQPNum val) {
for (unsigned r = 0; r < rows; ++r)
(*this)[r][c] -= val;
return *this;
}
//! \brief Returns true if this is a zero matrix.
bool isZero() const {
return find_if(data, data + (rows * cols),
std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) ==
data + (rows * cols);
}
private:
unsigned rows, cols;
PBQPNum *data;
};
#define EPS (1E-8)
#ifndef PBQP_TYPE
#define PBQP_TYPE
struct pbqp;
typedef struct pbqp pbqp;
#endif
/*****************
* PBQP routines *
*****************/
/* allocate pbqp problem */
pbqp *alloc_pbqp(int num);
/* add node costs */
void add_pbqp_nodecosts(pbqp *this_,int u, PBQPVector *costs);
/* add edge mat */
void add_pbqp_edgecosts(pbqp *this_,int u,int v,PBQPMatrix *costs);
/* solve PBQP problem */
void solve_pbqp(pbqp *this_);
/* get solution of a node */
int get_pbqp_solution(pbqp *this_,int u);
/* alloc PBQP */
pbqp *alloc_pbqp(int num);
/* free PBQP */
void free_pbqp(pbqp *this_);
/* is optimal */
bool is_pbqp_optimal(pbqp *this_);
}
#endif

View File

@ -1,892 +0,0 @@
//===- RegAllocBigBlock.cpp - A register allocator for large basic blocks -===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the RABigBlock class
//
//===----------------------------------------------------------------------===//
// This register allocator is derived from RegAllocLocal.cpp. Like it, this
// allocator works on one basic block at a time, oblivious to others.
// However, the algorithm used here is suited for long blocks of
// instructions - registers are spilled by greedily choosing those holding
// values that will not be needed for the longest amount of time. This works
// particularly well for blocks with 10 or more times as many instructions
// as machine registers, but can be used for general code.
//
//===----------------------------------------------------------------------===//
//
// TODO: - automagically invoke linearscan for (groups of) small BBs?
// - break ties when picking regs? (probably not worth it in a
// JIT context)
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "regalloc"
#include "llvm/BasicBlock.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include <algorithm>
using namespace llvm;
STATISTIC(NumStores, "Number of stores added");
STATISTIC(NumLoads , "Number of loads added");
STATISTIC(NumFolded, "Number of loads/stores folded into instructions");
static RegisterRegAlloc
bigBlockRegAlloc("bigblock", "Big-block register allocator",
createBigBlockRegisterAllocator);
namespace {
/// VRegKeyInfo - Defines magic values required to use VirtRegs as DenseMap
/// keys.
struct VRegKeyInfo {
static inline unsigned getEmptyKey() { return -1U; }
static inline unsigned getTombstoneKey() { return -2U; }
static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; }
static unsigned getHashValue(const unsigned &Key) { return Key; }
};
/// This register allocator is derived from RegAllocLocal.cpp. Like it, this
/// allocator works on one basic block at a time, oblivious to others.
/// However, the algorithm used here is suited for long blocks of
/// instructions - registers are spilled by greedily choosing those holding
/// values that will not be needed for the longest amount of time. This works
/// particularly well for blocks with 10 or more times as many instructions
/// as machine registers, but can be used for general code.
///
/// TODO: - automagically invoke linearscan for (groups of) small BBs?
/// - break ties when picking regs? (probably not worth it in a
/// JIT context)
///
class VISIBILITY_HIDDEN RABigBlock : public MachineFunctionPass {
public:
static char ID;
RABigBlock() : MachineFunctionPass(&ID) {}
private:
/// TM - For getting at TargetMachine info
///
const TargetMachine *TM;
/// MF - Our generic MachineFunction pointer
///
MachineFunction *MF;
/// RegInfo - For dealing with machine register info (aliases, folds
/// etc)
const TargetRegisterInfo *RegInfo;
typedef SmallVector<unsigned, 2> VRegTimes;
/// VRegReadTable - maps VRegs in a BB to the set of times they are read
///
DenseMap<unsigned, VRegTimes*, VRegKeyInfo> VRegReadTable;
/// VRegReadIdx - keeps track of the "current time" in terms of
/// positions in VRegReadTable
DenseMap<unsigned, unsigned , VRegKeyInfo> VRegReadIdx;
/// StackSlotForVirtReg - Maps virtual regs to the frame index where these
/// values are spilled.
IndexedMap<unsigned, VirtReg2IndexFunctor> StackSlotForVirtReg;
/// Virt2PhysRegMap - This map contains entries for each virtual register
/// that is currently available in a physical register.
IndexedMap<unsigned, VirtReg2IndexFunctor> Virt2PhysRegMap;
/// PhysRegsUsed - This array is effectively a map, containing entries for
/// each physical register that currently has a value (ie, it is in
/// Virt2PhysRegMap). The value mapped to is the virtual register
/// corresponding to the physical register (the inverse of the
/// Virt2PhysRegMap), or 0. The value is set to 0 if this register is pinned
/// because it is used by a future instruction, and to -2 if it is not
/// allocatable. If the entry for a physical register is -1, then the
/// physical register is "not in the map".
///
std::vector<int> PhysRegsUsed;
/// VirtRegModified - This bitset contains information about which virtual
/// registers need to be spilled back to memory when their registers are
/// scavenged. If a virtual register has simply been rematerialized, there
/// is no reason to spill it to memory when we need the register back.
///
std::vector<int> VirtRegModified;
/// MBBLastInsnTime - the number of the the last instruction in MBB
///
int MBBLastInsnTime;
/// MBBCurTime - the number of the the instruction being currently processed
///
int MBBCurTime;
unsigned &getVirt2PhysRegMapSlot(unsigned VirtReg) {
return Virt2PhysRegMap[VirtReg];
}
unsigned &getVirt2StackSlot(unsigned VirtReg) {
return StackSlotForVirtReg[VirtReg];
}
/// markVirtRegModified - Lets us flip bits in the VirtRegModified bitset
///
void markVirtRegModified(unsigned Reg, bool Val = true) {
assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Illegal VirtReg!");
Reg -= TargetRegisterInfo::FirstVirtualRegister;
if (VirtRegModified.size() <= Reg)
VirtRegModified.resize(Reg+1);
VirtRegModified[Reg] = Val;
}
/// isVirtRegModified - Lets us query the VirtRegModified bitset
///
bool isVirtRegModified(unsigned Reg) const {
assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Illegal VirtReg!");
assert(Reg - TargetRegisterInfo::FirstVirtualRegister < VirtRegModified.size()
&& "Illegal virtual register!");
return VirtRegModified[Reg - TargetRegisterInfo::FirstVirtualRegister];
}
public:
/// getPassName - returns the BigBlock allocator's name
///
virtual const char *getPassName() const {
return "BigBlock Register Allocator";
}
/// getAnalaysisUsage - declares the required analyses
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequiredID(PHIEliminationID);
AU.addRequiredID(TwoAddressInstructionPassID);
MachineFunctionPass::getAnalysisUsage(AU);
}
private:
/// runOnMachineFunction - Register allocate the whole function
///
bool runOnMachineFunction(MachineFunction &Fn);
/// AllocateBasicBlock - Register allocate the specified basic block.
///
void AllocateBasicBlock(MachineBasicBlock &MBB);
/// FillVRegReadTable - Fill out the table of vreg read times given a BB
///
void FillVRegReadTable(MachineBasicBlock &MBB);
/// areRegsEqual - This method returns true if the specified registers are
/// related to each other. To do this, it checks to see if they are equal
/// or if the first register is in the alias set of the second register.
///
bool areRegsEqual(unsigned R1, unsigned R2) const {
if (R1 == R2) return true;
for (const unsigned *AliasSet = RegInfo->getAliasSet(R2);
*AliasSet; ++AliasSet) {
if (*AliasSet == R1) return true;
}
return false;
}
/// getStackSpaceFor - This returns the frame index of the specified virtual
/// register on the stack, allocating space if necessary.
int getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC);
/// removePhysReg - This method marks the specified physical register as no
/// longer being in use.
///
void removePhysReg(unsigned PhysReg);
/// spillVirtReg - This method spills the value specified by PhysReg into
/// the virtual register slot specified by VirtReg. It then updates the RA
/// data structures to indicate the fact that PhysReg is now available.
///
void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
unsigned VirtReg, unsigned PhysReg);
/// spillPhysReg - This method spills the specified physical register into
/// the virtual register slot associated with it. If OnlyVirtRegs is set to
/// true, then the request is ignored if the physical register does not
/// contain a virtual register.
///
void spillPhysReg(MachineBasicBlock &MBB, MachineInstr *I,
unsigned PhysReg, bool OnlyVirtRegs = false);
/// assignVirtToPhysReg - This method updates local state so that we know
/// that PhysReg is the proper container for VirtReg now. The physical
/// register must not be used for anything else when this is called.
///
void assignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg);
/// isPhysRegAvailable - Return true if the specified physical register is
/// free and available for use. This also includes checking to see if
/// aliased registers are all free...
///
bool isPhysRegAvailable(unsigned PhysReg) const;
/// getFreeReg - Look to see if there is a free register available in the
/// specified register class. If not, return 0.
///
unsigned getFreeReg(const TargetRegisterClass *RC);
/// chooseReg - Pick a physical register to hold the specified
/// virtual register by choosing the one which will be read furthest
/// in the future.
///
unsigned chooseReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned VirtReg);
/// reloadVirtReg - This method transforms the specified specified virtual
/// register use to refer to a physical register. This method may do this
/// in one of several ways: if the register is available in a physical
/// register already, it uses that physical register. If the value is not
/// in a physical register, and if there are physical registers available,
/// it loads it into a register. If register pressure is high, and it is
/// possible, it tries to fold the load of the virtual register into the
/// instruction itself. It avoids doing this if register pressure is low to
/// improve the chance that subsequent instructions can use the reloaded
/// value. This method returns the modified instruction.
///
MachineInstr *reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned OpNum);
};
char RABigBlock::ID = 0;
}
/// getStackSpaceFor - This allocates space for the specified virtual register
/// to be held on the stack.
int RABigBlock::getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC) {
// Find the location Reg would belong...
int FrameIdx = getVirt2StackSlot(VirtReg);
if (FrameIdx)
return FrameIdx - 1; // Already has space allocated?
// Allocate a new stack object for this spill location...
FrameIdx = MF->getFrameInfo()->CreateStackObject(RC->getSize(),
RC->getAlignment());
// Assign the slot...
getVirt2StackSlot(VirtReg) = FrameIdx + 1;
return FrameIdx;
}
/// removePhysReg - This method marks the specified physical register as no
/// longer being in use.
///
void RABigBlock::removePhysReg(unsigned PhysReg) {
PhysRegsUsed[PhysReg] = -1; // PhyReg no longer used
}
/// spillVirtReg - This method spills the value specified by PhysReg into the
/// virtual register slot specified by VirtReg. It then updates the RA data
/// structures to indicate the fact that PhysReg is now available.
///
void RABigBlock::spillVirtReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned VirtReg, unsigned PhysReg) {
assert(VirtReg && "Spilling a physical register is illegal!"
" Must not have appropriate kill for the register or use exists beyond"
" the intended one.");
DOUT << " Spilling register " << RegInfo->getName(PhysReg)
<< " containing %reg" << VirtReg;
const TargetInstrInfo* TII = MBB.getParent()->getTarget().getInstrInfo();
if (!isVirtRegModified(VirtReg))
DOUT << " which has not been modified, so no store necessary!";
// Otherwise, there is a virtual register corresponding to this physical
// register. We only need to spill it into its stack slot if it has been
// modified.
if (isVirtRegModified(VirtReg)) {
const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg);
int FrameIndex = getStackSpaceFor(VirtReg, RC);
DOUT << " to stack slot #" << FrameIndex;
TII->storeRegToStackSlot(MBB, I, PhysReg, true, FrameIndex, RC);
++NumStores; // Update statistics
}
getVirt2PhysRegMapSlot(VirtReg) = 0; // VirtReg no longer available
DOUT << "\n";
removePhysReg(PhysReg);
}
/// spillPhysReg - This method spills the specified physical register into the
/// virtual register slot associated with it. If OnlyVirtRegs is set to true,
/// then the request is ignored if the physical register does not contain a
/// virtual register.
///
void RABigBlock::spillPhysReg(MachineBasicBlock &MBB, MachineInstr *I,
unsigned PhysReg, bool OnlyVirtRegs) {
if (PhysRegsUsed[PhysReg] != -1) { // Only spill it if it's used!
assert(PhysRegsUsed[PhysReg] != -2 && "Non allocable reg used!");
if (PhysRegsUsed[PhysReg] || !OnlyVirtRegs)
spillVirtReg(MBB, I, PhysRegsUsed[PhysReg], PhysReg);
} else {
// If the selected register aliases any other registers, we must make
// sure that one of the aliases isn't alive.
for (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg);
*AliasSet; ++AliasSet)
if (PhysRegsUsed[*AliasSet] != -1 && // Spill aliased register.
PhysRegsUsed[*AliasSet] != -2) // If allocatable.
if (PhysRegsUsed[*AliasSet])
spillVirtReg(MBB, I, PhysRegsUsed[*AliasSet], *AliasSet);
}
}
/// assignVirtToPhysReg - This method updates local state so that we know
/// that PhysReg is the proper container for VirtReg now. The physical
/// register must not be used for anything else when this is called.
///
void RABigBlock::assignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg) {
assert(PhysRegsUsed[PhysReg] == -1 && "Phys reg already assigned!");
// Update information to note the fact that this register was just used, and
// it holds VirtReg.
PhysRegsUsed[PhysReg] = VirtReg;
getVirt2PhysRegMapSlot(VirtReg) = PhysReg;
}
/// isPhysRegAvailable - Return true if the specified physical register is free
/// and available for use. This also includes checking to see if aliased
/// registers are all free...
///
bool RABigBlock::isPhysRegAvailable(unsigned PhysReg) const {
if (PhysRegsUsed[PhysReg] != -1) return false;
// If the selected register aliases any other allocated registers, it is
// not free!
for (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg);
*AliasSet; ++AliasSet)
if (PhysRegsUsed[*AliasSet] >= 0) // Aliased register in use?
return false; // Can't use this reg then.
return true;
}
/// getFreeReg - Look to see if there is a free register available in the
/// specified register class. If not, return 0.
///
unsigned RABigBlock::getFreeReg(const TargetRegisterClass *RC) {
// Get iterators defining the range of registers that are valid to allocate in
// this class, which also specifies the preferred allocation order.
TargetRegisterClass::iterator RI = RC->allocation_order_begin(*MF);
TargetRegisterClass::iterator RE = RC->allocation_order_end(*MF);
for (; RI != RE; ++RI)
if (isPhysRegAvailable(*RI)) { // Is reg unused?
assert(*RI != 0 && "Cannot use register!");
return *RI; // Found an unused register!
}
return 0;
}
/// chooseReg - Pick a physical register to hold the specified
/// virtual register by choosing the one whose value will be read
/// furthest in the future.
///
unsigned RABigBlock::chooseReg(MachineBasicBlock &MBB, MachineInstr *I,
unsigned VirtReg) {
const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg);
// First check to see if we have a free register of the requested type...
unsigned PhysReg = getFreeReg(RC);
// If we didn't find an unused register, find the one which will be
// read at the most distant point in time.
if (PhysReg == 0) {
unsigned delay=0, longest_delay=0;
VRegTimes* ReadTimes;
unsigned curTime = MBBCurTime;
// for all physical regs in the RC,
for(TargetRegisterClass::iterator pReg = RC->begin();
pReg != RC->end(); ++pReg) {
// how long until they're read?
if(PhysRegsUsed[*pReg]>0) { // ignore non-allocatable regs
ReadTimes = VRegReadTable[PhysRegsUsed[*pReg]];
if(ReadTimes && !ReadTimes->empty()) {
unsigned& pt = VRegReadIdx[PhysRegsUsed[*pReg]];
while(pt < ReadTimes->size() && (*ReadTimes)[pt] < curTime) {
++pt;
}
if(pt < ReadTimes->size())
delay = (*ReadTimes)[pt] - curTime;
else
delay = MBBLastInsnTime + 1 - curTime;
} else {
// This register is only defined, but never
// read in this MBB. Therefore the next read
// happens after the end of this MBB
delay = MBBLastInsnTime + 1 - curTime;
}
if(delay > longest_delay) {
longest_delay = delay;
PhysReg = *pReg;
}
}
}
if(PhysReg == 0) { // ok, now we're desperate. We couldn't choose
// a register to spill by looking through the
// read timetable, so now we just spill the
// first allocatable register we find.
// for all physical regs in the RC,
for(TargetRegisterClass::iterator pReg = RC->begin();
pReg != RC->end(); ++pReg) {
// if we find a register we can spill
if(PhysRegsUsed[*pReg]>=-1)
PhysReg = *pReg; // choose it to be spilled
}
}
assert(PhysReg && "couldn't choose a register to spill :( ");
// TODO: assert that RC->contains(PhysReg) / handle aliased registers?
// since we needed to look in the table we need to spill this register.
spillPhysReg(MBB, I, PhysReg);
}
// assign the vreg to our chosen physical register
assignVirtToPhysReg(VirtReg, PhysReg);
return PhysReg; // and return it
}
/// reloadVirtReg - This method transforms an instruction with a virtual
/// register use to one that references a physical register. It does this as
/// follows:
///
/// 1) If the register is already in a physical register, it uses it.
/// 2) Otherwise, if there is a free physical register, it uses that.
/// 3) Otherwise, it calls chooseReg() to get the physical register
/// holding the most distantly needed value, generating a spill in
/// the process.
///
/// This method returns the modified instruction.
MachineInstr *RABigBlock::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned OpNum) {
unsigned VirtReg = MI->getOperand(OpNum).getReg();
const TargetInstrInfo* TII = MBB.getParent()->getTarget().getInstrInfo();
// If the virtual register is already available in a physical register,
// just update the instruction and return.
if (unsigned PR = getVirt2PhysRegMapSlot(VirtReg)) {
MI->getOperand(OpNum).setReg(PR);
return MI;
}
// Otherwise, if we have free physical registers available to hold the
// value, use them.
const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg);
unsigned PhysReg = getFreeReg(RC);
int FrameIndex = getStackSpaceFor(VirtReg, RC);
if (PhysReg) { // we have a free register, so use it.
assignVirtToPhysReg(VirtReg, PhysReg);
} else { // no free registers available.
// try to fold the spill into the instruction
SmallVector<unsigned, 1> Ops;
Ops.push_back(OpNum);
if(MachineInstr* FMI = TII->foldMemoryOperand(*MF, MI, Ops, FrameIndex)) {
++NumFolded;
FMI->copyKillDeadInfo(MI);
return MBB.insert(MBB.erase(MI), FMI);
}
// determine which of the physical registers we'll kill off, since we
// couldn't fold.
PhysReg = chooseReg(MBB, MI, VirtReg);
}
// this virtual register is now unmodified (since we just reloaded it)
markVirtRegModified(VirtReg, false);
DOUT << " Reloading %reg" << VirtReg << " into "
<< RegInfo->getName(PhysReg) << "\n";
// Add move instruction(s)
TII->loadRegFromStackSlot(MBB, MI, PhysReg, FrameIndex, RC);
++NumLoads; // Update statistics
MF->getRegInfo().setPhysRegUsed(PhysReg);
MI->getOperand(OpNum).setReg(PhysReg); // Assign the input register
return MI;
}
/// Fill out the vreg read timetable. Since ReadTime increases
/// monotonically, the individual readtime sets will be sorted
/// in ascending order.
void RABigBlock::FillVRegReadTable(MachineBasicBlock &MBB) {
// loop over each instruction
MachineBasicBlock::iterator MII;
unsigned ReadTime;
for(ReadTime=0, MII = MBB.begin(); MII != MBB.end(); ++ReadTime, ++MII) {
MachineInstr *MI = MII;
for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
MachineOperand& MO = MI->getOperand(i);
// look for vreg reads..
if (MO.isReg() && !MO.isDef() && MO.getReg() &&
TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
// ..and add them to the read table.
VRegTimes* &Times = VRegReadTable[MO.getReg()];
if(!VRegReadTable[MO.getReg()]) {
Times = new VRegTimes;
VRegReadIdx[MO.getReg()] = 0;
}
Times->push_back(ReadTime);
}
}
}
MBBLastInsnTime = ReadTime;
for(DenseMap<unsigned, VRegTimes*, VRegKeyInfo>::iterator Reads = VRegReadTable.begin();
Reads != VRegReadTable.end(); ++Reads) {
if(Reads->second) {
DOUT << "Reads[" << Reads->first << "]=" << Reads->second->size() << "\n";
}
}
}
/// isReadModWriteImplicitKill - True if this is an implicit kill for a
/// read/mod/write register, i.e. update partial register.
static bool isReadModWriteImplicitKill(MachineInstr *MI, unsigned Reg) {
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand& MO = MI->getOperand(i);
if (MO.isReg() && MO.getReg() == Reg && MO.isImplicit() &&
MO.isDef() && !MO.isDead())
return true;
}
return false;
}
/// isReadModWriteImplicitDef - True if this is an implicit def for a
/// read/mod/write register, i.e. update partial register.
static bool isReadModWriteImplicitDef(MachineInstr *MI, unsigned Reg) {
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand& MO = MI->getOperand(i);
if (MO.isReg() && MO.getReg() == Reg && MO.isImplicit() &&
!MO.isDef() && MO.isKill())
return true;
}
return false;
}
void RABigBlock::AllocateBasicBlock(MachineBasicBlock &MBB) {
// loop over each instruction
MachineBasicBlock::iterator MII = MBB.begin();
const TargetInstrInfo &TII = *TM->getInstrInfo();
DEBUG(const BasicBlock *LBB = MBB.getBasicBlock();
if (LBB) DOUT << "\nStarting RegAlloc of BB: " << LBB->getName());
// If this is the first basic block in the machine function, add live-in
// registers as active.
if (&MBB == &*MF->begin()) {
for (MachineRegisterInfo::livein_iterator
I = MF->getRegInfo().livein_begin(),
E = MF->getRegInfo().livein_end(); I != E; ++I) {
unsigned Reg = I->first;
MF->getRegInfo().setPhysRegUsed(Reg);
PhysRegsUsed[Reg] = 0; // It is free and reserved now
for (const unsigned *AliasSet = RegInfo->getSubRegisters(Reg);
*AliasSet; ++AliasSet) {
if (PhysRegsUsed[*AliasSet] != -2) {
PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now
MF->getRegInfo().setPhysRegUsed(*AliasSet);
}
}
}
}
// Otherwise, sequentially allocate each instruction in the MBB.
MBBCurTime = -1;
while (MII != MBB.end()) {
MachineInstr *MI = MII++;
MBBCurTime++;
const TargetInstrDesc &TID = MI->getDesc();
DEBUG(DOUT << "\nTime=" << MBBCurTime << " Starting RegAlloc of: " << *MI;
DOUT << " Regs have values: ";
for (unsigned i = 0; i != RegInfo->getNumRegs(); ++i)
if (PhysRegsUsed[i] != -1 && PhysRegsUsed[i] != -2)
DOUT << "[" << RegInfo->getName(i)
<< ",%reg" << PhysRegsUsed[i] << "] ";
DOUT << "\n");
SmallVector<unsigned, 8> Kills;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand& MO = MI->getOperand(i);
if (MO.isReg() && MO.isKill()) {
if (!MO.isImplicit())
Kills.push_back(MO.getReg());
else if (!isReadModWriteImplicitKill(MI, MO.getReg()))
// These are extra physical register kills when a sub-register
// is defined (def of a sub-register is a read/mod/write of the
// larger registers). Ignore.
Kills.push_back(MO.getReg());
}
}
// Get the used operands into registers. This has the potential to spill
// incoming values if we are out of registers. Note that we completely
// ignore physical register uses here. We assume that if an explicit
// physical register is referenced by the instruction, that it is guaranteed
// to be live-in, or the input is badly hosed.
//
for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
MachineOperand& MO = MI->getOperand(i);
// here we are looking for only used operands (never def&use)
if (MO.isReg() && !MO.isDef() && MO.getReg() && !MO.isImplicit() &&
TargetRegisterInfo::isVirtualRegister(MO.getReg()))
MI = reloadVirtReg(MBB, MI, i);
}
// If this instruction is the last user of this register, kill the
// value, freeing the register being used, so it doesn't need to be
// spilled to memory.
//
for (unsigned i = 0, e = Kills.size(); i != e; ++i) {
unsigned VirtReg = Kills[i];
unsigned PhysReg = VirtReg;
if (TargetRegisterInfo::isVirtualRegister(VirtReg)) {
// If the virtual register was never materialized into a register, it
// might not be in the map, but it won't hurt to zero it out anyway.
unsigned &PhysRegSlot = getVirt2PhysRegMapSlot(VirtReg);
PhysReg = PhysRegSlot;
PhysRegSlot = 0;
} else if (PhysRegsUsed[PhysReg] == -2) {
// Unallocatable register dead, ignore.
continue;
} else {
assert((!PhysRegsUsed[PhysReg] || PhysRegsUsed[PhysReg] == -1) &&
"Silently clearing a virtual register?");
}
if (PhysReg) {
DOUT << " Last use of " << RegInfo->getName(PhysReg)
<< "[%reg" << VirtReg <<"], removing it from live set\n";
removePhysReg(PhysReg);
for (const unsigned *AliasSet = RegInfo->getSubRegisters(PhysReg);
*AliasSet; ++AliasSet) {
if (PhysRegsUsed[*AliasSet] != -2) {
DOUT << " Last use of "
<< RegInfo->getName(*AliasSet)
<< "[%reg" << VirtReg <<"], removing it from live set\n";
removePhysReg(*AliasSet);
}
}
}
}
// Loop over all of the operands of the instruction, spilling registers that
// are defined, and marking explicit destinations in the PhysRegsUsed map.
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand& MO = MI->getOperand(i);
if (MO.isReg() && MO.isDef() && !MO.isImplicit() && MO.getReg() &&
TargetRegisterInfo::isPhysicalRegister(MO.getReg())) {
unsigned Reg = MO.getReg();
if (PhysRegsUsed[Reg] == -2) continue; // Something like ESP.
// These are extra physical register defs when a sub-register
// is defined (def of a sub-register is a read/mod/write of the
// larger registers). Ignore.
if (isReadModWriteImplicitDef(MI, MO.getReg())) continue;
MF->getRegInfo().setPhysRegUsed(Reg);
spillPhysReg(MBB, MI, Reg, true); // Spill any existing value in reg
PhysRegsUsed[Reg] = 0; // It is free and reserved now
for (const unsigned *AliasSet = RegInfo->getSubRegisters(Reg);
*AliasSet; ++AliasSet) {
if (PhysRegsUsed[*AliasSet] != -2) {
PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now
MF->getRegInfo().setPhysRegUsed(*AliasSet);
}
}
}
}
// Loop over the implicit defs, spilling them as well.
if (TID.getImplicitDefs()) {
for (const unsigned *ImplicitDefs = TID.getImplicitDefs();
*ImplicitDefs; ++ImplicitDefs) {
unsigned Reg = *ImplicitDefs;
if (PhysRegsUsed[Reg] != -2) {
spillPhysReg(MBB, MI, Reg, true);
PhysRegsUsed[Reg] = 0; // It is free and reserved now
}
MF->getRegInfo().setPhysRegUsed(Reg);
for (const unsigned *AliasSet = RegInfo->getSubRegisters(Reg);
*AliasSet; ++AliasSet) {
if (PhysRegsUsed[*AliasSet] != -2) {
PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now
MF->getRegInfo().setPhysRegUsed(*AliasSet);
}
}
}
}
SmallVector<unsigned, 8> DeadDefs;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand& MO = MI->getOperand(i);
if (MO.isReg() && MO.isDead())
DeadDefs.push_back(MO.getReg());
}
// Okay, we have allocated all of the source operands and spilled any values
// that would be destroyed by defs of this instruction. Loop over the
// explicit defs and assign them to a register, spilling incoming values if
// we need to scavenge a register.
//
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand& MO = MI->getOperand(i);
if (MO.isReg() && MO.isDef() && MO.getReg() &&
TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
unsigned DestVirtReg = MO.getReg();
unsigned DestPhysReg;
// If DestVirtReg already has a value, use it.
if (!(DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg)))
DestPhysReg = chooseReg(MBB, MI, DestVirtReg);
MF->getRegInfo().setPhysRegUsed(DestPhysReg);
markVirtRegModified(DestVirtReg);
MI->getOperand(i).setReg(DestPhysReg); // Assign the output register
}
}
// If this instruction defines any registers that are immediately dead,
// kill them now.
//
for (unsigned i = 0, e = DeadDefs.size(); i != e; ++i) {
unsigned VirtReg = DeadDefs[i];
unsigned PhysReg = VirtReg;
if (TargetRegisterInfo::isVirtualRegister(VirtReg)) {
unsigned &PhysRegSlot = getVirt2PhysRegMapSlot(VirtReg);
PhysReg = PhysRegSlot;
assert(PhysReg != 0);
PhysRegSlot = 0;
} else if (PhysRegsUsed[PhysReg] == -2) {
// Unallocatable register dead, ignore.
continue;
}
if (PhysReg) {
DOUT << " Register " << RegInfo->getName(PhysReg)
<< " [%reg" << VirtReg
<< "] is never used, removing it from live set\n";
removePhysReg(PhysReg);
for (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg);
*AliasSet; ++AliasSet) {
if (PhysRegsUsed[*AliasSet] != -2) {
DOUT << " Register " << RegInfo->getName(*AliasSet)
<< " [%reg" << *AliasSet
<< "] is never used, removing it from live set\n";
removePhysReg(*AliasSet);
}
}
}
}
// Finally, if this is a noop copy instruction, zap it.
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if (TII.isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
SrcReg == DstReg)
MBB.erase(MI);
}
MachineBasicBlock::iterator MI = MBB.getFirstTerminator();
// Spill all physical registers holding virtual registers now.
for (unsigned i = 0, e = RegInfo->getNumRegs(); i != e; ++i)
if (PhysRegsUsed[i] != -1 && PhysRegsUsed[i] != -2) {
if (unsigned VirtReg = PhysRegsUsed[i])
spillVirtReg(MBB, MI, VirtReg, i);
else
removePhysReg(i);
}
}
/// runOnMachineFunction - Register allocate the whole function
///
bool RABigBlock::runOnMachineFunction(MachineFunction &Fn) {
DOUT << "Machine Function " << "\n";
MF = &Fn;
TM = &Fn.getTarget();
RegInfo = TM->getRegisterInfo();
PhysRegsUsed.assign(RegInfo->getNumRegs(), -1);
// At various places we want to efficiently check to see whether a register
// is allocatable. To handle this, we mark all unallocatable registers as
// being pinned down, permanently.
{
BitVector Allocable = RegInfo->getAllocatableSet(Fn);
for (unsigned i = 0, e = Allocable.size(); i != e; ++i)
if (!Allocable[i])
PhysRegsUsed[i] = -2; // Mark the reg unallocable.
}
// initialize the virtual->physical register map to have a 'null'
// mapping for all virtual registers
Virt2PhysRegMap.grow(MF->getRegInfo().getLastVirtReg());
StackSlotForVirtReg.grow(MF->getRegInfo().getLastVirtReg());
VirtRegModified.resize(MF->getRegInfo().getLastVirtReg() -
TargetRegisterInfo::FirstVirtualRegister + 1, 0);
// Loop over all of the basic blocks, eliminating virtual register references
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
MBB != MBBe; ++MBB) {
// fill out the read timetable
FillVRegReadTable(*MBB);
// use it to allocate the BB
AllocateBasicBlock(*MBB);
// clear it
VRegReadTable.clear();
}
StackSlotForVirtReg.clear();
PhysRegsUsed.clear();
VirtRegModified.clear();
Virt2PhysRegMap.clear();
return true;
}
FunctionPass *llvm::createBigBlockRegisterAllocator() {
return new RABigBlock();
}

View File

@ -1,257 +0,0 @@
//===-- RegAllocSimple.cpp - A simple generic register allocator ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a simple register allocator. *Very* simple: It immediate
// spills every value right after it is computed, and it reloads all used
// operands from the spill area to temporary registers before each instruction.
// It does not keep values in registers across instructions.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "regalloc"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include <map>
using namespace llvm;
STATISTIC(NumStores, "Number of stores added");
STATISTIC(NumLoads , "Number of loads added");
namespace {
static RegisterRegAlloc
simpleRegAlloc("simple", "simple register allocator",
createSimpleRegisterAllocator);
class VISIBILITY_HIDDEN RegAllocSimple : public MachineFunctionPass {
public:
static char ID;
RegAllocSimple() : MachineFunctionPass(&ID) {}
private:
MachineFunction *MF;
const TargetMachine *TM;
const TargetRegisterInfo *TRI;
const TargetInstrInfo *TII;
// StackSlotForVirtReg - Maps SSA Regs => frame index on the stack where
// these values are spilled
std::map<unsigned, int> StackSlotForVirtReg;
// RegsUsed - Keep track of what registers are currently in use. This is a
// bitset.
std::vector<bool> RegsUsed;
// RegClassIdx - Maps RegClass => which index we can take a register
// from. Since this is a simple register allocator, when we need a register
// of a certain class, we just take the next available one.
std::map<const TargetRegisterClass*, unsigned> RegClassIdx;
public:
virtual const char *getPassName() const {
return "Simple Register Allocator";
}
/// runOnMachineFunction - Register allocate the whole function
bool runOnMachineFunction(MachineFunction &Fn);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequiredID(PHIEliminationID); // Eliminate PHI nodes
MachineFunctionPass::getAnalysisUsage(AU);
}
private:
/// AllocateBasicBlock - Register allocate the specified basic block.
void AllocateBasicBlock(MachineBasicBlock &MBB);
/// getStackSpaceFor - This returns the offset of the specified virtual
/// register on the stack, allocating space if necessary.
int getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC);
/// Given a virtual register, return a compatible physical register that is
/// currently unused.
///
/// Side effect: marks that register as being used until manually cleared
///
unsigned getFreeReg(unsigned virtualReg);
/// Moves value from memory into that register
unsigned reloadVirtReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I, unsigned VirtReg);
/// Saves reg value on the stack (maps virtual register to stack value)
void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned VirtReg, unsigned PhysReg);
};
char RegAllocSimple::ID = 0;
}
/// getStackSpaceFor - This allocates space for the specified virtual
/// register to be held on the stack.
int RegAllocSimple::getStackSpaceFor(unsigned VirtReg,
const TargetRegisterClass *RC) {
// Find the location VirtReg would belong...
std::map<unsigned, int>::iterator I = StackSlotForVirtReg.find(VirtReg);
if (I != StackSlotForVirtReg.end())
return I->second; // Already has space allocated?
// Allocate a new stack object for this spill location...
int FrameIdx = MF->getFrameInfo()->CreateStackObject(RC->getSize(),
RC->getAlignment());
// Assign the slot...
StackSlotForVirtReg.insert(I, std::make_pair(VirtReg, FrameIdx));
return FrameIdx;
}
unsigned RegAllocSimple::getFreeReg(unsigned virtualReg) {
const TargetRegisterClass* RC = MF->getRegInfo().getRegClass(virtualReg);
TargetRegisterClass::iterator RI = RC->allocation_order_begin(*MF);
#ifndef NDEBUG
TargetRegisterClass::iterator RE = RC->allocation_order_end(*MF);
#endif
while (1) {
unsigned regIdx = RegClassIdx[RC]++;
assert(RI+regIdx != RE && "Not enough registers!");
unsigned PhysReg = *(RI+regIdx);
if (!RegsUsed[PhysReg]) {
MF->getRegInfo().setPhysRegUsed(PhysReg);
return PhysReg;
}
}
}
unsigned RegAllocSimple::reloadVirtReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned VirtReg) {
const TargetRegisterClass* RC = MF->getRegInfo().getRegClass(VirtReg);
int FrameIdx = getStackSpaceFor(VirtReg, RC);
unsigned PhysReg = getFreeReg(VirtReg);
// Add move instruction(s)
++NumLoads;
TII->loadRegFromStackSlot(MBB, I, PhysReg, FrameIdx, RC);
return PhysReg;
}
void RegAllocSimple::spillVirtReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned VirtReg, unsigned PhysReg) {
const TargetRegisterClass* RC = MF->getRegInfo().getRegClass(VirtReg);
int FrameIdx = getStackSpaceFor(VirtReg, RC);
// Add move instruction(s)
++NumStores;
TII->storeRegToStackSlot(MBB, I, PhysReg, true, FrameIdx, RC);
}
void RegAllocSimple::AllocateBasicBlock(MachineBasicBlock &MBB) {
// loop over each instruction
for (MachineBasicBlock::iterator MI = MBB.begin(); MI != MBB.end(); ++MI) {
// Made to combat the incorrect allocation of r2 = add r1, r1
std::map<unsigned, unsigned> Virt2PhysRegMap;
RegsUsed.resize(TRI->getNumRegs());
// This is a preliminary pass that will invalidate any registers that are
// used by the instruction (including implicit uses).
const TargetInstrDesc &Desc = MI->getDesc();
const unsigned *Regs;
if (Desc.ImplicitUses) {
for (Regs = Desc.ImplicitUses; *Regs; ++Regs)
RegsUsed[*Regs] = true;
}
if (Desc.ImplicitDefs) {
for (Regs = Desc.ImplicitDefs; *Regs; ++Regs) {
RegsUsed[*Regs] = true;
MF->getRegInfo().setPhysRegUsed(*Regs);
}
}
// Loop over uses, move from memory into registers.
for (int i = MI->getNumOperands() - 1; i >= 0; --i) {
MachineOperand &MO = MI->getOperand(i);
if (MO.isReg() && MO.getReg() &&
TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
unsigned virtualReg = (unsigned) MO.getReg();
DOUT << "op: " << MO << "\n";
DOUT << "\t inst[" << i << "]: ";
DEBUG(MI->print(*cerr.stream(), TM));
// make sure the same virtual register maps to the same physical
// register in any given instruction
unsigned physReg = Virt2PhysRegMap[virtualReg];
if (physReg == 0) {
if (MO.isDef()) {
unsigned TiedOp;
if (!MI->isRegTiedToUseOperand(i, &TiedOp)) {
physReg = getFreeReg(virtualReg);
} else {
// must be same register number as the source operand that is
// tied to. This maps a = b + c into b = b + c, and saves b into
// a's spot.
assert(MI->getOperand(TiedOp).isReg() &&
MI->getOperand(TiedOp).getReg() &&
MI->getOperand(TiedOp).isUse() &&
"Two address instruction invalid!");
physReg = MI->getOperand(TiedOp).getReg();
}
spillVirtReg(MBB, next(MI), virtualReg, physReg);
} else {
physReg = reloadVirtReg(MBB, MI, virtualReg);
Virt2PhysRegMap[virtualReg] = physReg;
}
}
MO.setReg(physReg);
DOUT << "virt: " << virtualReg << ", phys: " << MO.getReg() << "\n";
}
}
RegClassIdx.clear();
RegsUsed.clear();
}
}
/// runOnMachineFunction - Register allocate the whole function
///
bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) {
DOUT << "Machine Function\n";
MF = &Fn;
TM = &MF->getTarget();
TRI = TM->getRegisterInfo();
TII = TM->getInstrInfo();
// Loop over all of the basic blocks, eliminating virtual register references
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
MBB != MBBe; ++MBB)
AllocateBasicBlock(*MBB);
StackSlotForVirtReg.clear();
return true;
}
FunctionPass *llvm::createSimpleRegisterAllocator() {
return new RegAllocSimple();
}

View File

@ -1,671 +0,0 @@
//===---- ScheduleDAGEmit.cpp - Emit routines for the ScheduleDAG class ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements the Emit routines for the ScheduleDAG class, which creates
// MachineInstrs according to the computed schedule.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "pre-RA-sched"
#include "ScheduleDAGSDNodes.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
using namespace llvm;
/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
/// implicit physical register output.
void ScheduleDAGSDNodes::
EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned,
unsigned SrcReg, DenseMap<SDValue, unsigned> &VRBaseMap) {
unsigned VRBase = 0;
if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
// Just use the input register directly!
SDValue Op(Node, ResNo);
if (IsClone)
VRBaseMap.erase(Op);
bool isNew = VRBaseMap.insert(std::make_pair(Op, SrcReg)).second;
isNew = isNew; // Silence compiler warning.
assert(isNew && "Node emitted out of order - early");
return;
}
// If the node is only used by a CopyToReg and the dest reg is a vreg, use
// the CopyToReg'd destination register instead of creating a new vreg.
bool MatchReg = true;
const TargetRegisterClass *UseRC = NULL;
if (!IsClone && !IsCloned)
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
UI != E; ++UI) {
SDNode *User = *UI;
bool Match = true;
if (User->getOpcode() == ISD::CopyToReg &&
User->getOperand(2).getNode() == Node &&
User->getOperand(2).getResNo() == ResNo) {
unsigned DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
VRBase = DestReg;
Match = false;
} else if (DestReg != SrcReg)
Match = false;
} else {
for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
SDValue Op = User->getOperand(i);
if (Op.getNode() != Node || Op.getResNo() != ResNo)
continue;
MVT VT = Node->getValueType(Op.getResNo());
if (VT == MVT::Other || VT == MVT::Flag)
continue;
Match = false;
if (User->isMachineOpcode()) {
const TargetInstrDesc &II = TII->get(User->getMachineOpcode());
const TargetRegisterClass *RC =
getInstrOperandRegClass(TRI, II, i+II.getNumDefs());
if (!UseRC)
UseRC = RC;
else if (RC) {
if (UseRC->hasSuperClass(RC))
UseRC = RC;
else
assert((UseRC == RC || RC->hasSuperClass(UseRC)) &&
"Multiple uses expecting different register classes!");
}
}
}
}
MatchReg &= Match;
if (VRBase)
break;
}
MVT VT = Node->getValueType(ResNo);
const TargetRegisterClass *SrcRC = 0, *DstRC = 0;
SrcRC = TRI->getPhysicalRegisterRegClass(SrcReg, VT);
// Figure out the register class to create for the destreg.
if (VRBase) {
DstRC = MRI.getRegClass(VRBase);
} else if (UseRC) {
assert(UseRC->hasType(VT) && "Incompatible phys register def and uses!");
DstRC = UseRC;
} else {
DstRC = TLI->getRegClassFor(VT);
}
// If all uses are reading from the src physical register and copying the
// register is either impossible or very expensive, then don't create a copy.
if (MatchReg && SrcRC->getCopyCost() < 0) {
VRBase = SrcReg;
} else {
// Create the reg, emit the copy.
VRBase = MRI.createVirtualRegister(DstRC);
bool Emitted = TII->copyRegToReg(*BB, InsertPos, VRBase, SrcReg,
DstRC, SrcRC);
assert(Emitted && "Unable to issue a copy instruction!\n");
(void) Emitted;
}
SDValue Op(Node, ResNo);
if (IsClone)
VRBaseMap.erase(Op);
bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second;
isNew = isNew; // Silence compiler warning.
assert(isNew && "Node emitted out of order - early");
}
/// getDstOfCopyToRegUse - If the only use of the specified result number of
/// node is a CopyToReg, return its destination register. Return 0 otherwise.
unsigned ScheduleDAGSDNodes::getDstOfOnlyCopyToRegUse(SDNode *Node,
unsigned ResNo) const {
if (!Node->hasOneUse())
return 0;
SDNode *User = *Node->use_begin();
if (User->getOpcode() == ISD::CopyToReg &&
User->getOperand(2).getNode() == Node &&
User->getOperand(2).getResNo() == ResNo) {
unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
if (TargetRegisterInfo::isVirtualRegister(Reg))
return Reg;
}
return 0;
}
void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
const TargetInstrDesc &II,
bool IsClone, bool IsCloned,
DenseMap<SDValue, unsigned> &VRBaseMap) {
assert(Node->getMachineOpcode() != TargetInstrInfo::IMPLICIT_DEF &&
"IMPLICIT_DEF should have been handled as a special case elsewhere!");
for (unsigned i = 0; i < II.getNumDefs(); ++i) {
// If the specific node value is only used by a CopyToReg and the dest reg
// is a vreg in the same register class, use the CopyToReg'd destination
// register instead of creating a new vreg.
unsigned VRBase = 0;
const TargetRegisterClass *RC = getInstrOperandRegClass(TRI, II, i);
if (!IsClone && !IsCloned)
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
UI != E; ++UI) {
SDNode *User = *UI;
if (User->getOpcode() == ISD::CopyToReg &&
User->getOperand(2).getNode() == Node &&
User->getOperand(2).getResNo() == i) {
unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
if (RegRC == RC) {
VRBase = Reg;
MI->addOperand(MachineOperand::CreateReg(Reg, true));
break;
}
}
}
}
// Create the result registers for this node and add the result regs to
// the machine instruction.
if (VRBase == 0) {
assert(RC && "Isn't a register operand!");
VRBase = MRI.createVirtualRegister(RC);
MI->addOperand(MachineOperand::CreateReg(VRBase, true));
}
SDValue Op(Node, i);
if (IsClone)
VRBaseMap.erase(Op);
bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second;
isNew = isNew; // Silence compiler warning.
assert(isNew && "Node emitted out of order - early");
}
}
/// getVR - Return the virtual register corresponding to the specified result
/// of the specified node.
unsigned ScheduleDAGSDNodes::getVR(SDValue Op,
DenseMap<SDValue, unsigned> &VRBaseMap) {
if (Op.isMachineOpcode() &&
Op.getMachineOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
// Add an IMPLICIT_DEF instruction before every use.
unsigned VReg = getDstOfOnlyCopyToRegUse(Op.getNode(), Op.getResNo());
// IMPLICIT_DEF can produce any type of result so its TargetInstrDesc
// does not include operand register class info.
if (!VReg) {
const TargetRegisterClass *RC = TLI->getRegClassFor(Op.getValueType());
VReg = MRI.createVirtualRegister(RC);
}
BuildMI(BB, Op.getDebugLoc(), TII->get(TargetInstrInfo::IMPLICIT_DEF),VReg);
return VReg;
}
DenseMap<SDValue, unsigned>::iterator I = VRBaseMap.find(Op);
assert(I != VRBaseMap.end() && "Node emitted out of order - late");
return I->second;
}
/// AddRegisterOperand - Add the specified register as an operand to the
/// specified machine instr. Insert register copies if the register is
/// not in the required register class.
void
ScheduleDAGSDNodes::AddRegisterOperand(MachineInstr *MI, SDValue Op,
unsigned IIOpNum,
const TargetInstrDesc *II,
DenseMap<SDValue, unsigned> &VRBaseMap) {
assert(Op.getValueType() != MVT::Other &&
Op.getValueType() != MVT::Flag &&
"Chain and flag operands should occur at end of operand list!");
// Get/emit the operand.
unsigned VReg = getVR(Op, VRBaseMap);
assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?");
const TargetInstrDesc &TID = MI->getDesc();
bool isOptDef = IIOpNum < TID.getNumOperands() &&
TID.OpInfo[IIOpNum].isOptionalDef();
// If the instruction requires a register in a different class, create
// a new virtual register and copy the value into it.
if (II) {
const TargetRegisterClass *SrcRC =
MRI.getRegClass(VReg);
const TargetRegisterClass *DstRC =
getInstrOperandRegClass(TRI, *II, IIOpNum);
assert((DstRC || (TID.isVariadic() && IIOpNum >= TID.getNumOperands())) &&
"Don't have operand info for this instruction!");
if (DstRC && SrcRC != DstRC && !SrcRC->hasSuperClass(DstRC)) {
unsigned NewVReg = MRI.createVirtualRegister(DstRC);
bool Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
DstRC, SrcRC);
assert(Emitted && "Unable to issue a copy instruction!\n");
(void) Emitted;
VReg = NewVReg;
}
}
MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef));
}
/// AddOperand - Add the specified operand to the specified machine instr. II
/// specifies the instruction information for the node, and IIOpNum is the
/// operand number (in the II) that we are adding. IIOpNum and II are used for
/// assertions only.
void ScheduleDAGSDNodes::AddOperand(MachineInstr *MI, SDValue Op,
unsigned IIOpNum,
const TargetInstrDesc *II,
DenseMap<SDValue, unsigned> &VRBaseMap) {
if (Op.isMachineOpcode()) {
AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap);
} else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateImm(C->getZExtValue()));
} else if (ConstantFPSDNode *F = dyn_cast<ConstantFPSDNode>(Op)) {
const ConstantFP *CFP = F->getConstantFPValue();
MI->addOperand(MachineOperand::CreateFPImm(CFP));
} else if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateReg(R->getReg(), false));
} else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(), TGA->getOffset(),
TGA->getTargetFlags()));
} else if (BasicBlockSDNode *BBNode = dyn_cast<BasicBlockSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateMBB(BBNode->getBasicBlock()));
} else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateFI(FI->getIndex()));
} else if (JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateJTI(JT->getIndex(),
JT->getTargetFlags()));
} else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op)) {
int Offset = CP->getOffset();
unsigned Align = CP->getAlignment();
const Type *Type = CP->getType();
// MachineConstantPool wants an explicit alignment.
if (Align == 0) {
Align = TM.getTargetData()->getPrefTypeAlignment(Type);
if (Align == 0) {
// Alignment of vector types. FIXME!
Align = TM.getTargetData()->getTypeAllocSize(Type);
}
}
unsigned Idx;
if (CP->isMachineConstantPoolEntry())
Idx = ConstPool->getConstantPoolIndex(CP->getMachineCPVal(), Align);
else
Idx = ConstPool->getConstantPoolIndex(CP->getConstVal(), Align);
MI->addOperand(MachineOperand::CreateCPI(Idx, Offset,
CP->getTargetFlags()));
} else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateES(ES->getSymbol(), 0,
ES->getTargetFlags()));
} else {
assert(Op.getValueType() != MVT::Other &&
Op.getValueType() != MVT::Flag &&
"Chain and flag operands should occur at end of operand list!");
AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap);
}
}
/// getSuperRegisterRegClass - Returns the register class of a superreg A whose
/// "SubIdx"'th sub-register class is the specified register class and whose
/// type matches the specified type.
static const TargetRegisterClass*
getSuperRegisterRegClass(const TargetRegisterClass *TRC,
unsigned SubIdx, MVT VT) {
// Pick the register class of the superegister for this type
for (TargetRegisterInfo::regclass_iterator I = TRC->superregclasses_begin(),
E = TRC->superregclasses_end(); I != E; ++I)
if ((*I)->hasType(VT) && (*I)->getSubRegisterRegClass(SubIdx) == TRC)
return *I;
assert(false && "Couldn't find the register class");
return 0;
}
/// EmitSubregNode - Generate machine code for subreg nodes.
///
void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
DenseMap<SDValue, unsigned> &VRBaseMap){
unsigned VRBase = 0;
unsigned Opc = Node->getMachineOpcode();
// If the node is only used by a CopyToReg and the dest reg is a vreg, use
// the CopyToReg'd destination register instead of creating a new vreg.
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
UI != E; ++UI) {
SDNode *User = *UI;
if (User->getOpcode() == ISD::CopyToReg &&
User->getOperand(2).getNode() == Node) {
unsigned DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
VRBase = DestReg;
break;
}
}
}
if (Opc == TargetInstrInfo::EXTRACT_SUBREG) {
unsigned SubIdx = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
// Create the extract_subreg machine instruction.
MachineInstr *MI = BuildMI(MF, Node->getDebugLoc(),
TII->get(TargetInstrInfo::EXTRACT_SUBREG));
// Figure out the register class to create for the destreg.
unsigned VReg = getVR(Node->getOperand(0), VRBaseMap);
const TargetRegisterClass *TRC = MRI.getRegClass(VReg);
const TargetRegisterClass *SRC = TRC->getSubRegisterRegClass(SubIdx);
assert(SRC && "Invalid subregister index in EXTRACT_SUBREG");
// Figure out the register class to create for the destreg.
// Note that if we're going to directly use an existing register,
// it must be precisely the required class, and not a subclass
// thereof.
if (VRBase == 0 || SRC != MRI.getRegClass(VRBase)) {
// Create the reg
assert(SRC && "Couldn't find source register class");
VRBase = MRI.createVirtualRegister(SRC);
}
// Add def, source, and subreg index
MI->addOperand(MachineOperand::CreateReg(VRBase, true));
AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap);
MI->addOperand(MachineOperand::CreateImm(SubIdx));
BB->insert(InsertPos, MI);
} else if (Opc == TargetInstrInfo::INSERT_SUBREG ||
Opc == TargetInstrInfo::SUBREG_TO_REG) {
SDValue N0 = Node->getOperand(0);
SDValue N1 = Node->getOperand(1);
SDValue N2 = Node->getOperand(2);
unsigned SubReg = getVR(N1, VRBaseMap);
unsigned SubIdx = cast<ConstantSDNode>(N2)->getZExtValue();
const TargetRegisterClass *TRC = MRI.getRegClass(SubReg);
const TargetRegisterClass *SRC =
getSuperRegisterRegClass(TRC, SubIdx,
Node->getValueType(0));
// Figure out the register class to create for the destreg.
// Note that if we're going to directly use an existing register,
// it must be precisely the required class, and not a subclass
// thereof.
if (VRBase == 0 || SRC != MRI.getRegClass(VRBase)) {
// Create the reg
assert(SRC && "Couldn't find source register class");
VRBase = MRI.createVirtualRegister(SRC);
}
// Create the insert_subreg or subreg_to_reg machine instruction.
MachineInstr *MI = BuildMI(MF, Node->getDebugLoc(), TII->get(Opc));
MI->addOperand(MachineOperand::CreateReg(VRBase, true));
// If creating a subreg_to_reg, then the first input operand
// is an implicit value immediate, otherwise it's a register
if (Opc == TargetInstrInfo::SUBREG_TO_REG) {
const ConstantSDNode *SD = cast<ConstantSDNode>(N0);
MI->addOperand(MachineOperand::CreateImm(SD->getZExtValue()));
} else
AddOperand(MI, N0, 0, 0, VRBaseMap);
// Add the subregster being inserted
AddOperand(MI, N1, 0, 0, VRBaseMap);
MI->addOperand(MachineOperand::CreateImm(SubIdx));
BB->insert(InsertPos, MI);
} else
assert(0 && "Node is not insert_subreg, extract_subreg, or subreg_to_reg");
SDValue Op(Node, 0);
bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second;
isNew = isNew; // Silence compiler warning.
assert(isNew && "Node emitted out of order - early");
}
/// EmitCopyToRegClassNode - Generate machine code for COPY_TO_REGCLASS nodes.
/// COPY_TO_REGCLASS is just a normal copy, except that the destination
/// register is constrained to be in a particular register class.
///
void
ScheduleDAGSDNodes::EmitCopyToRegClassNode(SDNode *Node,
DenseMap<SDValue, unsigned> &VRBaseMap) {
unsigned VReg = getVR(Node->getOperand(0), VRBaseMap);
const TargetRegisterClass *SrcRC = MRI.getRegClass(VReg);
unsigned DstRCIdx = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
const TargetRegisterClass *DstRC = TRI->getRegClass(DstRCIdx);
// Create the new VReg in the destination class and emit a copy.
unsigned NewVReg = MRI.createVirtualRegister(DstRC);
bool Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
DstRC, SrcRC);
assert(Emitted &&
"Unable to issue a copy instruction for a COPY_TO_REGCLASS node!\n");
(void) Emitted;
SDValue Op(Node, 0);
bool isNew = VRBaseMap.insert(std::make_pair(Op, NewVReg)).second;
isNew = isNew; // Silence compiler warning.
assert(isNew && "Node emitted out of order - early");
}
/// EmitNode - Generate machine code for an node and needed dependencies.
///
void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
DenseMap<SDValue, unsigned> &VRBaseMap) {
// If machine instruction
if (Node->isMachineOpcode()) {
unsigned Opc = Node->getMachineOpcode();
// Handle subreg insert/extract specially
if (Opc == TargetInstrInfo::EXTRACT_SUBREG ||
Opc == TargetInstrInfo::INSERT_SUBREG ||
Opc == TargetInstrInfo::SUBREG_TO_REG) {
EmitSubregNode(Node, VRBaseMap);
return;
}
// Handle COPY_TO_REGCLASS specially.
if (Opc == TargetInstrInfo::COPY_TO_REGCLASS) {
EmitCopyToRegClassNode(Node, VRBaseMap);
return;
}
if (Opc == TargetInstrInfo::IMPLICIT_DEF)
// We want a unique VR for each IMPLICIT_DEF use.
return;
const TargetInstrDesc &II = TII->get(Opc);
unsigned NumResults = CountResults(Node);
unsigned NodeOperands = CountOperands(Node);
unsigned MemOperandsEnd = ComputeMemOperandsEnd(Node);
bool HasPhysRegOuts = (NumResults > II.getNumDefs()) &&
II.getImplicitDefs() != 0;
#ifndef NDEBUG
unsigned NumMIOperands = NodeOperands + NumResults;
assert((II.getNumOperands() == NumMIOperands ||
HasPhysRegOuts || II.isVariadic()) &&
"#operands for dag node doesn't match .td file!");
#endif
// Create the new machine instruction.
MachineInstr *MI = BuildMI(MF, Node->getDebugLoc(), II);
// Add result register values for things that are defined by this
// instruction.
if (NumResults)
CreateVirtualRegisters(Node, MI, II, IsClone, IsCloned, VRBaseMap);
// Emit all of the actual operands of this instruction, adding them to the
// instruction as appropriate.
for (unsigned i = 0; i != NodeOperands; ++i)
AddOperand(MI, Node->getOperand(i), i+II.getNumDefs(), &II, VRBaseMap);
// Emit all of the memory operands of this instruction
for (unsigned i = NodeOperands; i != MemOperandsEnd; ++i)
AddMemOperand(MI, cast<MemOperandSDNode>(Node->getOperand(i))->MO);
if (II.usesCustomDAGSchedInsertionHook()) {
// Insert this instruction into the basic block using a target
// specific inserter which may returns a new basic block.
BB = TLI->EmitInstrWithCustomInserter(MI, BB);
InsertPos = BB->end();
} else {
BB->insert(InsertPos, MI);
}
// Additional results must be an physical register def.
if (HasPhysRegOuts) {
for (unsigned i = II.getNumDefs(); i < NumResults; ++i) {
unsigned Reg = II.getImplicitDefs()[i - II.getNumDefs()];
if (Node->hasAnyUseOfValue(i))
EmitCopyFromReg(Node, i, IsClone, IsCloned, Reg, VRBaseMap);
}
}
return;
}
switch (Node->getOpcode()) {
default:
#ifndef NDEBUG
Node->dump(DAG);
#endif
assert(0 && "This target-independent node should have been selected!");
break;
case ISD::EntryToken:
assert(0 && "EntryToken should have been excluded from the schedule!");
break;
case ISD::TokenFactor: // fall thru
break;
case ISD::CopyToReg: {
unsigned SrcReg;
SDValue SrcVal = Node->getOperand(2);
if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(SrcVal))
SrcReg = R->getReg();
else
SrcReg = getVR(SrcVal, VRBaseMap);
unsigned DestReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
if (SrcReg == DestReg) // Coalesced away the copy? Ignore.
break;
const TargetRegisterClass *SrcTRC = 0, *DstTRC = 0;
// Get the register classes of the src/dst.
if (TargetRegisterInfo::isVirtualRegister(SrcReg))
SrcTRC = MRI.getRegClass(SrcReg);
else
SrcTRC = TRI->getPhysicalRegisterRegClass(SrcReg,SrcVal.getValueType());
if (TargetRegisterInfo::isVirtualRegister(DestReg))
DstTRC = MRI.getRegClass(DestReg);
else
DstTRC = TRI->getPhysicalRegisterRegClass(DestReg,
Node->getOperand(1).getValueType());
bool Emitted = TII->copyRegToReg(*BB, InsertPos, DestReg, SrcReg,
DstTRC, SrcTRC);
assert(Emitted && "Unable to issue a copy instruction!\n");
(void) Emitted;
break;
}
case ISD::CopyFromReg: {
unsigned SrcReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
EmitCopyFromReg(Node, 0, IsClone, IsCloned, SrcReg, VRBaseMap);
break;
}
case ISD::INLINEASM: {
unsigned NumOps = Node->getNumOperands();
if (Node->getOperand(NumOps-1).getValueType() == MVT::Flag)
--NumOps; // Ignore the flag operand.
// Create the inline asm machine instruction.
MachineInstr *MI = BuildMI(MF, Node->getDebugLoc(),
TII->get(TargetInstrInfo::INLINEASM));
// Add the asm string as an external symbol operand.
const char *AsmStr =
cast<ExternalSymbolSDNode>(Node->getOperand(1))->getSymbol();
MI->addOperand(MachineOperand::CreateES(AsmStr));
// Add all of the operand registers to the instruction.
for (unsigned i = 2; i != NumOps;) {
unsigned Flags =
cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
MI->addOperand(MachineOperand::CreateImm(Flags));
++i; // Skip the ID value.
switch (Flags & 7) {
default: assert(0 && "Bad flags!");
case 2: // Def of register.
for (; NumVals; --NumVals, ++i) {
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
MI->addOperand(MachineOperand::CreateReg(Reg, true));
}
break;
case 6: // Def of earlyclobber register.
for (; NumVals; --NumVals, ++i) {
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
MI->addOperand(MachineOperand::CreateReg(Reg, true, false, false,
false, false, true));
}
break;
case 1: // Use of register.
case 3: // Immediate.
case 4: // Addressing mode.
// The addressing mode has been selected, just add all of the
// operands to the machine instruction.
for (; NumVals; --NumVals, ++i)
AddOperand(MI, Node->getOperand(i), 0, 0, VRBaseMap);
break;
}
}
BB->insert(InsertPos, MI);
break;
}
}
}
/// EmitSchedule - Emit the machine code in scheduled order.
MachineBasicBlock *ScheduleDAGSDNodes::EmitSchedule() {
DenseMap<SDValue, unsigned> VRBaseMap;
DenseMap<SUnit*, unsigned> CopyVRBaseMap;
for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
SUnit *SU = Sequence[i];
if (!SU) {
// Null SUnit* is a noop.
EmitNoop();
continue;
}
// For pre-regalloc scheduling, create instructions corresponding to the
// SDNode and any flagged SDNodes and append them to the block.
if (!SU->getNode()) {
// Emit a copy.
EmitPhysRegCopy(SU, CopyVRBaseMap);
continue;
}
SmallVector<SDNode *, 4> FlaggedNodes;
for (SDNode *N = SU->getNode()->getFlaggedNode(); N;
N = N->getFlaggedNode())
FlaggedNodes.push_back(N);
while (!FlaggedNodes.empty()) {
EmitNode(FlaggedNodes.back(), SU->OrigNode != SU, SU->isCloned,VRBaseMap);
FlaggedNodes.pop_back();
}
EmitNode(SU->getNode(), SU->OrigNode != SU, SU->isCloned, VRBaseMap);
}
return BB;
}

View File

@ -1,10 +0,0 @@
add_llvm_library(LLVMDebugger
Debugger.cpp
ProgramInfo.cpp
RuntimeInfo.cpp
SourceFile.cpp
SourceLanguage-CFamily.cpp
SourceLanguage-CPlusPlus.cpp
SourceLanguage-Unknown.cpp
SourceLanguage.cpp
)

View File

@ -1,231 +0,0 @@
//===-- Debugger.cpp - LLVM debugger library implementation ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the main implementation of the LLVM debugger library.
//
//===----------------------------------------------------------------------===//
#include "llvm/Debugger/Debugger.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Debugger/InferiorProcess.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/StringExtras.h"
#include <cstdlib>
#include <memory>
using namespace llvm;
/// Debugger constructor - Initialize the debugger to its initial, empty, state.
///
Debugger::Debugger() : Environment(0), Program(0), Process(0) {
}
Debugger::~Debugger() {
// Killing the program could throw an exception. We don't want to progagate
// the exception out of our destructor though.
try {
killProgram();
} catch (const char *) {
} catch (const std::string &) {
}
unloadProgram();
}
/// getProgramPath - Get the path of the currently loaded program, or an
/// empty string if none is loaded.
std::string Debugger::getProgramPath() const {
return Program ? Program->getModuleIdentifier() : "";
}
static Module *
getMaterializedModuleProvider(const std::string &Filename,
LLVMContext& C) {
std::auto_ptr<MemoryBuffer> Buffer;
Buffer.reset(MemoryBuffer::getFileOrSTDIN(Filename.c_str()));
if (Buffer.get())
return ParseBitcodeFile(Buffer.get(), C);
return 0;
}
/// 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 Debugger::loadProgram(const std::string &Filename, LLVMContext& C) {
if ((Program = getMaterializedModuleProvider(Filename, C)) ||
(Program = getMaterializedModuleProvider(Filename+".bc", C)))
return; // Successfully loaded the program.
// Search the program path for the file...
if (const char *PathS = getenv("PATH")) {
std::string Path = PathS;
std::string Directory = getToken(Path, ":");
while (!Directory.empty()) {
if ((Program = getMaterializedModuleProvider(Directory +"/"+ Filename, C))
|| (Program = getMaterializedModuleProvider(Directory +"/"+ Filename
+ ".bc", C)))
return; // Successfully loaded the program.
Directory = getToken(Path, ":");
}
}
throw "Could not find program '" + Filename + "'!";
}
/// 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 Debugger::unloadProgram() {
if (!isProgramLoaded()) return;
killProgram();
delete Program;
Program = 0;
}
/// 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 Debugger::createProgram() {
if (!isProgramLoaded())
throw "Cannot start program: none is loaded.";
// Kill any existing program.
killProgram();
// Add argv[0] to the arguments vector..
std::vector<std::string> Args(ProgramArguments);
Args.insert(Args.begin(), getProgramPath());
// Start the new program... this could throw if the program cannot be started.
Process = InferiorProcess::create(Program, Args, Environment);
}
InferiorProcess *
InferiorProcess::create(Module *M, const std::vector<std::string> &Arguments,
const char * const *envp) {
throw"No supported binding to inferior processes (debugger not implemented).";
}
/// 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.
void Debugger::killProgram() {
// The destructor takes care of the dirty work.
try {
delete Process;
} catch (...) {
Process = 0;
throw;
}
Process = 0;
}
/// stepProgram - Implement the 'step' command, continuing execution until
/// the next possible stop point.
void Debugger::stepProgram() {
assert(isProgramRunning() && "Cannot step if the program isn't running!");
try {
Process->stepProgram();
} catch (InferiorProcessDead &IPD) {
killProgram();
throw NonErrorException("The program stopped with exit code " +
itostr(IPD.getExitCode()));
} catch (...) {
killProgram();
throw;
}
}
/// nextProgram - Implement the 'next' command, continuing execution until
/// the next possible stop point that is in the current function.
void Debugger::nextProgram() {
assert(isProgramRunning() && "Cannot next if the program isn't running!");
try {
// This should step the process. If the process enters a function, then it
// should 'finish' it. However, figuring this out is tricky. In
// particular, the program can do any of:
// 0. Not change current frame.
// 1. Entering or exiting a region within the current function
// (which changes the frame ID, but which we shouldn't 'finish')
// 2. Exiting the current function (which changes the frame ID)
// 3. Entering a function (which should be 'finish'ed)
// For this reason, we have to be very careful about when we decide to do
// the 'finish'.
// Get the current frame, but don't trust it. It could change...
void *CurrentFrame = Process->getPreviousFrame(0);
// Don't trust the current frame: get the caller frame.
void *ParentFrame = Process->getPreviousFrame(CurrentFrame);
// Ok, we have some information, run the program one step.
Process->stepProgram();
// Where is the new frame? The most common case, by far is that it has not
// been modified (Case #0), in which case we don't need to do anything more.
void *NewFrame = Process->getPreviousFrame(0);
if (NewFrame != CurrentFrame) {
// Ok, the frame changed. If we are case #1, then the parent frame will
// be identical.
void *NewParentFrame = Process->getPreviousFrame(NewFrame);
if (ParentFrame != NewParentFrame) {
// Ok, now we know we aren't case #0 or #1. Check to see if we entered
// a new function. If so, the parent frame will be "CurrentFrame".
if (CurrentFrame == NewParentFrame)
Process->finishProgram(NewFrame);
}
}
} catch (InferiorProcessDead &IPD) {
killProgram();
throw NonErrorException("The program stopped with exit code " +
itostr(IPD.getExitCode()));
} catch (...) {
killProgram();
throw;
}
}
/// finishProgram - Implement the 'finish' command, continuing execution
/// until the specified frame ID returns.
void Debugger::finishProgram(void *Frame) {
assert(isProgramRunning() && "Cannot cont if the program isn't running!");
try {
Process->finishProgram(Frame);
} catch (InferiorProcessDead &IPD) {
killProgram();
throw NonErrorException("The program stopped with exit code " +
itostr(IPD.getExitCode()));
} catch (...) {
killProgram();
throw;
}
}
/// contProgram - Implement the 'cont' command, continuing execution until
/// the next breakpoint is encountered.
void Debugger::contProgram() {
assert(isProgramRunning() && "Cannot cont if the program isn't running!");
try {
Process->contProgram();
} catch (InferiorProcessDead &IPD) {
killProgram();
throw NonErrorException("The program stopped with exit code " +
itostr(IPD.getExitCode()));
} catch (...) {
killProgram();
throw;
}
}

View File

@ -1,16 +0,0 @@
##===- lib/Debugger/Makefile -------------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL = ../..
LIBRARYNAME = LLVMDebugger
EXTRA_DIST = README.txt
REQUIRES_EH := 1
BUILD_ARCHIVE = 1
include $(LEVEL)/Makefile.common

View File

@ -1,375 +0,0 @@
//===-- ProgramInfo.cpp - Compute and cache info about a program ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ProgramInfo and related classes, by sorting through
// the loaded Module.
//
//===----------------------------------------------------------------------===//
#include "llvm/Debugger/ProgramInfo.h"
#include "llvm/Constants.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Intrinsics.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Debugger/SourceFile.h"
#include "llvm/Debugger/SourceLanguage.h"
#include "llvm/Support/SlowOperationInformer.h"
#include "llvm/Support/Streams.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;
/// getGlobalVariablesUsing - Return all of the global variables which have the
/// specified value in their initializer somewhere.
static void getGlobalVariablesUsing(Value *V,
std::vector<GlobalVariable*> &Found) {
for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I))
Found.push_back(GV);
else if (Constant *C = dyn_cast<Constant>(*I))
getGlobalVariablesUsing(C, Found);
}
}
/// getNextStopPoint - Follow the def-use chains of the specified LLVM value,
/// traversing the use chains until we get to a stoppoint. When we do, return
/// the source location of the stoppoint. If we don't find a stoppoint, return
/// null.
static const GlobalVariable *getNextStopPoint(const Value *V, unsigned &LineNo,
unsigned &ColNo) {
// The use-def chains can fork. As such, we pick the lowest numbered one we
// find.
const GlobalVariable *LastDesc = 0;
unsigned LastLineNo = ~0;
unsigned LastColNo = ~0;
for (Value::use_const_iterator UI = V->use_begin(), E = V->use_end();
UI != E; ++UI) {
bool ShouldRecurse = true;
if (cast<Instruction>(*UI)->getOpcode() == Instruction::PHI) {
// Infinite loops == bad, ignore PHI nodes.
ShouldRecurse = false;
} else if (const CallInst *CI = dyn_cast<CallInst>(*UI)) {
// If we found a stop point, check to see if it is earlier than what we
// already have. If so, remember it.
if (CI->getCalledFunction())
if (const DbgStopPointInst *SPI = dyn_cast<DbgStopPointInst>(CI)) {
unsigned CurLineNo = SPI->getLine();
unsigned CurColNo = SPI->getColumn();
const GlobalVariable *CurDesc = 0;
const Value *Op = SPI->getContext();
if ((CurDesc = dyn_cast<GlobalVariable>(Op)) &&
(LineNo < LastLineNo ||
(LineNo == LastLineNo && ColNo < LastColNo))) {
LastDesc = CurDesc;
LastLineNo = CurLineNo;
LastColNo = CurColNo;
}
ShouldRecurse = false;
}
}
// If this is not a phi node or a stopping point, recursively scan the users
// of this instruction to skip over region.begin's and the like.
if (ShouldRecurse) {
unsigned CurLineNo, CurColNo;
if (const GlobalVariable *GV = getNextStopPoint(*UI, CurLineNo,CurColNo)){
if (LineNo < LastLineNo || (LineNo == LastLineNo && ColNo < LastColNo)){
LastDesc = GV;
LastLineNo = CurLineNo;
LastColNo = CurColNo;
}
}
}
}
if (LastDesc) {
LineNo = LastLineNo != ~0U ? LastLineNo : 0;
ColNo = LastColNo != ~0U ? LastColNo : 0;
}
return LastDesc;
}
//===----------------------------------------------------------------------===//
// SourceFileInfo implementation
//
SourceFileInfo::SourceFileInfo(const GlobalVariable *Desc,
const SourceLanguage &Lang)
: Language(&Lang), Descriptor(Desc) {
Version = 0;
SourceText = 0;
if (Desc && Desc->hasInitializer())
if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer()))
if (CS->getNumOperands() > 4) {
if (ConstantInt *CUI = dyn_cast<ConstantInt>(CS->getOperand(1)))
Version = CUI->getZExtValue();
if (!GetConstantStringInfo(CS->getOperand(3), BaseName))
BaseName = "";
if (!GetConstantStringInfo(CS->getOperand(4), Directory))
Directory = "";
}
}
SourceFileInfo::~SourceFileInfo() {
delete SourceText;
}
SourceFile &SourceFileInfo::getSourceText() const {
// FIXME: this should take into account the source search directories!
if (SourceText == 0) { // Read the file in if we haven't already.
sys::Path tmpPath;
if (!Directory.empty())
tmpPath.set(Directory);
tmpPath.appendComponent(BaseName);
if (tmpPath.canRead())
SourceText = new SourceFile(tmpPath.toString(), Descriptor);
else
SourceText = new SourceFile(BaseName, Descriptor);
}
return *SourceText;
}
//===----------------------------------------------------------------------===//
// SourceFunctionInfo implementation
//
SourceFunctionInfo::SourceFunctionInfo(ProgramInfo &PI,
const GlobalVariable *Desc)
: Descriptor(Desc) {
LineNo = ColNo = 0;
if (Desc && Desc->hasInitializer())
if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer()))
if (CS->getNumOperands() > 2) {
// Entry #1 is the file descriptor.
if (const GlobalVariable *GV =
dyn_cast<GlobalVariable>(CS->getOperand(1)))
SourceFile = &PI.getSourceFile(GV);
// Entry #2 is the function name.
if (!GetConstantStringInfo(CS->getOperand(2), Name))
Name = "";
}
}
/// getSourceLocation - This method returns the location of the first stopping
/// point in the function.
void SourceFunctionInfo::getSourceLocation(unsigned &RetLineNo,
unsigned &RetColNo) const {
// If we haven't computed this yet...
if (!LineNo) {
// Look at all of the users of the function descriptor, looking for calls to
// %llvm.dbg.func.start.
for (Value::use_const_iterator UI = Descriptor->use_begin(),
E = Descriptor->use_end(); UI != E; ++UI)
if (const CallInst *CI = dyn_cast<CallInst>(*UI))
if (const Function *F = CI->getCalledFunction())
if (F->getIntrinsicID() == Intrinsic::dbg_func_start) {
// We found the start of the function. Check to see if there are
// any stop points on the use-list of the function start.
const GlobalVariable *SD = getNextStopPoint(CI, LineNo, ColNo);
if (SD) { // We found the first stop point!
// This is just a sanity check.
if (getSourceFile().getDescriptor() != SD)
cout << "WARNING: first line of function is not in the"
<< " file that the function descriptor claims it is in.\n";
break;
}
}
}
RetLineNo = LineNo; RetColNo = ColNo;
}
//===----------------------------------------------------------------------===//
// ProgramInfo implementation
//
ProgramInfo::ProgramInfo(Module *m) : M(m), ProgramTimeStamp(0,0) {
assert(M && "Cannot create program information with a null module!");
sys::PathWithStatus ModPath(M->getModuleIdentifier());
const sys::FileStatus *Stat = ModPath.getFileStatus();
if (Stat)
ProgramTimeStamp = Stat->getTimestamp();
SourceFilesIsComplete = false;
SourceFunctionsIsComplete = false;
}
ProgramInfo::~ProgramInfo() {
// Delete cached information about source program objects...
for (std::map<const GlobalVariable*, SourceFileInfo*>::iterator
I = SourceFiles.begin(), E = SourceFiles.end(); I != E; ++I)
delete I->second;
for (std::map<const GlobalVariable*, SourceFunctionInfo*>::iterator
I = SourceFunctions.begin(), E = SourceFunctions.end(); I != E; ++I)
delete I->second;
// Delete the source language caches.
for (unsigned i = 0, e = LanguageCaches.size(); i != e; ++i)
delete LanguageCaches[i].second;
}
//===----------------------------------------------------------------------===//
// SourceFileInfo tracking...
//
/// 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 &
ProgramInfo::getSourceFile(const GlobalVariable *Desc) {
SourceFileInfo *&Result = SourceFiles[Desc];
if (Result) return *Result;
// Figure out what language this source file comes from...
unsigned LangID = 0; // Zero is unknown language
if (Desc && Desc->hasInitializer())
if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer()))
if (CS->getNumOperands() > 2)
if (ConstantInt *CUI = dyn_cast<ConstantInt>(CS->getOperand(2)))
LangID = CUI->getZExtValue();
const SourceLanguage &Lang = SourceLanguage::get(LangID);
SourceFileInfo *New = Lang.createSourceFileInfo(Desc, *this);
// FIXME: this should check to see if there is already a Filename/WorkingDir
// pair that matches this one. If so, we shouldn't create the duplicate!
//
SourceFileIndex.insert(std::make_pair(New->getBaseName(), New));
return *(Result = New);
}
/// getSourceFiles - Index all of the source files in the program and return
/// a mapping of it. 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*> &
ProgramInfo::getSourceFiles(bool RequiresCompleteMap) {
// If we have a fully populated map, or if the client doesn't need one, just
// return what we have.
if (SourceFilesIsComplete || !RequiresCompleteMap)
return SourceFiles;
// Ok, all of the source file descriptors (compile_unit in dwarf terms),
// should be on the use list of the llvm.dbg.translation_units global.
//
GlobalVariable *Units =
M->getGlobalVariable("llvm.dbg.translation_units", StructType::get());
if (Units == 0)
throw "Program contains no debugging information!";
std::vector<GlobalVariable*> TranslationUnits;
getGlobalVariablesUsing(Units, TranslationUnits);
SlowOperationInformer SOI("building source files index");
// Loop over all of the translation units found, building the SourceFiles
// mapping.
for (unsigned i = 0, e = TranslationUnits.size(); i != e; ++i) {
getSourceFile(TranslationUnits[i]);
if (SOI.progress(i+1, e))
throw "While building source files index, operation cancelled.";
}
// Ok, if we got this far, then we indexed the whole program.
SourceFilesIsComplete = true;
return SourceFiles;
}
/// 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.
const SourceFileInfo &ProgramInfo::getSourceFile(const std::string &Filename) {
std::multimap<std::string, SourceFileInfo*>::const_iterator Start, End;
getSourceFiles();
tie(Start, End) = SourceFileIndex.equal_range(Filename);
if (Start == End) throw "Could not find source file '" + Filename + "'!";
const SourceFileInfo &SFI = *Start->second;
++Start;
if (Start == End) return SFI;
throw "FIXME: Multiple source files with the same name not implemented!";
}
//===----------------------------------------------------------------------===//
// SourceFunctionInfo tracking...
//
/// getFunction - Return 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 &
ProgramInfo::getFunction(const GlobalVariable *Desc) {
SourceFunctionInfo *&Result = SourceFunctions[Desc];
if (Result) return *Result;
// Figure out what language this function comes from...
const GlobalVariable *SourceFileDesc = 0;
if (Desc && Desc->hasInitializer())
if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer()))
if (CS->getNumOperands() > 0)
if (const GlobalVariable *GV =
dyn_cast<GlobalVariable>(CS->getOperand(1)))
SourceFileDesc = GV;
const SourceLanguage &Lang = getSourceFile(SourceFileDesc).getLanguage();
return *(Result = Lang.createSourceFunctionInfo(Desc, *this));
}
// 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*> &
ProgramInfo::getSourceFunctions(bool RequiresCompleteMap) {
if (SourceFunctionsIsComplete || !RequiresCompleteMap)
return SourceFunctions;
// Ok, all of the source function descriptors (subprogram in dwarf terms),
// should be on the use list of the llvm.dbg.translation_units global.
//
GlobalVariable *Units =
M->getGlobalVariable("llvm.dbg.globals", StructType::get());
if (Units == 0)
throw "Program contains no debugging information!";
std::vector<GlobalVariable*> Functions;
getGlobalVariablesUsing(Units, Functions);
SlowOperationInformer SOI("building functions index");
// Loop over all of the functions found, building the SourceFunctions mapping.
for (unsigned i = 0, e = Functions.size(); i != e; ++i) {
getFunction(Functions[i]);
if (SOI.progress(i+1, e))
throw "While functions index, operation cancelled.";
}
// Ok, if we got this far, then we indexed the whole program.
SourceFunctionsIsComplete = true;
return SourceFunctions;
}

View File

@ -1,7 +0,0 @@
//===-- llvm/lib/Debugger/ - LLVM Debugger interfaces ---------------------===//
This directory contains the implementation of the LLVM debugger backend. This
directory builds into a library which can be used by various debugger
front-ends to debug LLVM programs. The current command line LLVM debugger,
llvm-db is currently the only client of this library, but others could be
built, to provide a GUI front-end for example.

View File

@ -1,69 +0,0 @@
//===-- RuntimeInfo.cpp - Compute and cache info about running program ----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the RuntimeInfo and related classes, by querying and
// cachine information from the running inferior process.
//
//===----------------------------------------------------------------------===//
#include "llvm/Debugger/InferiorProcess.h"
#include "llvm/Debugger/ProgramInfo.h"
#include "llvm/Debugger/RuntimeInfo.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// StackFrame class implementation
StackFrame::StackFrame(RuntimeInfo &ri, void *ParentFrameID)
: RI(ri), SourceInfo(0) {
FrameID = RI.getInferiorProcess().getPreviousFrame(ParentFrameID);
if (FrameID == 0) throw "Stack frame does not exist!";
// Compute lazily as needed.
FunctionDesc = 0;
}
const GlobalVariable *StackFrame::getFunctionDesc() {
if (FunctionDesc == 0)
FunctionDesc = RI.getInferiorProcess().getSubprogramDesc(FrameID);
return FunctionDesc;
}
/// getSourceLocation - Return the source location that this stack frame is
/// sitting at.
void StackFrame::getSourceLocation(unsigned &lineNo, unsigned &colNo,
const SourceFileInfo *&sourceInfo) {
if (SourceInfo == 0) {
const GlobalVariable *SourceDesc = 0;
RI.getInferiorProcess().getFrameLocation(FrameID, LineNo,ColNo, SourceDesc);
SourceInfo = &RI.getProgramInfo().getSourceFile(SourceDesc);
}
lineNo = LineNo;
colNo = ColNo;
sourceInfo = SourceInfo;
}
//===----------------------------------------------------------------------===//
// RuntimeInfo class implementation
/// 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 RuntimeInfo::materializeFrame(unsigned ID) {
assert(ID >= CallStack.size() && "no need to materialize this frame!");
void *CurFrame = 0;
if (!CallStack.empty())
CurFrame = CallStack.back().getFrameID();
while (CallStack.size() <= ID) {
CallStack.push_back(StackFrame(*this, CurFrame));
CurFrame = CallStack.back().getFrameID();
}
}

View File

@ -1,82 +0,0 @@
//===-- SourceFile.cpp - SourceFile implementation for the debugger -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SourceFile class for the LLVM debugger.
//
//===----------------------------------------------------------------------===//
#include "llvm/Debugger/SourceFile.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cassert>
using namespace llvm;
static const char EmptyFile = 0;
SourceFile::SourceFile(const std::string &fn, const GlobalVariable *Desc)
: Filename(fn), Descriptor(Desc) {
File.reset(MemoryBuffer::getFileOrSTDIN(fn));
// On error, return an empty buffer.
if (File == 0)
File.reset(MemoryBuffer::getMemBuffer(&EmptyFile, &EmptyFile));
}
SourceFile::~SourceFile() {
}
/// calculateLineOffsets - Compute the LineOffset vector for the current file.
///
void SourceFile::calculateLineOffsets() const {
assert(LineOffset.empty() && "Line offsets already computed!");
const char *BufPtr = File->getBufferStart();
const char *FileStart = BufPtr;
const char *FileEnd = File->getBufferEnd();
do {
LineOffset.push_back(BufPtr-FileStart);
// Scan until we get to a newline.
while (BufPtr != FileEnd && *BufPtr != '\n' && *BufPtr != '\r')
++BufPtr;
if (BufPtr != FileEnd) {
++BufPtr; // Skip over the \n or \r
if (BufPtr[-1] == '\r' && BufPtr != FileEnd && BufPtr[0] == '\n')
++BufPtr; // Skip over dos/windows style \r\n's
}
} while (BufPtr != FileEnd);
}
/// 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.
void SourceFile::getSourceLine(unsigned LineNo, const char *&LineStart,
const char *&LineEnd) const {
LineStart = LineEnd = 0;
if (LineOffset.empty()) calculateLineOffsets();
// Asking for an out-of-range line number?
if (LineNo >= LineOffset.size()) return;
// Otherwise, they are asking for a valid line, which we can fulfill.
LineStart = File->getBufferStart()+LineOffset[LineNo];
if (LineNo+1 < LineOffset.size())
LineEnd = File->getBufferStart()+LineOffset[LineNo+1];
else
LineEnd = File->getBufferEnd();
// If the line ended with a newline, strip it off.
while (LineEnd != LineStart && (LineEnd[-1] == '\n' || LineEnd[-1] == '\r'))
--LineEnd;
assert(LineEnd >= LineStart && "We somehow got our pointers swizzled!");
}

View File

@ -1,28 +0,0 @@
//===-- SourceLanguage-CFamily.cpp - C family SourceLanguage impl ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SourceLanguage class for the C family of languages
// (K&R C, C89, C99, etc).
//
//===----------------------------------------------------------------------===//
#include "llvm/Debugger/SourceLanguage.h"
using namespace llvm;
#if 0
namespace {
struct CSL : public SourceLanguage {
} TheCSourceLanguageInstance;
}
#endif
const SourceLanguage &SourceLanguage::getCFamilyInstance() {
return get(0); // We don't have an implementation for C yet fall back on
// generic
}

View File

@ -1,27 +0,0 @@
//===-- SourceLanguage-CPlusPlus.cpp - C++ SourceLanguage impl ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SourceLanguage class for the C++ language.
//
//===----------------------------------------------------------------------===//
#include "llvm/Debugger/SourceLanguage.h"
using namespace llvm;
#if 0
namespace {
struct CPPSL : public SourceLanguage {
} TheCPlusPlusLanguageInstance;
}
#endif
const SourceLanguage &SourceLanguage::getCPlusPlusInstance() {
return get(0); // We don't have an implementation for C yet fall back on
// generic
}

View File

@ -1,138 +0,0 @@
//===-- SourceLanguage-Unknown.cpp - Implement itf for unknown languages --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// If the LLVM debugger does not have a module for a particular language, it
// falls back on using this one to perform the source-language interface. This
// interface is not wonderful, but it gets the job done.
//
//===----------------------------------------------------------------------===//
#include "llvm/Debugger/SourceLanguage.h"
#include "llvm/Debugger/ProgramInfo.h"
#include "llvm/Support/Streams.h"
#include <cassert>
#include <ostream>
using namespace llvm;
//===----------------------------------------------------------------------===//
// Implement the SourceLanguage cache for the Unknown language.
//
namespace {
/// SLUCache - This cache allows for efficient lookup of source functions by
/// name.
///
struct SLUCache : public SourceLanguageCache {
ProgramInfo &PI;
std::multimap<std::string, SourceFunctionInfo*> FunctionMap;
public:
SLUCache(ProgramInfo &pi);
typedef std::multimap<std::string, SourceFunctionInfo*>::const_iterator
fm_iterator;
std::pair<fm_iterator, fm_iterator>
getFunction(const std::string &Name) const {
return FunctionMap.equal_range(Name);
}
SourceFunctionInfo *addSourceFunction(SourceFunctionInfo *SF) {
FunctionMap.insert(std::make_pair(SF->getSymbolicName(), SF));
return SF;
}
};
}
SLUCache::SLUCache(ProgramInfo &pi) : PI(pi) {
}
//===----------------------------------------------------------------------===//
// Implement SourceLanguageUnknown class, which is used to handle unrecognized
// languages.
//
namespace {
static struct SLU : public SourceLanguage {
//===------------------------------------------------------------------===//
// Implement the miscellaneous methods...
//
virtual const char *getSourceLanguageName() const {
return "unknown";
}
/// 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;
//===------------------------------------------------------------------===//
// We do use a cache for information...
//
typedef SLUCache CacheType;
SLUCache *createSourceLanguageCache(ProgramInfo &PI) const {
return new SLUCache(PI);
}
/// createSourceFunctionInfo - Create the new object and inform the cache of
/// the new function.
virtual SourceFunctionInfo *
createSourceFunctionInfo(const GlobalVariable *Desc, ProgramInfo &PI) const;
} TheUnknownSourceLanguageInstance;
}
const SourceLanguage &SourceLanguage::getUnknownLanguageInstance() {
return TheUnknownSourceLanguageInstance;
}
SourceFunctionInfo *
SLU::createSourceFunctionInfo(const GlobalVariable *Desc,
ProgramInfo &PI) const {
SourceFunctionInfo *Result = new SourceFunctionInfo(PI, Desc);
return PI.getLanguageCache(this).addSourceFunction(Result);
}
/// 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.
///
SourceFunctionInfo *SLU::lookupFunction(const std::string &FunctionName,
ProgramInfo &PI, RuntimeInfo *RI) const{
SLUCache &Cache = PI.getLanguageCache(this);
std::pair<SLUCache::fm_iterator, SLUCache::fm_iterator> IP
= Cache.getFunction(FunctionName);
if (IP.first == IP.second) {
if (PI.allSourceFunctionsRead())
return 0; // Nothing found
// Otherwise, we might be able to find the function if we read all of them
// in. Do so now.
PI.getSourceFunctions();
assert(PI.allSourceFunctionsRead() && "Didn't read in all functions?");
return lookupFunction(FunctionName, PI, RI);
}
SourceFunctionInfo *Found = IP.first->second;
++IP.first;
if (IP.first != IP.second)
cout << "Whoa, found multiple functions with the same name. I should"
<< " ask the user which one to use: FIXME!\n";
return Found;
}

View File

@ -1,54 +0,0 @@
//===-- SourceLanguage.cpp - Implement the SourceLanguage class -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SourceLanguage class.
//
//===----------------------------------------------------------------------===//
#include "llvm/Debugger/SourceLanguage.h"
#include "llvm/Debugger/ProgramInfo.h"
using namespace llvm;
const SourceLanguage &SourceLanguage::get(unsigned ID) {
switch (ID) {
case 1: // DW_LANG_C89
case 2: // DW_LANG_C
case 12: // DW_LANG_C99
return getCFamilyInstance();
case 4: // DW_LANG_C_plus_plus
return getCPlusPlusInstance();
case 3: // DW_LANG_Ada83
case 5: // DW_LANG_Cobol74
case 6: // DW_LANG_Cobol85
case 7: // DW_LANG_Fortran77
case 8: // DW_LANG_Fortran90
case 9: // DW_LANG_Pascal83
case 10: // DW_LANG_Modula2
case 11: // DW_LANG_Java
case 13: // DW_LANG_Ada95
case 14: // DW_LANG_Fortran95
default:
return getUnknownLanguageInstance();
}
}
SourceFileInfo *
SourceLanguage::createSourceFileInfo(const GlobalVariable *Desc,
ProgramInfo &PI) const {
return new SourceFileInfo(Desc, *this);
}
SourceFunctionInfo *
SourceLanguage::createSourceFunctionInfo(const GlobalVariable *Desc,
ProgramInfo &PI) const {
return new SourceFunctionInfo(PI, Desc);
}

View File

@ -1,130 +0,0 @@
//===-- Annotation.cpp - Implement the Annotation Classes -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AnnotationManager class.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/Annotation.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/System/RWMutex.h"
#include <map>
#include <cstring>
using namespace llvm;
Annotation::~Annotation() {} // Designed to be subclassed
Annotable::~Annotable() { // Virtual because it's designed to be subclassed...
Annotation *A = AnnotationList;
while (A) {
Annotation *Next = A->getNext();
delete A;
A = Next;
}
}
namespace {
class StrCmp {
public:
bool operator()(const char *a, const char *b) const {
return strcmp(a, b) < 0;
}
};
}
typedef std::map<const char*, unsigned, StrCmp> IDMapType;
static volatile sys::cas_flag IDCounter = 0; // Unique ID counter
// Static member to ensure initialiation on demand.
static ManagedStatic<IDMapType> IDMap;
static ManagedStatic<sys::SmartRWMutex<true> > AnnotationsLock;
// On demand annotation creation support...
typedef Annotation *(*AnnFactory)(AnnotationID, const Annotable *, void *);
typedef std::map<unsigned, std::pair<AnnFactory,void*> > FactMapType;
static ManagedStatic<FactMapType> TheFactMap;
static FactMapType &getFactMap() {
return *TheFactMap;
}
static void eraseFromFactMap(unsigned ID) {
sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
TheFactMap->erase(ID);
}
AnnotationID AnnotationManager::getID(const char *Name) { // Name -> ID
AnnotationsLock->reader_acquire();
IDMapType::iterator I = IDMap->find(Name);
IDMapType::iterator E = IDMap->end();
AnnotationsLock->reader_release();
if (I == E) {
sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
I = IDMap->find(Name);
if (I == IDMap->end()) {
unsigned newCount = sys::AtomicIncrement(&IDCounter);
(*IDMap)[Name] = newCount-1; // Add a new element
return AnnotationID(newCount-1);
} else
return AnnotationID(I->second);
}
return AnnotationID(I->second);
}
// getID - Name -> ID + registration of a factory function for demand driven
// annotation support.
AnnotationID AnnotationManager::getID(const char *Name, Factory Fact,
void *Data) {
AnnotationID Result(getID(Name));
registerAnnotationFactory(Result, Fact, Data);
return Result;
}
// getName - This function is especially slow, but that's okay because it should
// only be used for debugging.
//
const char *AnnotationManager::getName(AnnotationID ID) { // ID -> Name
sys::SmartScopedReader<true> Reader(&*AnnotationsLock);
IDMapType &TheMap = *IDMap;
for (IDMapType::iterator I = TheMap.begin(); ; ++I) {
assert(I != TheMap.end() && "Annotation ID is unknown!");
if (I->second == ID.ID) return I->first;
}
}
// registerAnnotationFactory - This method is used to register a callback
// function used to create an annotation on demand if it is needed by the
// Annotable::findOrCreateAnnotation method.
//
void AnnotationManager::registerAnnotationFactory(AnnotationID ID, AnnFactory F,
void *ExtraData) {
if (F) {
sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
getFactMap()[ID.ID] = std::make_pair(F, ExtraData);
} else {
eraseFromFactMap(ID.ID);
}
}
// createAnnotation - Create an annotation of the specified ID for the
// specified object, using a register annotation creation function.
//
Annotation *AnnotationManager::createAnnotation(AnnotationID ID,
const Annotable *Obj) {
AnnotationsLock->reader_acquire();
FactMapType::iterator I = getFactMap().find(ID.ID);
if (I == getFactMap().end()) {
AnnotationsLock->reader_release();
return 0;
}
AnnotationsLock->reader_release();
return I->second.first(ID, Obj, I->second.second);
}

View File

@ -1,30 +0,0 @@
//===-- Streams.cpp - Wrappers for iostreams ------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a wrapper for the std::cout and std::cerr I/O streams.
// It prevents the need to include <iostream> to each file just to get I/O.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/Streams.h"
#include <iostream>
using namespace llvm;
OStream llvm::cout(std::cout);
OStream llvm::cerr(std::cerr);
IStream llvm::cin(std::cin);
namespace llvm {
/// FlushStream - Function called by BaseStream to flush an ostream.
void FlushStream(std::ostream &S) {
S << std::flush;
}
} // end anonymous namespace

View File

@ -1,6 +0,0 @@
LLVM System Interface Library
-------------------------------------------------------------------------------
The LLVM System Interface Library is licensed under the Illinois Open Source
License and has the following additional copyright:
Copyright (C) 2004 eXtensible Systems, Inc.

View File

@ -1,254 +0,0 @@
//===-- ARMTargetAsmInfo.cpp - ARM asm properties ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the ARMTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "ARMTargetAsmInfo.h"
#include "ARMTargetMachine.h"
#include <cstring>
#include <cctype>
using namespace llvm;
const char *const llvm::arm_asm_table[] = {
"{r0}", "r0",
"{r1}", "r1",
"{r2}", "r2",
"{r3}", "r3",
"{r4}", "r4",
"{r5}", "r5",
"{r6}", "r6",
"{r7}", "r7",
"{r8}", "r8",
"{r9}", "r9",
"{r10}", "r10",
"{r11}", "r11",
"{r12}", "r12",
"{r13}", "r13",
"{r14}", "r14",
"{lr}", "lr",
"{sp}", "sp",
"{ip}", "ip",
"{fp}", "fp",
"{sl}", "sl",
"{memory}", "memory",
"{cc}", "cc",
0,0
};
ARMDarwinTargetAsmInfo::ARMDarwinTargetAsmInfo(const ARMBaseTargetMachine &TM):
ARMTargetAsmInfo<DarwinTargetAsmInfo>(TM) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
ZeroDirective = "\t.space\t";
ZeroFillDirective = "\t.zerofill\t"; // Uses .zerofill
SetDirective = "\t.set\t";
ProtectedDirective = NULL;
HasDotTypeDotSizeDirective = false;
SupportsDebugInformation = true;
}
ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMBaseTargetMachine &TM):
ARMTargetAsmInfo<ELFTargetAsmInfo>(TM) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
NeedsSet = false;
HasLEB128 = true;
AbsoluteDebugSectionOffsets = true;
CStringSection = ".rodata.str";
PrivateGlobalPrefix = ".L";
WeakRefDirective = "\t.weak\t";
SetDirective = "\t.set\t";
DwarfRequiresFrameSection = false;
DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"\",%progbits";
DwarfInfoSection = "\t.section\t.debug_info,\"\",%progbits";
DwarfLineSection = "\t.section\t.debug_line,\"\",%progbits";
DwarfFrameSection = "\t.section\t.debug_frame,\"\",%progbits";
DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"\",%progbits";
DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"\",%progbits";
DwarfStrSection = "\t.section\t.debug_str,\"\",%progbits";
DwarfLocSection = "\t.section\t.debug_loc,\"\",%progbits";
DwarfARangesSection = "\t.section\t.debug_aranges,\"\",%progbits";
DwarfRangesSection = "\t.section\t.debug_ranges,\"\",%progbits";
DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"\",%progbits";
if (Subtarget->isAAPCS_ABI()) {
StaticCtorsSection = "\t.section .init_array,\"aw\",%init_array";
StaticDtorsSection = "\t.section .fini_array,\"aw\",%fini_array";
} else {
StaticCtorsSection = "\t.section .ctors,\"aw\",%progbits";
StaticDtorsSection = "\t.section .dtors,\"aw\",%progbits";
}
SupportsDebugInformation = true;
}
/// Count the number of comma-separated arguments.
/// Do not try to detect errors.
template <class BaseTAI>
unsigned ARMTargetAsmInfo<BaseTAI>::countArguments(const char* p) const {
unsigned count = 0;
while (*p && isspace(*p) && *p != '\n')
p++;
count++;
while (*p && *p!='\n' &&
strncmp(p, BaseTAI::CommentString,
strlen(BaseTAI::CommentString))!=0) {
if (*p==',')
count++;
p++;
}
return count;
}
/// Count the length of a string enclosed in quote characters.
/// Do not try to detect errors.
template <class BaseTAI>
unsigned ARMTargetAsmInfo<BaseTAI>::countString(const char* p) const {
unsigned count = 0;
while (*p && isspace(*p) && *p!='\n')
p++;
if (!*p || *p != '\"')
return count;
while (*++p && *p != '\"')
count++;
return count;
}
/// ARM-specific version of TargetAsmInfo::getInlineAsmLength.
template <class BaseTAI>
unsigned ARMTargetAsmInfo<BaseTAI>::getInlineAsmLength(const char *s) const {
// Make a lowercase-folded version of s for counting purposes.
char *q, *s_copy = (char *)malloc(strlen(s) + 1);
strcpy(s_copy, s);
for (q=s_copy; *q; q++)
*q = tolower(*q);
const char *Str = s_copy;
// Count the number of bytes in the asm.
bool atInsnStart = true;
bool inTextSection = true;
unsigned Length = 0;
for (; *Str; ++Str) {
if (atInsnStart) {
// Skip whitespace
while (*Str && isspace(*Str) && *Str != '\n')
Str++;
// Skip label
for (const char* p = Str; *p && !isspace(*p); p++)
if (*p == ':') {
Str = p+1;
while (*Str && isspace(*Str) && *Str != '\n')
Str++;
break;
}
if (*Str == 0) break;
// Ignore everything from comment char(s) to EOL
if (strncmp(Str, BaseTAI::CommentString,
strlen(BaseTAI::CommentString)) == 0)
atInsnStart = false;
// FIXME do something like the following for non-Darwin
else if (*Str == '.' && Subtarget->isTargetDarwin()) {
// Directive.
atInsnStart = false;
// Some change the section, but don't generate code.
if (strncmp(Str, ".literal4", strlen(".literal4"))==0 ||
strncmp(Str, ".literal8", strlen(".literal8"))==0 ||
strncmp(Str, ".const", strlen(".const"))==0 ||
strncmp(Str, ".constructor", strlen(".constructor"))==0 ||
strncmp(Str, ".cstring", strlen(".cstring"))==0 ||
strncmp(Str, ".data", strlen(".data"))==0 ||
strncmp(Str, ".destructor", strlen(".destructor"))==0 ||
strncmp(Str, ".fvmlib_init0", strlen(".fvmlib_init0"))==0 ||
strncmp(Str, ".fvmlib_init1", strlen(".fvmlib_init1"))==0 ||
strncmp(Str, ".mod_init_func", strlen(".mod_init_func"))==0 ||
strncmp(Str, ".mod_term_func", strlen(".mod_term_func"))==0 ||
strncmp(Str, ".picsymbol_stub", strlen(".picsymbol_stub"))==0 ||
strncmp(Str, ".symbol_stub", strlen(".symbol_stub"))==0 ||
strncmp(Str, ".static_data", strlen(".static_data"))==0 ||
strncmp(Str, ".section", strlen(".section"))==0 ||
strncmp(Str, ".lazy_symbol_pointer", strlen(".lazy_symbol_pointer"))==0 ||
strncmp(Str, ".non_lazy_symbol_pointer", strlen(".non_lazy_symbol_pointer"))==0 ||
strncmp(Str, ".dyld", strlen(".dyld"))==0 ||
strncmp(Str, ".const_data", strlen(".const_data"))==0 ||
strncmp(Str, ".objc", strlen(".objc"))==0 || //// many directives
strncmp(Str, ".static_const", strlen(".static_const"))==0)
inTextSection=false;
else if (strncmp(Str, ".text", strlen(".text"))==0)
inTextSection = true;
// Some can't really be handled without implementing significant pieces
// of an assembler. Others require dynamic adjustment of block sizes in
// AdjustBBOffsetsAfter; it's a big compile-time speed hit to check every
// instruction in there, and none of these are currently used in the kernel.
else if (strncmp(Str, ".macro", strlen(".macro"))==0 ||
strncmp(Str, ".if", strlen(".if"))==0 ||
strncmp(Str, ".align", strlen(".align"))==0 ||
strncmp(Str, ".fill", strlen(".fill"))==0 ||
strncmp(Str, ".space", strlen(".space"))==0 ||
strncmp(Str, ".zerofill", strlen(".zerofill"))==0 ||
strncmp(Str, ".p2align", strlen(".p2align"))==0 ||
strncmp(Str, ".p2alignw", strlen(".p2alignw"))==0 ||
strncmp(Str, ".p2alignl", strlen(".p2alignl"))==0 ||
strncmp(Str, ".align32", strlen(".p2align32"))==0 ||
strncmp(Str, ".include", strlen(".include"))==0)
cerr << "Directive " << Str << " in asm may lead to invalid offsets for" <<
" constant pools (the assembler will tell you if this happens).\n";
// Some generate code, but this is only interesting in the text section.
else if (inTextSection) {
if (strncmp(Str, ".long", strlen(".long"))==0)
Length += 4*countArguments(Str+strlen(".long"));
else if (strncmp(Str, ".short", strlen(".short"))==0)
Length += 2*countArguments(Str+strlen(".short"));
else if (strncmp(Str, ".byte", strlen(".byte"))==0)
Length += 1*countArguments(Str+strlen(".byte"));
else if (strncmp(Str, ".single", strlen(".single"))==0)
Length += 4*countArguments(Str+strlen(".single"));
else if (strncmp(Str, ".double", strlen(".double"))==0)
Length += 8*countArguments(Str+strlen(".double"));
else if (strncmp(Str, ".quad", strlen(".quad"))==0)
Length += 16*countArguments(Str+strlen(".quad"));
else if (strncmp(Str, ".ascii", strlen(".ascii"))==0)
Length += countString(Str+strlen(".ascii"));
else if (strncmp(Str, ".asciz", strlen(".asciz"))==0)
Length += countString(Str+strlen(".asciz"))+1;
}
} else if (inTextSection) {
// An instruction
atInsnStart = false;
if (Subtarget->isThumb()) {
// BL and BLX <non-reg> are 4 bytes, all others 2.
if (strncmp(Str, "blx", strlen("blx"))==0) {
const char* p = Str+3;
while (*p && isspace(*p))
p++;
if (*p == 'r' || *p=='R')
Length += 2; // BLX reg
else
Length += 4; // BLX non-reg
} else if (strncmp(Str, "bl", strlen("bl"))==0)
Length += 4; // BL
else
Length += 2; // Thumb anything else
}
else
Length += 4; // ARM
}
}
if (*Str == '\n' || *Str == BaseTAI::SeparatorChar)
atInsnStart = true;
}
free(s_copy);
return Length;
}
// Instantiate default implementation.
TEMPLATE_INSTANTIATION(class ARMTargetAsmInfo<TargetAsmInfo>);

View File

@ -1,63 +0,0 @@
//=====-- ARMTargetAsmInfo.h - ARM asm properties -------------*- C++ -*--====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the ARMTargetAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef ARMTARGETASMINFO_H
#define ARMTARGETASMINFO_H
#include "ARMTargetMachine.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
#include "llvm/Target/DarwinTargetAsmInfo.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
extern const char *const arm_asm_table[];
template <class BaseTAI>
struct ARMTargetAsmInfo : public BaseTAI {
explicit ARMTargetAsmInfo(const ARMBaseTargetMachine &TM) : BaseTAI(TM) {
BaseTAI::AsmTransCBE = arm_asm_table;
BaseTAI::AlignmentIsInBytes = false;
BaseTAI::Data64bitsDirective = 0;
BaseTAI::CommentString = "@";
BaseTAI::ConstantPoolSection = "\t.text\n";
BaseTAI::COMMDirectiveTakesAlignment = false;
BaseTAI::InlineAsmStart = "@ InlineAsm Start";
BaseTAI::InlineAsmEnd = "@ InlineAsm End";
BaseTAI::LCOMMDirective = "\t.lcomm\t";
}
const ARMSubtarget *Subtarget;
virtual unsigned getInlineAsmLength(const char *Str) const;
unsigned countArguments(const char *p) const;
unsigned countString(const char *p) const;
};
typedef ARMTargetAsmInfo<TargetAsmInfo> ARMGenericTargetAsmInfo;
EXTERN_TEMPLATE_INSTANTIATION(class ARMTargetAsmInfo<TargetAsmInfo>);
struct ARMDarwinTargetAsmInfo : public ARMTargetAsmInfo<DarwinTargetAsmInfo> {
explicit ARMDarwinTargetAsmInfo(const ARMBaseTargetMachine &TM);
};
struct ARMELFTargetAsmInfo : public ARMTargetAsmInfo<ELFTargetAsmInfo> {
explicit ARMELFTargetAsmInfo(const ARMBaseTargetMachine &TM);
};
} // namespace llvm
#endif

View File

@ -1,31 +0,0 @@
//===-- AlphaTargetAsmInfo.cpp - Alpha asm properties -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the AlphaTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "AlphaTargetMachine.h"
#include "AlphaTargetAsmInfo.h"
using namespace llvm;
AlphaTargetAsmInfo::AlphaTargetAsmInfo(const AlphaTargetMachine &TM)
: TargetAsmInfo(TM) {
AlignmentIsInBytes = false;
PrivateGlobalPrefix = "$";
JumpTableDirective = ".gprel32";
JumpTableDataSection = "\t.section .rodata\n";
WeakRefDirective = "\t.weak\t";
}
unsigned AlphaTargetAsmInfo::RelocBehaviour() const {
return (TM.getRelocationModel() != Reloc::Static ?
Reloc::LocalOrGlobal : Reloc::Global);
}

View File

@ -1,32 +0,0 @@
//=====-- AlphaTargetAsmInfo.h - Alpha asm properties ---------*- C++ -*--====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the AlphaTargetAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef ALPHATARGETASMINFO_H
#define ALPHATARGETASMINFO_H
#include "llvm/Target/TargetAsmInfo.h"
namespace llvm {
// Forward declaration.
class AlphaTargetMachine;
struct AlphaTargetAsmInfo : public TargetAsmInfo {
explicit AlphaTargetAsmInfo(const AlphaTargetMachine &TM);
virtual unsigned RelocBehaviour() const;
};
} // namespace llvm
#endif

View File

@ -1,73 +0,0 @@
//===-- SPUTargetAsmInfo.cpp - Cell SPU asm properties ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the SPUTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "SPUTargetAsmInfo.h"
#include "SPUTargetMachine.h"
#include "llvm/Function.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Dwarf.h"
using namespace llvm;
using namespace llvm::dwarf;
SPULinuxTargetAsmInfo::SPULinuxTargetAsmInfo(const SPUTargetMachine &TM) :
SPUTargetAsmInfo<ELFTargetAsmInfo>(TM) {
PCSymbol = ".";
CommentString = "#";
GlobalPrefix = "";
PrivateGlobalPrefix = ".L";
// This corresponds to what the gcc SPU compiler emits, for consistency.
CStringSection = ".rodata.str";
// Has leb128, .loc and .file
HasLEB128 = true;
HasDotLocAndDotFile = true;
// BSS section needs to be emitted as ".section"
BSSSection = "\t.section\t.bss";
BSSSection_ = getUnnamedSection("\t.section\t.bss",
SectionFlags::Writeable | SectionFlags::BSS,
true);
SupportsDebugInformation = true;
NeedsSet = true;
DwarfAbbrevSection = "\t.section .debug_abbrev,\"\",@progbits";
DwarfInfoSection = "\t.section .debug_info,\"\",@progbits";
DwarfLineSection = "\t.section .debug_line,\"\",@progbits";
DwarfFrameSection = "\t.section .debug_frame,\"\",@progbits";
DwarfPubNamesSection = "\t.section .debug_pubnames,\"\",@progbits";
DwarfPubTypesSection = "\t.section .debug_pubtypes,\"\",progbits";
DwarfStrSection = "\t.section .debug_str,\"MS\",@progbits,1";
DwarfLocSection = "\t.section .debug_loc,\"\",@progbits";
DwarfARangesSection = "\t.section .debug_aranges,\"\",@progbits";
DwarfRangesSection = "\t.section .debug_ranges,\"\",@progbits";
DwarfMacroInfoSection = 0; // macro info not supported.
// Exception handling is not supported on CellSPU (think about it: you only
// have 256K for code+data. Would you support exception handling?)
SupportsExceptionHandling = false;
}
/// PreferredEHDataFormat - This hook allows the target to select data
/// format used for encoding pointers in exception handling data. Reason is
/// 0 for data, 1 for code labels, 2 for function pointers. Global is true
/// if the symbol can be relocated.
unsigned
SPULinuxTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const {
// We really need to write something here.
return TargetAsmInfo::PreferredEHDataFormat(Reason, Global);
}
// Instantiate default implementation.
TEMPLATE_INSTANTIATION(class SPUTargetAsmInfo<TargetAsmInfo>);

View File

@ -1,51 +0,0 @@
//===-- SPUTargetAsmInfo.h - Cell SPU asm properties -----------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the SPUTargetAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef SPUTARGETASMINFO_H
#define SPUTARGETASMINFO_H
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
#include "SPUTargetMachine.h"
#include "SPUSubtarget.h"
namespace llvm {
// Forward declaration.
class SPUTargetMachine;
template <class BaseTAI>
struct SPUTargetAsmInfo : public BaseTAI {
explicit SPUTargetAsmInfo(const SPUTargetMachine &TM):
BaseTAI(TM) {
/* (unused today)
* const SPUSubtarget *Subtarget = &TM.getSubtarget<SPUSubtarget>(); */
BaseTAI::ZeroDirective = "\t.space\t";
BaseTAI::SetDirective = "\t.set";
BaseTAI::Data64bitsDirective = "\t.quad\t";
BaseTAI::AlignmentIsInBytes = false;
BaseTAI::LCOMMDirective = "\t.lcomm\t";
BaseTAI::InlineAsmStart = "# InlineAsm Start";
BaseTAI::InlineAsmEnd = "# InlineAsm End";
}
};
struct SPULinuxTargetAsmInfo : public SPUTargetAsmInfo<ELFTargetAsmInfo> {
explicit SPULinuxTargetAsmInfo(const SPUTargetMachine &TM);
virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const;
};
} // namespace llvm
#endif /* SPUTARGETASMINFO_H */

View File

@ -1,216 +0,0 @@
//===-- DarwinTargetAsmInfo.cpp - Darwin asm properties ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target asm properties related what form asm statements
// should take in general on Darwin-based targets
//
//===----------------------------------------------------------------------===//
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/DarwinTargetAsmInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"
using namespace llvm;
DarwinTargetAsmInfo::DarwinTargetAsmInfo(const TargetMachine &TM)
: TargetAsmInfo(TM) {
CStringSection_ = getUnnamedSection("\t.cstring",
SectionFlags::Mergeable | SectionFlags::Strings);
FourByteConstantSection = getUnnamedSection("\t.literal4\n",
SectionFlags::Mergeable);
EightByteConstantSection = getUnnamedSection("\t.literal8\n",
SectionFlags::Mergeable);
// Note: 16-byte constant section is subtarget specific and should be provided
// there, if needed.
SixteenByteConstantSection = 0;
ReadOnlySection = getUnnamedSection("\t.const\n", SectionFlags::None);
TextCoalSection =
getNamedSection("\t__TEXT,__textcoal_nt,coalesced,pure_instructions",
SectionFlags::Code);
ConstTextCoalSection = getNamedSection("\t__TEXT,__const_coal,coalesced",
SectionFlags::None);
ConstDataCoalSection = getNamedSection("\t__DATA,__const_coal,coalesced",
SectionFlags::None);
ConstDataSection = getUnnamedSection(".const_data", SectionFlags::None);
DataCoalSection = getNamedSection("\t__DATA,__datacoal_nt,coalesced",
SectionFlags::Writeable);
// Common settings for all Darwin targets.
// Syntax:
GlobalPrefix = "_";
PrivateGlobalPrefix = "L";
LessPrivateGlobalPrefix = "l"; // Marker for some ObjC metadata
StringConstantPrefix = "\1LC";
NeedsSet = true;
NeedsIndirectEncoding = true;
AllowQuotesInName = true;
HasSingleParameterDotFile = false;
// In non-PIC modes, emit a special label before jump tables so that the
// linker can perform more accurate dead code stripping. We do not check the
// relocation model here since it can be overridden later.
JumpTableSpecialLabelPrefix = "l";
// Directives:
WeakDefDirective = "\t.weak_definition ";
WeakRefDirective = "\t.weak_reference ";
HiddenDirective = "\t.private_extern ";
// Sections:
CStringSection = "\t.cstring";
JumpTableDataSection = "\t.const\n";
BSSSection = 0;
if (TM.getRelocationModel() == Reloc::Static) {
StaticCtorsSection = ".constructor";
StaticDtorsSection = ".destructor";
} else {
StaticCtorsSection = ".mod_init_func";
StaticDtorsSection = ".mod_term_func";
}
DwarfAbbrevSection = ".section __DWARF,__debug_abbrev,regular,debug";
DwarfInfoSection = ".section __DWARF,__debug_info,regular,debug";
DwarfLineSection = ".section __DWARF,__debug_line,regular,debug";
DwarfFrameSection = ".section __DWARF,__debug_frame,regular,debug";
DwarfPubNamesSection = ".section __DWARF,__debug_pubnames,regular,debug";
DwarfPubTypesSection = ".section __DWARF,__debug_pubtypes,regular,debug";
DwarfStrSection = ".section __DWARF,__debug_str,regular,debug";
DwarfLocSection = ".section __DWARF,__debug_loc,regular,debug";
DwarfARangesSection = ".section __DWARF,__debug_aranges,regular,debug";
DwarfRangesSection = ".section __DWARF,__debug_ranges,regular,debug";
DwarfMacroInfoSection = ".section __DWARF,__debug_macinfo,regular,debug";
}
/// emitUsedDirectiveFor - On Darwin, internally linked data beginning with
/// the PrivateGlobalPrefix or the LessPrivateGlobalPrefix does not have the
/// directive emitted (this occurs in ObjC metadata).
bool
DarwinTargetAsmInfo::emitUsedDirectiveFor(const GlobalValue* GV,
Mangler *Mang) const {
if (GV==0)
return false;
if (GV->hasLocalLinkage() && !isa<Function>(GV) &&
((strlen(getPrivateGlobalPrefix()) != 0 &&
Mang->getValueName(GV).substr(0,strlen(getPrivateGlobalPrefix())) ==
getPrivateGlobalPrefix()) ||
(strlen(getLessPrivateGlobalPrefix()) != 0 &&
Mang->getValueName(GV).substr(0,strlen(getLessPrivateGlobalPrefix())) ==
getLessPrivateGlobalPrefix())))
return false;
return true;
}
const Section*
DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
SectionKind::Kind Kind = SectionKindForGlobal(GV);
bool isWeak = GV->isWeakForLinker();
bool isNonStatic = TM.getRelocationModel() != Reloc::Static;
switch (Kind) {
case SectionKind::Text:
if (isWeak)
return TextCoalSection;
else
return TextSection;
case SectionKind::Data:
case SectionKind::ThreadData:
case SectionKind::BSS:
case SectionKind::ThreadBSS:
if (cast<GlobalVariable>(GV)->isConstant())
return (isWeak ? ConstDataCoalSection : ConstDataSection);
else
return (isWeak ? DataCoalSection : DataSection);
case SectionKind::ROData:
return (isWeak ? ConstDataCoalSection :
(isNonStatic ? ConstDataSection : getReadOnlySection()));
case SectionKind::RODataMergeStr:
return (isWeak ?
ConstTextCoalSection :
MergeableStringSection(cast<GlobalVariable>(GV)));
case SectionKind::RODataMergeConst:
return (isWeak ?
ConstDataCoalSection:
MergeableConstSection(cast<GlobalVariable>(GV)));
default:
assert(0 && "Unsuported section kind for global");
}
// FIXME: Do we have any extra special weird cases?
return NULL;
}
const Section*
DarwinTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const {
const TargetData *TD = TM.getTargetData();
Constant *C = cast<GlobalVariable>(GV)->getInitializer();
const Type *Ty = cast<ArrayType>(C->getType())->getElementType();
unsigned Size = TD->getTypeAllocSize(Ty);
if (Size) {
unsigned Align = TD->getPreferredAlignment(GV);
if (Align <= 32)
return getCStringSection_();
}
return getReadOnlySection();
}
const Section*
DarwinTargetAsmInfo::MergeableConstSection(const GlobalVariable *GV) const {
Constant *C = GV->getInitializer();
return MergeableConstSection(C->getType());
}
inline const Section*
DarwinTargetAsmInfo::MergeableConstSection(const Type *Ty) const {
const TargetData *TD = TM.getTargetData();
unsigned Size = TD->getTypeAllocSize(Ty);
if (Size == 4)
return FourByteConstantSection;
else if (Size == 8)
return EightByteConstantSection;
else if (Size == 16 && SixteenByteConstantSection)
return SixteenByteConstantSection;
return getReadOnlySection();
}
const Section*
DarwinTargetAsmInfo::SelectSectionForMachineConst(const Type *Ty) const {
const Section* S = MergeableConstSection(Ty);
// Handle weird special case, when compiling PIC stuff.
if (S == getReadOnlySection() &&
TM.getRelocationModel() != Reloc::Static)
return ConstDataSection;
return S;
}
std::string
DarwinTargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV,
SectionKind::Kind kind) const {
assert(0 && "Darwin does not use unique sections");
return "";
}

View File

@ -1,227 +0,0 @@
//===-- ELFTargetAsmInfo.cpp - ELF asm properties ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target asm properties related what form asm statements
// should take in general on ELF-based targets
//
//===----------------------------------------------------------------------===//
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"
using namespace llvm;
ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM)
: TargetAsmInfo(TM) {
BSSSection_ = getUnnamedSection("\t.bss",
SectionFlags::Writeable | SectionFlags::BSS);
ReadOnlySection = getNamedSection("\t.rodata", SectionFlags::None);
TLSDataSection = getNamedSection("\t.tdata",
SectionFlags::Writeable | SectionFlags::TLS);
TLSBSSSection = getNamedSection("\t.tbss",
SectionFlags::Writeable | SectionFlags::TLS | SectionFlags::BSS);
DataRelSection = getNamedSection("\t.data.rel", SectionFlags::Writeable);
DataRelLocalSection = getNamedSection("\t.data.rel.local",
SectionFlags::Writeable);
DataRelROSection = getNamedSection("\t.data.rel.ro",
SectionFlags::Writeable);
DataRelROLocalSection = getNamedSection("\t.data.rel.ro.local",
SectionFlags::Writeable);
}
SectionKind::Kind
ELFTargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const {
SectionKind::Kind Kind = TargetAsmInfo::SectionKindForGlobal(GV);
if (Kind != SectionKind::Data)
return Kind;
// Decide, whether we need data.rel stuff
const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV);
if (GVar->hasInitializer()) {
Constant *C = GVar->getInitializer();
bool isConstant = GVar->isConstant();
unsigned Reloc = RelocBehaviour();
if (Reloc != Reloc::None && C->ContainsRelocations(Reloc))
return (C->ContainsRelocations(Reloc::Global) ?
(isConstant ?
SectionKind::DataRelRO : SectionKind::DataRel) :
(isConstant ?
SectionKind::DataRelROLocal : SectionKind::DataRelLocal));
}
return Kind;
}
const Section*
ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
SectionKind::Kind Kind = SectionKindForGlobal(GV);
if (const Function *F = dyn_cast<Function>(GV)) {
switch (F->getLinkage()) {
default: assert(0 && "Unknown linkage type!");
case Function::PrivateLinkage:
case Function::InternalLinkage:
case Function::DLLExportLinkage:
case Function::ExternalLinkage:
return TextSection;
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
std::string Name = UniqueSectionForGlobal(GV, Kind);
unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str());
return getNamedSection(Name.c_str(), Flags);
}
} else if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
if (GVar->isWeakForLinker()) {
std::string Name = UniqueSectionForGlobal(GVar, Kind);
unsigned Flags = SectionFlagsForGlobal(GVar, Name.c_str());
return getNamedSection(Name.c_str(), Flags);
} else {
switch (Kind) {
case SectionKind::Data:
case SectionKind::SmallData:
return DataSection;
case SectionKind::DataRel:
return DataRelSection;
case SectionKind::DataRelLocal:
return DataRelLocalSection;
case SectionKind::DataRelRO:
return DataRelROSection;
case SectionKind::DataRelROLocal:
return DataRelROLocalSection;
case SectionKind::BSS:
case SectionKind::SmallBSS:
// ELF targets usually have BSS sections
return getBSSSection_();
case SectionKind::ROData:
case SectionKind::SmallROData:
return getReadOnlySection();
case SectionKind::RODataMergeStr:
return MergeableStringSection(GVar);
case SectionKind::RODataMergeConst:
return MergeableConstSection(GVar);
case SectionKind::ThreadData:
// ELF targets usually support TLS stuff
return TLSDataSection;
case SectionKind::ThreadBSS:
return TLSBSSSection;
default:
assert(0 && "Unsuported section kind for global");
}
}
} else
assert(0 && "Unsupported global");
return NULL;
}
const Section*
ELFTargetAsmInfo::SelectSectionForMachineConst(const Type *Ty) const {
// FIXME: Support data.rel stuff someday
return MergeableConstSection(Ty);
}
const Section*
ELFTargetAsmInfo::MergeableConstSection(const GlobalVariable *GV) const {
Constant *C = GV->getInitializer();
return MergeableConstSection(C->getType());
}
inline const Section*
ELFTargetAsmInfo::MergeableConstSection(const Type *Ty) const {
const TargetData *TD = TM.getTargetData();
// FIXME: string here is temporary, until stuff will fully land in.
// We cannot use {Four,Eight,Sixteen}ByteConstantSection here, since it's
// currently directly used by asmprinter.
unsigned Size = TD->getTypeAllocSize(Ty);
if (Size == 4 || Size == 8 || Size == 16) {
std::string Name = ".rodata.cst" + utostr(Size);
return getNamedSection(Name.c_str(),
SectionFlags::setEntitySize(SectionFlags::Mergeable,
Size));
}
return getReadOnlySection();
}
const Section*
ELFTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const {
const TargetData *TD = TM.getTargetData();
Constant *C = cast<GlobalVariable>(GV)->getInitializer();
const Type *Ty = cast<ArrayType>(C->getType())->getElementType();
unsigned Size = TD->getTypeAllocSize(Ty);
if (Size <= 16) {
assert(getCStringSection() && "Should have string section prefix");
// We also need alignment here
unsigned Align = TD->getPrefTypeAlignment(Ty);
if (Align < Size)
Align = Size;
std::string Name = getCStringSection() + utostr(Size) + '.' + utostr(Align);
unsigned Flags = SectionFlags::setEntitySize(SectionFlags::Mergeable |
SectionFlags::Strings,
Size);
return getNamedSection(Name.c_str(), Flags);
}
return getReadOnlySection();
}
std::string ELFTargetAsmInfo::printSectionFlags(unsigned flags) const {
std::string Flags = ",\"";
if (!(flags & SectionFlags::Debug))
Flags += 'a';
if (flags & SectionFlags::Code)
Flags += 'x';
if (flags & SectionFlags::Writeable)
Flags += 'w';
if (flags & SectionFlags::Mergeable)
Flags += 'M';
if (flags & SectionFlags::Strings)
Flags += 'S';
if (flags & SectionFlags::TLS)
Flags += 'T';
if (flags & SectionFlags::Small)
Flags += 's';
Flags += "\",";
// If comment string is '@', e.g. as on ARM - use '%' instead
if (strcmp(CommentString, "@") == 0)
Flags += '%';
else
Flags += '@';
// FIXME: There can be exceptions here
if (flags & SectionFlags::BSS)
Flags += "nobits";
else
Flags += "progbits";
if (unsigned entitySize = SectionFlags::getEntitySize(flags))
Flags += "," + utostr(entitySize);
return Flags;
}

View File

@ -1,9 +0,0 @@
include_directories(
${CMAKE_CURRENT_BINARY_DIR}/..
${CMAKE_CURRENT_SOURCE_DIR}/..
)
add_llvm_library(LLVMIA64AsmPrinter
IA64AsmPrinter.cpp
)
add_dependencies(LLVMIA64AsmPrinter IA64CodeGenTable_gen)

View File

@ -1,389 +0,0 @@
//===-- IA64AsmPrinter.cpp - Print out IA64 LLVM as assembly --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to assembly accepted by the GNU binutils 'gas'
// assembler. The Intel 'ias' and HP-UX 'as' assemblers *may* choke on this
// output, but if so that's a bug I'd like to hear about: please file a bug
// report in bugzilla. FYI, the not too bad 'ias' assembler is bundled with
// the Intel C/C++ compiler for Itanium Linux.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "IA64.h"
#include "IA64TargetMachine.h"
#include "llvm/Module.h"
#include "llvm/MDNode.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
namespace {
class IA64AsmPrinter : public AsmPrinter {
std::set<std::string> ExternalFunctionNames, ExternalObjectNames;
public:
explicit IA64AsmPrinter(raw_ostream &O, TargetMachine &TM,
const TargetAsmInfo *T, bool V)
: AsmPrinter(O, TM, T, V) {}
virtual const char *getPassName() const {
return "IA64 Assembly Printer";
}
/// printInstruction - This method is automatically generated by tablegen
/// from the instruction set description. This method returns true if the
/// machine instruction was sufficiently described to print it, otherwise it
/// returns false.
bool printInstruction(const MachineInstr *MI);
// This method is used by the tablegen'erated instruction printer.
void printOperand(const MachineInstr *MI, unsigned OpNo){
const MachineOperand &MO = MI->getOperand(OpNo);
if (MO.getType() == MachineOperand::MO_Register) {
assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
"Not physref??");
//XXX Bug Workaround: See note in Printer::doInitialization about %.
O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
} else {
printOp(MO);
}
}
void printS8ImmOperand(const MachineInstr *MI, unsigned OpNo) {
int val=(unsigned int)MI->getOperand(OpNo).getImm();
if(val>=128) val=val-256; // if negative, flip sign
O << val;
}
void printS14ImmOperand(const MachineInstr *MI, unsigned OpNo) {
int val=(unsigned int)MI->getOperand(OpNo).getImm();
if(val>=8192) val=val-16384; // if negative, flip sign
O << val;
}
void printS22ImmOperand(const MachineInstr *MI, unsigned OpNo) {
int val=(unsigned int)MI->getOperand(OpNo).getImm();
if(val>=2097152) val=val-4194304; // if negative, flip sign
O << val;
}
void printU64ImmOperand(const MachineInstr *MI, unsigned OpNo) {
O << (uint64_t)MI->getOperand(OpNo).getImm();
}
void printS64ImmOperand(const MachineInstr *MI, unsigned OpNo) {
// XXX : nasty hack to avoid GPREL22 "relocation truncated to fit" linker
// errors - instead of add rX = @gprel(CPI<whatever>), r1;; we now
// emit movl rX = @gprel(CPI<whatever);;
// add rX = rX, r1;
// this gives us 64 bits instead of 22 (for the add long imm) to play
// with, which shuts up the linker. The problem is that the constant
// pool entries aren't immediates at this stage, so we check here.
// If it's an immediate, print it the old fashioned way. If it's
// not, we print it as a constant pool index.
if (MI->getOperand(OpNo).isImm()) {
O << (int64_t)MI->getOperand(OpNo).getImm();
} else { // this is a constant pool reference: FIXME: assert this
printOp(MI->getOperand(OpNo));
}
}
void printGlobalOperand(const MachineInstr *MI, unsigned OpNo) {
printOp(MI->getOperand(OpNo), false); // this is NOT a br.call instruction
}
void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
printOp(MI->getOperand(OpNo), true); // this is a br.call instruction
}
void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO, bool isBRCALLinsn= false);
void printModuleLevelGV(const GlobalVariable* GVar);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
bool doFinalization(Module &M);
};
} // end of anonymous namespace
// Include the auto-generated portion of the assembly writer.
#include "IA64GenAsmWriter.inc"
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
bool IA64AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
this->MF = &MF;
SetupMachineFunction(MF);
O << "\n\n";
// Print out constants referenced by the function
EmitConstantPool(MF.getConstantPool());
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
// Print out labels for the function.
EmitAlignment(MF.getAlignment());
O << "\t.global\t" << CurrentFnName << '\n';
printVisibility(CurrentFnName, F->getVisibility());
O << "\t.type\t" << CurrentFnName << ", @function\n";
O << CurrentFnName << ":\n";
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block if there are any predecessors.
if (!I->pred_empty()) {
printBasicBlockLabel(I, true, true);
O << '\n';
}
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
printMachineInstruction(II);
}
}
// We didn't modify anything.
return false;
}
void IA64AsmPrinter::printOp(const MachineOperand &MO,
bool isBRCALLinsn /* = false */) {
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
switch (MO.getType()) {
case MachineOperand::MO_Register:
O << RI.get(MO.getReg()).AsmName;
return;
case MachineOperand::MO_Immediate:
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB());
return;
case MachineOperand::MO_ConstantPoolIndex: {
O << "@gprel(" << TAI->getPrivateGlobalPrefix()
<< "CPI" << getFunctionNumber() << "_" << MO.getIndex() << ")";
return;
}
case MachineOperand::MO_GlobalAddress: {
// functions need @ltoff(@fptr(fn_name)) form
GlobalValue *GV = MO.getGlobal();
Function *F = dyn_cast<Function>(GV);
bool Needfptr=false; // if we're computing an address @ltoff(X), do
// we need to decorate it so it becomes
// @ltoff(@fptr(X)) ?
if (F && !isBRCALLinsn /*&& F->isDeclaration()*/)
Needfptr=true;
// if this is the target of a call instruction, we should define
// the function somewhere (GNU gas has no problem without this, but
// Intel ias rightly complains of an 'undefined symbol')
if (F /*&& isBRCALLinsn*/ && F->isDeclaration())
ExternalFunctionNames.insert(Mang->getValueName(MO.getGlobal()));
else
if (GV->isDeclaration()) // e.g. stuff like 'stdin'
ExternalObjectNames.insert(Mang->getValueName(MO.getGlobal()));
if (!isBRCALLinsn)
O << "@ltoff(";
if (Needfptr)
O << "@fptr(";
O << Mang->getValueName(MO.getGlobal());
if (Needfptr && !isBRCALLinsn)
O << "#))"; // close both fptr( and ltoff(
else {
if (Needfptr)
O << "#)"; // close only fptr(
if (!isBRCALLinsn)
O << "#)"; // close only ltoff(
}
int Offset = MO.getOffset();
if (Offset > 0)
O << " + " << Offset;
else if (Offset < 0)
O << " - " << -Offset;
return;
}
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
ExternalFunctionNames.insert(MO.getSymbolName());
return;
default:
O << "<AsmPrinter: unknown operand type: " << MO.getType() << " >"; return;
}
}
/// printMachineInstruction -- Print out a single IA64 LLVM instruction
/// MI to the current output stream.
///
void IA64AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
// Call the autogenerated instruction printer routines.
printInstruction(MI);
}
bool IA64AsmPrinter::doInitialization(Module &M) {
bool Result = AsmPrinter::doInitialization(M);
O << "\n.ident \"LLVM-ia64\"\n\n"
<< "\t.psr lsb\n" // should be "msb" on HP-UX, for starters
<< "\t.radix C\n"
<< "\t.psr abi64\n"; // we only support 64 bits for now
return Result;
}
void IA64AsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
const TargetData *TD = TM.getTargetData();
if (!GVar->hasInitializer())
return; // External global require no code
// Check to see if this is a special global used by LLVM, if so, emit it.
if (EmitSpecialLLVMGlobal(GVar))
return;
O << "\n\n";
std::string name = Mang->getValueName(GVar);
Constant *C = GVar->getInitializer();
if (isa<MDNode>(C) || isa<MDString>(C))
return;
unsigned Size = TD->getTypeAllocSize(C->getType());
unsigned Align = TD->getPreferredAlignmentLog(GVar);
printVisibility(name, GVar->getVisibility());
SwitchToSection(TAI->SectionForGlobal(GVar));
if (C->isNullValue() && !GVar->hasSection()) {
if (!GVar->isThreadLocal() &&
(GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
if (GVar->hasLocalLinkage()) {
O << "\t.lcomm " << name << "#," << Size
<< ',' << (1 << Align);
O << '\n';
} else {
O << "\t.common " << name << "#," << Size
<< ',' << (1 << Align);
O << '\n';
}
return;
}
}
switch (GVar->getLinkage()) {
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::CommonLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
// Nonnull linkonce -> weak
O << "\t.weak " << name << '\n';
break;
case GlobalValue::AppendingLinkage:
// FIXME: appending linkage variables should go into a section of
// their name or something. For now, just emit them as external.
case GlobalValue::ExternalLinkage:
// If external or appending, declare as a global symbol
O << TAI->getGlobalDirective() << name << '\n';
// FALL THROUGH
case GlobalValue::InternalLinkage:
case GlobalValue::PrivateLinkage:
break;
case GlobalValue::GhostLinkage:
cerr << "GhostLinkage cannot appear in IA64AsmPrinter!\n";
abort();
case GlobalValue::DLLImportLinkage:
cerr << "DLLImport linkage is not supported by this target!\n";
abort();
case GlobalValue::DLLExportLinkage:
cerr << "DLLExport linkage is not supported by this target!\n";
abort();
default:
assert(0 && "Unknown linkage type!");
}
EmitAlignment(Align, GVar);
if (TAI->hasDotTypeDotSizeDirective()) {
O << "\t.type " << name << ",@object\n";
O << "\t.size " << name << ',' << Size << '\n';
}
O << name << ":\n";
EmitGlobalConstant(C);
}
bool IA64AsmPrinter::doFinalization(Module &M) {
// Print out module-level global variables here.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I)
printModuleLevelGV(I);
// we print out ".global X \n .type X, @function" for each external function
O << "\n\n// br.call targets referenced (and not defined) above: \n";
for (std::set<std::string>::iterator i = ExternalFunctionNames.begin(),
e = ExternalFunctionNames.end(); i!=e; ++i) {
O << "\t.global " << *i << "\n\t.type " << *i << ", @function\n";
}
O << "\n\n";
// we print out ".global X \n .type X, @object" for each external object
O << "\n\n// (external) symbols referenced (and not defined) above: \n";
for (std::set<std::string>::iterator i = ExternalObjectNames.begin(),
e = ExternalObjectNames.end(); i!=e; ++i) {
O << "\t.global " << *i << "\n\t.type " << *i << ", @object\n";
}
O << "\n\n";
return AsmPrinter::doFinalization(M);
}
/// createIA64CodePrinterPass - Returns a pass that prints the IA64
/// assembly code for a MachineFunction to the given output stream, using
/// the given target machine description.
///
FunctionPass *llvm::createIA64CodePrinterPass(raw_ostream &o,
IA64TargetMachine &tm,
bool verbose) {
return new IA64AsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
}
namespace {
static struct Register {
Register() {
IA64TargetMachine::registerAsmPrinter(createIA64CodePrinterPass);
}
} Registrator;
}
// Force static initialization.
extern "C" void LLVMInitializeIA64AsmPrinter() { }

View File

@ -1,17 +0,0 @@
##===- lib/Target/IA64/AsmPrinter/Makefile -----------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = LLVMIA64AsmPrinter
# Hack: we need to include 'main' IA64 target directory to grab
# private headers
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
include $(LEVEL)/Makefile.common

View File

@ -1,22 +0,0 @@
set(LLVM_TARGET_DEFINITIONS IA64.td)
tablegen(IA64GenRegisterInfo.h.inc -gen-register-desc-header)
tablegen(IA64GenRegisterNames.inc -gen-register-enums)
tablegen(IA64GenRegisterInfo.inc -gen-register-desc)
tablegen(IA64GenInstrNames.inc -gen-instr-enums)
tablegen(IA64GenInstrInfo.inc -gen-instr-desc)
tablegen(IA64GenAsmWriter.inc -gen-asm-writer)
tablegen(IA64GenDAGISel.inc -gen-dag-isel)
add_llvm_target(IA64CodeGen
IA64Bundling.cpp
IA64InstrInfo.cpp
IA64ISelDAGToDAG.cpp
IA64ISelLowering.cpp
IA64RegisterInfo.cpp
IA64Subtarget.cpp
IA64TargetAsmInfo.cpp
IA64TargetMachine.cpp
)
target_link_libraries (LLVMIA64CodeGen LLVMSelectionDAG)

View File

@ -1,57 +0,0 @@
//===-- IA64.h - Top-level interface for IA64 representation ------*- C++ -*-===//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the entry points for global functions defined in the IA64
// target library, as used by the LLVM JIT.
//
//===----------------------------------------------------------------------===//
#ifndef TARGET_IA64_H
#define TARGET_IA64_H
#include "llvm/Target/TargetMachine.h"
namespace llvm {
class IA64TargetMachine;
class FunctionPass;
class raw_ostream;
/// createIA64DAGToDAGInstructionSelector - This pass converts an LLVM
/// function into IA64 machine code in a sane, DAG->DAG transform.
///
FunctionPass *createIA64DAGToDAGInstructionSelector(IA64TargetMachine &TM);
/// createIA64BundlingPass - This pass adds stop bits and bundles
/// instructions.
///
FunctionPass *createIA64BundlingPass(IA64TargetMachine &TM);
/// createIA64CodePrinterPass - Returns a pass that prints the IA64
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description. This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *createIA64CodePrinterPass(raw_ostream &o,
IA64TargetMachine &tm,
bool verbose);
} // End llvm namespace
// Defines symbolic names for IA64 registers. This defines a mapping from
// register name to register number.
//
#include "IA64GenRegisterNames.inc"
// Defines symbolic names for the IA64 instructions.
//
#include "IA64GenInstrNames.inc"
#endif

View File

@ -1,39 +0,0 @@
//===-- IA64.td - Target definition file for Intel IA64 -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a target description file for the Intel IA64 architecture,
// also known variously as ia64, IA-64, IPF, "the Itanium architecture" etc.
//
//===----------------------------------------------------------------------===//
// Get the target-independent interfaces which we are implementing...
//
include "llvm/Target/Target.td"
//===----------------------------------------------------------------------===//
// Register File Description
//===----------------------------------------------------------------------===//
include "IA64RegisterInfo.td"
//===----------------------------------------------------------------------===//
// Instruction Descriptions
//===----------------------------------------------------------------------===//
include "IA64InstrInfo.td"
def IA64InstrInfo : InstrInfo { }
def IA64 : Target {
// Our instruction set
let InstructionSet = IA64InstrInfo;
}

View File

@ -1,118 +0,0 @@
//===-- IA64Bundling.cpp - IA-64 instruction bundling pass. ------------ --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Add stops where required to prevent read-after-write and write-after-write
// dependencies, for both registers and memory addresses. There are exceptions:
//
// - Compare instructions (cmp*, tbit, tnat, fcmp, frcpa) are OK with
// WAW dependencies so long as they all target p0, or are of parallel
// type (.and*/.or*)
//
// FIXME: bundling, for now, is left to the assembler.
// FIXME: this might be an appropriate place to translate between different
// instructions that do the same thing, if this helps bundling.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "ia64-codegen"
#include "IA64.h"
#include "IA64InstrInfo.h"
#include "IA64TargetMachine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
#include <set>
using namespace llvm;
STATISTIC(StopBitsAdded, "Number of stop bits added");
namespace {
struct IA64BundlingPass : public MachineFunctionPass {
static char ID;
/// Target machine description which we query for reg. names, data
/// layout, etc.
///
IA64TargetMachine &TM;
IA64BundlingPass(IA64TargetMachine &tm)
: MachineFunctionPass(&ID), TM(tm) { }
virtual const char *getPassName() const {
return "IA64 (Itanium) Bundling Pass";
}
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
bool runOnMachineFunction(MachineFunction &F) {
bool Changed = false;
for (MachineFunction::iterator FI = F.begin(), FE = F.end();
FI != FE; ++FI)
Changed |= runOnMachineBasicBlock(*FI);
return Changed;
}
// XXX: ugly global, but pending writes can cross basic blocks. Note that
// taken branches end instruction groups. So we only need to worry about
// 'fallthrough' code
std::set<unsigned> PendingRegWrites;
};
char IA64BundlingPass::ID = 0;
} // end of anonymous namespace
/// createIA64BundlingPass - Returns a pass that adds STOP (;;) instructions
/// and arranges the result into bundles.
///
FunctionPass *llvm::createIA64BundlingPass(IA64TargetMachine &tm) {
return new IA64BundlingPass(tm);
}
/// runOnMachineBasicBlock - add stops and bundle this MBB.
///
bool IA64BundlingPass::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
bool Changed = false;
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
MachineInstr *CurrentInsn = I++;
std::set<unsigned> CurrentReads, CurrentWrites, OrigWrites;
for(unsigned i=0; i < CurrentInsn->getNumOperands(); i++) {
MachineOperand &MO=CurrentInsn->getOperand(i);
if (MO.isReg()) {
if(MO.isUse()) { // TODO: exclude p0
CurrentReads.insert(MO.getReg());
}
if(MO.isDef()) { // TODO: exclude p0
CurrentWrites.insert(MO.getReg());
OrigWrites.insert(MO.getReg()); // FIXME: use a nondestructive
// set_intersect instead?
}
}
}
// CurrentReads/CurrentWrites contain info for the current instruction.
// Does it read or write any registers that are pending a write?
// (i.e. not separated by a stop)
set_intersect(CurrentReads, PendingRegWrites);
set_intersect(CurrentWrites, PendingRegWrites);
if(! (CurrentReads.empty() && CurrentWrites.empty()) ) {
// there is a conflict, insert a stop and reset PendingRegWrites
CurrentInsn = BuildMI(MBB, CurrentInsn, CurrentInsn->getDebugLoc(),
TM.getInstrInfo()->get(IA64::STOP), 0);
PendingRegWrites=OrigWrites; // carry over current writes to next insn
Changed=true; StopBitsAdded++; // update stats
} else { // otherwise, track additional pending writes
set_union(PendingRegWrites, OrigWrites);
}
} // onto the next insn in the MBB
return Changed;
}

View File

@ -1,575 +0,0 @@
//===---- IA64ISelDAGToDAG.cpp - IA64 pattern matching inst selector ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a pattern matching instruction selector for IA64,
// converting a legalized dag to an IA64 dag.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "ia64-codegen"
#include "IA64.h"
#include "IA64TargetMachine.h"
#include "IA64ISelLowering.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Constants.h"
#include "llvm/GlobalValue.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
using namespace llvm;
namespace {
//===--------------------------------------------------------------------===//
/// IA64DAGToDAGISel - IA64 specific code to select IA64 machine
/// instructions for SelectionDAG operations.
///
class IA64DAGToDAGISel : public SelectionDAGISel {
unsigned GlobalBaseReg;
public:
explicit IA64DAGToDAGISel(IA64TargetMachine &TM)
: SelectionDAGISel(TM) {}
virtual bool runOnFunction(Function &Fn) {
// Make sure we re-emit a set of the global base reg if necessary
GlobalBaseReg = 0;
return SelectionDAGISel::runOnFunction(Fn);
}
/// getI64Imm - Return a target constant with the specified value, of type
/// i64.
inline SDValue getI64Imm(uint64_t Imm) {
return CurDAG->getTargetConstant(Imm, MVT::i64);
}
/// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC
/// base register. Return the virtual register that holds this value.
// SDValue getGlobalBaseReg(); TODO: hmm
// Select - Convert the specified operand from a target-independent to a
// target-specific node if it hasn't already been changed.
SDNode *Select(SDValue N);
SDNode *SelectIntImmediateExpr(SDValue LHS, SDValue RHS,
unsigned OCHi, unsigned OCLo,
bool IsArithmetic = false,
bool Negate = false);
SDNode *SelectBitfieldInsert(SDNode *N);
/// SelectCC - Select a comparison of the specified values with the
/// specified condition code, returning the CR# of the expression.
SDValue SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC);
/// SelectAddr - Given the specified address, return the two operands for a
/// load/store instruction, and return true if it should be an indexed [r+r]
/// operation.
bool SelectAddr(SDValue Addr, SDValue &Op1, SDValue &Op2);
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
virtual void InstructionSelect();
virtual const char *getPassName() const {
return "IA64 (Itanium) DAG->DAG Instruction Selector";
}
// Include the pieces autogenerated from the target description.
#include "IA64GenDAGISel.inc"
private:
SDNode *SelectDIV(SDValue Op);
};
}
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void IA64DAGToDAGISel::InstructionSelect() {
DEBUG(BB->dump());
// Select target instructions for the DAG.
SelectRoot(*CurDAG);
CurDAG->RemoveDeadNodes();
}
SDNode *IA64DAGToDAGISel::SelectDIV(SDValue Op) {
SDNode *N = Op.getNode();
SDValue Chain = N->getOperand(0);
SDValue Tmp1 = N->getOperand(0);
SDValue Tmp2 = N->getOperand(1);
DebugLoc dl = N->getDebugLoc();
bool isFP=false;
if(Tmp1.getValueType().isFloatingPoint())
isFP=true;
bool isModulus=false; // is it a division or a modulus?
bool isSigned=false;
switch(N->getOpcode()) {
case ISD::FDIV:
case ISD::SDIV: isModulus=false; isSigned=true; break;
case ISD::UDIV: isModulus=false; isSigned=false; break;
case ISD::FREM:
case ISD::SREM: isModulus=true; isSigned=true; break;
case ISD::UREM: isModulus=true; isSigned=false; break;
}
// TODO: check for integer divides by powers of 2 (or other simple patterns?)
SDValue TmpPR, TmpPR2;
SDValue TmpF1, TmpF2, TmpF3, TmpF4, TmpF5, TmpF6, TmpF7, TmpF8;
SDValue TmpF9, TmpF10,TmpF11,TmpF12,TmpF13,TmpF14,TmpF15;
SDNode *Result;
// we'll need copies of F0 and F1
SDValue F0 = CurDAG->getRegister(IA64::F0, MVT::f64);
SDValue F1 = CurDAG->getRegister(IA64::F1, MVT::f64);
// OK, emit some code:
if(!isFP) {
// first, load the inputs into FP regs.
TmpF1 =
SDValue(CurDAG->getTargetNode(IA64::SETFSIG, dl, MVT::f64, Tmp1), 0);
Chain = TmpF1.getValue(1);
TmpF2 =
SDValue(CurDAG->getTargetNode(IA64::SETFSIG, dl, MVT::f64, Tmp2), 0);
Chain = TmpF2.getValue(1);
// next, convert the inputs to FP
if(isSigned) {
TmpF3 =
SDValue(CurDAG->getTargetNode(IA64::FCVTXF, dl, MVT::f64, TmpF1), 0);
Chain = TmpF3.getValue(1);
TmpF4 =
SDValue(CurDAG->getTargetNode(IA64::FCVTXF, dl, MVT::f64, TmpF2), 0);
Chain = TmpF4.getValue(1);
} else { // is unsigned
TmpF3 =
SDValue(CurDAG->getTargetNode(IA64::FCVTXUFS1, dl, MVT::f64, TmpF1),
0);
Chain = TmpF3.getValue(1);
TmpF4 =
SDValue(CurDAG->getTargetNode(IA64::FCVTXUFS1, dl, MVT::f64, TmpF2),
0);
Chain = TmpF4.getValue(1);
}
} else { // this is an FP divide/remainder, so we 'leak' some temp
// regs and assign TmpF3=Tmp1, TmpF4=Tmp2
TmpF3=Tmp1;
TmpF4=Tmp2;
}
// we start by computing an approximate reciprocal (good to 9 bits?)
// note, this instruction writes _both_ TmpF5 (answer) and TmpPR (predicate)
if(isFP)
TmpF5 = SDValue(CurDAG->getTargetNode(IA64::FRCPAS0, dl, MVT::f64,
MVT::i1, TmpF3, TmpF4), 0);
else
TmpF5 = SDValue(CurDAG->getTargetNode(IA64::FRCPAS1, dl, MVT::f64,
MVT::i1, TmpF3, TmpF4), 0);
TmpPR = TmpF5.getValue(1);
Chain = TmpF5.getValue(2);
SDValue minusB;
if(isModulus) { // for remainders, it'll be handy to have
// copies of -input_b
minusB = SDValue(CurDAG->getTargetNode(IA64::SUB, dl, MVT::i64,
CurDAG->getRegister(IA64::r0, MVT::i64), Tmp2), 0);
Chain = minusB.getValue(1);
}
SDValue TmpE0, TmpY1, TmpE1, TmpY2;
SDValue OpsE0[] = { TmpF4, TmpF5, F1, TmpPR };
TmpE0 = SDValue(CurDAG->getTargetNode(IA64::CFNMAS1, dl, MVT::f64,
OpsE0, 4), 0);
Chain = TmpE0.getValue(1);
SDValue OpsY1[] = { TmpF5, TmpE0, TmpF5, TmpPR };
TmpY1 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
OpsY1, 4), 0);
Chain = TmpY1.getValue(1);
SDValue OpsE1[] = { TmpE0, TmpE0, F0, TmpPR };
TmpE1 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
OpsE1, 4), 0);
Chain = TmpE1.getValue(1);
SDValue OpsY2[] = { TmpY1, TmpE1, TmpY1, TmpPR };
TmpY2 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
OpsY2, 4), 0);
Chain = TmpY2.getValue(1);
if(isFP) { // if this is an FP divide, we finish up here and exit early
if(isModulus)
assert(0 && "Sorry, try another FORTRAN compiler.");
SDValue TmpE2, TmpY3, TmpQ0, TmpR0;
SDValue OpsE2[] = { TmpE1, TmpE1, F0, TmpPR };
TmpE2 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
OpsE2, 4), 0);
Chain = TmpE2.getValue(1);
SDValue OpsY3[] = { TmpY2, TmpE2, TmpY2, TmpPR };
TmpY3 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
OpsY3, 4), 0);
Chain = TmpY3.getValue(1);
SDValue OpsQ0[] = { Tmp1, TmpY3, F0, TmpPR };
TmpQ0 =
SDValue(CurDAG->getTargetNode(IA64::CFMADS1, dl, // double prec!
MVT::f64, OpsQ0, 4), 0);
Chain = TmpQ0.getValue(1);
SDValue OpsR0[] = { Tmp2, TmpQ0, Tmp1, TmpPR };
TmpR0 =
SDValue(CurDAG->getTargetNode(IA64::CFNMADS1, dl, // double prec!
MVT::f64, OpsR0, 4), 0);
Chain = TmpR0.getValue(1);
// we want Result to have the same target register as the frcpa, so
// we two-address hack it. See the comment "for this to work..." on
// page 48 of Intel application note #245415
SDValue Ops[] = { TmpF5, TmpY3, TmpR0, TmpQ0, TmpPR };
Result = CurDAG->getTargetNode(IA64::TCFMADS0, dl, // d.p. s0 rndg!
MVT::f64, Ops, 5);
Chain = SDValue(Result, 1);
return Result; // XXX: early exit!
} else { // this is *not* an FP divide, so there's a bit left to do:
SDValue TmpQ2, TmpR2, TmpQ3, TmpQ;
SDValue OpsQ2[] = { TmpF3, TmpY2, F0, TmpPR };
TmpQ2 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
OpsQ2, 4), 0);
Chain = TmpQ2.getValue(1);
SDValue OpsR2[] = { TmpF4, TmpQ2, TmpF3, TmpPR };
TmpR2 = SDValue(CurDAG->getTargetNode(IA64::CFNMAS1, dl, MVT::f64,
OpsR2, 4), 0);
Chain = TmpR2.getValue(1);
// we want TmpQ3 to have the same target register as the frcpa? maybe we
// should two-address hack it. See the comment "for this to work..." on page
// 48 of Intel application note #245415
SDValue OpsQ3[] = { TmpF5, TmpR2, TmpY2, TmpQ2, TmpPR };
TmpQ3 = SDValue(CurDAG->getTargetNode(IA64::TCFMAS1, dl, MVT::f64,
OpsQ3, 5), 0);
Chain = TmpQ3.getValue(1);
// STORY: without these two-address instructions (TCFMAS1 and TCFMADS0)
// the FPSWA won't be able to help out in the case of large/tiny
// arguments. Other fun bugs may also appear, e.g. 0/x = x, not 0.
if(isSigned)
TmpQ = SDValue(CurDAG->getTargetNode(IA64::FCVTFXTRUNCS1, dl,
MVT::f64, TmpQ3), 0);
else
TmpQ = SDValue(CurDAG->getTargetNode(IA64::FCVTFXUTRUNCS1, dl,
MVT::f64, TmpQ3), 0);
Chain = TmpQ.getValue(1);
if(isModulus) {
SDValue FPminusB =
SDValue(CurDAG->getTargetNode(IA64::SETFSIG, dl, MVT::f64, minusB),
0);
Chain = FPminusB.getValue(1);
SDValue Remainder =
SDValue(CurDAG->getTargetNode(IA64::XMAL, dl, MVT::f64,
TmpQ, FPminusB, TmpF1), 0);
Chain = Remainder.getValue(1);
Result = CurDAG->getTargetNode(IA64::GETFSIG, dl, MVT::i64, Remainder);
Chain = SDValue(Result, 1);
} else { // just an integer divide
Result = CurDAG->getTargetNode(IA64::GETFSIG, dl, MVT::i64, TmpQ);
Chain = SDValue(Result, 1);
}
return Result;
} // wasn't an FP divide
}
// Select - Convert the specified operand from a target-independent to a
// target-specific node if it hasn't already been changed.
SDNode *IA64DAGToDAGISel::Select(SDValue Op) {
SDNode *N = Op.getNode();
if (N->isMachineOpcode())
return NULL; // Already selected.
DebugLoc dl = Op.getDebugLoc();
switch (N->getOpcode()) {
default: break;
case IA64ISD::BRCALL: { // XXX: this is also a hack!
SDValue Chain = N->getOperand(0);
SDValue InFlag; // Null incoming flag value.
if(N->getNumOperands()==3) { // we have an incoming chain, callee and flag
InFlag = N->getOperand(2);
}
unsigned CallOpcode;
SDValue CallOperand;
// if we can call directly, do so
if (GlobalAddressSDNode *GASD =
dyn_cast<GlobalAddressSDNode>(N->getOperand(1))) {
CallOpcode = IA64::BRCALL_IPREL_GA;
CallOperand = CurDAG->getTargetGlobalAddress(GASD->getGlobal(), MVT::i64);
} else if (isa<ExternalSymbolSDNode>(N->getOperand(1))) {
// FIXME: we currently NEED this case for correctness, to avoid
// "non-pic code with imm reloc.n against dynamic symbol" errors
CallOpcode = IA64::BRCALL_IPREL_ES;
CallOperand = N->getOperand(1);
} else {
// otherwise we need to load the function descriptor,
// load the branch target (function)'s entry point and GP,
// branch (call) then restore the GP
SDValue FnDescriptor = N->getOperand(1);
// load the branch target's entry point [mem] and
// GP value [mem+8]
SDValue targetEntryPoint=
SDValue(CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64, MVT::Other,
FnDescriptor, CurDAG->getEntryNode()), 0);
Chain = targetEntryPoint.getValue(1);
SDValue targetGPAddr=
SDValue(CurDAG->getTargetNode(IA64::ADDS, dl, MVT::i64,
FnDescriptor,
CurDAG->getConstant(8, MVT::i64)), 0);
Chain = targetGPAddr.getValue(1);
SDValue targetGP =
SDValue(CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64,MVT::Other,
targetGPAddr, CurDAG->getEntryNode()), 0);
Chain = targetGP.getValue(1);
Chain = CurDAG->getCopyToReg(Chain, dl, IA64::r1, targetGP, InFlag);
InFlag = Chain.getValue(1);
Chain = CurDAG->getCopyToReg(Chain, dl, IA64::B6,
targetEntryPoint, InFlag); // FLAG these?
InFlag = Chain.getValue(1);
CallOperand = CurDAG->getRegister(IA64::B6, MVT::i64);
CallOpcode = IA64::BRCALL_INDIRECT;
}
// Finally, once everything is setup, emit the call itself
if (InFlag.getNode())
Chain = SDValue(CurDAG->getTargetNode(CallOpcode, dl, MVT::Other,
MVT::Flag, CallOperand, InFlag), 0);
else // there might be no arguments
Chain = SDValue(CurDAG->getTargetNode(CallOpcode, dl, MVT::Other,
MVT::Flag, CallOperand, Chain), 0);
InFlag = Chain.getValue(1);
std::vector<SDValue> CallResults;
CallResults.push_back(Chain);
CallResults.push_back(InFlag);
for (unsigned i = 0, e = CallResults.size(); i != e; ++i)
ReplaceUses(Op.getValue(i), CallResults[i]);
return NULL;
}
case IA64ISD::GETFD: {
SDValue Input = N->getOperand(0);
return CurDAG->getTargetNode(IA64::GETFD, dl, MVT::i64, Input);
}
case ISD::FDIV:
case ISD::SDIV:
case ISD::UDIV:
case ISD::SREM:
case ISD::UREM:
return SelectDIV(Op);
case ISD::TargetConstantFP: {
SDValue Chain = CurDAG->getEntryNode(); // this is a constant, so..
SDValue V;
ConstantFPSDNode* N2 = cast<ConstantFPSDNode>(N);
if (N2->getValueAPF().isPosZero()) {
V = CurDAG->getCopyFromReg(Chain, dl, IA64::F0, MVT::f64);
} else if (N2->isExactlyValue(N2->getValueType(0) == MVT::f32 ?
APFloat(+1.0f) : APFloat(+1.0))) {
V = CurDAG->getCopyFromReg(Chain, dl, IA64::F1, MVT::f64);
} else
assert(0 && "Unexpected FP constant!");
ReplaceUses(SDValue(N, 0), V);
return 0;
}
case ISD::FrameIndex: { // TODO: reduce creepyness
int FI = cast<FrameIndexSDNode>(N)->getIndex();
if (N->hasOneUse())
return CurDAG->SelectNodeTo(N, IA64::MOV, MVT::i64,
CurDAG->getTargetFrameIndex(FI, MVT::i64));
else
return CurDAG->getTargetNode(IA64::MOV, dl, MVT::i64,
CurDAG->getTargetFrameIndex(FI, MVT::i64));
}
case ISD::ConstantPool: { // TODO: nuke the constant pool
// (ia64 doesn't need one)
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(N);
Constant *C = CP->getConstVal();
SDValue CPI = CurDAG->getTargetConstantPool(C, MVT::i64,
CP->getAlignment());
return CurDAG->getTargetNode(IA64::ADDL_GA, dl, MVT::i64, // ?
CurDAG->getRegister(IA64::r1, MVT::i64), CPI);
}
case ISD::GlobalAddress: {
GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
SDValue GA = CurDAG->getTargetGlobalAddress(GV, MVT::i64);
SDValue Tmp =
SDValue(CurDAG->getTargetNode(IA64::ADDL_GA, dl, MVT::i64,
CurDAG->getRegister(IA64::r1,
MVT::i64), GA), 0);
return CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64, MVT::Other, Tmp,
CurDAG->getEntryNode());
}
/* XXX
case ISD::ExternalSymbol: {
SDValue EA = CurDAG->getTargetExternalSymbol(
cast<ExternalSymbolSDNode>(N)->getSymbol(),
MVT::i64);
SDValue Tmp = CurDAG->getTargetNode(IA64::ADDL_EA, dl, MVT::i64,
CurDAG->getRegister(IA64::r1,
MVT::i64),
EA);
return CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64, Tmp);
}
*/
case ISD::LOAD: { // FIXME: load -1, not 1, for bools?
LoadSDNode *LD = cast<LoadSDNode>(N);
SDValue Chain = LD->getChain();
SDValue Address = LD->getBasePtr();
MVT TypeBeingLoaded = LD->getMemoryVT();
unsigned Opc;
switch (TypeBeingLoaded.getSimpleVT()) {
default:
#ifndef NDEBUG
N->dump(CurDAG);
#endif
assert(0 && "Cannot load this type!");
case MVT::i1: { // this is a bool
Opc = IA64::LD1; // first we load a byte, then compare for != 0
if(N->getValueType(0) == MVT::i1) { // XXX: early exit!
return CurDAG->SelectNodeTo(N, IA64::CMPNE, MVT::i1, MVT::Other,
SDValue(CurDAG->getTargetNode(Opc, dl,
MVT::i64,
Address), 0),
CurDAG->getRegister(IA64::r0, MVT::i64),
Chain);
}
/* otherwise, we want to load a bool into something bigger: LD1
will do that for us, so we just fall through */
}
case MVT::i8: Opc = IA64::LD1; break;
case MVT::i16: Opc = IA64::LD2; break;
case MVT::i32: Opc = IA64::LD4; break;
case MVT::i64: Opc = IA64::LD8; break;
case MVT::f32: Opc = IA64::LDF4; break;
case MVT::f64: Opc = IA64::LDF8; break;
}
// TODO: comment this
return CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), MVT::Other,
Address, Chain);
}
case ISD::STORE: {
StoreSDNode *ST = cast<StoreSDNode>(N);
SDValue Address = ST->getBasePtr();
SDValue Chain = ST->getChain();
unsigned Opc;
if (ISD::isNON_TRUNCStore(N)) {
switch (N->getOperand(1).getValueType().getSimpleVT()) {
default: assert(0 && "unknown type in store");
case MVT::i1: { // this is a bool
Opc = IA64::ST1; // we store either 0 or 1 as a byte
// first load zero!
SDValue Initial = CurDAG->getCopyFromReg(Chain, dl, IA64::r0, MVT::i64);
Chain = Initial.getValue(1);
// then load 1 into the same reg iff the predicate to store is 1
SDValue Tmp = ST->getValue();
Tmp =
SDValue(CurDAG->getTargetNode(IA64::TPCADDS, dl, MVT::i64, Initial,
CurDAG->getTargetConstant(1,
MVT::i64),
Tmp), 0);
return CurDAG->SelectNodeTo(N, Opc, MVT::Other, Address, Tmp, Chain);
}
case MVT::i64: Opc = IA64::ST8; break;
case MVT::f64: Opc = IA64::STF8; break;
}
} else { // Truncating store
switch(ST->getMemoryVT().getSimpleVT()) {
default: assert(0 && "unknown type in truncstore");
case MVT::i8: Opc = IA64::ST1; break;
case MVT::i16: Opc = IA64::ST2; break;
case MVT::i32: Opc = IA64::ST4; break;
case MVT::f32: Opc = IA64::STF4; break;
}
}
SDValue N1 = N->getOperand(1);
SDValue N2 = N->getOperand(2);
return CurDAG->SelectNodeTo(N, Opc, MVT::Other, N2, N1, Chain);
}
case ISD::BRCOND: {
SDValue Chain = N->getOperand(0);
SDValue CC = N->getOperand(1);
MachineBasicBlock *Dest =
cast<BasicBlockSDNode>(N->getOperand(2))->getBasicBlock();
//FIXME - we do NOT need long branches all the time
return CurDAG->SelectNodeTo(N, IA64::BRLCOND_NOTCALL, MVT::Other, CC,
CurDAG->getBasicBlock(Dest), Chain);
}
case ISD::CALLSEQ_START:
case ISD::CALLSEQ_END: {
int64_t Amt = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
unsigned Opc = N->getOpcode() == ISD::CALLSEQ_START ?
IA64::ADJUSTCALLSTACKDOWN : IA64::ADJUSTCALLSTACKUP;
SDValue N0 = N->getOperand(0);
return CurDAG->SelectNodeTo(N, Opc, MVT::Other, getI64Imm(Amt), N0);
}
case ISD::BR:
// FIXME: we don't need long branches all the time!
SDValue N0 = N->getOperand(0);
return CurDAG->SelectNodeTo(N, IA64::BRL_NOTCALL, MVT::Other,
N->getOperand(1), N0);
}
return SelectCode(Op);
}
/// createIA64DAGToDAGInstructionSelector - This pass converts a legalized DAG
/// into an IA64-specific DAG, ready for instruction scheduling.
///
FunctionPass
*llvm::createIA64DAGToDAGInstructionSelector(IA64TargetMachine &TM) {
return new IA64DAGToDAGISel(TM);
}

View File

@ -1,632 +0,0 @@
//===-- IA64ISelLowering.cpp - IA64 DAG Lowering Implementation -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the IA64ISelLowering class.
//
//===----------------------------------------------------------------------===//
#include "IA64ISelLowering.h"
#include "IA64MachineFunctionInfo.h"
#include "IA64TargetMachine.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
using namespace llvm;
IA64TargetLowering::IA64TargetLowering(TargetMachine &TM)
: TargetLowering(TM) {
// register class for general registers
addRegisterClass(MVT::i64, IA64::GRRegisterClass);
// register class for FP registers
addRegisterClass(MVT::f64, IA64::FPRegisterClass);
// register class for predicate registers
addRegisterClass(MVT::i1, IA64::PRRegisterClass);
setLoadExtAction(ISD::EXTLOAD , MVT::i1 , Promote);
setLoadExtAction(ISD::ZEXTLOAD , MVT::i1 , Promote);
setLoadExtAction(ISD::SEXTLOAD , MVT::i1 , Promote);
setLoadExtAction(ISD::SEXTLOAD , MVT::i8 , Expand);
setLoadExtAction(ISD::SEXTLOAD , MVT::i16 , Expand);
setLoadExtAction(ISD::SEXTLOAD , MVT::i32 , Expand);
setOperationAction(ISD::BRIND , MVT::Other, Expand);
setOperationAction(ISD::BR_JT , MVT::Other, Expand);
setOperationAction(ISD::BR_CC , MVT::Other, Expand);
setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand);
// ia64 uses SELECT not SELECT_CC
setOperationAction(ISD::SELECT_CC , MVT::Other, Expand);
// We need to handle ISD::RET for void functions ourselves,
// so we get a chance to restore ar.pfs before adding a
// br.ret insn
setOperationAction(ISD::RET, MVT::Other, Custom);
setShiftAmountType(MVT::i64);
setOperationAction(ISD::FREM , MVT::f32 , Expand);
setOperationAction(ISD::FREM , MVT::f64 , Expand);
setOperationAction(ISD::UREM , MVT::f32 , Expand);
setOperationAction(ISD::UREM , MVT::f64 , Expand);
setOperationAction(ISD::MEMBARRIER , MVT::Other, Expand);
setOperationAction(ISD::SINT_TO_FP , MVT::i1 , Promote);
setOperationAction(ISD::UINT_TO_FP , MVT::i1 , Promote);
// We don't support sin/cos/sqrt/pow
setOperationAction(ISD::FSIN , MVT::f64, Expand);
setOperationAction(ISD::FCOS , MVT::f64, Expand);
setOperationAction(ISD::FSQRT, MVT::f64, Expand);
setOperationAction(ISD::FPOW , MVT::f64, Expand);
setOperationAction(ISD::FSIN , MVT::f32, Expand);
setOperationAction(ISD::FCOS , MVT::f32, Expand);
setOperationAction(ISD::FSQRT, MVT::f32, Expand);
setOperationAction(ISD::FPOW , MVT::f32, Expand);
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
// FIXME: IA64 supports fcopysign natively!
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
// We don't have line number support yet.
setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand);
setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
// IA64 has ctlz in the form of the 'fnorm' instruction. The Legalizer
// expansion for ctlz/cttz in terms of ctpop is much larger, but lower
// latency.
// FIXME: Custom lower CTLZ when compiling for size?
setOperationAction(ISD::CTLZ , MVT::i64 , Expand);
setOperationAction(ISD::CTTZ , MVT::i64 , Expand);
setOperationAction(ISD::ROTL , MVT::i64 , Expand);
setOperationAction(ISD::ROTR , MVT::i64 , Expand);
// FIXME: IA64 has this, but is not implemented. should be mux @rev
setOperationAction(ISD::BSWAP, MVT::i64 , Expand);
// VASTART needs to be custom lowered to use the VarArgsFrameIndex
setOperationAction(ISD::VAARG , MVT::Other, Custom);
setOperationAction(ISD::VASTART , MVT::Other, Custom);
// FIXME: These should be legal
setOperationAction(ISD::BIT_CONVERT, MVT::i64, Expand);
setOperationAction(ISD::BIT_CONVERT, MVT::f64, Expand);
// Use the default implementation.
setOperationAction(ISD::VACOPY , MVT::Other, Expand);
setOperationAction(ISD::VAEND , MVT::Other, Expand);
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
// Thread Local Storage
setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
setStackPointerRegisterToSaveRestore(IA64::r12);
setJumpBufSize(704); // on ia64-linux, jmp_bufs are 704 bytes..
setJumpBufAlignment(16); // ...and must be 16-byte aligned
computeRegisterProperties();
addLegalFPImmediate(APFloat(+0.0));
addLegalFPImmediate(APFloat(-0.0));
addLegalFPImmediate(APFloat(+1.0));
addLegalFPImmediate(APFloat(-1.0));
}
const char *IA64TargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
default: return 0;
case IA64ISD::GETFD: return "IA64ISD::GETFD";
case IA64ISD::BRCALL: return "IA64ISD::BRCALL";
case IA64ISD::RET_FLAG: return "IA64ISD::RET_FLAG";
}
}
MVT IA64TargetLowering::getSetCCResultType(MVT VT) const {
return MVT::i1;
}
/// getFunctionAlignment - Return the Log2 alignment of this function.
unsigned IA64TargetLowering::getFunctionAlignment(const Function *) const {
return 5;
}
void IA64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &ArgValues,
DebugLoc dl) {
//
// add beautiful description of IA64 stack frame format
// here (from intel 24535803.pdf most likely)
//
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
GP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
SP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
RP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
MachineBasicBlock& BB = MF.front();
unsigned args_int[] = {IA64::r32, IA64::r33, IA64::r34, IA64::r35,
IA64::r36, IA64::r37, IA64::r38, IA64::r39};
unsigned args_FP[] = {IA64::F8, IA64::F9, IA64::F10, IA64::F11,
IA64::F12,IA64::F13,IA64::F14, IA64::F15};
unsigned argVreg[8];
unsigned argPreg[8];
unsigned argOpc[8];
unsigned used_FPArgs = 0; // how many FP args have been used so far?
unsigned ArgOffset = 0;
int count = 0;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
{
SDValue newroot, argt;
if(count < 8) { // need to fix this logic? maybe.
switch (getValueType(I->getType()).getSimpleVT()) {
default:
assert(0 && "ERROR in LowerArgs: can't lower this type of arg.\n");
case MVT::f32:
// fixme? (well, will need to for weird FP structy stuff,
// see intel ABI docs)
case MVT::f64:
//XXX BuildMI(&BB, IA64::IDEF, 0, args_FP[used_FPArgs]);
MF.getRegInfo().addLiveIn(args_FP[used_FPArgs]);
// mark this reg as liveIn
// floating point args go into f8..f15 as-needed, the increment
argVreg[count] = // is below..:
MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::f64));
// FP args go into f8..f15 as needed: (hence the ++)
argPreg[count] = args_FP[used_FPArgs++];
argOpc[count] = IA64::FMOV;
argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), dl,
argVreg[count], MVT::f64);
if (I->getType() == Type::FloatTy)
argt = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, argt,
DAG.getIntPtrConstant(0));
break;
case MVT::i1: // NOTE: as far as C abi stuff goes,
// bools are just boring old ints
case MVT::i8:
case MVT::i16:
case MVT::i32:
case MVT::i64:
//XXX BuildMI(&BB, IA64::IDEF, 0, args_int[count]);
MF.getRegInfo().addLiveIn(args_int[count]);
// mark this register as liveIn
argVreg[count] =
MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
argPreg[count] = args_int[count];
argOpc[count] = IA64::MOV;
argt = newroot =
DAG.getCopyFromReg(DAG.getRoot(), dl, argVreg[count], MVT::i64);
if ( getValueType(I->getType()) != MVT::i64)
argt = DAG.getNode(ISD::TRUNCATE, dl, getValueType(I->getType()),
newroot);
break;
}
} else { // more than 8 args go into the frame
// Create the frame index object for this incoming parameter...
ArgOffset = 16 + 8 * (count - 8);
int FI = MFI->CreateFixedObject(8, ArgOffset);
// Create the SelectionDAG nodes corresponding to a load
//from this parameter
SDValue FIN = DAG.getFrameIndex(FI, MVT::i64);
argt = newroot = DAG.getLoad(getValueType(I->getType()), dl,
DAG.getEntryNode(), FIN, NULL, 0);
}
++count;
DAG.setRoot(newroot.getValue(1));
ArgValues.push_back(argt);
}
// Create a vreg to hold the output of (what will become)
// the "alloc" instruction
VirtGPR = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
BuildMI(&BB, dl, TII->get(IA64::PSEUDO_ALLOC), VirtGPR);
// we create a PSEUDO_ALLOC (pseudo)instruction for now
/*
BuildMI(&BB, IA64::IDEF, 0, IA64::r1);
// hmm:
BuildMI(&BB, IA64::IDEF, 0, IA64::r12);
BuildMI(&BB, IA64::IDEF, 0, IA64::rp);
// ..hmm.
BuildMI(&BB, IA64::MOV, 1, GP).addReg(IA64::r1);
// hmm:
BuildMI(&BB, IA64::MOV, 1, SP).addReg(IA64::r12);
BuildMI(&BB, IA64::MOV, 1, RP).addReg(IA64::rp);
// ..hmm.
*/
unsigned tempOffset=0;
// if this is a varargs function, we simply lower llvm.va_start by
// pointing to the first entry
if(F.isVarArg()) {
tempOffset=0;
VarArgsFrameIndex = MFI->CreateFixedObject(8, tempOffset);
}
// here we actually do the moving of args, and store them to the stack
// too if this is a varargs function:
for (int i = 0; i < count && i < 8; ++i) {
BuildMI(&BB, dl, TII->get(argOpc[i]), argVreg[i]).addReg(argPreg[i]);
if(F.isVarArg()) {
// if this is a varargs function, we copy the input registers to the stack
int FI = MFI->CreateFixedObject(8, tempOffset);
tempOffset+=8; //XXX: is it safe to use r22 like this?
BuildMI(&BB, dl, TII->get(IA64::MOV), IA64::r22).addFrameIndex(FI);
// FIXME: we should use st8.spill here, one day
BuildMI(&BB, dl, TII->get(IA64::ST8), IA64::r22).addReg(argPreg[i]);
}
}
// Finally, inform the code generator which regs we return values in.
// (see the ISD::RET: case in the instruction selector)
switch (getValueType(F.getReturnType()).getSimpleVT()) {
default: assert(0 && "i have no idea where to return this type!");
case MVT::isVoid: break;
case MVT::i1:
case MVT::i8:
case MVT::i16:
case MVT::i32:
case MVT::i64:
MF.getRegInfo().addLiveOut(IA64::r8);
break;
case MVT::f32:
case MVT::f64:
MF.getRegInfo().addLiveOut(IA64::F8);
break;
}
}
std::pair<SDValue, SDValue>
IA64TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
bool RetSExt, bool RetZExt, bool isVarArg,
bool isInreg, unsigned NumFixedArgs,
unsigned CallingConv,
bool isTailCall, SDValue Callee,
ArgListTy &Args, SelectionDAG &DAG,
DebugLoc dl) {
MachineFunction &MF = DAG.getMachineFunction();
unsigned NumBytes = 16;
unsigned outRegsUsed = 0;
if (Args.size() > 8) {
NumBytes += (Args.size() - 8) * 8;
outRegsUsed = 8;
} else {
outRegsUsed = Args.size();
}
// FIXME? this WILL fail if we ever try to pass around an arg that
// consumes more than a single output slot (a 'real' double, int128
// some sort of aggregate etc.), as we'll underestimate how many 'outX'
// registers we use. Hopefully, the assembler will notice.
MF.getInfo<IA64FunctionInfo>()->outRegsUsed=
std::max(outRegsUsed, MF.getInfo<IA64FunctionInfo>()->outRegsUsed);
// keep stack frame 16-byte aligned
// assert(NumBytes==((NumBytes+15) & ~15) &&
// "stack frame not 16-byte aligned!");
NumBytes = (NumBytes+15) & ~15;
Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true));
SDValue StackPtr;
std::vector<SDValue> Stores;
std::vector<SDValue> Converts;
std::vector<SDValue> RegValuesToPass;
unsigned ArgOffset = 16;
for (unsigned i = 0, e = Args.size(); i != e; ++i)
{
SDValue Val = Args[i].Node;
MVT ObjectVT = Val.getValueType();
SDValue ValToStore(0, 0), ValToConvert(0, 0);
unsigned ObjSize=8;
switch (ObjectVT.getSimpleVT()) {
default: assert(0 && "unexpected argument type!");
case MVT::i1:
case MVT::i8:
case MVT::i16:
case MVT::i32: {
//promote to 64-bits, sign/zero extending based on type
//of the argument
ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
if (Args[i].isSExt)
ExtendKind = ISD::SIGN_EXTEND;
else if (Args[i].isZExt)
ExtendKind = ISD::ZERO_EXTEND;
Val = DAG.getNode(ExtendKind, dl, MVT::i64, Val);
// XXX: fall through
}
case MVT::i64:
//ObjSize = 8;
if(RegValuesToPass.size() >= 8) {
ValToStore = Val;
} else {
RegValuesToPass.push_back(Val);
}
break;
case MVT::f32:
//promote to 64-bits
Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val);
// XXX: fall through
case MVT::f64:
if(RegValuesToPass.size() >= 8) {
ValToStore = Val;
} else {
RegValuesToPass.push_back(Val);
if(1 /* TODO: if(calling external or varadic function)*/ ) {
ValToConvert = Val; // additionally pass this FP value as an int
}
}
break;
}
if(ValToStore.getNode()) {
if(!StackPtr.getNode()) {
StackPtr = DAG.getRegister(IA64::r12, MVT::i64);
}
SDValue PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i64, StackPtr, PtrOff);
Stores.push_back(DAG.getStore(Chain, dl, ValToStore, PtrOff, NULL, 0));
ArgOffset += ObjSize;
}
if(ValToConvert.getNode()) {
Converts.push_back(DAG.getNode(IA64ISD::GETFD, dl,
MVT::i64, ValToConvert));
}
}
// Emit all stores, make sure they occur before any copies into physregs.
if (!Stores.empty())
Chain = DAG.getNode(ISD::TokenFactor, dl,
MVT::Other, &Stores[0],Stores.size());
static const unsigned IntArgRegs[] = {
IA64::out0, IA64::out1, IA64::out2, IA64::out3,
IA64::out4, IA64::out5, IA64::out6, IA64::out7
};
static const unsigned FPArgRegs[] = {
IA64::F8, IA64::F9, IA64::F10, IA64::F11,
IA64::F12, IA64::F13, IA64::F14, IA64::F15
};
SDValue InFlag;
// save the current GP, SP and RP : FIXME: do we need to do all 3 always?
SDValue GPBeforeCall = DAG.getCopyFromReg(Chain, dl, IA64::r1,
MVT::i64, InFlag);
Chain = GPBeforeCall.getValue(1);
InFlag = Chain.getValue(2);
SDValue SPBeforeCall = DAG.getCopyFromReg(Chain, dl, IA64::r12,
MVT::i64, InFlag);
Chain = SPBeforeCall.getValue(1);
InFlag = Chain.getValue(2);
SDValue RPBeforeCall = DAG.getCopyFromReg(Chain, dl, IA64::rp,
MVT::i64, InFlag);
Chain = RPBeforeCall.getValue(1);
InFlag = Chain.getValue(2);
// Build a sequence of copy-to-reg nodes chained together with token chain
// and flag operands which copy the outgoing integer args into regs out[0-7]
// mapped 1:1 and the FP args into regs F8-F15 "lazily"
// TODO: for performance, we should only copy FP args into int regs when we
// know this is required (i.e. for varardic or external (unknown) functions)
// first to the FP->(integer representation) conversions, these are
// flagged for now, but shouldn't have to be (TODO)
unsigned seenConverts = 0;
for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
if(RegValuesToPass[i].getValueType().isFloatingPoint()) {
Chain = DAG.getCopyToReg(Chain, dl, IntArgRegs[i],
Converts[seenConverts++], InFlag);
InFlag = Chain.getValue(1);
}
}
// next copy args into the usual places, these are flagged
unsigned usedFPArgs = 0;
for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
Chain = DAG.getCopyToReg(Chain, dl,
RegValuesToPass[i].getValueType().isInteger() ?
IntArgRegs[i] : FPArgRegs[usedFPArgs++], RegValuesToPass[i], InFlag);
InFlag = Chain.getValue(1);
}
// If the callee is a GlobalAddress node (quite common, every direct call is)
// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
/*
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i64);
}
*/
std::vector<MVT> NodeTys;
std::vector<SDValue> CallOperands;
NodeTys.push_back(MVT::Other); // Returns a chain
NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
CallOperands.push_back(Chain);
CallOperands.push_back(Callee);
// emit the call itself
if (InFlag.getNode())
CallOperands.push_back(InFlag);
else
assert(0 && "this should never happen!\n");
// to make way for a hack:
Chain = DAG.getNode(IA64ISD::BRCALL, dl, NodeTys,
&CallOperands[0], CallOperands.size());
InFlag = Chain.getValue(1);
// restore the GP, SP and RP after the call
Chain = DAG.getCopyToReg(Chain, dl, IA64::r1, GPBeforeCall, InFlag);
InFlag = Chain.getValue(1);
Chain = DAG.getCopyToReg(Chain, dl, IA64::r12, SPBeforeCall, InFlag);
InFlag = Chain.getValue(1);
Chain = DAG.getCopyToReg(Chain, dl, IA64::rp, RPBeforeCall, InFlag);
InFlag = Chain.getValue(1);
std::vector<MVT> RetVals;
RetVals.push_back(MVT::Other);
RetVals.push_back(MVT::Flag);
MVT RetTyVT = getValueType(RetTy);
SDValue RetVal;
if (RetTyVT != MVT::isVoid) {
switch (RetTyVT.getSimpleVT()) {
default: assert(0 && "Unknown value type to return!");
case MVT::i1: { // bools are just like other integers (returned in r8)
// we *could* fall through to the truncate below, but this saves a
// few redundant predicate ops
SDValue boolInR8 = DAG.getCopyFromReg(Chain, dl, IA64::r8,
MVT::i64,InFlag);
InFlag = boolInR8.getValue(2);
Chain = boolInR8.getValue(1);
SDValue zeroReg = DAG.getCopyFromReg(Chain, dl, IA64::r0,
MVT::i64, InFlag);
InFlag = zeroReg.getValue(2);
Chain = zeroReg.getValue(1);
RetVal = DAG.getSetCC(dl, MVT::i1, boolInR8, zeroReg, ISD::SETNE);
break;
}
case MVT::i8:
case MVT::i16:
case MVT::i32:
RetVal = DAG.getCopyFromReg(Chain, dl, IA64::r8, MVT::i64, InFlag);
Chain = RetVal.getValue(1);
// keep track of whether it is sign or zero extended (todo: bools?)
/* XXX
RetVal = DAG.getNode(RetTy->isSigned() ? ISD::AssertSext :ISD::AssertZext,
dl, MVT::i64, RetVal, DAG.getValueType(RetTyVT));
*/
RetVal = DAG.getNode(ISD::TRUNCATE, dl, RetTyVT, RetVal);
break;
case MVT::i64:
RetVal = DAG.getCopyFromReg(Chain, dl, IA64::r8, MVT::i64, InFlag);
Chain = RetVal.getValue(1);
InFlag = RetVal.getValue(2); // XXX dead
break;
case MVT::f32:
RetVal = DAG.getCopyFromReg(Chain, dl, IA64::F8, MVT::f64, InFlag);
Chain = RetVal.getValue(1);
RetVal = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, RetVal,
DAG.getIntPtrConstant(0));
break;
case MVT::f64:
RetVal = DAG.getCopyFromReg(Chain, dl, IA64::F8, MVT::f64, InFlag);
Chain = RetVal.getValue(1);
InFlag = RetVal.getValue(2); // XXX dead
break;
}
}
Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
DAG.getIntPtrConstant(0, true), SDValue());
return std::make_pair(RetVal, Chain);
}
SDValue IA64TargetLowering::
LowerOperation(SDValue Op, SelectionDAG &DAG) {
DebugLoc dl = Op.getDebugLoc();
switch (Op.getOpcode()) {
default: assert(0 && "Should not custom lower this!");
case ISD::GlobalTLSAddress:
assert(0 && "TLS not implemented for IA64.");
case ISD::RET: {
SDValue AR_PFSVal, Copy;
switch(Op.getNumOperands()) {
default:
assert(0 && "Do not know how to return this many arguments!");
abort();
case 1:
AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), dl, VirtGPR, MVT::i64);
AR_PFSVal = DAG.getCopyToReg(AR_PFSVal.getValue(1), dl, IA64::AR_PFS,
AR_PFSVal);
return DAG.getNode(IA64ISD::RET_FLAG, dl, MVT::Other, AR_PFSVal);
case 3: {
// Copy the result into the output register & restore ar.pfs
MVT ArgVT = Op.getOperand(1).getValueType();
unsigned ArgReg = ArgVT.isInteger() ? IA64::r8 : IA64::F8;
AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), dl, VirtGPR, MVT::i64);
Copy = DAG.getCopyToReg(AR_PFSVal.getValue(1), dl, ArgReg,
Op.getOperand(1), SDValue());
AR_PFSVal = DAG.getCopyToReg(Copy.getValue(0), dl,
IA64::AR_PFS, AR_PFSVal, Copy.getValue(1));
return DAG.getNode(IA64ISD::RET_FLAG, dl, MVT::Other,
AR_PFSVal, AR_PFSVal.getValue(1));
}
}
return SDValue();
}
case ISD::VAARG: {
MVT VT = getPointerTy();
const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
SDValue VAList = DAG.getLoad(VT, dl, Op.getOperand(0), Op.getOperand(1),
SV, 0);
// Increment the pointer, VAList, to the next vaarg
SDValue VAIncr = DAG.getNode(ISD::ADD, dl, VT, VAList,
DAG.getConstant(VT.getSizeInBits()/8,
VT));
// Store the incremented VAList to the legalized pointer
VAIncr = DAG.getStore(VAList.getValue(1), dl, VAIncr,
Op.getOperand(1), SV, 0);
// Load the actual argument out of the pointer VAList
return DAG.getLoad(Op.getValueType(), dl, VAIncr, VAList, NULL, 0);
}
case ISD::VASTART: {
// vastart just stores the address of the VarArgsFrameIndex slot into the
// memory location argument.
SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64);
const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0);
}
// Frame & Return address. Currently unimplemented
case ISD::RETURNADDR: break;
case ISD::FRAMEADDR: break;
}
return SDValue();
}

View File

@ -1,78 +0,0 @@
//===-- IA64ISelLowering.h - IA64 DAG Lowering Interface --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interfaces that IA64 uses to lower LLVM code into a
// selection DAG.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TARGET_IA64_IA64ISELLOWERING_H
#define LLVM_TARGET_IA64_IA64ISELLOWERING_H
#include "llvm/Target/TargetLowering.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "IA64.h"
namespace llvm {
namespace IA64ISD {
enum NodeType {
// Start the numbering where the builting ops and target ops leave off.
FIRST_NUMBER = ISD::BUILTIN_OP_END,
/// GETFD - the getf.d instruction takes a floating point operand and
/// returns its 64-bit memory representation as an i64
GETFD,
// TODO: explain this hack
BRCALL,
// RET_FLAG - Return with a flag operand
RET_FLAG
};
}
class IA64TargetLowering : public TargetLowering {
int VarArgsFrameIndex; // FrameIndex for start of varargs area.
//int ReturnAddrIndex; // FrameIndex for return slot.
unsigned GP, SP, RP; // FIXME - clean this mess up
public:
explicit IA64TargetLowering(TargetMachine &TM);
unsigned VirtGPR; // this is public so it can be accessed in the selector
// for ISD::RET. add an accessor instead? FIXME
const char *getTargetNodeName(unsigned Opcode) const;
/// getSetCCResultType: return ISD::SETCC's result type.
virtual MVT getSetCCResultType(MVT VT) const;
/// LowerArguments - This hook must be implemented to indicate how we should
/// lower the arguments for the specified function, into the specified DAG.
virtual void LowerArguments(Function &F, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &ArgValues,
DebugLoc dl);
/// LowerCallTo - This hook lowers an abstract call to a function into an
/// actual call.
virtual std::pair<SDValue, SDValue>
LowerCallTo(SDValue Chain, const Type *RetTy,
bool RetSExt, bool RetZExt, bool isVarArg, bool isInreg,
unsigned NumFixedArgs, unsigned CC, bool isTailCall,
SDValue Callee, ArgListTy &Args, SelectionDAG &DAG,
DebugLoc dl);
/// LowerOperation - for custom lowering specific ops
/// (currently, only "ret void")
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
/// getFunctionAlignment - Return the Log2 alignment of this function.
virtual unsigned getFunctionAlignment(const Function *F) const;
};
}
#endif // LLVM_TARGET_IA64_IA64ISELLOWERING_H

View File

@ -1,40 +0,0 @@
//===-- IA64PCInstrBuilder.h - Aids for building IA64 insts -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file exposes functions that may be used with BuildMI from the
// MachineInstrBuilder.h file to simplify generating frame and constant pool
// references.
//
//===----------------------------------------------------------------------===//
#ifndef IA64_INSTRBUILDER_H
#define IA64_INSTRBUILDER_H
#include "llvm/CodeGen/MachineInstrBuilder.h"
namespace llvm {
/// addFrameReference - This function is used to add a reference to the base of
/// an abstract object on the stack frame of the current function. This
/// reference has base register as the FrameIndex offset until it is resolved.
/// This allows a constant offset to be specified as well...
///
inline const MachineInstrBuilder&
addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0,
bool mem = true) {
if (mem)
return MIB.addImm(Offset).addFrameIndex(FI);
else
return MIB.addFrameIndex(FI).addImm(Offset);
}
} // End llvm namespace
#endif

View File

@ -1,80 +0,0 @@
//===- IA64InstrFormats.td - IA64 Instruction Formats --*- tablegen -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// - Warning: the stuff in here isn't really being used, so is mostly
// junk. It'll get fixed as the JIT gets built.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Instruction format superclass
//===----------------------------------------------------------------------===//
class InstIA64<bits<4> op, dag OOL, dag IOL, string asmstr> : Instruction {
// IA64 instruction baseline
field bits<41> Inst;
let Namespace = "IA64";
let OutOperandList = OOL;
let InOperandList = IOL;
let AsmString = asmstr;
let Inst{40-37} = op;
}
//"Each Itanium instruction is categorized into one of six types."
//We should have:
// A, I, M, F, B, L+X
class AForm<bits<4> opcode, bits<6> qpReg, dag OOL, dag IOL, string asmstr> :
InstIA64<opcode, OOL, IOL, asmstr> {
let Inst{5-0} = qpReg;
}
class AForm_DAG<bits<4> opcode, bits<6> qpReg, dag OOL, dag IOL, string asmstr,
list<dag> pattern> :
InstIA64<opcode, OOL, IOL, asmstr> {
let Pattern = pattern;
let Inst{5-0} = qpReg;
}
let isBranch = 1, isTerminator = 1 in
class BForm<bits<4> opcode, bits<6> x6, bits<3> btype, dag OOL, dag IOL, string asmstr> :
InstIA64<opcode, OOL, IOL, asmstr> {
let Inst{32-27} = x6;
let Inst{8-6} = btype;
}
class MForm<bits<4> opcode, bits<6> x6, dag OOL, dag IOL, string asmstr> :
InstIA64<opcode, OOL, IOL, asmstr> {
bits<7> Ra;
bits<7> Rb;
bits<16> disp;
let Inst{35-30} = x6;
// let Inst{20-16} = Rb;
let Inst{15-0} = disp;
}
class RawForm<bits<4> opcode, bits<26> rest, dag OOL, dag IOL, string asmstr> :
InstIA64<opcode, OOL, IOL, asmstr> {
let Inst{25-0} = rest;
}
// Pseudo instructions.
class PseudoInstIA64<dag OOL, dag IOL, string nm> : InstIA64<0, OOL, IOL, nm> {
}
class PseudoInstIA64_DAG<dag OOL, dag IOL, string nm, list<dag> pattern>
: InstIA64<0, OOL, IOL, nm> {
let Pattern = pattern;
}

View File

@ -1,193 +0,0 @@
//===- IA64InstrInfo.cpp - IA64 Instruction Information -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the IA64 implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#include "IA64InstrInfo.h"
#include "IA64.h"
#include "IA64InstrBuilder.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/ADT/SmallVector.h"
#include "IA64GenInstrInfo.inc"
using namespace llvm;
IA64InstrInfo::IA64InstrInfo()
: TargetInstrInfoImpl(IA64Insts, sizeof(IA64Insts)/sizeof(IA64Insts[0])),
RI(*this) {
}
bool IA64InstrInfo::isMoveInstr(const MachineInstr& MI,
unsigned& sourceReg,
unsigned& destReg,
unsigned& SrcSR, unsigned& DstSR) const {
SrcSR = DstSR = 0; // No sub-registers.
unsigned oc = MI.getOpcode();
if (oc == IA64::MOV || oc == IA64::FMOV) {
// TODO: this doesn't detect predicate moves
assert(MI.getNumOperands() >= 2 &&
/* MI.getOperand(0).isReg() &&
MI.getOperand(1).isReg() && */
"invalid register-register move instruction");
if (MI.getOperand(0).isReg() &&
MI.getOperand(1).isReg()) {
// if both operands of the MOV/FMOV are registers, then
// yes, this is a move instruction
sourceReg = MI.getOperand(1).getReg();
destReg = MI.getOperand(0).getReg();
return true;
}
}
return false; // we don't consider e.g. %regN = MOV <FrameIndex #x> a
// move instruction
}
unsigned
IA64InstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
const SmallVectorImpl<MachineOperand> &Cond)const {
// FIXME this should probably have a DebugLoc argument
DebugLoc dl = DebugLoc::getUnknownLoc();
// Can only insert uncond branches so far.
assert(Cond.empty() && !FBB && TBB && "Can only handle uncond branches!");
BuildMI(&MBB, dl, get(IA64::BRL_NOTCALL)).addMBB(TBB);
return 1;
}
bool IA64InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *DestRC,
const TargetRegisterClass *SrcRC) const {
if (DestRC != SrcRC) {
// Not yet supported!
return false;
}
DebugLoc DL = DebugLoc::getUnknownLoc();
if (MI != MBB.end()) DL = MI->getDebugLoc();
if(DestRC == IA64::PRRegisterClass ) // if a bool, we use pseudocode
// (SrcReg) DestReg = cmp.eq.unc(r0, r0)
BuildMI(MBB, MI, DL, get(IA64::PCMPEQUNC), DestReg)
.addReg(IA64::r0).addReg(IA64::r0).addReg(SrcReg);
else // otherwise, MOV works (for both gen. regs and FP regs)
BuildMI(MBB, MI, DL, get(IA64::MOV), DestReg).addReg(SrcReg);
return true;
}
void IA64InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned SrcReg, bool isKill,
int FrameIdx,
const TargetRegisterClass *RC) const{
DebugLoc DL = DebugLoc::getUnknownLoc();
if (MI != MBB.end()) DL = MI->getDebugLoc();
if (RC == IA64::FPRegisterClass) {
BuildMI(MBB, MI, DL, get(IA64::STF_SPILL)).addFrameIndex(FrameIdx)
.addReg(SrcReg, getKillRegState(isKill));
} else if (RC == IA64::GRRegisterClass) {
BuildMI(MBB, MI, DL, get(IA64::ST8)).addFrameIndex(FrameIdx)
.addReg(SrcReg, getKillRegState(isKill));
} else if (RC == IA64::PRRegisterClass) {
/* we use IA64::r2 as a temporary register for doing this hackery. */
// first we load 0:
BuildMI(MBB, MI, DL, get(IA64::MOV), IA64::r2).addReg(IA64::r0);
// then conditionally add 1:
BuildMI(MBB, MI, DL, get(IA64::CADDIMM22), IA64::r2).addReg(IA64::r2)
.addImm(1).addReg(SrcReg, getKillRegState(isKill));
// and then store it to the stack
BuildMI(MBB, MI, DL, get(IA64::ST8))
.addFrameIndex(FrameIdx)
.addReg(IA64::r2);
} else assert(0 &&
"sorry, I don't know how to store this sort of reg in the stack\n");
}
void IA64InstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
bool isKill,
SmallVectorImpl<MachineOperand> &Addr,
const TargetRegisterClass *RC,
SmallVectorImpl<MachineInstr*> &NewMIs) const {
unsigned Opc = 0;
if (RC == IA64::FPRegisterClass) {
Opc = IA64::STF8;
} else if (RC == IA64::GRRegisterClass) {
Opc = IA64::ST8;
} else if (RC == IA64::PRRegisterClass) {
Opc = IA64::ST1;
} else {
assert(0 &&
"sorry, I don't know how to store this sort of reg\n");
}
DebugLoc DL = DebugLoc::getUnknownLoc();
MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc));
for (unsigned i = 0, e = Addr.size(); i != e; ++i)
MIB.addOperand(Addr[i]);
MIB.addReg(SrcReg, getKillRegState(isKill));
NewMIs.push_back(MIB);
return;
}
void IA64InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, int FrameIdx,
const TargetRegisterClass *RC)const{
DebugLoc DL = DebugLoc::getUnknownLoc();
if (MI != MBB.end()) DL = MI->getDebugLoc();
if (RC == IA64::FPRegisterClass) {
BuildMI(MBB, MI, DL, get(IA64::LDF_FILL), DestReg).addFrameIndex(FrameIdx);
} else if (RC == IA64::GRRegisterClass) {
BuildMI(MBB, MI, DL, get(IA64::LD8), DestReg).addFrameIndex(FrameIdx);
} else if (RC == IA64::PRRegisterClass) {
// first we load a byte from the stack into r2, our 'predicate hackery'
// scratch reg
BuildMI(MBB, MI, DL, get(IA64::LD8), IA64::r2).addFrameIndex(FrameIdx);
// then we compare it to zero. If it _is_ zero, compare-not-equal to
// r0 gives us 0, which is what we want, so that's nice.
BuildMI(MBB, MI, DL, get(IA64::CMPNE), DestReg)
.addReg(IA64::r2)
.addReg(IA64::r0);
} else {
assert(0 &&
"sorry, I don't know how to load this sort of reg from the stack\n");
}
}
void IA64InstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
SmallVectorImpl<MachineOperand> &Addr,
const TargetRegisterClass *RC,
SmallVectorImpl<MachineInstr*> &NewMIs) const {
unsigned Opc = 0;
if (RC == IA64::FPRegisterClass) {
Opc = IA64::LDF8;
} else if (RC == IA64::GRRegisterClass) {
Opc = IA64::LD8;
} else if (RC == IA64::PRRegisterClass) {
Opc = IA64::LD1;
} else {
assert(0 &&
"sorry, I don't know how to load this sort of reg\n");
}
DebugLoc DL = DebugLoc::getUnknownLoc();
MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
for (unsigned i = 0, e = Addr.size(); i != e; ++i)
MIB.addOperand(Addr[i]);
NewMIs.push_back(MIB);
return;
}

View File

@ -1,70 +0,0 @@
//===- IA64InstrInfo.h - IA64 Instruction Information ----------*- C++ -*- ===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the IA64 implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef IA64INSTRUCTIONINFO_H
#define IA64INSTRUCTIONINFO_H
#include "llvm/Target/TargetInstrInfo.h"
#include "IA64RegisterInfo.h"
namespace llvm {
class IA64InstrInfo : public TargetInstrInfoImpl {
const IA64RegisterInfo RI;
public:
IA64InstrInfo();
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
/// such, whenever a client has an instance of instruction info, it should
/// always be able to get register info as well (through this method).
///
virtual const IA64RegisterInfo &getRegisterInfo() const { return RI; }
/// Return true if the instruction is a register to register move and return
/// the source and dest operands and their sub-register indices by reference.
virtual bool isMoveInstr(const MachineInstr &MI,
unsigned &SrcReg, unsigned &DstReg,
unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
const SmallVectorImpl<MachineOperand> &Cond) const;
virtual bool copyRegToReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *DestRC,
const TargetRegisterClass *SrcRC) const;
virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned SrcReg, bool isKill, int FrameIndex,
const TargetRegisterClass *RC) const;
virtual void storeRegToAddr(MachineFunction &MF, unsigned SrcReg, bool isKill,
SmallVectorImpl<MachineOperand> &Addr,
const TargetRegisterClass *RC,
SmallVectorImpl<MachineInstr*> &NewMIs) const;
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, int FrameIndex,
const TargetRegisterClass *RC) const;
virtual void loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
SmallVectorImpl<MachineOperand> &Addr,
const TargetRegisterClass *RC,
SmallVectorImpl<MachineInstr*> &NewMIs) const;
};
} // End llvm namespace
#endif

View File

@ -1,751 +0,0 @@
//===- IA64InstrInfo.td - Describe the IA64 Instruction Set -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the IA64 instruction set, defining the instructions, and
// properties of the instructions which are needed for code generation, machine
// code emission, and analysis.
//
//===----------------------------------------------------------------------===//
include "IA64InstrFormats.td"
//===----------------------------------------------------------------------===//
// IA-64 specific DAG Nodes.
//
def IA64getfd : SDNode<"IA64ISD::GETFD", SDTFPToIntOp, []>;
def retflag : SDNode<"IA64ISD::RET_FLAG", SDTNone,
[SDNPHasChain, SDNPOptInFlag]>;
//===---------
// Instruction types
class isA { bit A=1; } // I or M unit
class isM { bit M=1; } // M unit
class isI { bit I=1; } // I unit
class isB { bit B=1; } // B unit
class isF { bit F=1; } // F unit
class isLX { bit LX=1; } // I/B
//===---------
def u2imm : Operand<i8>;
def u6imm : Operand<i8>;
def s8imm : Operand<i8> {
let PrintMethod = "printS8ImmOperand";
}
def s14imm : Operand<i64> {
let PrintMethod = "printS14ImmOperand";
}
def s22imm : Operand<i64> {
let PrintMethod = "printS22ImmOperand";
}
def u64imm : Operand<i64> {
let PrintMethod = "printU64ImmOperand";
}
def s64imm : Operand<i64> {
let PrintMethod = "printS64ImmOperand";
}
let PrintMethod = "printGlobalOperand" in
def globaladdress : Operand<i64>;
// the asmprinter needs to know about calls
let PrintMethod = "printCallOperand" in
def calltarget : Operand<i64>;
/* new daggy action!!! */
def is32ones : PatLeaf<(i64 imm), [{
// is32ones predicate - True if the immediate is 0x00000000FFFFFFFF
// Used to create ZXT4s appropriately
uint64_t v = (uint64_t)N->getZExtValue();
return (v == 0x00000000FFFFFFFFLL);
}]>;
// isMIXable predicates - True if the immediate is
// 0xFF00FF00FF00FF00, 0x00FF00FF00FF00FF
// etc, through 0x00000000FFFFFFFF
// Used to test for the suitability of mix*
def isMIX1Lable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getZExtValue()==0xFF00FF00FF00FF00LL);
}]>;
def isMIX1Rable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getZExtValue()==0x00FF00FF00FF00FFLL);
}]>;
def isMIX2Lable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getZExtValue()==0xFFFF0000FFFF0000LL);
}]>;
def isMIX2Rable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getZExtValue()==0x0000FFFF0000FFFFLL);
}]>;
def isMIX4Lable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getZExtValue()==0xFFFFFFFF00000000LL);
}]>;
def isMIX4Rable: PatLeaf<(i64 imm), [{
return((uint64_t)N->getZExtValue()==0x00000000FFFFFFFFLL);
}]>;
def isSHLADDimm: PatLeaf<(i64 imm), [{
// isSHLADDimm predicate - True if the immediate is exactly 1, 2, 3 or 4
// - 0 is *not* okay.
// Used to create shladd instructions appropriately
int64_t v = (int64_t)N->getZExtValue();
return (v >= 1 && v <= 4);
}]>;
def immSExt14 : PatLeaf<(i64 imm), [{
// immSExt14 predicate - True if the immediate fits in a 14-bit sign extended
// field. Used by instructions like 'adds'.
int64_t v = (int64_t)N->getZExtValue();
return (v <= 8191 && v >= -8192);
}]>;
// imm64 predicate - True if the immediate fits in a 64-bit
// field - i.e., true. used to keep movl happy
def imm64 : PatLeaf<(i64 imm)>;
def ADD : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"add $dst = $src1, $src2",
[(set GR:$dst, (add GR:$src1, GR:$src2))]>, isA;
def ADD1 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"add $dst = $src1, $src2, 1",
[(set GR:$dst, (add (add GR:$src1, GR:$src2), 1))]>, isA;
def ADDS : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, s14imm:$imm),
"adds $dst = $imm, $src1",
[(set GR:$dst, (add GR:$src1, immSExt14:$imm))]>, isA;
def MOVL : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins s64imm:$imm),
"movl $dst = $imm",
[(set GR:$dst, imm64:$imm)]>, isLX;
def ADDL_GA : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, globaladdress:$imm),
"addl $dst = $imm, $src1",
[]>, isA;
// hmm
def ADDL_EA : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, calltarget:$imm),
"addl $dst = $imm, $src1",
[]>, isA;
def SUB : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"sub $dst = $src1, $src2",
[(set GR:$dst, (sub GR:$src1, GR:$src2))]>, isA;
def SUB1 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"sub $dst = $src1, $src2, 1",
[(set GR:$dst, (add (sub GR: $src1, GR:$src2), -1))]>, isA;
let isTwoAddress = 1 in {
def TPCADDIMM22 : AForm<0x03, 0x0b,
(outs GR:$dst), (ins GR:$src1, s22imm:$imm, PR:$qp),
"($qp) add $dst = $imm, $dst">, isA;
def TPCADDS : AForm_DAG<0x03, 0x0b,
(outs GR:$dst), (ins GR:$src1, s14imm:$imm, PR:$qp),
"($qp) adds $dst = $imm, $dst",
[]>, isA;
def TPCMPIMM8NE : AForm<0x03, 0x0b,
(outs PR:$dst), (ins PR:$src1, s22imm:$imm, GR:$src2, PR:$qp),
"($qp) cmp.ne $dst , p0 = $imm, $src2">, isA;
}
// zero extend a bool (predicate reg) into an integer reg
def ZXTb : Pat<(zext PR:$src),
(TPCADDIMM22 (ADDS r0, 0), 1, PR:$src)>;
def AXTb : Pat<(anyext PR:$src),
(TPCADDIMM22 (ADDS r0, 0), 1, PR:$src)>;
// normal sign/zero-extends
def SXT1 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "sxt1 $dst = $src",
[(set GR:$dst, (sext_inreg GR:$src, i8))]>, isI;
def ZXT1 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "zxt1 $dst = $src",
[(set GR:$dst, (and GR:$src, 255))]>, isI;
def SXT2 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "sxt2 $dst = $src",
[(set GR:$dst, (sext_inreg GR:$src, i16))]>, isI;
def ZXT2 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "zxt2 $dst = $src",
[(set GR:$dst, (and GR:$src, 65535))]>, isI;
def SXT4 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "sxt4 $dst = $src",
[(set GR:$dst, (sext_inreg GR:$src, i32))]>, isI;
def ZXT4 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "zxt4 $dst = $src",
[(set GR:$dst, (and GR:$src, is32ones))]>, isI;
// fixme: shrs vs shru?
def MIX1L : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"mix1.l $dst = $src1, $src2",
[(set GR:$dst, (or (and GR:$src1, isMIX1Lable),
(and (srl GR:$src2, (i64 8)), isMIX1Lable)))]>, isI;
def MIX2L : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"mix2.l $dst = $src1, $src2",
[(set GR:$dst, (or (and GR:$src1, isMIX2Lable),
(and (srl GR:$src2, (i64 16)), isMIX2Lable)))]>, isI;
def MIX4L : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"mix4.l $dst = $src1, $src2",
[(set GR:$dst, (or (and GR:$src1, isMIX4Lable),
(and (srl GR:$src2, (i64 32)), isMIX4Lable)))]>, isI;
def MIX1R : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"mix1.r $dst = $src1, $src2",
[(set GR:$dst, (or (and (shl GR:$src1, (i64 8)), isMIX1Rable),
(and GR:$src2, isMIX1Rable)))]>, isI;
def MIX2R : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"mix2.r $dst = $src1, $src2",
[(set GR:$dst, (or (and (shl GR:$src1, (i64 16)), isMIX2Rable),
(and GR:$src2, isMIX2Rable)))]>, isI;
def MIX4R : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"mix4.r $dst = $src1, $src2",
[(set GR:$dst, (or (and (shl GR:$src1, (i64 32)), isMIX4Rable),
(and GR:$src2, isMIX4Rable)))]>, isI;
def GETFSIGD : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins FP:$src),
"getf.sig $dst = $src",
[]>, isM;
def SETFSIGD : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins GR:$src),
"setf.sig $dst = $src",
[]>, isM;
def XMALD : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
"xma.l $dst = $src1, $src2, $src3",
[]>, isF;
def XMAHD : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
"xma.h $dst = $src1, $src2, $src3",
[]>, isF;
def XMAHUD : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
"xma.hu $dst = $src1, $src2, $src3",
[]>, isF;
// pseudocode for integer multiplication
def : Pat<(mul GR:$src1, GR:$src2),
(GETFSIGD (XMALD (SETFSIGD GR:$src1), (SETFSIGD GR:$src2), F0))>;
def : Pat<(mulhs GR:$src1, GR:$src2),
(GETFSIGD (XMAHD (SETFSIGD GR:$src1), (SETFSIGD GR:$src2), F0))>;
def : Pat<(mulhu GR:$src1, GR:$src2),
(GETFSIGD (XMAHUD (SETFSIGD GR:$src1), (SETFSIGD GR:$src2), F0))>;
// TODO: addp4 (addp4 dst = src, r0 is a 32-bit add)
// has imm form, too
// def ADDS : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, s14imm:$imm),
// "adds $dst = $imm, $src1">;
def AND : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"and $dst = $src1, $src2",
[(set GR:$dst, (and GR:$src1, GR:$src2))]>, isA;
def ANDCM : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"andcm $dst = $src1, $src2",
[(set GR:$dst, (and GR:$src1, (not GR:$src2)))]>, isA;
// TODO: and/andcm/or/xor/add/sub/shift immediate forms
def OR : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"or $dst = $src1, $src2",
[(set GR:$dst, (or GR:$src1, GR:$src2))]>, isA;
def pOR : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2, PR:$qp),
"($qp) or $dst = $src1, $src2">, isA;
// the following are all a bit unfortunate: we throw away the complement
// of the compare!
def CMPEQ : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
"cmp.eq $dst, p0 = $src1, $src2",
[(set PR:$dst, (seteq GR:$src1, GR:$src2))]>, isA;
def CMPGT : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
"cmp.gt $dst, p0 = $src1, $src2",
[(set PR:$dst, (setgt GR:$src1, GR:$src2))]>, isA;
def CMPGE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
"cmp.ge $dst, p0 = $src1, $src2",
[(set PR:$dst, (setge GR:$src1, GR:$src2))]>, isA;
def CMPLT : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
"cmp.lt $dst, p0 = $src1, $src2",
[(set PR:$dst, (setlt GR:$src1, GR:$src2))]>, isA;
def CMPLE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
"cmp.le $dst, p0 = $src1, $src2",
[(set PR:$dst, (setle GR:$src1, GR:$src2))]>, isA;
def CMPNE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
"cmp.ne $dst, p0 = $src1, $src2",
[(set PR:$dst, (setne GR:$src1, GR:$src2))]>, isA;
def CMPLTU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
"cmp.ltu $dst, p0 = $src1, $src2",
[(set PR:$dst, (setult GR:$src1, GR:$src2))]>, isA;
def CMPGTU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
"cmp.gtu $dst, p0 = $src1, $src2",
[(set PR:$dst, (setugt GR:$src1, GR:$src2))]>, isA;
def CMPLEU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
"cmp.leu $dst, p0 = $src1, $src2",
[(set PR:$dst, (setule GR:$src1, GR:$src2))]>, isA;
def CMPGEU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
"cmp.geu $dst, p0 = $src1, $src2",
[(set PR:$dst, (setuge GR:$src1, GR:$src2))]>, isA;
// and we do the whole thing again for FP compares!
def FCMPEQ : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
"fcmp.eq $dst, p0 = $src1, $src2",
[(set PR:$dst, (seteq FP:$src1, FP:$src2))]>, isF;
def FCMPGT : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
"fcmp.gt $dst, p0 = $src1, $src2",
[(set PR:$dst, (setgt FP:$src1, FP:$src2))]>, isF;
def FCMPGE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
"fcmp.ge $dst, p0 = $src1, $src2",
[(set PR:$dst, (setge FP:$src1, FP:$src2))]>, isF;
def FCMPLT : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
"fcmp.lt $dst, p0 = $src1, $src2",
[(set PR:$dst, (setlt FP:$src1, FP:$src2))]>, isF;
def FCMPLE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
"fcmp.le $dst, p0 = $src1, $src2",
[(set PR:$dst, (setle FP:$src1, FP:$src2))]>, isF;
def FCMPNE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
"fcmp.neq $dst, p0 = $src1, $src2",
[(set PR:$dst, (setne FP:$src1, FP:$src2))]>, isF;
def FCMPLTU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
"fcmp.lt $dst, p0 = $src1, $src2",
[(set PR:$dst, (setult FP:$src1, FP:$src2))]>, isF;
def FCMPGTU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
"fcmp.gt $dst, p0 = $src1, $src2",
[(set PR:$dst, (setugt FP:$src1, FP:$src2))]>, isF;
def FCMPLEU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
"fcmp.le $dst, p0 = $src1, $src2",
[(set PR:$dst, (setule FP:$src1, FP:$src2))]>, isF;
def FCMPGEU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
"fcmp.ge $dst, p0 = $src1, $src2",
[(set PR:$dst, (setuge FP:$src1, FP:$src2))]>, isF;
def PCMPEQUNCR0R0 : AForm<0x03, 0x0b, (outs PR:$dst), (ins PR:$qp),
"($qp) cmp.eq.unc $dst, p0 = r0, r0">, isA;
def : Pat<(trunc GR:$src), // truncate i64 to i1
(CMPNE GR:$src, r0)>; // $src!=0? If so, PR:$dst=true
let isTwoAddress=1 in {
def TPCMPEQR0R0 : AForm<0x03, 0x0b, (outs PR:$dst), (ins PR:$bogus, PR:$qp),
"($qp) cmp.eq $dst, p0 = r0, r0">, isA;
def TPCMPNER0R0 : AForm<0x03, 0x0b, (outs PR:$dst), (ins PR:$bogus, PR:$qp),
"($qp) cmp.ne $dst, p0 = r0, r0">, isA;
}
/* our pseudocode for OR on predicates is:
pC = pA OR pB
-------------
(pA) cmp.eq.unc pC,p0 = r0,r0 // pC = pA
;;
(pB) cmp.eq pC,p0 = r0,r0 // if (pB) pC = 1 */
def bOR : Pat<(or PR:$src1, PR:$src2),
(TPCMPEQR0R0 (PCMPEQUNCR0R0 PR:$src1), PR:$src2)>;
/* our pseudocode for AND on predicates is:
*
(pA) cmp.eq.unc pC,p0 = r0,r0 // pC = pA
cmp.eq pTemp,p0 = r0,r0 // pTemp = NOT pB
;;
(pB) cmp.ne pTemp,p0 = r0,r0
;;
(pTemp)cmp.ne pC,p0 = r0,r0 // if (NOT pB) pC = 0 */
def bAND : Pat<(and PR:$src1, PR:$src2),
( TPCMPNER0R0 (PCMPEQUNCR0R0 PR:$src1),
(TPCMPNER0R0 (CMPEQ r0, r0), PR:$src2) )>;
/* one possible routine for XOR on predicates is:
// Compute px = py ^ pz
// using sum of products: px = (py & !pz) | (pz & !py)
// Uses 5 instructions in 3 cycles.
// cycle 1
(pz) cmp.eq.unc px = r0, r0 // px = pz
(py) cmp.eq.unc pt = r0, r0 // pt = py
;;
// cycle 2
(pt) cmp.ne.and px = r0, r0 // px = px & !pt (px = pz & !pt)
(pz) cmp.ne.and pt = r0, r0 // pt = pt & !pz
;;
} { .mmi
// cycle 3
(pt) cmp.eq.or px = r0, r0 // px = px | pt
*** Another, which we use here, requires one scratch GR. it is:
mov rt = 0 // initialize rt off critical path
;;
// cycle 1
(pz) cmp.eq.unc px = r0, r0 // px = pz
(pz) mov rt = 1 // rt = pz
;;
// cycle 2
(py) cmp.ne px = 1, rt // if (py) px = !pz
.. these routines kindly provided by Jim Hull
*/
def bXOR : Pat<(xor PR:$src1, PR:$src2),
(TPCMPIMM8NE (PCMPEQUNCR0R0 PR:$src2), 1,
(TPCADDS (ADDS r0, 0), 1, PR:$src2),
PR:$src1)>;
def XOR : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"xor $dst = $src1, $src2",
[(set GR:$dst, (xor GR:$src1, GR:$src2))]>, isA;
def SHLADD: AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1,s64imm:$imm,GR:$src2),
"shladd $dst = $src1, $imm, $src2",
[(set GR:$dst, (add GR:$src2, (shl GR:$src1, isSHLADDimm:$imm)))]>, isA;
def SHL : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"shl $dst = $src1, $src2",
[(set GR:$dst, (shl GR:$src1, GR:$src2))]>, isI;
def SHRU : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"shr.u $dst = $src1, $src2",
[(set GR:$dst, (srl GR:$src1, GR:$src2))]>, isI;
def SHRS : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
"shr $dst = $src1, $src2",
[(set GR:$dst, (sra GR:$src1, GR:$src2))]>, isI;
def MOV : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "mov $dst = $src">, isA;
def FMOV : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"mov $dst = $src">, isF; // XXX: there _is_ no fmov
def PMOV : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src, PR:$qp),
"($qp) mov $dst = $src">, isA;
def SPILL_ALL_PREDICATES_TO_GR : AForm<0x03, 0x0b, (outs GR:$dst), (ins),
"mov $dst = pr">, isI;
def FILL_ALL_PREDICATES_FROM_GR : AForm<0x03, 0x0b, (outs), (ins GR:$src),
"mov pr = $src">, isI;
let isTwoAddress = 1 in {
def CMOV : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src2, GR:$src, PR:$qp),
"($qp) mov $dst = $src">, isA;
}
def PFMOV : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src, PR:$qp),
"($qp) mov $dst = $src">, isF;
let isTwoAddress = 1 in {
def CFMOV : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src2, FP:$src, PR:$qp),
"($qp) mov $dst = $src">, isF;
}
def SELECTINT : Pat<(select PR:$which, GR:$src1, GR:$src2),
(CMOV (MOV GR:$src2), GR:$src1, PR:$which)>; // note order!
def SELECTFP : Pat<(select PR:$which, FP:$src1, FP:$src2),
(CFMOV (FMOV FP:$src2), FP:$src1, PR:$which)>; // note order!
// TODO: can do this faster, w/o using any integer regs (see pattern isel)
def SELECTBOOL : Pat<(select PR:$which, PR:$src1, PR:$src2), // note order!
(CMPNE (CMOV
(MOV (TPCADDIMM22 (ADDS r0, 0), 1, PR:$src2)),
(TPCADDIMM22 (ADDS r0, 0), 1, PR:$src1), PR:$which), r0)>;
// load constants of various sizes // FIXME: prettyprint -ve constants
def : Pat<(i64 immSExt14:$imm), (ADDS r0, immSExt14:$imm)>;
def : Pat<(i1 -1), (CMPEQ r0, r0)>; // TODO: this should just be a ref to p0
def : Pat<(i1 0), (CMPNE r0, r0)>; // TODO: any instruction actually *using*
// this predicate should be killed!
// TODO: support postincrement (reg, imm9) loads+stores - this needs more
// tablegen support
def IUSE : PseudoInstIA64<(outs), (ins variable_ops), "// IUSE">;
def ADJUSTCALLSTACKUP : PseudoInstIA64<(outs), (ins variable_ops),
"// ADJUSTCALLSTACKUP">;
def ADJUSTCALLSTACKDOWN : PseudoInstIA64<(outs), (ins variable_ops),
"// ADJUSTCALLSTACKDOWN">;
def PSEUDO_ALLOC : PseudoInstIA64<(outs), (ins GR:$foo), "// PSEUDO_ALLOC">;
def ALLOC : AForm<0x03, 0x0b,
(outs GR:$dst), (ins i8imm:$inputs, i8imm:$locals, i8imm:$outputs, i8imm:$rotating),
"alloc $dst = ar.pfs,$inputs,$locals,$outputs,$rotating">, isM;
let isTwoAddress = 1 in {
def TCMPNE : AForm<0x03, 0x0b,
(outs PR:$dst), (ins PR:$src2, GR:$src3, GR:$src4),
"cmp.ne $dst, p0 = $src3, $src4">, isA;
def TPCMPEQOR : AForm<0x03, 0x0b,
(outs PR:$dst), (ins PR:$src2, GR:$src3, GR:$src4, PR:$qp),
"($qp) cmp.eq.or $dst, p0 = $src3, $src4">, isA;
def TPCMPNE : AForm<0x03, 0x0b,
(outs PR:$dst), (ins PR:$src2, GR:$src3, GR:$src4, PR:$qp),
"($qp) cmp.ne $dst, p0 = $src3, $src4">, isA;
def TPCMPEQ : AForm<0x03, 0x0b,
(outs PR:$dst), (ins PR:$src2, GR:$src3, GR:$src4, PR:$qp),
"($qp) cmp.eq $dst, p0 = $src3, $src4">, isA;
}
def MOVSIMM14 : AForm<0x03, 0x0b, (outs GR:$dst), (ins s14imm:$imm),
"mov $dst = $imm">, isA;
def MOVSIMM22 : AForm<0x03, 0x0b, (outs GR:$dst), (ins s22imm:$imm),
"mov $dst = $imm">, isA;
def MOVLIMM64 : AForm<0x03, 0x0b, (outs GR:$dst), (ins s64imm:$imm),
"movl $dst = $imm">, isLX;
def SHLI : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, u6imm:$imm),
"shl $dst = $src1, $imm">, isI;
def SHRUI : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, u6imm:$imm),
"shr.u $dst = $src1, $imm">, isI;
def SHRSI : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, u6imm:$imm),
"shr $dst = $src1, $imm">, isI;
def EXTRU : AForm<0x03, 0x0b,
(outs GR:$dst), (ins GR:$src1, u6imm:$imm1, u6imm:$imm2),
"extr.u $dst = $src1, $imm1, $imm2">, isI;
def DEPZ : AForm<0x03, 0x0b,
(outs GR:$dst), (ins GR:$src1, u6imm:$imm1, u6imm:$imm2),
"dep.z $dst = $src1, $imm1, $imm2">, isI;
def PCMPEQOR : AForm<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2, PR:$qp),
"($qp) cmp.eq.or $dst, p0 = $src1, $src2">, isA;
def PCMPEQUNC : AForm<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2, PR:$qp),
"($qp) cmp.eq.unc $dst, p0 = $src1, $src2">, isA;
def PCMPNE : AForm<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2, PR:$qp),
"($qp) cmp.ne $dst, p0 = $src1, $src2">, isA;
// two destinations!
def BCMPEQ : AForm<0x03, 0x0b, (outs PR:$dst1, PR:$dst2), (ins GR:$src1, GR:$src2),
"cmp.eq $dst1, dst2 = $src1, $src2">, isA;
def ADDIMM14 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, s14imm:$imm),
"adds $dst = $imm, $src1">, isA;
def ADDIMM22 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, s22imm:$imm),
"add $dst = $imm, $src1">, isA;
def CADDIMM22 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, s22imm:$imm, PR:$qp),
"($qp) add $dst = $imm, $src1">, isA;
def SUBIMM8 : AForm<0x03, 0x0b, (outs GR:$dst), (ins s8imm:$imm, GR:$src2),
"sub $dst = $imm, $src2">, isA;
let mayStore = 1 in {
def ST1 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, GR:$value),
"st1 [$dstPtr] = $value">, isM;
def ST2 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, GR:$value),
"st2 [$dstPtr] = $value">, isM;
def ST4 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, GR:$value),
"st4 [$dstPtr] = $value">, isM;
def ST8 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, GR:$value),
"st8 [$dstPtr] = $value">, isM;
def STF4 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, FP:$value),
"stfs [$dstPtr] = $value">, isM;
def STF8 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, FP:$value),
"stfd [$dstPtr] = $value">, isM;
def STF_SPILL : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, FP:$value),
"stf.spill [$dstPtr] = $value">, isM;
}
let canFoldAsLoad = 1 in {
def LD1 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$srcPtr),
"ld1 $dst = [$srcPtr]">, isM;
def LD2 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$srcPtr),
"ld2 $dst = [$srcPtr]">, isM;
def LD4 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$srcPtr),
"ld4 $dst = [$srcPtr]">, isM;
def LD8 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$srcPtr),
"ld8 $dst = [$srcPtr]">, isM;
def LDF4 : AForm<0x03, 0x0b, (outs FP:$dst), (ins GR:$srcPtr),
"ldfs $dst = [$srcPtr]">, isM;
def LDF8 : AForm<0x03, 0x0b, (outs FP:$dst), (ins GR:$srcPtr),
"ldfd $dst = [$srcPtr]">, isM;
def LDF_FILL : AForm<0x03, 0x0b, (outs FP:$dst), (ins GR:$srcPtr),
"ldf.fill $dst = [$srcPtr]">, isM;
}
def POPCNT : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src),
"popcnt $dst = $src",
[(set GR:$dst, (ctpop GR:$src))]>, isI;
// some FP stuff: // TODO: single-precision stuff?
def FADD : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2),
"fadd $dst = $src1, $src2",
[(set FP:$dst, (fadd FP:$src1, FP:$src2))]>, isF;
def FADDS: AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2),
"fadd.s $dst = $src1, $src2">, isF;
def FSUB : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2),
"fsub $dst = $src1, $src2",
[(set FP:$dst, (fsub FP:$src1, FP:$src2))]>, isF;
def FMPY : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2),
"fmpy $dst = $src1, $src2",
[(set FP:$dst, (fmul FP:$src1, FP:$src2))]>, isF;
def FMA : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
"fma $dst = $src1, $src2, $src3",
[(set FP:$dst, (fadd (fmul FP:$src1, FP:$src2), FP:$src3))]>, isF;
def FMS : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
"fms $dst = $src1, $src2, $src3",
[(set FP:$dst, (fsub (fmul FP:$src1, FP:$src2), FP:$src3))]>, isF;
def FNMA : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
"fnma $dst = $src1, $src2, $src3",
[(set FP:$dst, (fneg (fadd (fmul FP:$src1, FP:$src2), FP:$src3)))]>, isF;
def FABS : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fabs $dst = $src",
[(set FP:$dst, (fabs FP:$src))]>, isF;
def FNEG : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fneg $dst = $src",
[(set FP:$dst, (fneg FP:$src))]>, isF;
def FNEGABS : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fnegabs $dst = $src",
[(set FP:$dst, (fneg (fabs FP:$src)))]>, isF;
let isTwoAddress=1 in {
def TCFMAS1 : AForm<0x03, 0x0b,
(outs FP:$dst), (ins FP:$bogussrc, FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fma.s1 $dst = $src1, $src2, $src3">, isF;
def TCFMADS0 : AForm<0x03, 0x0b,
(outs FP:$dst), (ins FP:$bogussrc, FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fma.d.s0 $dst = $src1, $src2, $src3">, isF;
}
def CFMAS1 : AForm<0x03, 0x0b,
(outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fma.s1 $dst = $src1, $src2, $src3">, isF;
def CFNMAS1 : AForm<0x03, 0x0b,
(outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fnma.s1 $dst = $src1, $src2, $src3">, isF;
def CFMADS1 : AForm<0x03, 0x0b,
(outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fma.d.s1 $dst = $src1, $src2, $src3">, isF;
def CFMADS0 : AForm<0x03, 0x0b,
(outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fma.d.s0 $dst = $src1, $src2, $src3">, isF;
def CFNMADS1 : AForm<0x03, 0x0b,
(outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3, PR:$qp),
"($qp) fnma.d.s1 $dst = $src1, $src2, $src3">, isF;
def FRCPAS0 : AForm<0x03, 0x0b, (outs FP:$dstFR, PR:$dstPR), (ins FP:$src1, FP:$src2),
"frcpa.s0 $dstFR, $dstPR = $src1, $src2">, isF;
def FRCPAS1 : AForm<0x03, 0x0b, (outs FP:$dstFR, PR:$dstPR), (ins FP:$src1, FP:$src2),
"frcpa.s1 $dstFR, $dstPR = $src1, $src2">, isF;
def XMAL : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
"xma.l $dst = $src1, $src2, $src3">, isF;
def FCVTXF : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fcvt.xf $dst = $src">, isF;
def FCVTXUF : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fcvt.xuf $dst = $src">, isF;
def FCVTXUFS1 : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fcvt.xuf.s1 $dst = $src">, isF;
def FCVTFX : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fcvt.fx $dst = $src">, isF;
def FCVTFXU : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fcvt.fxu $dst = $src">, isF;
def FCVTFXTRUNC : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fcvt.fx.trunc $dst = $src">, isF;
def FCVTFXUTRUNC : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fcvt.fxu.trunc $dst = $src">, isF;
def FCVTFXTRUNCS1 : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fcvt.fx.trunc.s1 $dst = $src">, isF;
def FCVTFXUTRUNCS1 : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fcvt.fxu.trunc.s1 $dst = $src">, isF;
def FNORMD : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
"fnorm.d $dst = $src">, isF;
def GETFD : AForm<0x03, 0x0b, (outs GR:$dst), (ins FP:$src),
"getf.d $dst = $src">, isM;
def SETFD : AForm<0x03, 0x0b, (outs FP:$dst), (ins GR:$src),
"setf.d $dst = $src">, isM;
def GETFSIG : AForm<0x03, 0x0b, (outs GR:$dst), (ins FP:$src),
"getf.sig $dst = $src">, isM;
def SETFSIG : AForm<0x03, 0x0b, (outs FP:$dst), (ins GR:$src),
"setf.sig $dst = $src">, isM;
// these four FP<->int conversion patterns need checking/cleaning
def SINT_TO_FP : Pat<(sint_to_fp GR:$src),
(FNORMD (FCVTXF (SETFSIG GR:$src)))>;
def UINT_TO_FP : Pat<(uint_to_fp GR:$src),
(FNORMD (FCVTXUF (SETFSIG GR:$src)))>;
def FP_TO_SINT : Pat<(i64 (fp_to_sint FP:$src)),
(GETFSIG (FCVTFXTRUNC FP:$src))>;
def FP_TO_UINT : Pat<(i64 (fp_to_uint FP:$src)),
(GETFSIG (FCVTFXUTRUNC FP:$src))>;
def fpimm0 : PatLeaf<(fpimm), [{
return N->isExactlyValue(+0.0);
}]>;
def fpimm1 : PatLeaf<(fpimm), [{
return N->isExactlyValue(+1.0);
}]>;
def fpimmn0 : PatLeaf<(fpimm), [{
return N->isExactlyValue(-0.0);
}]>;
def fpimmn1 : PatLeaf<(fpimm), [{
return N->isExactlyValue(-1.0);
}]>;
def : Pat<(f64 fpimm0), (FMOV F0)>;
def : Pat<(f64 fpimm1), (FMOV F1)>;
def : Pat<(f64 fpimmn0), (FNEG F0)>;
def : Pat<(f64 fpimmn1), (FNEG F1)>;
let isTerminator = 1, isBranch = 1 in {
def BRL_NOTCALL : RawForm<0x03, 0xb0, (outs), (ins i64imm:$dst),
"(p0) brl.cond.sptk $dst">, isB;
def BRLCOND_NOTCALL : RawForm<0x03, 0xb0, (outs), (ins PR:$qp, i64imm:$dst),
"($qp) brl.cond.sptk $dst">, isB;
def BRCOND_NOTCALL : RawForm<0x03, 0xb0, (outs), (ins PR:$qp, GR:$dst),
"($qp) br.cond.sptk $dst">, isB;
}
let isCall = 1, /* isTerminator = 1, isBranch = 1, */
Uses = [out0,out1,out2,out3,out4,out5,out6,out7],
// all calls clobber non-callee-saved registers, and for now, they are these:
Defs = [r2,r3,r8,r9,r10,r11,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,
r25,r26,r27,r28,r29,r30,r31,
p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,
F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,
F32,F33,F34,F35,F36,F37,F38,F39,F40,F41,F42,F43,F44,F45,F46,F47,F48,F49,
F50,F51,F52,F53,F54,F55,F56,
F57,F58,F59,F60,F61,F62,F63,F64,F65,F66,F67,F68,F69,F70,F71,F72,F73,F74,
F75,F76,F77,F78,F79,F80,F81,
F82,F83,F84,F85,F86,F87,F88,F89,F90,F91,F92,F93,F94,F95,F96,F97,F98,F99,
F100,F101,F102,F103,F104,F105,
F106,F107,F108,F109,F110,F111,F112,F113,F114,F115,F116,F117,F118,F119,
F120,F121,F122,F123,F124,F125,F126,F127,
out0,out1,out2,out3,out4,out5,out6,out7] in {
// old pattern call
def BRCALL: RawForm<0x03, 0xb0, (outs), (ins calltarget:$dst),
"br.call.sptk rp = $dst">, isB; // FIXME: teach llvm about branch regs?
// new daggy stuff!
// calls a globaladdress
def BRCALL_IPREL_GA : RawForm<0x03, 0xb0, (outs), (ins calltarget:$dst),
"br.call.sptk rp = $dst">, isB; // FIXME: teach llvm about branch regs?
// calls an externalsymbol
def BRCALL_IPREL_ES : RawForm<0x03, 0xb0, (outs), (ins calltarget:$dst),
"br.call.sptk rp = $dst">, isB; // FIXME: teach llvm about branch regs?
// calls through a function descriptor
def BRCALL_INDIRECT : RawForm<0x03, 0xb0, (outs), (ins GR:$branchreg),
"br.call.sptk rp = $branchreg">, isB; // FIXME: teach llvm about branch regs?
def BRLCOND_CALL : RawForm<0x03, 0xb0, (outs), (ins PR:$qp, i64imm:$dst),
"($qp) brl.cond.call.sptk $dst">, isB;
def BRCOND_CALL : RawForm<0x03, 0xb0, (outs), (ins PR:$qp, GR:$dst),
"($qp) br.cond.call.sptk $dst">, isB;
}
// Return branch:
let isTerminator = 1, isReturn = 1 in
def RET : AForm_DAG<0x03, 0x0b, (outs), (ins),
"br.ret.sptk.many rp",
[(retflag)]>, isB; // return
def : Pat<(ret), (RET)>;
// the evil stop bit of despair
def STOP : PseudoInstIA64<(outs), (ins variable_ops), ";;">;

View File

@ -1,34 +0,0 @@
//===-- IA64MachineFunctionInfo.h - IA64-specific information ---*- C++ -*-===//
//===-- for MachineFunction ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
//===----------------------------------------------------------------------===//
//
// This file declares IA64-specific per-machine-function information.
//
//===----------------------------------------------------------------------===//
#ifndef IA64MACHINEFUNCTIONINFO_H
#define IA64MACHINEFUNCTIONINFO_H
#include "llvm/CodeGen/MachineFunction.h"
//#include "IA64JITInfo.h"
namespace llvm {
class IA64FunctionInfo : public MachineFunctionInfo {
public:
unsigned outRegsUsed; // how many 'out' registers are used
// by this machinefunction? (used to compute the appropriate
// entry in the 'alloc' instruction at the top of the
// machinefunction)
explicit IA64FunctionInfo(MachineFunction& MF) { outRegsUsed=0; };
};
} // End llvm namespace
#endif

View File

@ -1,319 +0,0 @@
//===- IA64RegisterInfo.cpp - IA64 Register Information ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the IA64 implementation of the TargetRegisterInfo class.
// This file is responsible for the frame pointer elimination optimization
// on IA64.
//
//===----------------------------------------------------------------------===//
#include "IA64.h"
#include "IA64RegisterInfo.h"
#include "IA64InstrBuilder.h"
#include "IA64MachineFunctionInfo.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;
IA64RegisterInfo::IA64RegisterInfo(const TargetInstrInfo &tii)
: IA64GenRegisterInfo(IA64::ADJUSTCALLSTACKDOWN, IA64::ADJUSTCALLSTACKUP),
TII(tii) {}
const unsigned* IA64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
const {
static const unsigned CalleeSavedRegs[] = {
IA64::r5, 0
};
return CalleeSavedRegs;
}
const TargetRegisterClass* const*
IA64RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
static const TargetRegisterClass * const CalleeSavedRegClasses[] = {
&IA64::GRRegClass, 0
};
return CalleeSavedRegClasses;
}
BitVector IA64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
Reserved.set(IA64::r0);
Reserved.set(IA64::r1);
Reserved.set(IA64::r2);
Reserved.set(IA64::r5);
Reserved.set(IA64::r12);
Reserved.set(IA64::r13);
Reserved.set(IA64::r22);
Reserved.set(IA64::rp);
return Reserved;
}
//===----------------------------------------------------------------------===//
// Stack Frame Processing methods
//===----------------------------------------------------------------------===//
// hasFP - Return true if the specified function should have a dedicated frame
// pointer register. This is true if the function has variable sized allocas or
// if frame pointer elimination is disabled.
//
bool IA64RegisterInfo::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
return NoFramePointerElim || MFI->hasVarSizedObjects();
}
void IA64RegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
if (hasFP(MF)) {
// If we have a frame pointer, turn the adjcallstackup instruction into a
// 'sub SP, <amt>' and the adjcallstackdown instruction into 'add SP,
// <amt>'
MachineInstr *Old = I;
unsigned Amount = Old->getOperand(0).getImm();
DebugLoc dl = Old->getDebugLoc();
if (Amount != 0) {
// We need to keep the stack aligned properly. To do this, we round the
// amount of space needed for the outgoing arguments up to the next
// alignment boundary.
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
Amount = (Amount+Align-1)/Align*Align;
// Replace the pseudo instruction with a new instruction...
if (Old->getOpcode() == IA64::ADJUSTCALLSTACKDOWN) {
BuildMI(MBB, I, dl, TII.get(IA64::ADDIMM22), IA64::r12)
.addReg(IA64::r12).addImm(-Amount);
} else {
assert(Old->getOpcode() == IA64::ADJUSTCALLSTACKUP);
BuildMI(MBB, I, dl, TII.get(IA64::ADDIMM22), IA64::r12)
.addReg(IA64::r12).addImm(Amount);
}
}
}
MBB.erase(I);
}
void IA64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, RegScavenger *RS)const{
assert(SPAdj == 0 && "Unexpected");
unsigned i = 0;
MachineInstr &MI = *II;
MachineBasicBlock &MBB = *MI.getParent();
MachineFunction &MF = *MBB.getParent();
DebugLoc dl = MI.getDebugLoc();
bool FP = hasFP(MF);
while (!MI.getOperand(i).isFI()) {
++i;
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
}
int FrameIndex = MI.getOperand(i).getIndex();
// choose a base register: ( hasFP? framepointer : stack pointer )
unsigned BaseRegister = FP ? IA64::r5 : IA64::r12;
// Add the base register
MI.getOperand(i).ChangeToRegister(BaseRegister, false);
// Now add the frame object offset to the offset from r1.
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
// If we're not using a Frame Pointer that has been set to the value of the
// SP before having the stack size subtracted from it, then add the stack size
// to Offset to get the correct offset.
Offset += MF.getFrameInfo()->getStackSize();
// XXX: we use 'r22' as another hack+slash temporary register here :(
if (Offset <= 8191 && Offset >= -8192) { // smallish offset
// Fix up the old:
MI.getOperand(i).ChangeToRegister(IA64::r22, false);
//insert the new
BuildMI(MBB, II, dl, TII.get(IA64::ADDIMM22), IA64::r22)
.addReg(BaseRegister).addImm(Offset);
} else { // it's big
//fix up the old:
MI.getOperand(i).ChangeToRegister(IA64::r22, false);
BuildMI(MBB, II, dl, TII.get(IA64::MOVLIMM64), IA64::r22).addImm(Offset);
BuildMI(MBB, II, dl, TII.get(IA64::ADD), IA64::r22).addReg(BaseRegister)
.addReg(IA64::r22);
}
}
void IA64RegisterInfo::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
MachineBasicBlock::iterator MBBI = MBB.begin();
MachineFrameInfo *MFI = MF.getFrameInfo();
bool FP = hasFP(MF);
DebugLoc dl = (MBBI != MBB.end() ?
MBBI->getDebugLoc() : DebugLoc::getUnknownLoc());
// first, we handle the 'alloc' instruction, that should be right up the
// top of any function
static const unsigned RegsInOrder[96] = { // there are 96 GPRs the
// RSE worries about
IA64::r32, IA64::r33, IA64::r34, IA64::r35,
IA64::r36, IA64::r37, IA64::r38, IA64::r39, IA64::r40, IA64::r41,
IA64::r42, IA64::r43, IA64::r44, IA64::r45, IA64::r46, IA64::r47,
IA64::r48, IA64::r49, IA64::r50, IA64::r51, IA64::r52, IA64::r53,
IA64::r54, IA64::r55, IA64::r56, IA64::r57, IA64::r58, IA64::r59,
IA64::r60, IA64::r61, IA64::r62, IA64::r63, IA64::r64, IA64::r65,
IA64::r66, IA64::r67, IA64::r68, IA64::r69, IA64::r70, IA64::r71,
IA64::r72, IA64::r73, IA64::r74, IA64::r75, IA64::r76, IA64::r77,
IA64::r78, IA64::r79, IA64::r80, IA64::r81, IA64::r82, IA64::r83,
IA64::r84, IA64::r85, IA64::r86, IA64::r87, IA64::r88, IA64::r89,
IA64::r90, IA64::r91, IA64::r92, IA64::r93, IA64::r94, IA64::r95,
IA64::r96, IA64::r97, IA64::r98, IA64::r99, IA64::r100, IA64::r101,
IA64::r102, IA64::r103, IA64::r104, IA64::r105, IA64::r106, IA64::r107,
IA64::r108, IA64::r109, IA64::r110, IA64::r111, IA64::r112, IA64::r113,
IA64::r114, IA64::r115, IA64::r116, IA64::r117, IA64::r118, IA64::r119,
IA64::r120, IA64::r121, IA64::r122, IA64::r123, IA64::r124, IA64::r125,
IA64::r126, IA64::r127 };
unsigned numStackedGPRsUsed=0;
for (int i=0; i != 96; i++) {
if (MF.getRegInfo().isPhysRegUsed(RegsInOrder[i]))
numStackedGPRsUsed=i+1; // (i+1 and not ++ - consider fn(fp, fp, int)
}
unsigned numOutRegsUsed=MF.getInfo<IA64FunctionInfo>()->outRegsUsed;
// XXX FIXME : this code should be a bit more reliable (in case there _isn't_
// a pseudo_alloc in the MBB)
unsigned dstRegOfPseudoAlloc;
for(MBBI = MBB.begin(); /*MBBI->getOpcode() != IA64::PSEUDO_ALLOC*/; ++MBBI) {
assert(MBBI != MBB.end());
if(MBBI->getOpcode() == IA64::PSEUDO_ALLOC) {
dstRegOfPseudoAlloc=MBBI->getOperand(0).getReg();
break;
}
}
if (MBBI != MBB.end()) dl = MBBI->getDebugLoc();
BuildMI(MBB, MBBI, dl, TII.get(IA64::ALLOC)).
addReg(dstRegOfPseudoAlloc).addImm(0).
addImm(numStackedGPRsUsed).addImm(numOutRegsUsed).addImm(0);
// Get the number of bytes to allocate from the FrameInfo
unsigned NumBytes = MFI->getStackSize();
if(FP)
NumBytes += 8; // reserve space for the old FP
// Do we need to allocate space on the stack?
if (NumBytes == 0)
return;
// Add 16 bytes at the bottom of the stack (scratch area)
// and round the size to a multiple of the alignment.
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
unsigned Size = 16 + (FP ? 8 : 0);
NumBytes = (NumBytes+Size+Align-1)/Align*Align;
// Update frame info to pretend that this is part of the stack...
MFI->setStackSize(NumBytes);
// adjust stack pointer: r12 -= numbytes
if (NumBytes <= 8191) {
BuildMI(MBB, MBBI, dl, TII.get(IA64::ADDIMM22),IA64::r12).addReg(IA64::r12).
addImm(-NumBytes);
} else { // we use r22 as a scratch register here
// first load the decrement into r22
BuildMI(MBB, MBBI, dl, TII.get(IA64::MOVLIMM64), IA64::r22).
addImm(-NumBytes);
// FIXME: MOVLSI32 expects a _u_32imm
// then add (subtract) it to r12 (stack ptr)
BuildMI(MBB, MBBI, dl, TII.get(IA64::ADD), IA64::r12)
.addReg(IA64::r12).addReg(IA64::r22);
}
// now if we need to, save the old FP and set the new
if (FP) {
BuildMI(MBB, MBBI,dl,TII.get(IA64::ST8)).addReg(IA64::r12).addReg(IA64::r5);
// this must be the last instr in the prolog ? (XXX: why??)
BuildMI(MBB, MBBI, dl, TII.get(IA64::MOV), IA64::r5).addReg(IA64::r12);
}
}
void IA64RegisterInfo::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
MachineBasicBlock::iterator MBBI = prior(MBB.end());
assert(MBBI->getOpcode() == IA64::RET &&
"Can only insert epilog into returning blocks");
DebugLoc dl = MBBI->getDebugLoc();
bool FP = hasFP(MF);
// Get the number of bytes allocated from the FrameInfo...
unsigned NumBytes = MFI->getStackSize();
//now if we need to, restore the old FP
if (FP) {
//copy the FP into the SP (discards allocas)
BuildMI(MBB, MBBI, dl, TII.get(IA64::MOV), IA64::r12).addReg(IA64::r5);
//restore the FP
BuildMI(MBB, MBBI, dl, TII.get(IA64::LD8), IA64::r5).addReg(IA64::r5);
}
if (NumBytes != 0) {
if (NumBytes <= 8191) {
BuildMI(MBB, MBBI, dl, TII.get(IA64::ADDIMM22),IA64::r12).
addReg(IA64::r12).addImm(NumBytes);
} else {
BuildMI(MBB, MBBI, dl, TII.get(IA64::MOVLIMM64), IA64::r22).
addImm(NumBytes);
BuildMI(MBB, MBBI, dl, TII.get(IA64::ADD), IA64::r12).addReg(IA64::r12).
addReg(IA64::r22);
}
}
}
unsigned IA64RegisterInfo::getRARegister() const {
assert(0 && "What is the return address register");
return 0;
}
unsigned IA64RegisterInfo::getFrameRegister(MachineFunction &MF) const {
return hasFP(MF) ? IA64::r5 : IA64::r12;
}
unsigned IA64RegisterInfo::getEHExceptionRegister() const {
assert(0 && "What is the exception register");
return 0;
}
unsigned IA64RegisterInfo::getEHHandlerRegister() const {
assert(0 && "What is the exception handler register");
return 0;
}
int IA64RegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
assert(0 && "What is the dwarf register number");
return -1;
}
#include "IA64GenRegisterInfo.inc"

View File

@ -1,63 +0,0 @@
//===- IA64RegisterInfo.h - IA64 Register Information Impl ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the IA64 implementation of the TargetRegisterInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef IA64REGISTERINFO_H
#define IA64REGISTERINFO_H
#include "llvm/Target/TargetRegisterInfo.h"
#include "IA64GenRegisterInfo.h.inc"
namespace llvm {
class TargetInstrInfo;
struct IA64RegisterInfo : public IA64GenRegisterInfo {
const TargetInstrInfo &TII;
IA64RegisterInfo(const TargetInstrInfo &tii);
/// Code Generation virtual methods...
const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const;
const TargetRegisterClass* const* getCalleeSavedRegClasses(
const MachineFunction *MF = 0) const;
BitVector getReservedRegs(const MachineFunction &MF) const;
bool hasFP(const MachineFunction &MF) const;
void eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const;
void eliminateFrameIndex(MachineBasicBlock::iterator MI,
int SPAdj, RegScavenger *RS = NULL) const;
void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
// Debug information queries.
unsigned getRARegister() const;
unsigned getFrameRegister(MachineFunction &MF) const;
// Exception handling queries.
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
};
} // End llvm namespace
#endif

View File

@ -1,509 +0,0 @@
//===- IA64RegisterInfo.td - Describe the IA64 Register File ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the IA64 register file, defining the registers
// themselves, aliases between the registers, and the register classes built
// out of the registers.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Register definitions...
//
class IA64Register<string n> : Register<n> {
let Namespace = "IA64";
}
// GR - One of 128 32-bit general registers
class GR<bits<7> num, string n> : IA64Register<n> {
field bits<7> Num = num;
}
// FP - One of 128 82-bit floating-point registers
class FP<bits<7> num, string n> : IA64Register<n> {
field bits<7> Num = num;
}
// PR - One of 64 1-bit predicate registers
class PR<bits<6> num, string n> : IA64Register<n> {
field bits<6> Num = num;
}
/* general registers */
def r0 : GR< 0, "r0">, DwarfRegNum<[0]>;
def r1 : GR< 1, "r1">, DwarfRegNum<[1]>;
def r2 : GR< 2, "r2">, DwarfRegNum<[2]>;
def r3 : GR< 3, "r3">, DwarfRegNum<[3]>;
def r4 : GR< 4, "r4">, DwarfRegNum<[4]>;
def r5 : GR< 5, "r5">, DwarfRegNum<[5]>;
def r6 : GR< 6, "r6">, DwarfRegNum<[6]>;
def r7 : GR< 7, "r7">, DwarfRegNum<[7]>;
def r8 : GR< 8, "r8">, DwarfRegNum<[8]>;
def r9 : GR< 9, "r9">, DwarfRegNum<[9]>;
def r10 : GR< 10, "r10">, DwarfRegNum<[10]>;
def r11 : GR< 11, "r11">, DwarfRegNum<[11]>;
def r12 : GR< 12, "r12">, DwarfRegNum<[12]>;
def r13 : GR< 13, "r13">, DwarfRegNum<[13]>;
def r14 : GR< 14, "r14">, DwarfRegNum<[14]>;
def r15 : GR< 15, "r15">, DwarfRegNum<[15]>;
def r16 : GR< 16, "r16">, DwarfRegNum<[16]>;
def r17 : GR< 17, "r17">, DwarfRegNum<[17]>;
def r18 : GR< 18, "r18">, DwarfRegNum<[18]>;
def r19 : GR< 19, "r19">, DwarfRegNum<[19]>;
def r20 : GR< 20, "r20">, DwarfRegNum<[20]>;
def r21 : GR< 21, "r21">, DwarfRegNum<[21]>;
def r22 : GR< 22, "r22">, DwarfRegNum<[22]>;
def r23 : GR< 23, "r23">, DwarfRegNum<[23]>;
def r24 : GR< 24, "r24">, DwarfRegNum<[24]>;
def r25 : GR< 25, "r25">, DwarfRegNum<[25]>;
def r26 : GR< 26, "r26">, DwarfRegNum<[26]>;
def r27 : GR< 27, "r27">, DwarfRegNum<[27]>;
def r28 : GR< 28, "r28">, DwarfRegNum<[28]>;
def r29 : GR< 29, "r29">, DwarfRegNum<[29]>;
def r30 : GR< 30, "r30">, DwarfRegNum<[30]>;
def r31 : GR< 31, "r31">, DwarfRegNum<[31]>;
def r32 : GR< 32, "r32">, DwarfRegNum<[32]>;
def r33 : GR< 33, "r33">, DwarfRegNum<[33]>;
def r34 : GR< 34, "r34">, DwarfRegNum<[34]>;
def r35 : GR< 35, "r35">, DwarfRegNum<[35]>;
def r36 : GR< 36, "r36">, DwarfRegNum<[36]>;
def r37 : GR< 37, "r37">, DwarfRegNum<[37]>;
def r38 : GR< 38, "r38">, DwarfRegNum<[38]>;
def r39 : GR< 39, "r39">, DwarfRegNum<[39]>;
def r40 : GR< 40, "r40">, DwarfRegNum<[40]>;
def r41 : GR< 41, "r41">, DwarfRegNum<[41]>;
def r42 : GR< 42, "r42">, DwarfRegNum<[42]>;
def r43 : GR< 43, "r43">, DwarfRegNum<[43]>;
def r44 : GR< 44, "r44">, DwarfRegNum<[44]>;
def r45 : GR< 45, "r45">, DwarfRegNum<[45]>;
def r46 : GR< 46, "r46">, DwarfRegNum<[46]>;
def r47 : GR< 47, "r47">, DwarfRegNum<[47]>;
def r48 : GR< 48, "r48">, DwarfRegNum<[48]>;
def r49 : GR< 49, "r49">, DwarfRegNum<[49]>;
def r50 : GR< 50, "r50">, DwarfRegNum<[50]>;
def r51 : GR< 51, "r51">, DwarfRegNum<[51]>;
def r52 : GR< 52, "r52">, DwarfRegNum<[52]>;
def r53 : GR< 53, "r53">, DwarfRegNum<[53]>;
def r54 : GR< 54, "r54">, DwarfRegNum<[54]>;
def r55 : GR< 55, "r55">, DwarfRegNum<[55]>;
def r56 : GR< 56, "r56">, DwarfRegNum<[56]>;
def r57 : GR< 57, "r57">, DwarfRegNum<[57]>;
def r58 : GR< 58, "r58">, DwarfRegNum<[58]>;
def r59 : GR< 59, "r59">, DwarfRegNum<[59]>;
def r60 : GR< 60, "r60">, DwarfRegNum<[60]>;
def r61 : GR< 61, "r61">, DwarfRegNum<[61]>;
def r62 : GR< 62, "r62">, DwarfRegNum<[62]>;
def r63 : GR< 63, "r63">, DwarfRegNum<[63]>;
def r64 : GR< 64, "r64">, DwarfRegNum<[64]>;
def r65 : GR< 65, "r65">, DwarfRegNum<[65]>;
def r66 : GR< 66, "r66">, DwarfRegNum<[66]>;
def r67 : GR< 67, "r67">, DwarfRegNum<[67]>;
def r68 : GR< 68, "r68">, DwarfRegNum<[68]>;
def r69 : GR< 69, "r69">, DwarfRegNum<[69]>;
def r70 : GR< 70, "r70">, DwarfRegNum<[70]>;
def r71 : GR< 71, "r71">, DwarfRegNum<[71]>;
def r72 : GR< 72, "r72">, DwarfRegNum<[72]>;
def r73 : GR< 73, "r73">, DwarfRegNum<[73]>;
def r74 : GR< 74, "r74">, DwarfRegNum<[74]>;
def r75 : GR< 75, "r75">, DwarfRegNum<[75]>;
def r76 : GR< 76, "r76">, DwarfRegNum<[76]>;
def r77 : GR< 77, "r77">, DwarfRegNum<[77]>;
def r78 : GR< 78, "r78">, DwarfRegNum<[78]>;
def r79 : GR< 79, "r79">, DwarfRegNum<[79]>;
def r80 : GR< 80, "r80">, DwarfRegNum<[80]>;
def r81 : GR< 81, "r81">, DwarfRegNum<[81]>;
def r82 : GR< 82, "r82">, DwarfRegNum<[82]>;
def r83 : GR< 83, "r83">, DwarfRegNum<[83]>;
def r84 : GR< 84, "r84">, DwarfRegNum<[84]>;
def r85 : GR< 85, "r85">, DwarfRegNum<[85]>;
def r86 : GR< 86, "r86">, DwarfRegNum<[86]>;
def r87 : GR< 87, "r87">, DwarfRegNum<[87]>;
def r88 : GR< 88, "r88">, DwarfRegNum<[88]>;
def r89 : GR< 89, "r89">, DwarfRegNum<[89]>;
def r90 : GR< 90, "r90">, DwarfRegNum<[90]>;
def r91 : GR< 91, "r91">, DwarfRegNum<[91]>;
def r92 : GR< 92, "r92">, DwarfRegNum<[92]>;
def r93 : GR< 93, "r93">, DwarfRegNum<[93]>;
def r94 : GR< 94, "r94">, DwarfRegNum<[94]>;
def r95 : GR< 95, "r95">, DwarfRegNum<[95]>;
def r96 : GR< 96, "r96">, DwarfRegNum<[96]>;
def r97 : GR< 97, "r97">, DwarfRegNum<[97]>;
def r98 : GR< 98, "r98">, DwarfRegNum<[98]>;
def r99 : GR< 99, "r99">, DwarfRegNum<[99]>;
def r100 : GR< 100, "r100">, DwarfRegNum<[100]>;
def r101 : GR< 101, "r101">, DwarfRegNum<[101]>;
def r102 : GR< 102, "r102">, DwarfRegNum<[102]>;
def r103 : GR< 103, "r103">, DwarfRegNum<[103]>;
def r104 : GR< 104, "r104">, DwarfRegNum<[104]>;
def r105 : GR< 105, "r105">, DwarfRegNum<[105]>;
def r106 : GR< 106, "r106">, DwarfRegNum<[106]>;
def r107 : GR< 107, "r107">, DwarfRegNum<[107]>;
def r108 : GR< 108, "r108">, DwarfRegNum<[108]>;
def r109 : GR< 109, "r109">, DwarfRegNum<[109]>;
def r110 : GR< 110, "r110">, DwarfRegNum<[110]>;
def r111 : GR< 111, "r111">, DwarfRegNum<[111]>;
def r112 : GR< 112, "r112">, DwarfRegNum<[112]>;
def r113 : GR< 113, "r113">, DwarfRegNum<[113]>;
def r114 : GR< 114, "r114">, DwarfRegNum<[114]>;
def r115 : GR< 115, "r115">, DwarfRegNum<[115]>;
def r116 : GR< 116, "r116">, DwarfRegNum<[116]>;
def r117 : GR< 117, "r117">, DwarfRegNum<[117]>;
def r118 : GR< 118, "r118">, DwarfRegNum<[118]>;
def r119 : GR< 119, "r119">, DwarfRegNum<[119]>;
def r120 : GR< 120, "r120">, DwarfRegNum<[120]>;
def r121 : GR< 121, "r121">, DwarfRegNum<[121]>;
def r122 : GR< 122, "r122">, DwarfRegNum<[122]>;
def r123 : GR< 123, "r123">, DwarfRegNum<[123]>;
def r124 : GR< 124, "r124">, DwarfRegNum<[124]>;
def r125 : GR< 125, "r125">, DwarfRegNum<[125]>;
def r126 : GR< 126, "r126">, DwarfRegNum<[126]>;
def r127 : GR< 127, "r127">, DwarfRegNum<[127]>;
/* floating-point registers */
def F0 : FP< 0, "f0">, DwarfRegNum<[128]>;
def F1 : FP< 1, "f1">, DwarfRegNum<[129]>;
def F2 : FP< 2, "f2">, DwarfRegNum<[130]>;
def F3 : FP< 3, "f3">, DwarfRegNum<[131]>;
def F4 : FP< 4, "f4">, DwarfRegNum<[132]>;
def F5 : FP< 5, "f5">, DwarfRegNum<[133]>;
def F6 : FP< 6, "f6">, DwarfRegNum<[134]>;
def F7 : FP< 7, "f7">, DwarfRegNum<[135]>;
def F8 : FP< 8, "f8">, DwarfRegNum<[136]>;
def F9 : FP< 9, "f9">, DwarfRegNum<[137]>;
def F10 : FP< 10, "f10">, DwarfRegNum<[138]>;
def F11 : FP< 11, "f11">, DwarfRegNum<[139]>;
def F12 : FP< 12, "f12">, DwarfRegNum<[140]>;
def F13 : FP< 13, "f13">, DwarfRegNum<[141]>;
def F14 : FP< 14, "f14">, DwarfRegNum<[142]>;
def F15 : FP< 15, "f15">, DwarfRegNum<[143]>;
def F16 : FP< 16, "f16">, DwarfRegNum<[144]>;
def F17 : FP< 17, "f17">, DwarfRegNum<[145]>;
def F18 : FP< 18, "f18">, DwarfRegNum<[146]>;
def F19 : FP< 19, "f19">, DwarfRegNum<[147]>;
def F20 : FP< 20, "f20">, DwarfRegNum<[148]>;
def F21 : FP< 21, "f21">, DwarfRegNum<[149]>;
def F22 : FP< 22, "f22">, DwarfRegNum<[150]>;
def F23 : FP< 23, "f23">, DwarfRegNum<[151]>;
def F24 : FP< 24, "f24">, DwarfRegNum<[152]>;
def F25 : FP< 25, "f25">, DwarfRegNum<[153]>;
def F26 : FP< 26, "f26">, DwarfRegNum<[154]>;
def F27 : FP< 27, "f27">, DwarfRegNum<[155]>;
def F28 : FP< 28, "f28">, DwarfRegNum<[156]>;
def F29 : FP< 29, "f29">, DwarfRegNum<[157]>;
def F30 : FP< 30, "f30">, DwarfRegNum<[158]>;
def F31 : FP< 31, "f31">, DwarfRegNum<[159]>;
def F32 : FP< 32, "f32">, DwarfRegNum<[160]>;
def F33 : FP< 33, "f33">, DwarfRegNum<[161]>;
def F34 : FP< 34, "f34">, DwarfRegNum<[162]>;
def F35 : FP< 35, "f35">, DwarfRegNum<[163]>;
def F36 : FP< 36, "f36">, DwarfRegNum<[164]>;
def F37 : FP< 37, "f37">, DwarfRegNum<[165]>;
def F38 : FP< 38, "f38">, DwarfRegNum<[166]>;
def F39 : FP< 39, "f39">, DwarfRegNum<[167]>;
def F40 : FP< 40, "f40">, DwarfRegNum<[168]>;
def F41 : FP< 41, "f41">, DwarfRegNum<[169]>;
def F42 : FP< 42, "f42">, DwarfRegNum<[170]>;
def F43 : FP< 43, "f43">, DwarfRegNum<[171]>;
def F44 : FP< 44, "f44">, DwarfRegNum<[172]>;
def F45 : FP< 45, "f45">, DwarfRegNum<[173]>;
def F46 : FP< 46, "f46">, DwarfRegNum<[174]>;
def F47 : FP< 47, "f47">, DwarfRegNum<[175]>;
def F48 : FP< 48, "f48">, DwarfRegNum<[176]>;
def F49 : FP< 49, "f49">, DwarfRegNum<[177]>;
def F50 : FP< 50, "f50">, DwarfRegNum<[178]>;
def F51 : FP< 51, "f51">, DwarfRegNum<[179]>;
def F52 : FP< 52, "f52">, DwarfRegNum<[180]>;
def F53 : FP< 53, "f53">, DwarfRegNum<[181]>;
def F54 : FP< 54, "f54">, DwarfRegNum<[182]>;
def F55 : FP< 55, "f55">, DwarfRegNum<[183]>;
def F56 : FP< 56, "f56">, DwarfRegNum<[184]>;
def F57 : FP< 57, "f57">, DwarfRegNum<[185]>;
def F58 : FP< 58, "f58">, DwarfRegNum<[186]>;
def F59 : FP< 59, "f59">, DwarfRegNum<[187]>;
def F60 : FP< 60, "f60">, DwarfRegNum<[188]>;
def F61 : FP< 61, "f61">, DwarfRegNum<[189]>;
def F62 : FP< 62, "f62">, DwarfRegNum<[190]>;
def F63 : FP< 63, "f63">, DwarfRegNum<[191]>;
def F64 : FP< 64, "f64">, DwarfRegNum<[192]>;
def F65 : FP< 65, "f65">, DwarfRegNum<[193]>;
def F66 : FP< 66, "f66">, DwarfRegNum<[194]>;
def F67 : FP< 67, "f67">, DwarfRegNum<[195]>;
def F68 : FP< 68, "f68">, DwarfRegNum<[196]>;
def F69 : FP< 69, "f69">, DwarfRegNum<[197]>;
def F70 : FP< 70, "f70">, DwarfRegNum<[198]>;
def F71 : FP< 71, "f71">, DwarfRegNum<[199]>;
def F72 : FP< 72, "f72">, DwarfRegNum<[200]>;
def F73 : FP< 73, "f73">, DwarfRegNum<[201]>;
def F74 : FP< 74, "f74">, DwarfRegNum<[202]>;
def F75 : FP< 75, "f75">, DwarfRegNum<[203]>;
def F76 : FP< 76, "f76">, DwarfRegNum<[204]>;
def F77 : FP< 77, "f77">, DwarfRegNum<[205]>;
def F78 : FP< 78, "f78">, DwarfRegNum<[206]>;
def F79 : FP< 79, "f79">, DwarfRegNum<[207]>;
def F80 : FP< 80, "f80">, DwarfRegNum<[208]>;
def F81 : FP< 81, "f81">, DwarfRegNum<[209]>;
def F82 : FP< 82, "f82">, DwarfRegNum<[210]>;
def F83 : FP< 83, "f83">, DwarfRegNum<[211]>;
def F84 : FP< 84, "f84">, DwarfRegNum<[212]>;
def F85 : FP< 85, "f85">, DwarfRegNum<[213]>;
def F86 : FP< 86, "f86">, DwarfRegNum<[214]>;
def F87 : FP< 87, "f87">, DwarfRegNum<[215]>;
def F88 : FP< 88, "f88">, DwarfRegNum<[216]>;
def F89 : FP< 89, "f89">, DwarfRegNum<[217]>;
def F90 : FP< 90, "f90">, DwarfRegNum<[218]>;
def F91 : FP< 91, "f91">, DwarfRegNum<[219]>;
def F92 : FP< 92, "f92">, DwarfRegNum<[220]>;
def F93 : FP< 93, "f93">, DwarfRegNum<[221]>;
def F94 : FP< 94, "f94">, DwarfRegNum<[222]>;
def F95 : FP< 95, "f95">, DwarfRegNum<[223]>;
def F96 : FP< 96, "f96">, DwarfRegNum<[224]>;
def F97 : FP< 97, "f97">, DwarfRegNum<[225]>;
def F98 : FP< 98, "f98">, DwarfRegNum<[226]>;
def F99 : FP< 99, "f99">, DwarfRegNum<[227]>;
def F100 : FP< 100, "f100">, DwarfRegNum<[228]>;
def F101 : FP< 101, "f101">, DwarfRegNum<[229]>;
def F102 : FP< 102, "f102">, DwarfRegNum<[230]>;
def F103 : FP< 103, "f103">, DwarfRegNum<[231]>;
def F104 : FP< 104, "f104">, DwarfRegNum<[232]>;
def F105 : FP< 105, "f105">, DwarfRegNum<[233]>;
def F106 : FP< 106, "f106">, DwarfRegNum<[234]>;
def F107 : FP< 107, "f107">, DwarfRegNum<[235]>;
def F108 : FP< 108, "f108">, DwarfRegNum<[236]>;
def F109 : FP< 109, "f109">, DwarfRegNum<[237]>;
def F110 : FP< 110, "f110">, DwarfRegNum<[238]>;
def F111 : FP< 111, "f111">, DwarfRegNum<[239]>;
def F112 : FP< 112, "f112">, DwarfRegNum<[240]>;
def F113 : FP< 113, "f113">, DwarfRegNum<[241]>;
def F114 : FP< 114, "f114">, DwarfRegNum<[242]>;
def F115 : FP< 115, "f115">, DwarfRegNum<[243]>;
def F116 : FP< 116, "f116">, DwarfRegNum<[244]>;
def F117 : FP< 117, "f117">, DwarfRegNum<[245]>;
def F118 : FP< 118, "f118">, DwarfRegNum<[246]>;
def F119 : FP< 119, "f119">, DwarfRegNum<[247]>;
def F120 : FP< 120, "f120">, DwarfRegNum<[248]>;
def F121 : FP< 121, "f121">, DwarfRegNum<[249]>;
def F122 : FP< 122, "f122">, DwarfRegNum<[250]>;
def F123 : FP< 123, "f123">, DwarfRegNum<[251]>;
def F124 : FP< 124, "f124">, DwarfRegNum<[252]>;
def F125 : FP< 125, "f125">, DwarfRegNum<[253]>;
def F126 : FP< 126, "f126">, DwarfRegNum<[254]>;
def F127 : FP< 127, "f127">, DwarfRegNum<[255]>;
/* predicate registers */
def p0 : PR< 0, "p0">, DwarfRegNum<[256]>;
def p1 : PR< 1, "p1">, DwarfRegNum<[257]>;
def p2 : PR< 2, "p2">, DwarfRegNum<[258]>;
def p3 : PR< 3, "p3">, DwarfRegNum<[259]>;
def p4 : PR< 4, "p4">, DwarfRegNum<[260]>;
def p5 : PR< 5, "p5">, DwarfRegNum<[261]>;
def p6 : PR< 6, "p6">, DwarfRegNum<[262]>;
def p7 : PR< 7, "p7">, DwarfRegNum<[263]>;
def p8 : PR< 8, "p8">, DwarfRegNum<[264]>;
def p9 : PR< 9, "p9">, DwarfRegNum<[265]>;
def p10 : PR< 10, "p10">, DwarfRegNum<[266]>;
def p11 : PR< 11, "p11">, DwarfRegNum<[267]>;
def p12 : PR< 12, "p12">, DwarfRegNum<[268]>;
def p13 : PR< 13, "p13">, DwarfRegNum<[269]>;
def p14 : PR< 14, "p14">, DwarfRegNum<[270]>;
def p15 : PR< 15, "p15">, DwarfRegNum<[271]>;
def p16 : PR< 16, "p16">, DwarfRegNum<[272]>;
def p17 : PR< 17, "p17">, DwarfRegNum<[273]>;
def p18 : PR< 18, "p18">, DwarfRegNum<[274]>;
def p19 : PR< 19, "p19">, DwarfRegNum<[275]>;
def p20 : PR< 20, "p20">, DwarfRegNum<[276]>;
def p21 : PR< 21, "p21">, DwarfRegNum<[277]>;
def p22 : PR< 22, "p22">, DwarfRegNum<[278]>;
def p23 : PR< 23, "p23">, DwarfRegNum<[279]>;
def p24 : PR< 24, "p24">, DwarfRegNum<[280]>;
def p25 : PR< 25, "p25">, DwarfRegNum<[281]>;
def p26 : PR< 26, "p26">, DwarfRegNum<[282]>;
def p27 : PR< 27, "p27">, DwarfRegNum<[283]>;
def p28 : PR< 28, "p28">, DwarfRegNum<[284]>;
def p29 : PR< 29, "p29">, DwarfRegNum<[285]>;
def p30 : PR< 30, "p30">, DwarfRegNum<[286]>;
def p31 : PR< 31, "p31">, DwarfRegNum<[287]>;
def p32 : PR< 32, "p32">, DwarfRegNum<[288]>;
def p33 : PR< 33, "p33">, DwarfRegNum<[289]>;
def p34 : PR< 34, "p34">, DwarfRegNum<[290]>;
def p35 : PR< 35, "p35">, DwarfRegNum<[291]>;
def p36 : PR< 36, "p36">, DwarfRegNum<[292]>;
def p37 : PR< 37, "p37">, DwarfRegNum<[293]>;
def p38 : PR< 38, "p38">, DwarfRegNum<[294]>;
def p39 : PR< 39, "p39">, DwarfRegNum<[295]>;
def p40 : PR< 40, "p40">, DwarfRegNum<[296]>;
def p41 : PR< 41, "p41">, DwarfRegNum<[297]>;
def p42 : PR< 42, "p42">, DwarfRegNum<[298]>;
def p43 : PR< 43, "p43">, DwarfRegNum<[299]>;
def p44 : PR< 44, "p44">, DwarfRegNum<[300]>;
def p45 : PR< 45, "p45">, DwarfRegNum<[301]>;
def p46 : PR< 46, "p46">, DwarfRegNum<[302]>;
def p47 : PR< 47, "p47">, DwarfRegNum<[303]>;
def p48 : PR< 48, "p48">, DwarfRegNum<[304]>;
def p49 : PR< 49, "p49">, DwarfRegNum<[305]>;
def p50 : PR< 50, "p50">, DwarfRegNum<[306]>;
def p51 : PR< 51, "p51">, DwarfRegNum<[307]>;
def p52 : PR< 52, "p52">, DwarfRegNum<[308]>;
def p53 : PR< 53, "p53">, DwarfRegNum<[309]>;
def p54 : PR< 54, "p54">, DwarfRegNum<[310]>;
def p55 : PR< 55, "p55">, DwarfRegNum<[311]>;
def p56 : PR< 56, "p56">, DwarfRegNum<[312]>;
def p57 : PR< 57, "p57">, DwarfRegNum<[313]>;
def p58 : PR< 58, "p58">, DwarfRegNum<[314]>;
def p59 : PR< 59, "p59">, DwarfRegNum<[315]>;
def p60 : PR< 60, "p60">, DwarfRegNum<[316]>;
def p61 : PR< 61, "p61">, DwarfRegNum<[317]>;
def p62 : PR< 62, "p62">, DwarfRegNum<[318]>;
def p63 : PR< 63, "p63">, DwarfRegNum<[319]>;
// XXX : this is temporary, we'll eventually have the output registers
// in the general purpose register class too?
def out0 : GR<0, "out0">, DwarfRegNum<[120]>;
def out1 : GR<1, "out1">, DwarfRegNum<[121]>;
def out2 : GR<2, "out2">, DwarfRegNum<[122]>;
def out3 : GR<3, "out3">, DwarfRegNum<[123]>;
def out4 : GR<4, "out4">, DwarfRegNum<[124]>;
def out5 : GR<5, "out5">, DwarfRegNum<[125]>;
def out6 : GR<6, "out6">, DwarfRegNum<[126]>;
def out7 : GR<7, "out7">, DwarfRegNum<[127]>;
// application (special) registers:
// "previous function state" application register
def AR_PFS : GR<0, "ar.pfs">, DwarfRegNum<[331]>;
// "return pointer" (this is really branch register b0)
def rp : GR<0, "rp">, DwarfRegNum<[-1]>;
// branch reg 6
def B6 : GR<0, "b6">, DwarfRegNum<[326]>;
//===----------------------------------------------------------------------===//
// Register Class Definitions... now that we have all of the pieces, define the
// top-level register classes. The order specified in the register list is
// implicitly defined to be the register allocation order.
//
// these are the scratch (+stacked) general registers
// FIXME/XXX we also reserve a frame pointer (r5)
// FIXME/XXX we also reserve r2 for spilling/filling predicates
// in IA64RegisterInfo.cpp
// FIXME/XXX we also reserve r22 for calculating addresses
// in IA64RegisterInfo.cpp
def GR : RegisterClass<"IA64", [i64], 64,
[
//FIXME!: for both readability and performance, we don't want the out
// registers to be the first ones allocated
out7, out6, out5, out4, out3, out2, out1, out0,
r3, r8, r9, r10, r11, r14, r15,
r16, r17, r18, r19, r20, r21, r23,
r24, r25, r26, r27, r28, r29, r30, r31,
r32, r33, r34, r35, r36, r37, r38, r39,
r40, r41, r42, r43, r44, r45, r46, r47,
r48, r49, r50, r51, r52, r53, r54, r55,
r56, r57, r58, r59, r60, r61, r62, r63,
r64, r65, r66, r67, r68, r69, r70, r71,
r72, r73, r74, r75, r76, r77, r78, r79,
r80, r81, r82, r83, r84, r85, r86, r87,
r88, r89, r90, r91, r92, r93, r94, r95,
r96, r97, r98, r99, r100, r101, r102, r103,
r104, r105, r106, r107, r108, r109, r110, r111,
r112, r113, r114, r115, r116, r117, r118, r119,
// last 17 are special (look down)
r120, r121, r122, r123, r124, r125, r126, r127,
r0, r1, r2, r5, r12, r13, r22, rp, AR_PFS]>
{
let MethodProtos = [{
iterator allocation_order_begin(const MachineFunction &MF) const;
iterator allocation_order_end(const MachineFunction &MF) const;
}];
let MethodBodies = [{
GRClass::iterator
GRClass::allocation_order_begin(const MachineFunction &MF) const {
// hide the 8 out? registers appropriately:
return begin()+(8-(MF.getInfo<IA64FunctionInfo>()->outRegsUsed));
}
GRClass::iterator
GRClass::allocation_order_end(const MachineFunction &MF) const {
// the 9 special registers r0,r1,r2,r5,r12,r13 etc
int numReservedRegs=9;
// we also can't allocate registers for use as locals if they're already
// required as 'out' registers
numReservedRegs+=MF.getInfo<IA64FunctionInfo>()->outRegsUsed;
return end()-numReservedRegs; // hide registers appropriately
}
}];
}
// these are the scratch (+stacked) FP registers
def FP : RegisterClass<"IA64", [f64], 64,
[F6, F7,
F8, F9, F10, F11, F12, F13, F14, F15,
F32, F33, F34, F35, F36, F37, F38, F39,
F40, F41, F42, F43, F44, F45, F46, F47,
F48, F49, F50, F51, F52, F53, F54, F55,
F56, F57, F58, F59, F60, F61, F62, F63,
F64, F65, F66, F67, F68, F69, F70, F71,
F72, F73, F74, F75, F76, F77, F78, F79,
F80, F81, F82, F83, F84, F85, F86, F87,
F88, F89, F90, F91, F92, F93, F94, F95,
F96, F97, F98, F99, F100, F101, F102, F103,
F104, F105, F106, F107, F108, F109, F110, F111,
F112, F113, F114, F115, F116, F117, F118, F119,
F120, F121, F122, F123, F124, F125, F126, F127,
F0, F1]> // these last two are hidden
{
// the 128s here are to make stf.spill/ldf.fill happy,
// when storing full (82-bit) FP regs to stack slots
// we need to 16-byte align
let Size=128;
let Alignment=128;
let MethodProtos = [{
iterator allocation_order_begin(const MachineFunction &MF) const;
iterator allocation_order_end(const MachineFunction &MF) const;
}];
let MethodBodies = [{
FPClass::iterator
FPClass::allocation_order_begin(const MachineFunction &MF) const {
return begin(); // we don't hide any FP regs from the start
}
FPClass::iterator
FPClass::allocation_order_end(const MachineFunction &MF) const {
return end()-2; // we hide regs F0, F1 from the end
}
}];
}
// these are the predicate registers, p0 (1/TRUE) is not here
def PR : RegisterClass<"IA64", [i1], 64,
// for now, let's be wimps and only have the scratch predicate regs
[p6, p7, p8, p9, p10, p11, p12, p13, p14, p15]> {
let Size = 64;
}
/*
[p1, p2, p3, p4, p5, p6, p7,
p8, p9, p10, p11, p12, p13, p14, p15,
p16, p17, p18, p19, p20, p21, p22, p23,
p24, p25, p26, p27, p28, p29, p30, p31,
p32, p33, p34, p35, p36, p37, p38, p39,
p40, p41, p42, p43, p44, p45, p46, p47,
p48, p49, p50, p51, p52, p53, p54, p55,
p56, p57, p58, p59, p60, p61, p62, p63]>;
*/

View File

@ -1,18 +0,0 @@
//===-- IA64Subtarget.cpp - IA64 Subtarget Information ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the IA64 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "subtarget"
#include "IA64Subtarget.h"
using namespace llvm;
IA64Subtarget::IA64Subtarget() {}

View File

@ -1,28 +0,0 @@
//====---- IA64Subtarget.h - Define Subtarget for the IA64 -----*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the IA64 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//
#ifndef IA64SUBTARGET_H
#define IA64SUBTARGET_H
#include "llvm/Target/TargetSubtarget.h"
namespace llvm {
class IA64Subtarget : public TargetSubtarget {
public:
IA64Subtarget();
};
} // End llvm namespace
#endif

View File

@ -1,44 +0,0 @@
//===-- IA64TargetAsmInfo.cpp - IA64 asm properties -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the IA64TargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "IA64TargetAsmInfo.h"
#include "llvm/Constants.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
IA64TargetAsmInfo::IA64TargetAsmInfo(const TargetMachine &TM):
ELFTargetAsmInfo(TM) {
CommentString = "//";
Data8bitsDirective = "\tdata1\t"; // FIXME: check that we are
Data16bitsDirective = "\tdata2.ua\t"; // disabling auto-alignment
Data32bitsDirective = "\tdata4.ua\t"; // properly
Data64bitsDirective = "\tdata8.ua\t";
ZeroDirective = "\t.skip\t";
AsciiDirective = "\tstring\t";
GlobalVarAddrPrefix="";
GlobalVarAddrSuffix="";
FunctionAddrPrefix="@fptr(";
FunctionAddrSuffix=")";
// FIXME: would be nice to have rodata (no 'w') when appropriate?
ConstantPoolSection = "\n\t.section .data, \"aw\", \"progbits\"\n";
}
unsigned IA64TargetAsmInfo::RelocBehaviour() const {
return (TM.getRelocationModel() != Reloc::Static ?
Reloc::LocalOrGlobal : Reloc::Global);
}
// FIXME: Support small data/bss/rodata sections someday.

View File

@ -1,33 +0,0 @@
//=====-- IA64TargetAsmInfo.h - IA64 asm properties -----------*- C++ -*--====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the IA64TargetAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef IA64TARGETASMINFO_H
#define IA64TARGETASMINFO_H
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
namespace llvm {
// Forward declaration.
class TargetMachine;
struct IA64TargetAsmInfo : public ELFTargetAsmInfo {
explicit IA64TargetAsmInfo(const TargetMachine &TM);
virtual unsigned RelocBehaviour() const;
};
} // namespace llvm
#endif

View File

@ -1,97 +0,0 @@
//===-- IA64TargetMachine.cpp - Define TargetMachine for IA64 -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the IA64 specific subclass of TargetMachine.
//
//===----------------------------------------------------------------------===//
#include "IA64TargetAsmInfo.h"
#include "IA64TargetMachine.h"
#include "IA64.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Target/TargetMachineRegistry.h"
using namespace llvm;
// Register the target
static RegisterTarget<IA64TargetMachine> X("ia64",
"IA-64 (Itanium) [experimental]");
// No assembler printer by default
IA64TargetMachine::AsmPrinterCtorFn IA64TargetMachine::AsmPrinterCtor = 0;
// Force static initialization.
extern "C" void LLVMInitializeIA64Target() { }
const TargetAsmInfo *IA64TargetMachine::createTargetAsmInfo() const {
return new IA64TargetAsmInfo(*this);
}
unsigned IA64TargetMachine::getModuleMatchQuality(const Module &M) {
// we match [iI][aA]*64
bool seenIA64=false;
std::string TT = M.getTargetTriple();
if (TT.size() >= 4) {
if( (TT[0]=='i' || TT[0]=='I') &&
(TT[1]=='a' || TT[1]=='A') ) {
for(unsigned int i=2; i<(TT.size()-1); i++)
if(TT[i]=='6' && TT[i+1]=='4')
seenIA64=true;
}
if (seenIA64)
return 20; // strong match
}
// If the target triple is something non-ia64, we don't match.
if (!TT.empty()) return 0;
#if defined(__ia64__) || defined(__IA64__)
return 5;
#else
return 0;
#endif
}
/// IA64TargetMachine ctor - Create an LP64 architecture model
///
IA64TargetMachine::IA64TargetMachine(const Module &M, const std::string &FS)
: DataLayout("e-f80:128:128"),
FrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0),
TLInfo(*this) { // FIXME? check this stuff
}
//===----------------------------------------------------------------------===//
// Pass Pipeline Configuration
//===----------------------------------------------------------------------===//
bool IA64TargetMachine::addInstSelector(PassManagerBase &PM,
CodeGenOpt::Level OptLevel) {
PM.add(createIA64DAGToDAGInstructionSelector(*this));
return false;
}
bool IA64TargetMachine::addPreEmitPass(PassManagerBase &PM,
CodeGenOpt::Level OptLevel) {
// Make sure everything is bundled happily
PM.add(createIA64BundlingPass(*this));
return true;
}
bool IA64TargetMachine::addAssemblyEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool Verbose,
raw_ostream &Out) {
// Output assembly language.
assert(AsmPrinterCtor && "AsmPrinter was not linked in");
if (AsmPrinterCtor)
PM.add(AsmPrinterCtor(Out, *this, Verbose));
return false;
}

View File

@ -1,75 +0,0 @@
//===-- IA64TargetMachine.h - Define TargetMachine for IA64 ---*- C++ -*---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the IA64 specific subclass of TargetMachine.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TARGET_IA64TARGETMACHINE_H
#define LLVM_TARGET_IA64TARGETMACHINE_H
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "IA64InstrInfo.h"
#include "IA64ISelLowering.h"
#include "IA64Subtarget.h"
namespace llvm {
class IA64TargetMachine : public LLVMTargetMachine {
IA64Subtarget Subtarget;
const TargetData DataLayout; // Calculates type size & alignment
IA64InstrInfo InstrInfo;
TargetFrameInfo FrameInfo;
//IA64JITInfo JITInfo;
IA64TargetLowering TLInfo;
protected:
virtual const TargetAsmInfo *createTargetAsmInfo() const;
// To avoid having target depend on the asmprinter stuff libraries, asmprinter
// set this functions to ctor pointer at startup time if they are linked in.
typedef FunctionPass *(*AsmPrinterCtorFn)(raw_ostream &o,
IA64TargetMachine &tm,
bool verbose);
static AsmPrinterCtorFn AsmPrinterCtor;
public:
IA64TargetMachine(const Module &M, const std::string &FS);
virtual const IA64InstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
virtual const IA64Subtarget *getSubtargetImpl() const { return &Subtarget; }
virtual IA64TargetLowering *getTargetLowering() const {
return const_cast<IA64TargetLowering*>(&TLInfo);
}
virtual const IA64RegisterInfo *getRegisterInfo() const {
return &InstrInfo.getRegisterInfo();
}
virtual const TargetData *getTargetData() const { return &DataLayout; }
static unsigned getModuleMatchQuality(const Module &M);
// Pass Pipeline Configuration
virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
virtual bool addAssemblyEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool Verbose, raw_ostream &Out);
static void registerAsmPrinter(AsmPrinterCtorFn F) {
AsmPrinterCtor = F;
}
};
} // End llvm namespace
#endif

View File

@ -1,20 +0,0 @@
##===- lib/Target/IA64/Makefile -----------------------------*- Makefile -*-===##
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL = ../../..
LIBRARYNAME = LLVMIA64CodeGen
TARGET = IA64
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = IA64GenRegisterInfo.h.inc IA64GenRegisterNames.inc \
IA64GenRegisterInfo.inc IA64GenInstrNames.inc \
IA64GenInstrInfo.inc IA64GenAsmWriter.inc \
IA64GenDAGISel.inc
DIRS = AsmPrinter
include $(LEVEL)/Makefile.common

View File

@ -1,48 +0,0 @@
TODO:
- Un-bitrot ISel
- Hook up If-Conversion a la ARM target
- Hook up all branch analysis functions
- Instruction scheduling
- Bundling
- Dynamic Optimization
- Testing and bugfixing
- stop passing FP args in both FP *and* integer regs when not required
- allocate low (nonstacked) registers more aggressively
- clean up and thoroughly test the isel patterns.
- fix stacked register allocation order: (for readability) we don't want
the out? registers being the first ones used
- fix up floating point
(nb http://gcc.gnu.org/wiki?pagename=ia64%20floating%20point )
- bundling!
(we will avoid the mess that is:
http://gcc.gnu.org/ml/gcc/2003-12/msg00832.html )
- instruction scheduling (hmmmm! ;)
- counted loop support
- make integer + FP mul/div more clever (we have fixed pseudocode atm)
- track and use comparison complements
INFO:
- we are strictly LP64 here, no support for ILP32 on HP-UX. Linux users
don't need to worry about this.
- i have instruction scheduling/bundling pseudocode, that really works
(has been tested, albeit at the perl-script level).
so, before you go write your own, send me an email!
KNOWN DEFECTS AT THE CURRENT TIME:
- C++ vtables contain naked function pointers, not function descriptors,
which is bad. see http://llvm.cs.uiuc.edu/bugs/show_bug.cgi?id=406
- varargs are broken
- alloca doesn't work (indeed, stack frame layout is bogus)
- no support for big-endian environments
- (not really the backend, but...) the CFE has some issues on IA64.
these will probably be fixed soon.
ACKNOWLEDGEMENTS:
- Chris Lattner (x100)
- Other LLVM developers ("hey, that looks familiar")
CONTACT:
- You can email me at duraid@octopus.com.au. If you find a small bug,
just email me. If you find a big bug, please file a bug report
in bugzilla! http://llvm.cs.uiuc.edu is your one stop shop for all
things LLVM.

View File

@ -1,262 +0,0 @@
//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to the MSP430 assembly language.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "MSP430.h"
#include "MSP430InstrInfo.h"
#include "MSP430TargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
namespace {
class VISIBILITY_HIDDEN MSP430AsmPrinter : public AsmPrinter {
public:
MSP430AsmPrinter(raw_ostream &O, MSP430TargetMachine &TM,
const TargetAsmInfo *TAI, bool V)
: AsmPrinter(O, TM, TAI, V) {}
virtual const char *getPassName() const {
return "MSP430 Assembly Printer";
}
void printOperand(const MachineInstr *MI, int OpNum,
const char* Modifier = 0);
void printSrcMemOperand(const MachineInstr *MI, int OpNum,
const char* Modifier = 0);
void printCCOperand(const MachineInstr *MI, int OpNum);
bool printInstruction(const MachineInstr *MI); // autogenerated.
void printMachineInstruction(const MachineInstr * MI);
void emitFunctionHeader(const MachineFunction &MF);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
bool doFinalization(Module &M);
void getAnalysisUsage(AnalysisUsage &AU) const {
AsmPrinter::getAnalysisUsage(AU);
AU.setPreservesAll();
}
};
} // end of anonymous namespace
#include "MSP430GenAsmWriter.inc"
/// createMSP430CodePrinterPass - Returns a pass that prints the MSP430
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description. This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *llvm::createMSP430CodePrinterPass(raw_ostream &o,
MSP430TargetMachine &tm,
bool verbose) {
return new MSP430AsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
}
bool MSP430AsmPrinter::doInitialization(Module &M) {
Mang = new Mangler(M, "", TAI->getPrivateGlobalPrefix());
return false; // success
}
bool MSP430AsmPrinter::doFinalization(Module &M) {
return AsmPrinter::doFinalization(M);
}
void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
unsigned FnAlign = MF.getAlignment();
EmitAlignment(FnAlign, F);
switch (F->getLinkage()) {
default: assert(0 && "Unknown linkage type!");
case Function::InternalLinkage: // Symbols default to internal.
case Function::PrivateLinkage:
break;
case Function::ExternalLinkage:
O << "\t.globl\t" << CurrentFnName << '\n';
break;
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
O << "\t.weak\t" << CurrentFnName << '\n';
break;
}
printVisibility(CurrentFnName, F->getVisibility());
O << "\t.type\t" << CurrentFnName << ",@function\n"
<< CurrentFnName << ":\n";
}
bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
SetupMachineFunction(MF);
O << "\n\n";
// Print the 'header' of function
emitFunctionHeader(MF);
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
if (!VerboseAsm && (I->pred_empty() || I->isOnlyReachableByFallthrough())) {
// This is an entry block or a block that's only reachable via a
// fallthrough edge. In non-VerboseAsm mode, don't print the label.
} else {
printBasicBlockLabel(I, true, true, VerboseAsm);
O << '\n';
}
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II)
// Print the assembly for the instruction.
printMachineInstruction(II);
}
if (TAI->hasDotTypeDotSizeDirective())
O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
O.flush();
// We didn't modify anything
return false;
}
void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
// Call the autogenerated instruction printer routines.
if (printInstruction(MI))
return;
assert(0 && "Should not happen");
}
void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
const char* Modifier) {
const MachineOperand &MO = MI->getOperand(OpNum);
switch (MO.getType()) {
case MachineOperand::MO_Register:
assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
"Virtual registers should be already mapped!");
O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
return;
case MachineOperand::MO_Immediate:
if (!Modifier || strcmp(Modifier, "nohash"))
O << '#';
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB());
return;
case MachineOperand::MO_GlobalAddress: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
bool isCallOp = Modifier && !strcmp(Modifier, "call");
std::string Name = Mang->getValueName(MO.getGlobal());
assert(MO.getOffset() == 0 && "No offsets allowed!");
if (isCallOp)
O << '#';
else if (isMemOp)
O << '&';
O << Name;
return;
}
case MachineOperand::MO_ExternalSymbol: {
bool isCallOp = Modifier && !strcmp(Modifier, "call");
std::string Name(TAI->getGlobalPrefix());
Name += MO.getSymbolName();
if (isCallOp)
O << '#';
O << Name;
return;
}
default:
assert(0 && "Not implemented yet!");
}
}
void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
const char* Modifier) {
const MachineOperand &Base = MI->getOperand(OpNum);
const MachineOperand &Disp = MI->getOperand(OpNum+1);
if (Base.isGlobal())
printOperand(MI, OpNum, "mem");
else if (Disp.isImm() && !Base.getReg())
printOperand(MI, OpNum);
else if (Base.getReg()) {
if (Disp.getImm()) {
printOperand(MI, OpNum + 1, "nohash");
O << '(';
printOperand(MI, OpNum);
O << ')';
} else {
O << '@';
printOperand(MI, OpNum);
}
} else
assert(0 && "Unsupported memory operand");
}
void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
unsigned CC = MI->getOperand(OpNum).getImm();
switch (CC) {
default:
assert(0 && "Unsupported CC code");
break;
case MSP430::COND_E:
O << "eq";
break;
case MSP430::COND_NE:
O << "ne";
break;
case MSP430::COND_HS:
O << "hs";
break;
case MSP430::COND_LO:
O << "lo";
break;
case MSP430::COND_GE:
O << "ge";
break;
case MSP430::COND_L:
O << 'l';
break;
}
}

View File

@ -1,22 +0,0 @@
//===-- MSP430TargetAsmInfo.cpp - MSP430 asm properties -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the MSP430TargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "MSP430TargetAsmInfo.h"
#include "MSP430TargetMachine.h"
using namespace llvm;
MSP430TargetAsmInfo::MSP430TargetAsmInfo(const MSP430TargetMachine &TM)
: ELFTargetAsmInfo(TM) {
AlignmentIsInBytes = false;
}

View File

@ -1,31 +0,0 @@
//=====-- MSP430TargetAsmInfo.h - MSP430 asm properties -------*- C++ -*--====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the MSP430TargetAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef MSP430TARGETASMINFO_H
#define MSP430TARGETASMINFO_H
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
namespace llvm {
// Forward declaration.
class MSP430TargetMachine;
struct MSP430TargetAsmInfo : public ELFTargetAsmInfo {
explicit MSP430TargetAsmInfo(const MSP430TargetMachine &TM);
};
} // namespace llvm
#endif

View File

@ -1,98 +0,0 @@
//===-- MipsTargetAsmInfo.cpp - Mips asm properties -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the MipsTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "MipsTargetAsmInfo.h"
#include "MipsTargetMachine.h"
#include "llvm/GlobalVariable.h"
using namespace llvm;
MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM):
ELFTargetAsmInfo(TM) {
Subtarget = &TM.getSubtarget<MipsSubtarget>();
AlignmentIsInBytes = false;
COMMDirectiveTakesAlignment = true;
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
Data64bitsDirective = NULL;
PrivateGlobalPrefix = "$";
JumpTableDataSection = "\t.rdata";
CommentString = "#";
ZeroDirective = "\t.space\t";
BSSSection = "\t.section\t.bss";
CStringSection = ".rodata.str";
if (!Subtarget->hasABICall()) {
JumpTableDirective = "\t.word\t";
SmallDataSection = getNamedSection("\t.sdata", SectionFlags::Writeable);
SmallBSSSection = getNamedSection("\t.sbss",
SectionFlags::Writeable |
SectionFlags::BSS);
} else
JumpTableDirective = "\t.gpword\t";
}
unsigned MipsTargetAsmInfo::
SectionFlagsForGlobal(const GlobalValue *GV, const char* Name) const {
unsigned Flags = ELFTargetAsmInfo::SectionFlagsForGlobal(GV, Name);
// Mask out Small Section flag bit, Mips doesnt support 's' section symbol
// for its small sections.
return (Flags & (~SectionFlags::Small));
}
SectionKind::Kind MipsTargetAsmInfo::
SectionKindForGlobal(const GlobalValue *GV) const {
SectionKind::Kind K = ELFTargetAsmInfo::SectionKindForGlobal(GV);
if (Subtarget->hasABICall())
return K;
if (K != SectionKind::Data && K != SectionKind::BSS &&
K != SectionKind::RODataMergeConst)
return K;
if (isa<GlobalVariable>(GV)) {
const TargetData *TD = TM.getTargetData();
unsigned Size = TD->getTypeAllocSize(GV->getType()->getElementType());
unsigned Threshold = Subtarget->getSSectionThreshold();
if (Size > 0 && Size <= Threshold) {
if (K == SectionKind::BSS)
return SectionKind::SmallBSS;
else
return SectionKind::SmallData;
}
}
return K;
}
const Section* MipsTargetAsmInfo::
SelectSectionForGlobal(const GlobalValue *GV) const {
SectionKind::Kind K = SectionKindForGlobal(GV);
const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV);
if (GVA && (!GVA->isWeakForLinker()))
switch (K) {
case SectionKind::SmallData:
return getSmallDataSection();
case SectionKind::SmallBSS:
return getSmallBSSSection();
default: break;
}
return ELFTargetAsmInfo::SelectSectionForGlobal(GV);
}

View File

@ -1,51 +0,0 @@
//=====-- MipsTargetAsmInfo.h - Mips asm properties -----------*- C++ -*--====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the MipsTargetAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef MIPSTARGETASMINFO_H
#define MIPSTARGETASMINFO_H
#include "MipsSubtarget.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
namespace llvm {
// Forward declaration.
class GlobalValue;
class MipsTargetMachine;
struct MipsTargetAsmInfo : public ELFTargetAsmInfo {
explicit MipsTargetAsmInfo(const MipsTargetMachine &TM);
/// SectionKindForGlobal - This hook allows the target to select proper
/// section kind used for global emission.
virtual SectionKind::Kind
SectionKindForGlobal(const GlobalValue *GV) const;
/// SectionFlagsForGlobal - This hook allows the target to select proper
/// section flags either for given global or for section.
virtual unsigned
SectionFlagsForGlobal(const GlobalValue *GV = NULL,
const char* name = NULL) const;
virtual const Section* SelectSectionForGlobal(const GlobalValue *GV) const;
private:
const MipsSubtarget *Subtarget;
};
} // namespace llvm
#endif

View File

@ -1,442 +0,0 @@
//===-- PIC16AsmPrinter.cpp - PIC16 LLVM assembly writer ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to PIC16 assembly language.
//
//===----------------------------------------------------------------------===//
#include "PIC16AsmPrinter.h"
#include "PIC16TargetAsmInfo.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Mangler.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
using namespace llvm;
#include "PIC16GenAsmWriter.inc"
bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
printInstruction(MI);
return true;
}
/// runOnMachineFunction - This emits the frame section, autos section and
/// assembly for each instruction. Also takes care of function begin debug
/// directive and file begin debug directive (if required) for the function.
///
bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
this->MF = &MF;
// This calls the base class function required to be called at beginning
// of runOnMachineFunction.
SetupMachineFunction(MF);
// Get the mangled name.
const Function *F = MF.getFunction();
CurrentFnName = Mang->getValueName(F);
// Emit the function frame (args and temps).
EmitFunctionFrame(MF);
DbgInfo.BeginFunction(MF);
// Emit the autos section of function.
EmitAutos(CurrentFnName);
// Now emit the instructions of function in its code section.
const char *codeSection = PAN::getCodeSectionName(CurrentFnName).c_str();
const Section *fCodeSection = TAI->getNamedSection(codeSection,
SectionFlags::Code);
// Start the Code Section.
O << "\n";
SwitchToSection (fCodeSection);
// Emit the frame address of the function at the beginning of code.
O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
// Emit function start label.
O << CurrentFnName << ":\n";
DebugLoc CurDL;
O << "\n";
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
if (I != MF.begin()) {
printBasicBlockLabel(I, true);
O << '\n';
}
// Print a basic block.
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Emit the line directive if source line changed.
const DebugLoc DL = II->getDebugLoc();
if (!DL.isUnknown() && DL != CurDL) {
DbgInfo.ChangeDebugLoc(MF, DL);
CurDL = DL;
}
// Print the assembly for the instruction.
printMachineInstruction(II);
}
}
// Emit function end debug directives.
DbgInfo.EndFunction(MF);
return false; // we didn't modify anything.
}
/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description. This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
PIC16TargetMachine &tm,
bool verbose) {
return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
}
// printOperand - print operand of insn.
void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
const MachineOperand &MO = MI->getOperand(opNum);
switch (MO.getType()) {
case MachineOperand::MO_Register:
if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
else
assert(0 && "not implemented");
return;
case MachineOperand::MO_Immediate:
O << (int)MO.getImm();
return;
case MachineOperand::MO_GlobalAddress: {
O << Mang->getValueName(MO.getGlobal());
break;
}
case MachineOperand::MO_ExternalSymbol: {
const char *Sname = MO.getSymbolName();
// If its a libcall name, record it to decls section.
if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) {
LibcallDecls.push_back(Sname);
}
O << Sname;
break;
}
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB());
return;
default:
assert(0 && " Operand type not supported.");
}
}
/// printCCOperand - Print the cond code operand.
///
void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
int CC = (int)MI->getOperand(opNum).getImm();
O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
}
/// printLibcallDecls - print the extern declarations for compiler
/// intrinsics.
///
void PIC16AsmPrinter::printLibcallDecls(void) {
// If no libcalls used, return.
if (LibcallDecls.empty()) return;
O << TAI->getCommentString() << "External decls for libcalls - BEGIN." <<"\n";
// Remove duplicate entries.
LibcallDecls.sort();
LibcallDecls.unique();
for (std::list<const char*>::const_iterator I = LibcallDecls.begin();
I != LibcallDecls.end(); I++) {
O << TAI->getExternDirective() << *I << "\n";
O << TAI->getExternDirective() << PAN::getArgsLabel(*I) << "\n";
O << TAI->getExternDirective() << PAN::getRetvalLabel(*I) << "\n";
}
O << TAI->getCommentString() << "External decls for libcalls - END." <<"\n";
}
/// doInitialization - Perfrom Module level initializations here.
/// One task that we do here is to sectionize all global variables.
/// The MemSelOptimizer pass depends on the sectionizing.
///
bool PIC16AsmPrinter::doInitialization (Module &M) {
bool Result = AsmPrinter::doInitialization(M);
// FIXME:: This is temporary solution to generate the include file.
// The processor should be passed to llc as in input and the header file
// should be generated accordingly.
O << "\n\t#include P16F1937.INC\n";
// Set the section names for all globals.
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
I->setSection(TAI->SectionForGlobal(I)->getName());
}
DbgInfo.BeginModule(M);
EmitFunctionDecls(M);
EmitUndefinedVars(M);
EmitDefinedVars(M);
EmitIData(M);
EmitUData(M);
EmitRomData(M);
return Result;
}
/// Emit extern decls for functions imported from other modules, and emit
/// global declarations for function defined in this module and which are
/// available to other modules.
///
void PIC16AsmPrinter::EmitFunctionDecls (Module &M) {
// Emit declarations for external functions.
O <<"\n"<<TAI->getCommentString() << "Function Declarations - BEGIN." <<"\n";
for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
std::string Name = Mang->getValueName(I);
if (Name.compare("@abort") == 0)
continue;
// If it is llvm intrinsic call then don't emit
if (Name.find("llvm.") != std::string::npos)
continue;
if (! (I->isDeclaration() || I->hasExternalLinkage()))
continue;
const char *directive = I->isDeclaration() ? TAI->getExternDirective() :
TAI->getGlobalDirective();
O << directive << Name << "\n";
O << directive << PAN::getRetvalLabel(Name) << "\n";
O << directive << PAN::getArgsLabel(Name) << "\n";
}
O << TAI->getCommentString() << "Function Declarations - END." <<"\n";
}
// Emit variables imported from other Modules.
void PIC16AsmPrinter::EmitUndefinedVars (Module &M)
{
std::vector<const GlobalVariable*> Items = PTAI->ExternalVarDecls->Items;
if (! Items.size()) return;
O << "\n" << TAI->getCommentString() << "Imported Variables - BEGIN" << "\n";
for (unsigned j = 0; j < Items.size(); j++) {
O << TAI->getExternDirective() << Mang->getValueName(Items[j]) << "\n";
}
O << TAI->getCommentString() << "Imported Variables - END" << "\n";
}
// Emit variables defined in this module and are available to other modules.
void PIC16AsmPrinter::EmitDefinedVars (Module &M)
{
std::vector<const GlobalVariable*> Items = PTAI->ExternalVarDefs->Items;
if (! Items.size()) return;
O << "\n" << TAI->getCommentString() << "Exported Variables - BEGIN" << "\n";
for (unsigned j = 0; j < Items.size(); j++) {
O << TAI->getGlobalDirective() << Mang->getValueName(Items[j]) << "\n";
}
O << TAI->getCommentString() << "Exported Variables - END" << "\n";
}
// Emit initialized data placed in ROM.
void PIC16AsmPrinter::EmitRomData (Module &M)
{
std::vector<const GlobalVariable*> Items = PTAI->ROSection->Items;
if (! Items.size()) return;
// Print ROData ection.
O << "\n";
SwitchToSection(PTAI->ROSection->S_);
for (unsigned j = 0; j < Items.size(); j++) {
O << Mang->getValueName(Items[j]);
Constant *C = Items[j]->getInitializer();
int AddrSpace = Items[j]->getType()->getAddressSpace();
EmitGlobalConstant(C, AddrSpace);
}
}
bool PIC16AsmPrinter::doFinalization(Module &M) {
printLibcallDecls();
EmitRemainingAutos();
DbgInfo.EndModule(M);
O << "\n\t" << "END\n";
bool Result = AsmPrinter::doFinalization(M);
return Result;
}
void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
const Function *F = MF.getFunction();
std::string FuncName = Mang->getValueName(F);
const TargetData *TD = TM.getTargetData();
// Emit the data section name.
O << "\n";
const char *SectionName = PAN::getFrameSectionName(CurrentFnName).c_str();
const Section *fPDataSection = TAI->getNamedSection(SectionName,
SectionFlags::Writeable);
SwitchToSection(fPDataSection);
// Emit function frame label
O << PAN::getFrameLabel(CurrentFnName) << ":\n";
const Type *RetType = F->getReturnType();
unsigned RetSize = 0;
if (RetType->getTypeID() != Type::VoidTyID)
RetSize = TD->getTypeAllocSize(RetType);
//Emit function return value space
// FIXME: Do not emit RetvalLable when retsize is zero. To do this
// we will need to avoid printing a global directive for Retval label
// in emitExternandGloblas.
if(RetSize > 0)
O << PAN::getRetvalLabel(CurrentFnName) << " RES " << RetSize << "\n";
else
O << PAN::getRetvalLabel(CurrentFnName) << ": \n";
// Emit variable to hold the space for function arguments
unsigned ArgSize = 0;
for (Function::const_arg_iterator argi = F->arg_begin(),
arge = F->arg_end(); argi != arge ; ++argi) {
const Type *Ty = argi->getType();
ArgSize += TD->getTypeAllocSize(Ty);
}
O << PAN::getArgsLabel(CurrentFnName) << " RES " << ArgSize << "\n";
// Emit temporary space
int TempSize = PTLI->GetTmpSize();
if (TempSize > 0 )
O << PAN::getTempdataLabel(CurrentFnName) << " RES " << TempSize <<"\n";
}
void PIC16AsmPrinter::EmitIData (Module &M) {
// Print all IDATA sections.
std::vector <PIC16Section *>IDATASections = PTAI->IDATASections;
for (unsigned i = 0; i < IDATASections.size(); i++) {
O << "\n";
SwitchToSection(IDATASections[i]->S_);
std::vector<const GlobalVariable*> Items = IDATASections[i]->Items;
for (unsigned j = 0; j < Items.size(); j++) {
std::string Name = Mang->getValueName(Items[j]);
Constant *C = Items[j]->getInitializer();
int AddrSpace = Items[j]->getType()->getAddressSpace();
O << Name;
EmitGlobalConstant(C, AddrSpace);
}
}
}
void PIC16AsmPrinter::EmitUData (Module &M) {
const TargetData *TD = TM.getTargetData();
// Print all BSS sections.
std::vector <PIC16Section *>BSSSections = PTAI->BSSSections;
for (unsigned i = 0; i < BSSSections.size(); i++) {
O << "\n";
SwitchToSection(BSSSections[i]->S_);
std::vector<const GlobalVariable*> Items = BSSSections[i]->Items;
for (unsigned j = 0; j < Items.size(); j++) {
std::string Name = Mang->getValueName(Items[j]);
Constant *C = Items[j]->getInitializer();
const Type *Ty = C->getType();
unsigned Size = TD->getTypeAllocSize(Ty);
O << Name << " " <<"RES"<< " " << Size ;
O << "\n";
}
}
}
void PIC16AsmPrinter::EmitAutos (std::string FunctName)
{
// Section names for all globals are already set.
const TargetData *TD = TM.getTargetData();
// Now print Autos section for this function.
std::string SectionName = PAN::getAutosSectionName(FunctName);
std::vector <PIC16Section *>AutosSections = PTAI->AutosSections;
for (unsigned i = 0; i < AutosSections.size(); i++) {
O << "\n";
if (AutosSections[i]->S_->getName() == SectionName) {
// Set the printing status to true
AutosSections[i]->setPrintedStatus(true);
SwitchToSection(AutosSections[i]->S_);
std::vector<const GlobalVariable*> Items = AutosSections[i]->Items;
for (unsigned j = 0; j < Items.size(); j++) {
std::string VarName = Mang->getValueName(Items[j]);
Constant *C = Items[j]->getInitializer();
const Type *Ty = C->getType();
unsigned Size = TD->getTypeAllocSize(Ty);
// Emit memory reserve directive.
O << VarName << " RES " << Size << "\n";
}
break;
}
}
}
// Print autos that were not printed during the code printing of functions.
// As the functions might themselves would have got deleted by the optimizer.
void PIC16AsmPrinter::EmitRemainingAutos()
{
const TargetData *TD = TM.getTargetData();
// Now print Autos section for this function.
std::vector <PIC16Section *>AutosSections = PTAI->AutosSections;
for (unsigned i = 0; i < AutosSections.size(); i++) {
// if the section is already printed then don't print again
if (AutosSections[i]->isPrinted())
continue;
// Set status as printed
AutosSections[i]->setPrintedStatus(true);
O << "\n";
SwitchToSection(AutosSections[i]->S_);
std::vector<const GlobalVariable*> Items = AutosSections[i]->Items;
for (unsigned j = 0; j < Items.size(); j++) {
std::string VarName = Mang->getValueName(Items[j]);
Constant *C = Items[j]->getInitializer();
const Type *Ty = C->getType();
unsigned Size = TD->getTypeAllocSize(Ty);
// Emit memory reserve directive.
O << VarName << " RES " << Size << "\n";
}
}
}

View File

@ -1,70 +0,0 @@
//===-- PIC16AsmPrinter.h - PIC16 LLVM assembly writer ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to PIC16 assembly language.
//
//===----------------------------------------------------------------------===//
#ifndef PIC16ASMPRINTER_H
#define PIC16ASMPRINTER_H
#include "PIC16.h"
#include "PIC16TargetMachine.h"
#include "PIC16DebugInfo.h"
#include "llvm/Analysis/DebugInfo.h"
#include "PIC16TargetAsmInfo.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetMachine.h"
#include <list>
#include <string>
namespace llvm {
struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
explicit PIC16AsmPrinter(raw_ostream &O, PIC16TargetMachine &TM,
const TargetAsmInfo *T, bool V)
: AsmPrinter(O, TM, T, V), DbgInfo(O, T) {
PTLI = TM.getTargetLowering();
PTAI = static_cast<const PIC16TargetAsmInfo *> (T);
}
private :
virtual const char *getPassName() const {
return "PIC16 Assembly Printer";
}
bool runOnMachineFunction(MachineFunction &F);
void printOperand(const MachineInstr *MI, int opNum);
void printCCOperand(const MachineInstr *MI, int opNum);
bool printInstruction(const MachineInstr *MI); // definition autogenerated.
bool printMachineInstruction(const MachineInstr *MI);
void EmitFunctionDecls (Module &M);
void EmitUndefinedVars (Module &M);
void EmitDefinedVars (Module &M);
void EmitIData (Module &M);
void EmitUData (Module &M);
void EmitAutos (std::string FunctName);
void EmitRemainingAutos ();
void EmitRomData (Module &M);
void EmitFunctionFrame(MachineFunction &MF);
void printLibcallDecls(void);
protected:
bool doInitialization(Module &M);
bool doFinalization(Module &M);
private:
PIC16TargetLowering *PTLI;
PIC16DbgInfo DbgInfo;
const PIC16TargetAsmInfo *PTAI;
std::list<const char *> LibcallDecls; // List of extern decls.
};
} // end of namespace
#endif

View File

@ -1,264 +0,0 @@
//===-- PIC16TargetAsmInfo.cpp - PIC16 asm properties ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the PIC16TargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "PIC16TargetAsmInfo.h"
#include "PIC16TargetMachine.h"
#include "llvm/GlobalValue.h"
#include "llvm/GlobalVariable.h"
#include "llvm/DerivedTypes.h"
using namespace llvm;
PIC16TargetAsmInfo::
PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
: TargetAsmInfo(TM) {
CommentString = ";";
GlobalPrefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
GlobalDirective = "\tglobal\t";
ExternDirective = "\textern\t";
Data8bitsDirective = " db ";
Data16bitsDirective = " dw ";
Data32bitsDirective = " dl ";
RomData8bitsDirective = " dw ";
RomData16bitsDirective = " rom_di ";
RomData32bitsDirective = " rom_dl ";
ZeroDirective = NULL;
AsciiDirective = " dt ";
AscizDirective = NULL;
BSSSection_ = getNamedSection("udata.# UDATA",
SectionFlags::Writeable | SectionFlags::BSS);
ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None);
DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writeable);
SwitchToSectionDirective = "";
// Need because otherwise a .text symbol is emitted by DwarfWriter
// in BeginModule, and gpasm cribbs for that .text symbol.
TextSection = getUnnamedSection("", SectionFlags::Code);
ROSection = new PIC16Section(getReadOnlySection());
ExternalVarDecls = new PIC16Section(getNamedSection("ExternalVarDecls"));
ExternalVarDefs = new PIC16Section(getNamedSection("ExternalVarDefs"));
// Set it to false because we weed to generate c file name and not bc file
// name.
HasSingleParameterDotFile = false;
}
const char *PIC16TargetAsmInfo::getRomDirective(unsigned size) const
{
if (size == 8)
return RomData8bitsDirective;
else if (size == 16)
return RomData16bitsDirective;
else if (size == 32)
return RomData32bitsDirective;
else
return NULL;
}
const char *PIC16TargetAsmInfo::getASDirective(unsigned size,
unsigned AS) const {
if (AS == PIC16ISD::ROM_SPACE)
return getRomDirective(size);
else
return NULL;
}
const Section *
PIC16TargetAsmInfo::getBSSSectionForGlobal(const GlobalVariable *GV) const {
assert (GV->hasInitializer() && "This global doesn't need space");
Constant *C = GV->getInitializer();
assert (C->isNullValue() && "Unitialized globals has non-zero initializer");
// Find how much space this global needs.
const TargetData *TD = TM.getTargetData();
const Type *Ty = C->getType();
unsigned ValSize = TD->getTypeAllocSize(Ty);
// Go through all BSS Sections and assign this variable
// to the first available section having enough space.
PIC16Section *FoundBSS = NULL;
for (unsigned i = 0; i < BSSSections.size(); i++) {
if (DataBankSize - BSSSections[i]->Size >= ValSize) {
FoundBSS = BSSSections[i];
break;
}
}
// No BSS section spacious enough was found. Crate a new one.
if (! FoundBSS) {
std::string name = PAN::getUdataSectionName(BSSSections.size());
const Section *NewSection = getNamedSection (name.c_str());
FoundBSS = new PIC16Section(NewSection);
// Add this newly created BSS section to the list of BSSSections.
BSSSections.push_back(FoundBSS);
}
// Insert the GV into this BSS.
FoundBSS->Items.push_back(GV);
FoundBSS->Size += ValSize;
// We can't do this here because GV is const .
// const std::string SName = FoundBSS->S_->getName();
// GV->setSection(SName);
return FoundBSS->S_;
}
const Section *
PIC16TargetAsmInfo::getIDATASectionForGlobal(const GlobalVariable *GV) const {
assert (GV->hasInitializer() && "This global doesn't need space");
Constant *C = GV->getInitializer();
assert (!C->isNullValue() && "initialized globals has zero initializer");
assert (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
"can split initialized RAM data only");
// Find how much space this global needs.
const TargetData *TD = TM.getTargetData();
const Type *Ty = C->getType();
unsigned ValSize = TD->getTypeAllocSize(Ty);
// Go through all IDATA Sections and assign this variable
// to the first available section having enough space.
PIC16Section *FoundIDATA = NULL;
for (unsigned i = 0; i < IDATASections.size(); i++) {
if ( DataBankSize - IDATASections[i]->Size >= ValSize) {
FoundIDATA = IDATASections[i];
break;
}
}
// No IDATA section spacious enough was found. Crate a new one.
if (! FoundIDATA) {
std::string name = PAN::getIdataSectionName(IDATASections.size());
const Section *NewSection = getNamedSection (name.c_str());
FoundIDATA = new PIC16Section(NewSection);
// Add this newly created IDATA section to the list of IDATASections.
IDATASections.push_back(FoundIDATA);
}
// Insert the GV into this IDATA.
FoundIDATA->Items.push_back(GV);
FoundIDATA->Size += ValSize;
// We can't do this here because GV is const .
// GV->setSection(FoundIDATA->S->getName());
return FoundIDATA->S_;
}
// Get the section for an automatic variable of a function.
// For PIC16 they are globals only with mangled names.
const Section *
PIC16TargetAsmInfo::getSectionForAuto(const GlobalVariable *GV) const {
const std::string name = PAN::getSectionNameForSym(GV->getName());
// Go through all Auto Sections and assign this variable
// to the appropriate section.
PIC16Section *FoundAutoSec = NULL;
for (unsigned i = 0; i < AutosSections.size(); i++) {
if ( AutosSections[i]->S_->getName() == name) {
FoundAutoSec = AutosSections[i];
break;
}
}
// No Auto section was found. Crate a new one.
if (! FoundAutoSec) {
const Section *NewSection = getNamedSection (name.c_str());
FoundAutoSec = new PIC16Section(NewSection);
// Add this newly created autos section to the list of AutosSections.
AutosSections.push_back(FoundAutoSec);
}
// Insert the auto into this section.
FoundAutoSec->Items.push_back(GV);
return FoundAutoSec->S_;
}
// Override default implementation to put the true globals into
// multiple data sections if required.
const Section*
PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1) const {
// We select the section based on the initializer here, so it really
// has to be a GlobalVariable.
const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
if (!GV)
return TargetAsmInfo::SelectSectionForGlobal(GV1);
// Record Exteranl Var Decls.
if (GV->isDeclaration()) {
ExternalVarDecls->Items.push_back(GV);
return ExternalVarDecls->S_;
}
assert (GV->hasInitializer() && "A def without initializer?");
// First, if this is an automatic variable for a function, get the section
// name for it and return.
const std::string name = GV->getName();
if (PAN::isLocalName(name)) {
return getSectionForAuto(GV);
}
// Record Exteranl Var Defs.
if (GV->hasExternalLinkage() || GV->hasCommonLinkage()) {
ExternalVarDefs->Items.push_back(GV);
}
// See if this is an uninitialized global.
const Constant *C = GV->getInitializer();
if (C->isNullValue())
return getBSSSectionForGlobal(GV);
// If this is initialized data in RAM. Put it in the correct IDATA section.
if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
return getIDATASectionForGlobal(GV);
// This is initialized data in rom, put it in the readonly section.
if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) {
ROSection->Items.push_back(GV);
return ROSection->S_;
}
// Else let the default implementation take care of it.
return TargetAsmInfo::SelectSectionForGlobal(GV);
}
PIC16TargetAsmInfo::~PIC16TargetAsmInfo() {
for (unsigned i = 0; i < BSSSections.size(); i++) {
delete BSSSections[i];
}
for (unsigned i = 0; i < IDATASections.size(); i++) {
delete IDATASections[i];
}
for (unsigned i = 0; i < AutosSections.size(); i++) {
delete AutosSections[i];
}
delete ROSection;
delete ExternalVarDecls;
delete ExternalVarDefs;
}

View File

@ -1,83 +0,0 @@
//=====-- PIC16TargetAsmInfo.h - PIC16 asm properties ---------*- C++ -*--====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the PIC16TargetAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef PIC16TARGETASMINFO_H
#define PIC16TARGETASMINFO_H
#include "PIC16.h"
#include "llvm/Target/TargetAsmInfo.h"
#include <vector>
#include "llvm/Module.h"
#define DataBankSize 80
namespace llvm {
// Forward declaration.
class PIC16TargetMachine;
class GlobalVariable;
// PIC16 Splits the global data into mulitple udata and idata sections.
// Each udata and idata section needs to contain a list of globals that
// they contain, in order to avoid scanning over all the global values
// again and printing only those that match the current section.
// Keeping values inside the sections make printing a section much easier.
struct PIC16Section {
const Section *S_; // Connection to actual Section.
unsigned Size; // Total size of the objects contained.
bool SectionPrinted;
std::vector<const GlobalVariable*> Items;
PIC16Section (const Section *s) { S_ = s; Size = 0;
SectionPrinted = false;}
bool isPrinted() { return SectionPrinted ; }
void setPrintedStatus(bool status) { SectionPrinted = status ;}
};
struct PIC16TargetAsmInfo : public TargetAsmInfo {
std::string getSectionNameForSym(const std::string &Sym) const;
PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
mutable std::vector<PIC16Section *> BSSSections;
mutable std::vector<PIC16Section *> IDATASections;
mutable std::vector<PIC16Section *> AutosSections;
mutable PIC16Section *ROSection;
mutable PIC16Section *ExternalVarDecls;
mutable PIC16Section *ExternalVarDefs;
virtual ~PIC16TargetAsmInfo();
private:
const char *RomData8bitsDirective;
const char *RomData16bitsDirective;
const char *RomData32bitsDirective;
const char *getRomDirective(unsigned size) const;
virtual const char *getASDirective(unsigned size, unsigned AS) const;
const Section *getBSSSectionForGlobal(const GlobalVariable *GV) const;
const Section *getIDATASectionForGlobal(const GlobalVariable *GV) const;
const Section *getSectionForAuto(const GlobalVariable *GV) const;
virtual const Section *SelectSectionForGlobal(const GlobalValue *GV) const;
public:
void SetSectionForGVs(Module &M);
std::vector<PIC16Section *> getBSSSections() const {
return BSSSections;
}
std::vector<PIC16Section *> getIDATASections() const {
return IDATASections;
}
std::vector<PIC16Section *> getAutosSections() const {
return AutosSections;
}
};
} // namespace llvm
#endif

View File

@ -1,121 +0,0 @@
//===-- PPCTargetAsmInfo.cpp - PPC asm properties ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the DarwinTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "PPCTargetAsmInfo.h"
#include "PPCTargetMachine.h"
#include "llvm/Function.h"
#include "llvm/Support/Dwarf.h"
using namespace llvm;
using namespace llvm::dwarf;
PPCDarwinTargetAsmInfo::PPCDarwinTargetAsmInfo(const PPCTargetMachine &TM) :
PPCTargetAsmInfo<DarwinTargetAsmInfo>(TM) {
PCSymbol = ".";
CommentString = ";";
ConstantPoolSection = "\t.const\t";
UsedDirective = "\t.no_dead_strip\t";
SupportsExceptionHandling = true;
DwarfEHFrameSection =
".section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support";
DwarfExceptionSection = ".section __DATA,__gcc_except_tab";
GlobalEHDirective = "\t.globl\t";
SupportsWeakOmittedEHFrame = false;
}
/// PreferredEHDataFormat - This hook allows the target to select data
/// format used for encoding pointers in exception handling data. Reason is
/// 0 for data, 1 for code labels, 2 for function pointers. Global is true
/// if the symbol can be relocated.
unsigned
PPCDarwinTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const {
if (Reason == DwarfEncoding::Functions && Global)
return (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4);
else if (Reason == DwarfEncoding::CodeLabels || !Global)
return DW_EH_PE_pcrel;
else
return DW_EH_PE_absptr;
}
const char *
PPCDarwinTargetAsmInfo::getEHGlobalPrefix() const
{
const PPCSubtarget* Subtarget = &TM.getSubtarget<PPCSubtarget>();
if (Subtarget->getDarwinVers() > 9)
return PrivateGlobalPrefix;
else
return "";
}
PPCLinuxTargetAsmInfo::PPCLinuxTargetAsmInfo(const PPCTargetMachine &TM) :
PPCTargetAsmInfo<ELFTargetAsmInfo>(TM) {
CommentString = "#";
GlobalPrefix = "";
PrivateGlobalPrefix = ".L";
ConstantPoolSection = "\t.section .rodata.cst4\t";
JumpTableDataSection = ".section .rodata.cst4";
CStringSection = ".rodata.str";
StaticCtorsSection = ".section\t.ctors,\"aw\",@progbits";
StaticDtorsSection = ".section\t.dtors,\"aw\",@progbits";
UsedDirective = "\t# .no_dead_strip\t";
WeakRefDirective = "\t.weak\t";
BSSSection = "\t.section\t\".sbss\",\"aw\",@nobits";
// PPC/Linux normally uses named section for BSS.
BSSSection_ = getNamedSection("\t.bss",
SectionFlags::Writeable | SectionFlags::BSS,
/* Override */ true);
// Debug Information
AbsoluteDebugSectionOffsets = true;
SupportsDebugInformation = true;
DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"\",@progbits";
DwarfInfoSection = "\t.section\t.debug_info,\"\",@progbits";
DwarfLineSection = "\t.section\t.debug_line,\"\",@progbits";
DwarfFrameSection = "\t.section\t.debug_frame,\"\",@progbits";
DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"\",@progbits";
DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"\",@progbits";
DwarfStrSection = "\t.section\t.debug_str,\"\",@progbits";
DwarfLocSection = "\t.section\t.debug_loc,\"\",@progbits";
DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits";
DwarfRangesSection = "\t.section\t.debug_ranges,\"\",@progbits";
DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
PCSymbol = ".";
// Set up DWARF directives
HasLEB128 = true; // Target asm supports leb128 directives (little-endian)
// Exceptions handling
if (!TM.getSubtargetImpl()->isPPC64())
SupportsExceptionHandling = true;
AbsoluteEHSectionOffsets = false;
DwarfEHFrameSection = "\t.section\t.eh_frame,\"aw\",@progbits";
DwarfExceptionSection = "\t.section\t.gcc_except_table,\"a\",@progbits";
}
/// PreferredEHDataFormat - This hook allows the target to select data
/// format used for encoding pointers in exception handling data. Reason is
/// 0 for data, 1 for code labels, 2 for function pointers. Global is true
/// if the symbol can be relocated.
unsigned
PPCLinuxTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const {
// We really need to write something here.
return TargetAsmInfo::PreferredEHDataFormat(Reason, Global);
}
// Instantiate default implementation.
TEMPLATE_INSTANTIATION(class PPCTargetAsmInfo<TargetAsmInfo>);

View File

@ -1,62 +0,0 @@
//=====-- PPCTargetAsmInfo.h - PPC asm properties -------------*- C++ -*--====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the DarwinTargetAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef PPCTARGETASMINFO_H
#define PPCTARGETASMINFO_H
#include "PPCTargetMachine.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/DarwinTargetAsmInfo.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
template <class BaseTAI>
struct PPCTargetAsmInfo : public BaseTAI {
explicit PPCTargetAsmInfo(const PPCTargetMachine &TM):
BaseTAI(TM) {
const PPCSubtarget *Subtarget = &TM.getSubtarget<PPCSubtarget>();
bool isPPC64 = Subtarget->isPPC64();
BaseTAI::ZeroDirective = "\t.space\t";
BaseTAI::SetDirective = "\t.set";
BaseTAI::Data64bitsDirective = isPPC64 ? "\t.quad\t" : 0;
BaseTAI::AlignmentIsInBytes = false;
BaseTAI::LCOMMDirective = "\t.lcomm\t";
BaseTAI::InlineAsmStart = "# InlineAsm Start";
BaseTAI::InlineAsmEnd = "# InlineAsm End";
BaseTAI::AssemblerDialect = Subtarget->getAsmFlavor();
}
};
typedef PPCTargetAsmInfo<TargetAsmInfo> PPCGenericTargetAsmInfo;
EXTERN_TEMPLATE_INSTANTIATION(class PPCTargetAsmInfo<TargetAsmInfo>);
struct PPCDarwinTargetAsmInfo : public PPCTargetAsmInfo<DarwinTargetAsmInfo> {
explicit PPCDarwinTargetAsmInfo(const PPCTargetMachine &TM);
virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const;
virtual const char *getEHGlobalPrefix() const;
};
struct PPCLinuxTargetAsmInfo : public PPCTargetAsmInfo<ELFTargetAsmInfo> {
explicit PPCLinuxTargetAsmInfo(const PPCTargetMachine &TM);
virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const;
};
} // namespace llvm
#endif

View File

@ -1,50 +0,0 @@
//===-- SparcTargetAsmInfo.cpp - Sparc asm properties -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the SparcTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "SparcTargetAsmInfo.h"
using namespace llvm;
SparcELFTargetAsmInfo::SparcELFTargetAsmInfo(const TargetMachine &TM):
ELFTargetAsmInfo(TM) {
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
Data64bitsDirective = 0; // .xword is only supported by V9.
ZeroDirective = "\t.skip\t";
CommentString = "!";
ConstantPoolSection = "\t.section \".rodata\",#alloc\n";
COMMDirectiveTakesAlignment = true;
CStringSection=".rodata.str";
// Sparc normally uses named section for BSS.
BSSSection_ = getNamedSection("\t.bss",
SectionFlags::Writeable | SectionFlags::BSS,
/* Override */ true);
}
std::string SparcELFTargetAsmInfo::printSectionFlags(unsigned flags) const {
if (flags & SectionFlags::Mergeable)
return ELFTargetAsmInfo::printSectionFlags(flags);
std::string Flags;
if (!(flags & SectionFlags::Debug))
Flags += ",#alloc";
if (flags & SectionFlags::Code)
Flags += ",#execinstr";
if (flags & SectionFlags::Writeable)
Flags += ",#write";
if (flags & SectionFlags::TLS)
Flags += ",#tls";
return Flags;
}

View File

@ -1,33 +0,0 @@
//=====-- SparcTargetAsmInfo.h - Sparc asm properties ---------*- C++ -*--====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the SparcTargetAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef SPARCTARGETASMINFO_H
#define SPARCTARGETASMINFO_H
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
namespace llvm {
// Forward declaration.
class TargetMachine;
struct SparcELFTargetAsmInfo : public ELFTargetAsmInfo {
explicit SparcELFTargetAsmInfo(const TargetMachine &TM);
std::string printSectionFlags(unsigned flags) const;
};
} // namespace llvm
#endif

View File

@ -1,456 +0,0 @@
//===-- TargetAsmInfo.cpp - Asm Info ---------------------------------------==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target asm properties related what form asm statements
// should take.
//
//===----------------------------------------------------------------------===//
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Dwarf.h"
#include <cctype>
#include <cstring>
using namespace llvm;
TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm)
: TM(tm) {
BSSSection = "\t.bss";
BSSSection_ = 0;
ReadOnlySection = 0;
SmallDataSection = 0;
SmallBSSSection = 0;
SmallRODataSection = 0;
TLSDataSection = 0;
TLSBSSSection = 0;
ZeroFillDirective = 0;
NonexecutableStackDirective = 0;
NeedsSet = false;
MaxInstLength = 4;
PCSymbol = "$";
SeparatorChar = ';';
CommentString = "#";
GlobalPrefix = "";
PrivateGlobalPrefix = ".";
LessPrivateGlobalPrefix = "";
JumpTableSpecialLabelPrefix = 0;
GlobalVarAddrPrefix = "";
GlobalVarAddrSuffix = "";
FunctionAddrPrefix = "";
FunctionAddrSuffix = "";
PersonalityPrefix = "";
PersonalitySuffix = "";
NeedsIndirectEncoding = false;
InlineAsmStart = "#APP";
InlineAsmEnd = "#NO_APP";
AssemblerDialect = 0;
StringConstantPrefix = ".str";
AllowQuotesInName = false;
ZeroDirective = "\t.zero\t";
ZeroDirectiveSuffix = 0;
AsciiDirective = "\t.ascii\t";
AscizDirective = "\t.asciz\t";
Data8bitsDirective = "\t.byte\t";
Data16bitsDirective = "\t.short\t";
Data32bitsDirective = "\t.long\t";
Data64bitsDirective = "\t.quad\t";
AlignDirective = "\t.align\t";
AlignmentIsInBytes = true;
TextAlignFillValue = 0;
SwitchToSectionDirective = "\t.section\t";
TextSectionStartSuffix = "";
DataSectionStartSuffix = "";
SectionEndDirectiveSuffix = 0;
ConstantPoolSection = "\t.section .rodata";
JumpTableDataSection = "\t.section .rodata";
JumpTableDirective = 0;
CStringSection = 0;
CStringSection_ = 0;
// FIXME: Flags are ELFish - replace with normal section stuff.
StaticCtorsSection = "\t.section .ctors,\"aw\",@progbits";
StaticDtorsSection = "\t.section .dtors,\"aw\",@progbits";
GlobalDirective = "\t.globl\t";
SetDirective = 0;
LCOMMDirective = 0;
COMMDirective = "\t.comm\t";
COMMDirectiveTakesAlignment = true;
HasDotTypeDotSizeDirective = true;
HasSingleParameterDotFile = true;
UsedDirective = 0;
WeakRefDirective = 0;
WeakDefDirective = 0;
// FIXME: These are ELFish - move to ELFTAI.
HiddenDirective = "\t.hidden\t";
ProtectedDirective = "\t.protected\t";
AbsoluteDebugSectionOffsets = false;
AbsoluteEHSectionOffsets = false;
HasLEB128 = false;
HasDotLocAndDotFile = false;
SupportsDebugInformation = false;
SupportsExceptionHandling = false;
DwarfRequiresFrameSection = true;
DwarfUsesInlineInfoSection = false;
NonLocalEHFrameLabel = false;
GlobalEHDirective = 0;
SupportsWeakOmittedEHFrame = true;
DwarfSectionOffsetDirective = 0;
DwarfAbbrevSection = ".debug_abbrev";
DwarfInfoSection = ".debug_info";
DwarfLineSection = ".debug_line";
DwarfFrameSection = ".debug_frame";
DwarfPubNamesSection = ".debug_pubnames";
DwarfPubTypesSection = ".debug_pubtypes";
DwarfDebugInlineSection = ".debug_inlined";
DwarfStrSection = ".debug_str";
DwarfLocSection = ".debug_loc";
DwarfARangesSection = ".debug_aranges";
DwarfRangesSection = ".debug_ranges";
DwarfMacroInfoSection = ".debug_macinfo";
DwarfEHFrameSection = ".eh_frame";
DwarfExceptionSection = ".gcc_except_table";
AsmTransCBE = 0;
TextSection = getUnnamedSection("\t.text", SectionFlags::Code);
DataSection = getUnnamedSection("\t.data", SectionFlags::Writeable);
}
TargetAsmInfo::~TargetAsmInfo() {
}
/// Measure the specified inline asm to determine an approximation of its
/// length.
/// Comments (which run till the next SeparatorChar or newline) do not
/// count as an instruction.
/// Any other non-whitespace text is considered an instruction, with
/// multiple instructions separated by SeparatorChar or newlines.
/// Variable-length instructions are not handled here; this function
/// may be overloaded in the target code to do that.
unsigned TargetAsmInfo::getInlineAsmLength(const char *Str) const {
// Count the number of instructions in the asm.
bool atInsnStart = true;
unsigned Length = 0;
for (; *Str; ++Str) {
if (*Str == '\n' || *Str == SeparatorChar)
atInsnStart = true;
if (atInsnStart && !isspace(*Str)) {
Length += MaxInstLength;
atInsnStart = false;
}
if (atInsnStart && strncmp(Str, CommentString, strlen(CommentString))==0)
atInsnStart = false;
}
return Length;
}
unsigned TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const {
return dwarf::DW_EH_PE_absptr;
}
static bool isSuitableForBSS(const GlobalVariable *GV) {
if (!GV->hasInitializer())
return true;
// Leave constant zeros in readonly constant sections, so they can be shared
Constant *C = GV->getInitializer();
return (C->isNullValue() && !GV->isConstant() && !NoZerosInBSS);
}
static bool isConstantString(const Constant *C) {
// First check: is we have constant array of i8 terminated with zero
const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
// Check, if initializer is a null-terminated string
if (CVA && CVA->isCString())
return true;
// Another possibility: [1 x i8] zeroinitializer
if (isa<ConstantAggregateZero>(C)) {
if (const ArrayType *Ty = dyn_cast<ArrayType>(C->getType())) {
return (Ty->getElementType() == Type::Int8Ty &&
Ty->getNumElements() == 1);
}
}
return false;
}
unsigned TargetAsmInfo::RelocBehaviour() const {
// By default - all relocations in PIC mode would force symbol to be
// placed in r/w section.
return (TM.getRelocationModel() != Reloc::Static ?
Reloc::LocalOrGlobal : Reloc::None);
}
SectionKind::Kind
TargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const {
// Early exit - functions should be always in text sections.
if (isa<Function>(GV))
return SectionKind::Text;
const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV);
bool isThreadLocal = GVar->isThreadLocal();
assert(GVar && "Invalid global value for section selection");
if (isSuitableForBSS(GVar)) {
// Variable can be easily put to BSS section.
return (isThreadLocal ? SectionKind::ThreadBSS : SectionKind::BSS);
} else if (GVar->isConstant() && !isThreadLocal) {
// Now we know, that varible has initializer and it is constant. We need to
// check its initializer to decide, which section to output it into. Also
// note, there is no thread-local r/o section.
Constant *C = GVar->getInitializer();
if (C->ContainsRelocations(Reloc::LocalOrGlobal)) {
// Decide, whether it is still possible to put symbol into r/o section.
unsigned Reloc = RelocBehaviour();
// We already did a query for 'all' relocs, thus - early exits.
if (Reloc == Reloc::LocalOrGlobal)
return SectionKind::Data;
else if (Reloc == Reloc::None)
return SectionKind::ROData;
else {
// Ok, target wants something funny. Honour it.
return (C->ContainsRelocations(Reloc) ?
SectionKind::Data : SectionKind::ROData);
}
} else {
// Check, if initializer is a null-terminated string
if (isConstantString(C))
return SectionKind::RODataMergeStr;
else
return SectionKind::RODataMergeConst;
}
}
// Variable either is not constant or thread-local - output to data section.
return (isThreadLocal ? SectionKind::ThreadData : SectionKind::Data);
}
unsigned
TargetAsmInfo::SectionFlagsForGlobal(const GlobalValue *GV,
const char* Name) const {
unsigned Flags = SectionFlags::None;
// Decode flags from global itself.
if (GV) {
SectionKind::Kind Kind = SectionKindForGlobal(GV);
switch (Kind) {
case SectionKind::Text:
Flags |= SectionFlags::Code;
break;
case SectionKind::ThreadData:
case SectionKind::ThreadBSS:
Flags |= SectionFlags::TLS;
// FALLS THROUGH
case SectionKind::Data:
case SectionKind::DataRel:
case SectionKind::DataRelLocal:
case SectionKind::DataRelRO:
case SectionKind::DataRelROLocal:
case SectionKind::BSS:
Flags |= SectionFlags::Writeable;
break;
case SectionKind::ROData:
case SectionKind::RODataMergeStr:
case SectionKind::RODataMergeConst:
// No additional flags here
break;
case SectionKind::SmallData:
case SectionKind::SmallBSS:
Flags |= SectionFlags::Writeable;
// FALLS THROUGH
case SectionKind::SmallROData:
Flags |= SectionFlags::Small;
break;
default:
assert(0 && "Unexpected section kind!");
}
if (GV->isWeakForLinker())
Flags |= SectionFlags::Linkonce;
}
// Add flags from sections, if any.
if (Name && *Name) {
Flags |= SectionFlags::Named;
// Some lame default implementation based on some magic section names.
if (strncmp(Name, ".gnu.linkonce.b.", 16) == 0 ||
strncmp(Name, ".llvm.linkonce.b.", 17) == 0 ||
strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 ||
strncmp(Name, ".llvm.linkonce.sb.", 18) == 0)
Flags |= SectionFlags::BSS;
else if (strcmp(Name, ".tdata") == 0 ||
strncmp(Name, ".tdata.", 7) == 0 ||
strncmp(Name, ".gnu.linkonce.td.", 17) == 0 ||
strncmp(Name, ".llvm.linkonce.td.", 18) == 0)
Flags |= SectionFlags::TLS;
else if (strcmp(Name, ".tbss") == 0 ||
strncmp(Name, ".tbss.", 6) == 0 ||
strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 ||
strncmp(Name, ".llvm.linkonce.tb.", 18) == 0)
Flags |= SectionFlags::BSS | SectionFlags::TLS;
}
return Flags;
}
const Section*
TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
const Section* S;
// Select section name
if (GV->hasSection()) {
// Honour section already set, if any
unsigned Flags = SectionFlagsForGlobal(GV,
GV->getSection().c_str());
S = getNamedSection(GV->getSection().c_str(), Flags);
} else {
// Use default section depending on the 'type' of global
S = SelectSectionForGlobal(GV);
}
return S;
}
// Lame default implementation. Calculate the section name for global.
const Section*
TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
SectionKind::Kind Kind = SectionKindForGlobal(GV);
if (GV->isWeakForLinker()) {
std::string Name = UniqueSectionForGlobal(GV, Kind);
unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str());
return getNamedSection(Name.c_str(), Flags);
} else {
if (Kind == SectionKind::Text)
return getTextSection();
else if (isBSS(Kind) && getBSSSection_())
return getBSSSection_();
else if (getReadOnlySection() && SectionKind::isReadOnly(Kind))
return getReadOnlySection();
}
return getDataSection();
}
// Lame default implementation. Calculate the section name for machine const.
const Section*
TargetAsmInfo::SelectSectionForMachineConst(const Type *Ty) const {
// FIXME: Support data.rel stuff someday
return getDataSection();
}
std::string
TargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV,
SectionKind::Kind Kind) const {
switch (Kind) {
case SectionKind::Text:
return ".gnu.linkonce.t." + GV->getName();
case SectionKind::Data:
return ".gnu.linkonce.d." + GV->getName();
case SectionKind::DataRel:
return ".gnu.linkonce.d.rel" + GV->getName();
case SectionKind::DataRelLocal:
return ".gnu.linkonce.d.rel.local" + GV->getName();
case SectionKind::DataRelRO:
return ".gnu.linkonce.d.rel.ro" + GV->getName();
case SectionKind::DataRelROLocal:
return ".gnu.linkonce.d.rel.ro.local" + GV->getName();
case SectionKind::SmallData:
return ".gnu.linkonce.s." + GV->getName();
case SectionKind::BSS:
return ".gnu.linkonce.b." + GV->getName();
case SectionKind::SmallBSS:
return ".gnu.linkonce.sb." + GV->getName();
case SectionKind::ROData:
case SectionKind::RODataMergeConst:
case SectionKind::RODataMergeStr:
return ".gnu.linkonce.r." + GV->getName();
case SectionKind::SmallROData:
return ".gnu.linkonce.s2." + GV->getName();
case SectionKind::ThreadData:
return ".gnu.linkonce.td." + GV->getName();
case SectionKind::ThreadBSS:
return ".gnu.linkonce.tb." + GV->getName();
default:
assert(0 && "Unknown section kind");
}
return NULL;
}
const Section*
TargetAsmInfo::getNamedSection(const char *Name, unsigned Flags,
bool Override) const {
Section& S = Sections[Name];
// This is newly-created section, set it up properly.
if (S.Flags == SectionFlags::Invalid || Override) {
S.Flags = Flags | SectionFlags::Named;
S.Name = Name;
}
return &S;
}
const Section*
TargetAsmInfo::getUnnamedSection(const char *Directive, unsigned Flags,
bool Override) const {
Section& S = Sections[Directive];
// This is newly-created section, set it up properly.
if (S.Flags == SectionFlags::Invalid || Override) {
S.Flags = Flags & ~SectionFlags::Named;
S.Name = Directive;
}
return &S;
}
const std::string&
TargetAsmInfo::getSectionFlags(unsigned Flags) const {
SectionFlags::FlagsStringsMapType::iterator I = FlagsStrings.find(Flags);
// We didn't print these flags yet, print and save them to map. This reduces
// amount of heap trashing due to std::string construction / concatenation.
if (I == FlagsStrings.end())
I = FlagsStrings.insert(std::make_pair(Flags,
printSectionFlags(Flags))).first;
return I->second;
}
unsigned TargetAsmInfo::getULEB128Size(unsigned Value) {
unsigned Size = 0;
do {
Value >>= 7;
Size += sizeof(int8_t);
} while (Value);
return Size;
}
unsigned TargetAsmInfo::getSLEB128Size(int Value) {
unsigned Size = 0;
int Sign = Value >> (8 * sizeof(Value) - 1);
bool IsMore;
do {
unsigned Byte = Value & 0x7f;
Value >>= 7;
IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
Size += sizeof(int8_t);
} while (IsMore);
return Size;
}

View File

@ -1,78 +0,0 @@
//===-- TargetMachineRegistry.cpp - Target Auto Registration Impl ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file exposes the RegisterTarget class, which TargetMachine
// implementations should use to register themselves with the system. This file
// also exposes the TargetMachineRegistry class, which allows tools to inspect
// all of registered targets.
//
//===----------------------------------------------------------------------===//
#include "llvm/Target/TargetMachineRegistry.h"
#include <algorithm>
using namespace llvm;
/// getClosestStaticTargetForModule - Given an LLVM module, pick the best target
/// that is compatible with the module. If no close target can be found, this
/// returns null and sets the Error string to a reason.
const TargetMachineRegistry::entry *
TargetMachineRegistry::getClosestStaticTargetForModule(const Module &M,
std::string &Error) {
std::vector<std::pair<unsigned, const entry *> > UsableTargets;
for (Registry<TargetMachine>::iterator I = begin(), E = end(); I != E; ++I)
if (unsigned Qual = I->ModuleMatchQualityFn(M))
UsableTargets.push_back(std::make_pair(Qual, &*I));
if (UsableTargets.empty()) {
Error = "No available targets are compatible with this module";
return 0;
} else if (UsableTargets.size() == 1)
return UsableTargets.back().second;
// Otherwise, take the best target, but make sure we don't have two equally
// good best targets.
std::sort(UsableTargets.begin(), UsableTargets.end());
if (UsableTargets.back().first ==UsableTargets[UsableTargets.size()-2].first){
Error = "Cannot choose between targets \"" +
std::string(UsableTargets.back().second->Name) + "\" and \"" +
std::string(UsableTargets[UsableTargets.size()-2].second->Name) + "\"";
return 0;
}
return UsableTargets.back().second;
}
/// getClosestTargetForJIT - Pick the best target that is compatible with
/// the current host. If no close target can be found, this returns null
/// and sets the Error string to a reason.
const TargetMachineRegistry::entry *
TargetMachineRegistry::getClosestTargetForJIT(std::string &Error) {
std::vector<std::pair<unsigned, const entry *> > UsableTargets;
for (Registry<TargetMachine>::iterator I = begin(), E = end(); I != E; ++I)
if (unsigned Qual = I->JITMatchQualityFn())
UsableTargets.push_back(std::make_pair(Qual, &*I));
if (UsableTargets.empty()) {
Error = "No JIT is available for this host";
return 0;
} else if (UsableTargets.size() == 1)
return UsableTargets.back().second;
// Otherwise, take the best target. If there is a tie, just pick one.
unsigned MaxQual = UsableTargets.front().first;
const entry *MaxQualTarget = UsableTargets.front().second;
for (unsigned i = 1, e = UsableTargets.size(); i != e; ++i)
if (UsableTargets[i].first > MaxQual) {
MaxQual = UsableTargets[i].first;
MaxQualTarget = UsableTargets[i].second;
}
return MaxQualTarget;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,226 +0,0 @@
//===-- X86ATTAsmPrinter.h - Convert X86 LLVM code to AT&T assembly -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// AT&T assembly code printer class.
//
//===----------------------------------------------------------------------===//
#ifndef X86ATTASMPRINTER_H
#define X86ATTASMPRINTER_H
#include "../X86.h"
#include "../X86MachineFunctionInfo.h"
#include "../X86TargetMachine.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
class MachineJumpTableInfo;
class MCContext;
class MCInst;
class MCStreamer;
class VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter {
const X86Subtarget *Subtarget;
MCContext *Context;
MCStreamer *Streamer;
public:
explicit X86ATTAsmPrinter(raw_ostream &O, X86TargetMachine &TM,
const TargetAsmInfo *T, bool V)
: AsmPrinter(O, TM, T, V) {
Subtarget = &TM.getSubtarget<X86Subtarget>();
Context = 0;
Streamer = 0;
}
virtual const char *getPassName() const {
return "X86 AT&T-Style Assembly Printer";
}
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
if (Subtarget->isTargetDarwin() ||
Subtarget->isTargetELF() ||
Subtarget->isTargetCygMing()) {
AU.addRequired<MachineModuleInfo>();
}
AU.addRequired<DwarfWriter>();
AsmPrinter::getAnalysisUsage(AU);
}
bool doInitialization(Module &M);
bool doFinalization(Module &M);
/// printInstruction - This method is automatically generated by tablegen
/// from the instruction set description. This method returns true if the
/// machine instruction was sufficiently described to print it, otherwise it
/// returns false.
bool printInstruction(const MachineInstr *MI);
// New MCInst printing stuff.
bool printInstruction(const MCInst *MI);
void printOperand(const MCInst *MI, unsigned OpNo,
const char *Modifier = 0);
void printMemReference(const MCInst *MI, unsigned Op);
void printLeaMemReference(const MCInst *MI, unsigned Op);
void printSSECC(const MCInst *MI, unsigned Op);
void printPICLabel(const MCInst *MI, unsigned Op);
void print_pcrel_imm(const MCInst *MI, unsigned OpNo);
void printi8mem(const MCInst *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printi16mem(const MCInst *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printi32mem(const MCInst *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printi64mem(const MCInst *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printi128mem(const MCInst *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printf32mem(const MCInst *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printf64mem(const MCInst *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printf80mem(const MCInst *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printf128mem(const MCInst *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printlea32mem(const MCInst *MI, unsigned OpNo) {
printLeaMemReference(MI, OpNo);
}
void printlea64mem(const MCInst *MI, unsigned OpNo) {
printLeaMemReference(MI, OpNo);
}
void printlea64_32mem(const MCInst *MI, unsigned OpNo) {
printLeaMemReference(MI, OpNo);
}
// These methods are used by the tablegen'erated instruction printer.
void printOperand(const MachineInstr *MI, unsigned OpNo,
const char *Modifier = 0);
void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo);
void printi8mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printi16mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printi32mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printi64mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printi128mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printi256mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printf32mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printf64mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printf80mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printf128mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printf256mem(const MachineInstr *MI, unsigned OpNo) {
printMemReference(MI, OpNo);
}
void printlea32mem(const MachineInstr *MI, unsigned OpNo) {
printLeaMemReference(MI, OpNo);
}
void printlea64mem(const MachineInstr *MI, unsigned OpNo) {
printLeaMemReference(MI, OpNo);
}
void printlea64_32mem(const MachineInstr *MI, unsigned OpNo) {
printLeaMemReference(MI, OpNo, "subreg64");
}
bool printAsmMRegister(const MachineOperand &MO, char Mode);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
void printMachineInstruction(const MachineInstr *MI);
void printSSECC(const MachineInstr *MI, unsigned Op);
void printMemReference(const MachineInstr *MI, unsigned Op,
const char *Modifier=NULL);
void printLeaMemReference(const MachineInstr *MI, unsigned Op,
const char *Modifier=NULL);
void printPICJumpTableSetLabel(unsigned uid,
const MachineBasicBlock *MBB) const;
void printPICJumpTableSetLabel(unsigned uid, unsigned uid2,
const MachineBasicBlock *MBB) const {
AsmPrinter::printPICJumpTableSetLabel(uid, uid2, MBB);
}
void printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
const MachineBasicBlock *MBB,
unsigned uid) const;
void printPICLabel(const MachineInstr *MI, unsigned Op);
void printModuleLevelGV(const GlobalVariable* GVar);
void PrintPICBaseSymbol() const;
bool runOnMachineFunction(MachineFunction &F);
void emitFunctionHeader(const MachineFunction &MF);
// Necessary for Darwin to print out the apprioriate types of linker stubs
StringSet<> FnStubs, GVStubs, HiddenGVStubs;
// Necessary for dllexport support
StringSet<> DLLExportedFns, DLLExportedGVs;
// We have to propagate some information about MachineFunction to
// AsmPrinter. It's ok, when we're printing the function, since we have
// access to MachineFunction and can get the appropriate MachineFunctionInfo.
// Unfortunately, this is not possible when we're printing reference to
// Function (e.g. calling it and so on). Even more, there is no way to get the
// corresponding MachineFunctions: it can even be not created at all. That's
// why we should use additional structure, when we're collecting all necessary
// information.
//
// This structure is using e.g. for name decoration for stdcall & fastcall'ed
// function, since we have to use arguments' size for decoration.
typedef std::map<const Function*, X86MachineFunctionInfo> FMFInfoMap;
FMFInfoMap FunctionInfoMap;
void decorateName(std::string& Name, const GlobalValue* GV);
};
} // end namespace llvm
#endif

View File

@ -1,633 +0,0 @@
//===-- X86IntelAsmPrinter.cpp - Convert X86 LLVM code to Intel assembly --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to Intel format assembly language.
// This printer is the output mechanism used by `llc'.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "X86IntelAsmPrinter.h"
#include "X86InstrInfo.h"
#include "X86TargetAsmInfo.h"
#include "X86.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
static X86MachineFunctionInfo calculateFunctionInfo(const Function *F,
const TargetData *TD) {
X86MachineFunctionInfo Info;
uint64_t Size = 0;
switch (F->getCallingConv()) {
case CallingConv::X86_StdCall:
Info.setDecorationStyle(StdCall);
break;
case CallingConv::X86_FastCall:
Info.setDecorationStyle(FastCall);
break;
default:
return Info;
}
unsigned argNum = 1;
for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
AI != AE; ++AI, ++argNum) {
const Type* Ty = AI->getType();
// 'Dereference' type in case of byval parameter attribute
if (F->paramHasAttr(argNum, Attribute::ByVal))
Ty = cast<PointerType>(Ty)->getElementType();
// Size should be aligned to DWORD boundary
Size += ((TD->getTypeAllocSize(Ty) + 3)/4)*4;
}
// We're not supporting tooooo huge arguments :)
Info.setBytesToPopOnReturn((unsigned int)Size);
return Info;
}
/// decorateName - Query FunctionInfoMap and use this information for various
/// name decoration.
void X86IntelAsmPrinter::decorateName(std::string &Name,
const GlobalValue *GV) {
const Function *F = dyn_cast<Function>(GV);
if (!F) return;
// We don't want to decorate non-stdcall or non-fastcall functions right now
unsigned CC = F->getCallingConv();
if (CC != CallingConv::X86_StdCall && CC != CallingConv::X86_FastCall)
return;
FMFInfoMap::const_iterator info_item = FunctionInfoMap.find(F);
const X86MachineFunctionInfo *Info;
if (info_item == FunctionInfoMap.end()) {
// Calculate apropriate function info and populate map
FunctionInfoMap[F] = calculateFunctionInfo(F, TM.getTargetData());
Info = &FunctionInfoMap[F];
} else {
Info = &info_item->second;
}
const FunctionType *FT = F->getFunctionType();
switch (Info->getDecorationStyle()) {
case None:
break;
case StdCall:
// "Pure" variadic functions do not receive @0 suffix.
if (!FT->isVarArg() || (FT->getNumParams() == 0) ||
(FT->getNumParams() == 1 && F->hasStructRetAttr()))
Name += '@' + utostr_32(Info->getBytesToPopOnReturn());
break;
case FastCall:
// "Pure" variadic functions do not receive @0 suffix.
if (!FT->isVarArg() || (FT->getNumParams() == 0) ||
(FT->getNumParams() == 1 && F->hasStructRetAttr()))
Name += '@' + utostr_32(Info->getBytesToPopOnReturn());
if (Name[0] == '_')
Name[0] = '@';
else
Name = '@' + Name;
break;
default:
assert(0 && "Unsupported DecorationStyle");
}
}
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
this->MF = &MF;
SetupMachineFunction(MF);
O << "\n\n";
// Print out constants referenced by the function
EmitConstantPool(MF.getConstantPool());
// Print out labels for the function.
const Function *F = MF.getFunction();
unsigned CC = F->getCallingConv();
unsigned FnAlign = MF.getAlignment();
// Populate function information map. Actually, We don't want to populate
// non-stdcall or non-fastcall functions' information right now.
if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall)
FunctionInfoMap[F] = *MF.getInfo<X86MachineFunctionInfo>();
decorateName(CurrentFnName, F);
SwitchToTextSection("_text", F);
switch (F->getLinkage()) {
default: assert(0 && "Unsupported linkage type!");
case Function::PrivateLinkage:
case Function::InternalLinkage:
EmitAlignment(FnAlign);
break;
case Function::DLLExportLinkage:
DLLExportedFns.insert(CurrentFnName);
//FALLS THROUGH
case Function::ExternalLinkage:
O << "\tpublic " << CurrentFnName << "\n";
EmitAlignment(FnAlign);
break;
}
O << CurrentFnName << "\tproc near\n";
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block if there are any predecessors.
if (!I->pred_empty()) {
printBasicBlockLabel(I, true, true);
O << '\n';
}
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
printMachineInstruction(II);
}
}
// Print out jump tables referenced by the function.
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
O << CurrentFnName << "\tendp\n";
O.flush();
// We didn't modify anything.
return false;
}
void X86IntelAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
unsigned char value = MI->getOperand(Op).getImm();
assert(value <= 7 && "Invalid ssecc argument!");
switch (value) {
case 0: O << "eq"; break;
case 1: O << "lt"; break;
case 2: O << "le"; break;
case 3: O << "unord"; break;
case 4: O << "neq"; break;
case 5: O << "nlt"; break;
case 6: O << "nle"; break;
case 7: O << "ord"; break;
}
}
void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
const char *Modifier) {
switch (MO.getType()) {
case MachineOperand::MO_Register: {
if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) {
unsigned Reg = MO.getReg();
if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
MVT VT = (strcmp(Modifier,"subreg64") == 0) ?
MVT::i64 : ((strcmp(Modifier, "subreg32") == 0) ? MVT::i32 :
((strcmp(Modifier,"subreg16") == 0) ? MVT::i16 :MVT::i8));
Reg = getX86SubSuperRegister(Reg, VT);
}
O << TRI->getName(Reg);
} else
O << "reg" << MO.getReg();
return;
}
case MachineOperand::MO_Immediate:
O << MO.getImm();
return;
case MachineOperand::MO_JumpTableIndex: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
if (!isMemOp) O << "OFFSET ";
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< "_" << MO.getIndex();
return;
}
case MachineOperand::MO_ConstantPoolIndex: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
if (!isMemOp) O << "OFFSET ";
O << "[" << TAI->getPrivateGlobalPrefix() << "CPI"
<< getFunctionNumber() << "_" << MO.getIndex();
printOffset(MO.getOffset());
O << "]";
return;
}
case MachineOperand::MO_GlobalAddress: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
GlobalValue *GV = MO.getGlobal();
std::string Name = Mang->getValueName(GV);
decorateName(Name, GV);
if (!isMemOp) O << "OFFSET ";
if (GV->hasDLLImportLinkage()) {
// FIXME: This should be fixed with full support of stdcall & fastcall
// CC's
O << "__imp_";
}
O << Name;
printOffset(MO.getOffset());
return;
}
case MachineOperand::MO_ExternalSymbol: {
O << TAI->getGlobalPrefix() << MO.getSymbolName();
return;
}
default:
O << "<unknown operand type>"; return;
}
}
void X86IntelAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo){
const MachineOperand &MO = MI->getOperand(OpNo);
switch (MO.getType()) {
default: assert(0 && "Unknown pcrel immediate operand");
case MachineOperand::MO_Immediate:
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB());
return;
case MachineOperand::MO_GlobalAddress: {
GlobalValue *GV = MO.getGlobal();
std::string Name = Mang->getValueName(GV);
decorateName(Name, GV);
if (GV->hasDLLImportLinkage()) {
// FIXME: This should be fixed with full support of stdcall & fastcall
// CC's
O << "__imp_";
}
O << Name;
printOffset(MO.getOffset());
return;
}
case MachineOperand::MO_ExternalSymbol:
O << TAI->getGlobalPrefix() << MO.getSymbolName();
return;
}
}
void X86IntelAsmPrinter::printLeaMemReference(const MachineInstr *MI,
unsigned Op,
const char *Modifier) {
const MachineOperand &BaseReg = MI->getOperand(Op);
int ScaleVal = MI->getOperand(Op+1).getImm();
const MachineOperand &IndexReg = MI->getOperand(Op+2);
const MachineOperand &DispSpec = MI->getOperand(Op+3);
O << "[";
bool NeedPlus = false;
if (BaseReg.getReg()) {
printOp(BaseReg, Modifier);
NeedPlus = true;
}
if (IndexReg.getReg()) {
if (NeedPlus) O << " + ";
if (ScaleVal != 1)
O << ScaleVal << "*";
printOp(IndexReg, Modifier);
NeedPlus = true;
}
if (DispSpec.isGlobal() || DispSpec.isCPI() ||
DispSpec.isJTI()) {
if (NeedPlus)
O << " + ";
printOp(DispSpec, "mem");
} else {
int DispVal = DispSpec.getImm();
if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) {
if (NeedPlus) {
if (DispVal > 0)
O << " + ";
else {
O << " - ";
DispVal = -DispVal;
}
}
O << DispVal;
}
}
O << "]";
}
void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op,
const char *Modifier) {
assert(isMem(MI, Op) && "Invalid memory reference!");
MachineOperand Segment = MI->getOperand(Op+4);
if (Segment.getReg()) {
printOperand(MI, Op+4, Modifier);
O << ':';
}
printLeaMemReference(MI, Op, Modifier);
}
void X86IntelAsmPrinter::printPICJumpTableSetLabel(unsigned uid,
const MachineBasicBlock *MBB) const {
if (!TAI->getSetDirective())
return;
O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix()
<< getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',';
printBasicBlockLabel(MBB, false, false, false);
O << '-' << "\"L" << getFunctionNumber() << "$pb\"'\n";
}
void X86IntelAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
O << "L" << getFunctionNumber() << "$pb\n";
O << "L" << getFunctionNumber() << "$pb:";
}
bool X86IntelAsmPrinter::printAsmMRegister(const MachineOperand &MO,
const char Mode) {
unsigned Reg = MO.getReg();
switch (Mode) {
default: return true; // Unknown mode.
case 'b': // Print QImode register
Reg = getX86SubSuperRegister(Reg, MVT::i8);
break;
case 'h': // Print QImode high register
Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
break;
case 'w': // Print HImode register
Reg = getX86SubSuperRegister(Reg, MVT::i16);
break;
case 'k': // Print SImode register
Reg = getX86SubSuperRegister(Reg, MVT::i32);
break;
}
O << TRI->getName(Reg);
return false;
}
/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool X86IntelAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant,
const char *ExtraCode) {
// Does this asm operand have a single letter operand modifier?
if (ExtraCode && ExtraCode[0]) {
if (ExtraCode[1] != 0) return true; // Unknown modifier.
switch (ExtraCode[0]) {
default: return true; // Unknown modifier.
case 'b': // Print QImode register
case 'h': // Print QImode high register
case 'w': // Print HImode register
case 'k': // Print SImode register
return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]);
}
}
printOperand(MI, OpNo);
return false;
}
bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
unsigned OpNo,
unsigned AsmVariant,
const char *ExtraCode) {
if (ExtraCode && ExtraCode[0])
return true; // Unknown modifier.
printMemReference(MI, OpNo);
return false;
}
/// printMachineInstruction -- Print out a single X86 LLVM instruction
/// MI in Intel syntax to the current output stream.
///
void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
// Call the autogenerated instruction printer routines.
printInstruction(MI);
}
bool X86IntelAsmPrinter::doInitialization(Module &M) {
bool Result = AsmPrinter::doInitialization(M);
Mang->markCharUnacceptable('.');
O << "\t.686\n\t.MMX\n\t.XMM\n\t.model flat\n\n";
// Emit declarations for external functions.
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
if (I->isDeclaration()) {
std::string Name = Mang->getValueName(I);
decorateName(Name, I);
O << "\tEXTERN " ;
if (I->hasDLLImportLinkage()) {
O << "__imp_";
}
O << Name << ":near\n";
}
// Emit declarations for external globals. Note that VC++ always declares
// external globals to have type byte, and if that's good enough for VC++...
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (I->isDeclaration()) {
std::string Name = Mang->getValueName(I);
O << "\tEXTERN " ;
if (I->hasDLLImportLinkage()) {
O << "__imp_";
}
O << Name << ":byte\n";
}
}
return Result;
}
bool X86IntelAsmPrinter::doFinalization(Module &M) {
const TargetData *TD = TM.getTargetData();
// Print out module-level global variables here.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (I->isDeclaration()) continue; // External global require no code
// Check to see if this is a special global used by LLVM, if so, emit it.
if (EmitSpecialLLVMGlobal(I))
continue;
std::string name = Mang->getValueName(I);
Constant *C = I->getInitializer();
unsigned Align = TD->getPreferredAlignmentLog(I);
bool bCustomSegment = false;
switch (I->getLinkage()) {
case GlobalValue::CommonLinkage:
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
SwitchToDataSection("");
O << name << "?\tSEGEMNT PARA common 'COMMON'\n";
bCustomSegment = true;
// FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256
// are also available.
break;
case GlobalValue::AppendingLinkage:
SwitchToDataSection("");
O << name << "?\tSEGMENT PARA public 'DATA'\n";
bCustomSegment = true;
// FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256
// are also available.
break;
case GlobalValue::DLLExportLinkage:
DLLExportedGVs.insert(name);
// FALL THROUGH
case GlobalValue::ExternalLinkage:
O << "\tpublic " << name << "\n";
// FALL THROUGH
case GlobalValue::InternalLinkage:
SwitchToSection(TAI->getDataSection());
break;
default:
assert(0 && "Unknown linkage type!");
}
if (!bCustomSegment)
EmitAlignment(Align, I);
O << name << ":";
if (VerboseAsm)
O << "\t\t\t\t" << TAI->getCommentString()
<< " " << I->getName();
O << '\n';
EmitGlobalConstant(C);
if (bCustomSegment)
O << name << "?\tends\n";
}
// Output linker support code for dllexported globals
if (!DLLExportedGVs.empty() || !DLLExportedFns.empty()) {
SwitchToDataSection("");
O << "; WARNING: The following code is valid only with MASM v8.x"
<< "and (possible) higher\n"
<< "; This version of MASM is usually shipped with Microsoft "
<< "Visual Studio 2005\n"
<< "; or (possible) further versions. Unfortunately, there is no "
<< "way to support\n"
<< "; dllexported symbols in the earlier versions of MASM in fully "
<< "automatic way\n\n";
O << "_drectve\t segment info alias('.drectve')\n";
}
for (StringSet<>::iterator i = DLLExportedGVs.begin(),
e = DLLExportedGVs.end();
i != e; ++i)
O << "\t db ' /EXPORT:" << i->getKeyData() << ",data'\n";
for (StringSet<>::iterator i = DLLExportedFns.begin(),
e = DLLExportedFns.end();
i != e; ++i)
O << "\t db ' /EXPORT:" << i->getKeyData() << "'\n";
if (!DLLExportedGVs.empty() || !DLLExportedFns.empty())
O << "_drectve\t ends\n";
// Bypass X86SharedAsmPrinter::doFinalization().
bool Result = AsmPrinter::doFinalization(M);
SwitchToDataSection("");
O << "\tend\n";
return Result;
}
void X86IntelAsmPrinter::EmitString(const ConstantArray *CVA) const {
unsigned NumElts = CVA->getNumOperands();
if (NumElts) {
// ML does not have escape sequences except '' for '. It also has a maximum
// string length of 255.
unsigned len = 0;
bool inString = false;
for (unsigned i = 0; i < NumElts; i++) {
int n = cast<ConstantInt>(CVA->getOperand(i))->getZExtValue() & 255;
if (len == 0)
O << "\tdb ";
if (n >= 32 && n <= 127) {
if (!inString) {
if (len > 0) {
O << ",'";
len += 2;
} else {
O << "'";
len++;
}
inString = true;
}
if (n == '\'') {
O << "'";
len++;
}
O << char(n);
} else {
if (inString) {
O << "'";
len++;
inString = false;
}
if (len > 0) {
O << ",";
len++;
}
O << n;
len += 1 + (n > 9) + (n > 99);
}
if (len > 60) {
if (inString) {
O << "'";
inString = false;
}
O << "\n";
len = 0;
}
}
if (len > 0) {
if (inString)
O << "'";
O << "\n";
}
}
}
// Include the auto-generated portion of the assembly writer.
#include "X86GenAsmWriter1.inc"

View File

@ -1,162 +0,0 @@
//===-- X86IntelAsmPrinter.h - Convert X86 LLVM code to Intel assembly ----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Intel assembly code printer class.
//
//===----------------------------------------------------------------------===//
#ifndef X86INTELASMPRINTER_H
#define X86INTELASMPRINTER_H
#include "../X86.h"
#include "../X86MachineFunctionInfo.h"
#include "../X86TargetMachine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
struct VISIBILITY_HIDDEN X86IntelAsmPrinter : public AsmPrinter {
explicit X86IntelAsmPrinter(raw_ostream &O, X86TargetMachine &TM,
const TargetAsmInfo *T, bool V)
: AsmPrinter(O, TM, T, V) {}
virtual const char *getPassName() const {
return "X86 Intel-Style Assembly Printer";
}
/// printInstruction - This method is automatically generated by tablegen
/// from the instruction set description. This method returns true if the
/// machine instruction was sufficiently described to print it, otherwise it
/// returns false.
bool printInstruction(const MachineInstr *MI);
// This method is used by the tablegen'erated instruction printer.
void printOperand(const MachineInstr *MI, unsigned OpNo,
const char *Modifier = 0) {
const MachineOperand &MO = MI->getOperand(OpNo);
if (MO.isReg()) {
assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
"Not physreg??");
O << TM.getRegisterInfo()->get(MO.getReg()).Name; // Capitalized names
} else {
printOp(MO, Modifier);
}
}
void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo);
void printi8mem(const MachineInstr *MI, unsigned OpNo) {
O << "BYTE PTR ";
printMemReference(MI, OpNo);
}
void printi16mem(const MachineInstr *MI, unsigned OpNo) {
O << "WORD PTR ";
printMemReference(MI, OpNo);
}
void printi32mem(const MachineInstr *MI, unsigned OpNo) {
O << "DWORD PTR ";
printMemReference(MI, OpNo);
}
void printi64mem(const MachineInstr *MI, unsigned OpNo) {
O << "QWORD PTR ";
printMemReference(MI, OpNo);
}
void printi128mem(const MachineInstr *MI, unsigned OpNo) {
O << "XMMWORD PTR ";
printMemReference(MI, OpNo);
}
void printi256mem(const MachineInstr *MI, unsigned OpNo) {
O << "YMMWORD PTR ";
printMemReference(MI, OpNo);
}
void printf32mem(const MachineInstr *MI, unsigned OpNo) {
O << "DWORD PTR ";
printMemReference(MI, OpNo);
}
void printf64mem(const MachineInstr *MI, unsigned OpNo) {
O << "QWORD PTR ";
printMemReference(MI, OpNo);
}
void printf80mem(const MachineInstr *MI, unsigned OpNo) {
O << "XWORD PTR ";
printMemReference(MI, OpNo);
}
void printf128mem(const MachineInstr *MI, unsigned OpNo) {
O << "XMMWORD PTR ";
printMemReference(MI, OpNo);
}
void printf256mem(const MachineInstr *MI, unsigned OpNo) {
O << "YMMWORD PTR ";
printMemReference(MI, OpNo);
}
void printlea32mem(const MachineInstr *MI, unsigned OpNo) {
O << "DWORD PTR ";
printLeaMemReference(MI, OpNo);
}
void printlea64mem(const MachineInstr *MI, unsigned OpNo) {
O << "QWORD PTR ";
printLeaMemReference(MI, OpNo);
}
void printlea64_32mem(const MachineInstr *MI, unsigned OpNo) {
O << "QWORD PTR ";
printLeaMemReference(MI, OpNo, "subreg64");
}
bool printAsmMRegister(const MachineOperand &MO, const char Mode);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO, const char *Modifier = 0);
void printSSECC(const MachineInstr *MI, unsigned Op);
void printMemReference(const MachineInstr *MI, unsigned Op,
const char *Modifier=NULL);
void printLeaMemReference(const MachineInstr *MI, unsigned Op,
const char *Modifier=NULL);
void printPICJumpTableSetLabel(unsigned uid,
const MachineBasicBlock *MBB) const;
void printPICJumpTableSetLabel(unsigned uid, unsigned uid2,
const MachineBasicBlock *MBB) const {
AsmPrinter::printPICJumpTableSetLabel(uid, uid2, MBB);
}
void printPICLabel(const MachineInstr *MI, unsigned Op);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
bool doFinalization(Module &M);
// We have to propagate some information about MachineFunction to
// AsmPrinter. It's ok, when we're printing the function, since we have
// access to MachineFunction and can get the appropriate MachineFunctionInfo.
// Unfortunately, this is not possible when we're printing reference to
// Function (e.g. calling it and so on). Even more, there is no way to get the
// corresponding MachineFunctions: it can even be not created at all. That's
// why we should use additional structure, when we're collecting all necessary
// information.
//
// This structure is using e.g. for name decoration for stdcall & fastcall'ed
// function, since we have to use arguments' size for decoration.
typedef std::map<const Function*, X86MachineFunctionInfo> FMFInfoMap;
FMFInfoMap FunctionInfoMap;
void decorateName(std::string& Name, const GlobalValue* GV);
virtual void EmitString(const ConstantArray *CVA) const;
// Necessary for dllexport support
StringSet<> DLLExportedFns, DLLExportedGVs;
};
} // end namespace llvm
#endif

View File

@ -1,429 +0,0 @@
//===-- X86TargetAsmInfo.cpp - X86 asm properties ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the X86TargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "X86TargetAsmInfo.h"
#include "X86TargetMachine.h"
#include "X86Subtarget.h"
#include "llvm/DerivedTypes.h"
#include "llvm/InlineAsm.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Module.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Dwarf.h"
using namespace llvm;
using namespace llvm::dwarf;
const char *const llvm::x86_asm_table[] = {
"{si}", "S",
"{di}", "D",
"{ax}", "a",
"{cx}", "c",
"{memory}", "memory",
"{flags}", "",
"{dirflag}", "",
"{fpsr}", "",
"{cc}", "cc",
0,0};
X86DarwinTargetAsmInfo::X86DarwinTargetAsmInfo(const X86TargetMachine &TM):
X86TargetAsmInfo<DarwinTargetAsmInfo>(TM) {
const X86Subtarget* Subtarget = &TM.getSubtarget<X86Subtarget>();
bool is64Bit = Subtarget->is64Bit();
AlignmentIsInBytes = false;
TextAlignFillValue = 0x90;
if (!is64Bit)
Data64bitsDirective = 0; // we can't emit a 64-bit unit
ZeroDirective = "\t.space\t"; // ".space N" emits N zeros.
ZeroFillDirective = "\t.zerofill\t"; // Uses .zerofill
if (TM.getRelocationModel() != Reloc::Static)
ConstantPoolSection = "\t.const_data";
else
ConstantPoolSection = "\t.const\n";
// FIXME: Why don't we always use this section?
if (is64Bit)
SixteenByteConstantSection = getUnnamedSection("\t.literal16\n",
SectionFlags::Mergeable);
LCOMMDirective = "\t.lcomm\t";
// Leopard and above support aligned common symbols.
COMMDirectiveTakesAlignment = (Subtarget->getDarwinVers() >= 9);
HasDotTypeDotSizeDirective = false;
NonLocalEHFrameLabel = true;
if (is64Bit) {
PersonalityPrefix = "";
PersonalitySuffix = "+4@GOTPCREL";
} else {
PersonalityPrefix = "L";
PersonalitySuffix = "$non_lazy_ptr";
}
InlineAsmStart = "## InlineAsm Start";
InlineAsmEnd = "## InlineAsm End";
CommentString = "##";
SetDirective = "\t.set";
PCSymbol = ".";
UsedDirective = "\t.no_dead_strip\t";
ProtectedDirective = "\t.globl\t";
SupportsDebugInformation = true;
DwarfDebugInlineSection = ".section __DWARF,__debug_inlined,regular,debug";
DwarfUsesInlineInfoSection = true;
// Exceptions handling
SupportsExceptionHandling = true;
GlobalEHDirective = "\t.globl\t";
SupportsWeakOmittedEHFrame = false;
AbsoluteEHSectionOffsets = false;
DwarfEHFrameSection =
".section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support";
DwarfExceptionSection = ".section __DATA,__gcc_except_tab";
}
unsigned
X86DarwinTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const {
if (Reason == DwarfEncoding::Functions && Global)
return (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4);
else if (Reason == DwarfEncoding::CodeLabels || !Global)
return DW_EH_PE_pcrel;
else
return DW_EH_PE_absptr;
}
const char *
X86DarwinTargetAsmInfo::getEHGlobalPrefix() const
{
const X86Subtarget* Subtarget = &TM.getSubtarget<X86Subtarget>();
if (Subtarget->getDarwinVers() > 9)
return PrivateGlobalPrefix;
else
return "";
}
X86ELFTargetAsmInfo::X86ELFTargetAsmInfo(const X86TargetMachine &TM):
X86TargetAsmInfo<ELFTargetAsmInfo>(TM) {
CStringSection = ".rodata.str";
PrivateGlobalPrefix = ".L";
WeakRefDirective = "\t.weak\t";
SetDirective = "\t.set\t";
PCSymbol = ".";
// Set up DWARF directives
HasLEB128 = true; // Target asm supports leb128 directives (little-endian)
// Debug Information
AbsoluteDebugSectionOffsets = true;
SupportsDebugInformation = true;
DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"\",@progbits";
DwarfInfoSection = "\t.section\t.debug_info,\"\",@progbits";
DwarfLineSection = "\t.section\t.debug_line,\"\",@progbits";
DwarfFrameSection = "\t.section\t.debug_frame,\"\",@progbits";
DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"\",@progbits";
DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"\",@progbits";
DwarfStrSection = "\t.section\t.debug_str,\"\",@progbits";
DwarfLocSection = "\t.section\t.debug_loc,\"\",@progbits";
DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits";
DwarfRangesSection = "\t.section\t.debug_ranges,\"\",@progbits";
DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
// Exceptions handling
SupportsExceptionHandling = true;
AbsoluteEHSectionOffsets = false;
DwarfEHFrameSection = "\t.section\t.eh_frame,\"aw\",@progbits";
DwarfExceptionSection = "\t.section\t.gcc_except_table,\"a\",@progbits";
// On Linux we must declare when we can use a non-executable stack.
if (TM.getSubtarget<X86Subtarget>().isLinux())
NonexecutableStackDirective = "\t.section\t.note.GNU-stack,\"\",@progbits";
}
unsigned
X86ELFTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const {
CodeModel::Model CM = TM.getCodeModel();
bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit();
if (TM.getRelocationModel() == Reloc::PIC_) {
unsigned Format = 0;
if (!is64Bit)
// 32 bit targets always encode pointers as 4 bytes
Format = DW_EH_PE_sdata4;
else {
// 64 bit targets encode pointers in 4 bytes iff:
// - code model is small OR
// - code model is medium and we're emitting externally visible symbols
// or any code symbols
if (CM == CodeModel::Small ||
(CM == CodeModel::Medium && (Global ||
Reason != DwarfEncoding::Data)))
Format = DW_EH_PE_sdata4;
else
Format = DW_EH_PE_sdata8;
}
if (Global)
Format |= DW_EH_PE_indirect;
return (Format | DW_EH_PE_pcrel);
} else {
if (is64Bit &&
(CM == CodeModel::Small ||
(CM == CodeModel::Medium && Reason != DwarfEncoding::Data)))
return DW_EH_PE_udata4;
else
return DW_EH_PE_absptr;
}
}
X86COFFTargetAsmInfo::X86COFFTargetAsmInfo(const X86TargetMachine &TM):
X86GenericTargetAsmInfo(TM) {
GlobalPrefix = "_";
LCOMMDirective = "\t.lcomm\t";
COMMDirectiveTakesAlignment = false;
HasDotTypeDotSizeDirective = false;
HasSingleParameterDotFile = false;
StaticCtorsSection = "\t.section .ctors,\"aw\"";
StaticDtorsSection = "\t.section .dtors,\"aw\"";
HiddenDirective = NULL;
PrivateGlobalPrefix = "L"; // Prefix for private global symbols
WeakRefDirective = "\t.weak\t";
SetDirective = "\t.set\t";
// Set up DWARF directives
HasLEB128 = true; // Target asm supports leb128 directives (little-endian)
AbsoluteDebugSectionOffsets = true;
AbsoluteEHSectionOffsets = false;
SupportsDebugInformation = true;
DwarfSectionOffsetDirective = "\t.secrel32\t";
DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"dr\"";
DwarfInfoSection = "\t.section\t.debug_info,\"dr\"";
DwarfLineSection = "\t.section\t.debug_line,\"dr\"";
DwarfFrameSection = "\t.section\t.debug_frame,\"dr\"";
DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"dr\"";
DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"dr\"";
DwarfStrSection = "\t.section\t.debug_str,\"dr\"";
DwarfLocSection = "\t.section\t.debug_loc,\"dr\"";
DwarfARangesSection = "\t.section\t.debug_aranges,\"dr\"";
DwarfRangesSection = "\t.section\t.debug_ranges,\"dr\"";
DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"dr\"";
}
unsigned
X86COFFTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const {
CodeModel::Model CM = TM.getCodeModel();
bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit();
if (TM.getRelocationModel() == Reloc::PIC_) {
unsigned Format = 0;
if (!is64Bit)
// 32 bit targets always encode pointers as 4 bytes
Format = DW_EH_PE_sdata4;
else {
// 64 bit targets encode pointers in 4 bytes iff:
// - code model is small OR
// - code model is medium and we're emitting externally visible symbols
// or any code symbols
if (CM == CodeModel::Small ||
(CM == CodeModel::Medium && (Global ||
Reason != DwarfEncoding::Data)))
Format = DW_EH_PE_sdata4;
else
Format = DW_EH_PE_sdata8;
}
if (Global)
Format |= DW_EH_PE_indirect;
return (Format | DW_EH_PE_pcrel);
} else {
if (is64Bit &&
(CM == CodeModel::Small ||
(CM == CodeModel::Medium && Reason != DwarfEncoding::Data)))
return DW_EH_PE_udata4;
else
return DW_EH_PE_absptr;
}
}
std::string
X86COFFTargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV,
SectionKind::Kind kind) const {
switch (kind) {
case SectionKind::Text:
return ".text$linkonce" + GV->getName();
case SectionKind::Data:
case SectionKind::BSS:
case SectionKind::ThreadData:
case SectionKind::ThreadBSS:
return ".data$linkonce" + GV->getName();
case SectionKind::ROData:
case SectionKind::RODataMergeConst:
case SectionKind::RODataMergeStr:
return ".rdata$linkonce" + GV->getName();
default:
assert(0 && "Unknown section kind");
}
return NULL;
}
std::string X86COFFTargetAsmInfo::printSectionFlags(unsigned flags) const {
std::string Flags = ",\"";
if (flags & SectionFlags::Code)
Flags += 'x';
if (flags & SectionFlags::Writeable)
Flags += 'w';
Flags += "\"";
return Flags;
}
X86WinTargetAsmInfo::X86WinTargetAsmInfo(const X86TargetMachine &TM):
X86GenericTargetAsmInfo(TM) {
GlobalPrefix = "_";
CommentString = ";";
InlineAsmStart = "; InlineAsm Start";
InlineAsmEnd = "; InlineAsm End";
PrivateGlobalPrefix = "$";
AlignDirective = "\tALIGN\t";
ZeroDirective = "\tdb\t";
ZeroDirectiveSuffix = " dup(0)";
AsciiDirective = "\tdb\t";
AscizDirective = 0;
Data8bitsDirective = "\tdb\t";
Data16bitsDirective = "\tdw\t";
Data32bitsDirective = "\tdd\t";
Data64bitsDirective = "\tdq\t";
HasDotTypeDotSizeDirective = false;
HasSingleParameterDotFile = false;
AlignmentIsInBytes = true;
TextSection = getUnnamedSection("_text", SectionFlags::Code);
DataSection = getUnnamedSection("_data", SectionFlags::Writeable);
JumpTableDataSection = NULL;
SwitchToSectionDirective = "";
TextSectionStartSuffix = "\tSEGMENT PARA 'CODE'";
DataSectionStartSuffix = "\tSEGMENT PARA 'DATA'";
SectionEndDirectiveSuffix = "\tends\n";
}
template <class BaseTAI>
bool X86TargetAsmInfo<BaseTAI>::LowerToBSwap(CallInst *CI) const {
// FIXME: this should verify that we are targetting a 486 or better. If not,
// we will turn this bswap into something that will be lowered to logical ops
// instead of emitting the bswap asm. For now, we don't support 486 or lower
// so don't worry about this.
// Verify this is a simple bswap.
if (CI->getNumOperands() != 2 ||
CI->getType() != CI->getOperand(1)->getType() ||
!CI->getType()->isInteger())
return false;
const IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
if (!Ty || Ty->getBitWidth() % 16 != 0)
return false;
// Okay, we can do this xform, do so now.
const Type *Tys[] = { Ty };
Module *M = CI->getParent()->getParent()->getParent();
Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Tys, 1);
Value *Op = CI->getOperand(1);
Op = CallInst::Create(Int, Op, CI->getName(), CI);
CI->replaceAllUsesWith(Op);
CI->eraseFromParent();
return true;
}
template <class BaseTAI>
bool X86TargetAsmInfo<BaseTAI>::ExpandInlineAsm(CallInst *CI) const {
InlineAsm *IA = cast<InlineAsm>(CI->getCalledValue());
std::vector<InlineAsm::ConstraintInfo> Constraints = IA->ParseConstraints();
std::string AsmStr = IA->getAsmString();
// TODO: should remove alternatives from the asmstring: "foo {a|b}" -> "foo a"
std::vector<std::string> AsmPieces;
SplitString(AsmStr, AsmPieces, "\n"); // ; as separator?
switch (AsmPieces.size()) {
default: return false;
case 1:
AsmStr = AsmPieces[0];
AsmPieces.clear();
SplitString(AsmStr, AsmPieces, " \t"); // Split with whitespace.
// bswap $0
if (AsmPieces.size() == 2 &&
(AsmPieces[0] == "bswap" ||
AsmPieces[0] == "bswapq" ||
AsmPieces[0] == "bswapl") &&
(AsmPieces[1] == "$0" ||
AsmPieces[1] == "${0:q}")) {
// No need to check constraints, nothing other than the equivalent of
// "=r,0" would be valid here.
return LowerToBSwap(CI);
}
// rorw $$8, ${0:w} --> llvm.bswap.i16
if (CI->getType() == Type::Int16Ty &&
AsmPieces.size() == 3 &&
AsmPieces[0] == "rorw" &&
AsmPieces[1] == "$$8," &&
AsmPieces[2] == "${0:w}" &&
IA->getConstraintString() == "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}") {
return LowerToBSwap(CI);
}
break;
case 3:
if (CI->getType() == Type::Int64Ty && Constraints.size() >= 2 &&
Constraints[0].Codes.size() == 1 && Constraints[0].Codes[0] == "A" &&
Constraints[1].Codes.size() == 1 && Constraints[1].Codes[0] == "0") {
// bswap %eax / bswap %edx / xchgl %eax, %edx -> llvm.bswap.i64
std::vector<std::string> Words;
SplitString(AsmPieces[0], Words, " \t");
if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%eax") {
Words.clear();
SplitString(AsmPieces[1], Words, " \t");
if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%edx") {
Words.clear();
SplitString(AsmPieces[2], Words, " \t,");
if (Words.size() == 3 && Words[0] == "xchgl" && Words[1] == "%eax" &&
Words[2] == "%edx") {
return LowerToBSwap(CI);
}
}
}
}
break;
}
return false;
}
// Instantiate default implementation.
TEMPLATE_INSTANTIATION(class X86TargetAsmInfo<TargetAsmInfo>);

View File

@ -1,75 +0,0 @@
//=====-- X86TargetAsmInfo.h - X86 asm properties -------------*- C++ -*--====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the X86TargetAsmInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef X86TARGETASMINFO_H
#define X86TARGETASMINFO_H
#include "X86TargetMachine.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
#include "llvm/Target/DarwinTargetAsmInfo.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
extern const char *const x86_asm_table[];
template <class BaseTAI>
struct X86TargetAsmInfo : public BaseTAI {
explicit X86TargetAsmInfo(const X86TargetMachine &TM):
BaseTAI(TM) {
const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
BaseTAI::AsmTransCBE = x86_asm_table;
BaseTAI::AssemblerDialect = Subtarget->getAsmFlavor();
}
virtual bool ExpandInlineAsm(CallInst *CI) const;
private:
bool LowerToBSwap(CallInst *CI) const;
};
typedef X86TargetAsmInfo<TargetAsmInfo> X86GenericTargetAsmInfo;
EXTERN_TEMPLATE_INSTANTIATION(class X86TargetAsmInfo<TargetAsmInfo>);
struct X86DarwinTargetAsmInfo : public X86TargetAsmInfo<DarwinTargetAsmInfo> {
explicit X86DarwinTargetAsmInfo(const X86TargetMachine &TM);
virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const;
virtual const char *getEHGlobalPrefix() const;
};
struct X86ELFTargetAsmInfo : public X86TargetAsmInfo<ELFTargetAsmInfo> {
explicit X86ELFTargetAsmInfo(const X86TargetMachine &TM);
virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const;
};
struct X86COFFTargetAsmInfo : public X86GenericTargetAsmInfo {
explicit X86COFFTargetAsmInfo(const X86TargetMachine &TM);
virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
bool Global) const;
virtual std::string UniqueSectionForGlobal(const GlobalValue* GV,
SectionKind::Kind kind) const;
virtual std::string printSectionFlags(unsigned flags) const;
};
struct X86WinTargetAsmInfo : public X86GenericTargetAsmInfo {
explicit X86WinTargetAsmInfo(const X86TargetMachine &TM);
};
} // namespace llvm
#endif

View File

@ -1,438 +0,0 @@
//===-- XCoreAsmPrinter.cpp - XCore LLVM assembly writer ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to the XAS-format XCore assembly language.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "XCore.h"
#include "XCoreInstrInfo.h"
#include "XCoreSubtarget.h"
#include "XCoreTargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/Mangler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cctype>
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
static cl::opt<std::string> FileDirective("xcore-file-directive", cl::Optional,
cl::desc("Output a file directive into the assembly file"),
cl::Hidden,
cl::value_desc("filename"),
cl::init(""));
static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional,
cl::desc("Maximum number of threads (for emulation thread-local storage)"),
cl::Hidden,
cl::value_desc("number"),
cl::init(8));
namespace {
class VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter {
DwarfWriter *DW;
const XCoreSubtarget &Subtarget;
public:
explicit XCoreAsmPrinter(raw_ostream &O, XCoreTargetMachine &TM,
const TargetAsmInfo *T, bool V)
: AsmPrinter(O, TM, T, V), DW(0),
Subtarget(*TM.getSubtargetImpl()) {}
virtual const char *getPassName() const {
return "XCore Assembly Printer";
}
void printMemOperand(const MachineInstr *MI, int opNum);
void printOperand(const MachineInstr *MI, int opNum);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
void emitFileDirective(const std::string &filename);
void emitGlobalDirective(const std::string &name);
void emitExternDirective(const std::string &name);
void emitArrayBound(const std::string &name, const GlobalVariable *GV);
void emitGlobal(const GlobalVariable *GV);
void emitFunctionStart(MachineFunction &MF);
void emitFunctionEnd(MachineFunction &MF);
bool printInstruction(const MachineInstr *MI); // autogenerated.
void printMachineInstruction(const MachineInstr *MI);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
bool doFinalization(Module &M);
void getAnalysisUsage(AnalysisUsage &AU) const {
AsmPrinter::getAnalysisUsage(AU);
AU.setPreservesAll();
AU.addRequired<MachineModuleInfo>();
AU.addRequired<DwarfWriter>();
}
};
} // end of anonymous namespace
#include "XCoreGenAsmWriter.inc"
/// createXCoreCodePrinterPass - Returns a pass that prints the XCore
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description. This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *llvm::createXCoreCodePrinterPass(raw_ostream &o,
XCoreTargetMachine &tm,
bool verbose) {
return new XCoreAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
}
// PrintEscapedString - Print each character of the specified string, escaping
// it if it is not printable or if it is an escape char.
static void PrintEscapedString(const std::string &Str, raw_ostream &Out) {
for (unsigned i = 0, e = Str.size(); i != e; ++i) {
unsigned char C = Str[i];
if (isprint(C) && C != '"' && C != '\\') {
Out << C;
} else {
Out << '\\'
<< (char) ((C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A'))
<< (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'));
}
}
}
void XCoreAsmPrinter::
emitFileDirective(const std::string &name)
{
O << "\t.file\t\"";
PrintEscapedString(name, O);
O << "\"\n";
}
void XCoreAsmPrinter::
emitGlobalDirective(const std::string &name)
{
O << TAI->getGlobalDirective() << name;
O << "\n";
}
void XCoreAsmPrinter::
emitExternDirective(const std::string &name)
{
O << "\t.extern\t" << name;
O << '\n';
}
void XCoreAsmPrinter::
emitArrayBound(const std::string &name, const GlobalVariable *GV)
{
assert(((GV->hasExternalLinkage() ||
GV->hasWeakLinkage()) ||
GV->hasLinkOnceLinkage()) && "Unexpected linkage");
if (const ArrayType *ATy = dyn_cast<ArrayType>(
cast<PointerType>(GV->getType())->getElementType()))
{
O << TAI->getGlobalDirective() << name << ".globound" << "\n";
O << TAI->getSetDirective() << name << ".globound" << ","
<< ATy->getNumElements() << "\n";
if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
// TODO Use COMDAT groups for LinkOnceLinkage
O << TAI->getWeakDefDirective() << name << ".globound" << "\n";
}
}
}
void XCoreAsmPrinter::
emitGlobal(const GlobalVariable *GV)
{
const TargetData *TD = TM.getTargetData();
if (GV->hasInitializer()) {
// Check to see if this is a special global used by LLVM, if so, emit it.
if (EmitSpecialLLVMGlobal(GV))
return;
SwitchToSection(TAI->SectionForGlobal(GV));
std::string name = Mang->getValueName(GV);
Constant *C = GV->getInitializer();
unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
// Mark the start of the global
O << "\t.cc_top " << name << ".data," << name << "\n";
switch (GV->getLinkage()) {
case GlobalValue::AppendingLinkage:
cerr << "AppendingLinkage is not supported by this target!\n";
abort();
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
case GlobalValue::ExternalLinkage:
emitArrayBound(name, GV);
emitGlobalDirective(name);
// TODO Use COMDAT groups for LinkOnceLinkage
if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
O << TAI->getWeakDefDirective() << name << "\n";
}
// FALL THROUGH
case GlobalValue::InternalLinkage:
case GlobalValue::PrivateLinkage:
break;
case GlobalValue::GhostLinkage:
cerr << "Should not have any unmaterialized functions!\n";
abort();
case GlobalValue::DLLImportLinkage:
cerr << "DLLImport linkage is not supported by this target!\n";
abort();
case GlobalValue::DLLExportLinkage:
cerr << "DLLExport linkage is not supported by this target!\n";
abort();
default:
assert(0 && "Unknown linkage type!");
}
EmitAlignment(Align, GV, 2);
unsigned Size = TD->getTypeAllocSize(C->getType());
if (GV->isThreadLocal()) {
Size *= MaxThreads;
}
if (TAI->hasDotTypeDotSizeDirective()) {
O << "\t.type " << name << ",@object\n";
O << "\t.size " << name << "," << Size << "\n";
}
O << name << ":\n";
EmitGlobalConstant(C);
if (GV->isThreadLocal()) {
for (unsigned i = 1; i < MaxThreads; ++i) {
EmitGlobalConstant(C);
}
}
if (Size < 4) {
// The ABI requires that unsigned scalar types smaller than 32 bits
// are are padded to 32 bits.
EmitZeros(4 - Size);
}
// Mark the end of the global
O << "\t.cc_bottom " << name << ".data\n";
}
}
/// Emit the directives on the start of functions
void XCoreAsmPrinter::
emitFunctionStart(MachineFunction &MF)
{
// Print out the label for the function.
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
// Mark the start of the function
O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n";
switch (F->getLinkage()) {
default: assert(0 && "Unknown linkage type!");
case Function::InternalLinkage: // Symbols default to internal.
case Function::PrivateLinkage:
break;
case Function::ExternalLinkage:
emitGlobalDirective(CurrentFnName);
break;
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
// TODO Use COMDAT groups for LinkOnceLinkage
O << TAI->getGlobalDirective() << CurrentFnName << "\n";
O << TAI->getWeakDefDirective() << CurrentFnName << "\n";
break;
}
// (1 << 1) byte aligned
EmitAlignment(MF.getAlignment(), F, 1);
if (TAI->hasDotTypeDotSizeDirective()) {
O << "\t.type " << CurrentFnName << ",@function\n";
}
O << CurrentFnName << ":\n";
}
/// Emit the directives on the end of functions
void XCoreAsmPrinter::
emitFunctionEnd(MachineFunction &MF)
{
// Mark the end of the function
O << "\t.cc_bottom " << CurrentFnName << ".function\n";
}
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF)
{
this->MF = &MF;
SetupMachineFunction(MF);
// Print out constants referenced by the function
EmitConstantPool(MF.getConstantPool());
// Print out jump tables referenced by the function
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
// Emit the function start directives
emitFunctionStart(MF);
// Emit pre-function debug information.
DW->BeginFunction(&MF);
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
if (I != MF.begin()) {
printBasicBlockLabel(I, true , true);
O << '\n';
}
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
O << "\t";
printMachineInstruction(II);
}
// Each Basic Block is separated by a newline
O << '\n';
}
// Emit function end directives
emitFunctionEnd(MF);
// Emit post-function debug information.
DW->EndFunction(&MF);
// We didn't modify anything.
return false;
}
void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum)
{
printOperand(MI, opNum);
if (MI->getOperand(opNum+1).isImm()
&& MI->getOperand(opNum+1).getImm() == 0)
return;
O << "+";
printOperand(MI, opNum+1);
}
void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
const MachineOperand &MO = MI->getOperand(opNum);
switch (MO.getType()) {
case MachineOperand::MO_Register:
if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
else
assert(0 && "not implemented");
break;
case MachineOperand::MO_Immediate:
O << MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB());
break;
case MachineOperand::MO_GlobalAddress:
O << Mang->getValueName(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
break;
case MachineOperand::MO_ConstantPoolIndex:
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
<< '_' << MO.getIndex();
break;
case MachineOperand::MO_JumpTableIndex:
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << MO.getIndex();
break;
default:
assert(0 && "not implemented");
}
}
/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant,
const char *ExtraCode) {
printOperand(MI, OpNo);
return false;
}
void XCoreAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
// Check for mov mnemonic
unsigned src, dst, srcSR, dstSR;
if (TM.getInstrInfo()->isMoveInstr(*MI, src, dst, srcSR, dstSR)) {
O << "\tmov ";
O << TM.getRegisterInfo()->get(dst).AsmName;
O << ", ";
O << TM.getRegisterInfo()->get(src).AsmName;
O << "\n";
return;
}
if (printInstruction(MI)) {
return;
}
assert(0 && "Unhandled instruction in asm writer!");
}
bool XCoreAsmPrinter::doInitialization(Module &M) {
bool Result = AsmPrinter::doInitialization(M);
DW = getAnalysisIfAvailable<DwarfWriter>();
if (!FileDirective.empty())
emitFileDirective(FileDirective);
return Result;
}
bool XCoreAsmPrinter::doFinalization(Module &M) {
// Print out module-level global variables.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
emitGlobal(I);
}
return AsmPrinter::doFinalization(M);
}

Some files were not shown because too many files have changed in this diff Show More