summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2010-09-17 15:48:55 +0000
committerdim <dim@FreeBSD.org>2010-09-17 15:48:55 +0000
commit5d5cc59cc77afe655b3707cb0e69e0827b444cad (patch)
tree36453626c792cccd91f783a38a169d610a6b9db9 /tools
parent786a18553586229ad99ecb5ecde8a9d914c45e27 (diff)
downloadFreeBSD-src-5d5cc59cc77afe655b3707cb0e69e0827b444cad.zip
FreeBSD-src-5d5cc59cc77afe655b3707cb0e69e0827b444cad.tar.gz
Vendor import of llvm r114020 (from the release_28 branch):
http://llvm.org/svn/llvm-project/llvm/branches/release_28@114020 Approved by: rpaulo (mentor)
Diffstat (limited to 'tools')
-rw-r--r--tools/CMakeLists.txt2
-rw-r--r--tools/Makefile20
-rw-r--r--tools/bugpoint-passes/CMakeLists.txt3
-rw-r--r--tools/bugpoint-passes/Makefile23
-rw-r--r--tools/bugpoint-passes/TestPasses.cpp (renamed from tools/bugpoint/TestPasses.cpp)16
-rw-r--r--tools/bugpoint-passes/bugpoint.exports0
-rw-r--r--tools/bugpoint/BugDriver.cpp29
-rw-r--r--tools/bugpoint/BugDriver.h67
-rw-r--r--tools/bugpoint/CMakeLists.txt1
-rw-r--r--tools/bugpoint/CrashDebugger.cpp73
-rw-r--r--tools/bugpoint/ExecutionDriver.cpp24
-rw-r--r--tools/bugpoint/ExtractFunction.cpp93
-rw-r--r--tools/bugpoint/FindBugs.cpp8
-rw-r--r--tools/bugpoint/Miscompilation.cpp157
-rw-r--r--tools/bugpoint/OptimizerDriver.cpp113
-rw-r--r--tools/bugpoint/ToolRunner.cpp12
-rw-r--r--tools/bugpoint/bugpoint.cpp26
-rw-r--r--tools/edis/CMakeLists.txt14
-rw-r--r--tools/edis/EDDisassembler.cpp407
-rw-r--r--tools/edis/EDDisassembler.h256
-rw-r--r--tools/edis/EDInfo.td1
-rw-r--r--tools/edis/EDInst.cpp207
-rw-r--r--tools/edis/EDInst.h175
-rw-r--r--tools/edis/EDMain.cpp158
-rw-r--r--tools/edis/EDOperand.cpp284
-rw-r--r--tools/edis/EDOperand.h78
-rw-r--r--tools/edis/EDToken.cpp208
-rw-r--r--tools/edis/EDToken.h135
-rw-r--r--tools/edis/Makefile30
-rw-r--r--tools/gold/README.txt4
-rw-r--r--tools/gold/gold-plugin.cpp40
-rw-r--r--tools/llc/llc.cpp153
-rw-r--r--tools/lli/lli.cpp3
-rw-r--r--tools/llvm-as/llvm-as.cpp18
-rw-r--r--tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp17
-rw-r--r--tools/llvm-config/CMakeLists.txt2
-rw-r--r--tools/llvm-diff/CMakeLists.txt6
-rw-r--r--tools/llvm-diff/DifferenceEngine.cpp676
-rw-r--r--tools/llvm-diff/DifferenceEngine.h179
-rw-r--r--tools/llvm-diff/Makefile (renamed from tools/llvmc/example/Skeleton/plugins/Plugin/Makefile)16
-rw-r--r--tools/llvm-diff/llvm-diff.cpp331
-rw-r--r--tools/llvm-dis/llvm-dis.cpp47
-rw-r--r--tools/llvm-extract/llvm-extract.cpp38
-rw-r--r--tools/llvm-ld/llvm-ld.cpp38
-rw-r--r--tools/llvm-link/llvm-link.cpp19
-rw-r--r--tools/llvm-mc/CMakeLists.txt3
-rw-r--r--tools/llvm-mc/Disassembler.cpp182
-rw-r--r--tools/llvm-mc/Disassembler.h7
-rw-r--r--tools/llvm-mc/Makefile4
-rw-r--r--tools/llvm-mc/llvm-mc.cpp177
-rw-r--r--tools/llvm-nm/llvm-nm.cpp15
-rw-r--r--tools/llvm-prof/llvm-prof.cpp15
-rw-r--r--tools/llvm-shlib/Makefile53
-rw-r--r--tools/llvmc/CMakeLists.txt2
-rw-r--r--tools/llvmc/Makefile8
-rw-r--r--tools/llvmc/doc/LLVMC-Reference.rst9
-rw-r--r--tools/llvmc/example/Hello/Hello.cpp33
-rw-r--r--tools/llvmc/example/Simple/PluginMain.cpp1
-rw-r--r--tools/llvmc/example/Skeleton/Makefile24
-rw-r--r--tools/llvmc/example/Skeleton/driver/Makefile13
-rw-r--r--tools/llvmc/example/Skeleton/plugins/Makefile18
-rw-r--r--tools/llvmc/example/Skeleton/plugins/Plugin/PluginMain.cpp1
-rw-r--r--tools/llvmc/example/mcc16/Makefile18
-rw-r--r--tools/llvmc/example/mcc16/driver/Makefile13
-rw-r--r--tools/llvmc/example/mcc16/plugins/Makefile18
-rw-r--r--tools/llvmc/example/mcc16/plugins/PIC16Base/Makefile17
-rw-r--r--tools/llvmc/examples/Hello/Hello.cpp29
-rw-r--r--tools/llvmc/examples/Hello/Makefile (renamed from tools/llvmc/example/Hello/Makefile)4
-rw-r--r--tools/llvmc/examples/Makefile (renamed from tools/llvmc/example/Simple/Makefile)7
-rw-r--r--tools/llvmc/examples/Simple/Makefile (renamed from tools/llvmc/plugins/Clang/Makefile)6
-rw-r--r--tools/llvmc/examples/Simple/Simple.cpp2
-rw-r--r--tools/llvmc/examples/Simple/Simple.td (renamed from tools/llvmc/example/Simple/Simple.td)24
-rw-r--r--tools/llvmc/examples/Skeleton/AutoGenerated.td (renamed from tools/llvmc/example/Skeleton/plugins/Plugin/Plugin.td)4
-rw-r--r--tools/llvmc/examples/Skeleton/Hooks.cpp12
-rw-r--r--tools/llvmc/examples/Skeleton/Main.cpp (renamed from tools/llvmc/driver/Main.cpp)3
-rw-r--r--tools/llvmc/examples/Skeleton/Makefile20
-rw-r--r--tools/llvmc/examples/Skeleton/README (renamed from tools/llvmc/example/Skeleton/README)2
-rw-r--r--tools/llvmc/examples/mcc16/Hooks.cpp (renamed from tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp)35
-rw-r--r--tools/llvmc/examples/mcc16/Main.cpp (renamed from tools/llvmc/example/mcc16/driver/Main.cpp)17
-rw-r--r--tools/llvmc/examples/mcc16/Makefile (renamed from tools/llvmc/plugins/Base/Makefile)6
-rw-r--r--tools/llvmc/examples/mcc16/PIC16.td (renamed from tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td)50
-rw-r--r--tools/llvmc/examples/mcc16/README (renamed from tools/llvmc/example/mcc16/README)2
-rw-r--r--tools/llvmc/plugins/Base/PluginMain.cpp1
-rw-r--r--tools/llvmc/plugins/Clang/PluginMain.cpp1
-rw-r--r--tools/llvmc/plugins/Makefile18
-rw-r--r--tools/llvmc/src/AutoGenerated.td17
-rw-r--r--tools/llvmc/src/Base.td.in (renamed from tools/llvmc/plugins/Base/Base.td.in)109
-rw-r--r--tools/llvmc/src/Clang.td (renamed from tools/llvmc/plugins/Clang/Clang.td)68
-rw-r--r--tools/llvmc/src/Hooks.cpp (renamed from tools/llvmc/plugins/Base/Hooks.cpp)0
-rw-r--r--tools/llvmc/src/Main.cpp (renamed from tools/llvmc/example/Skeleton/driver/Main.cpp)4
-rw-r--r--tools/llvmc/src/Makefile (renamed from tools/llvmc/driver/Makefile)5
-rw-r--r--tools/lto/LTOCodeGenerator.cpp50
-rw-r--r--tools/lto/LTOCodeGenerator.h6
-rw-r--r--tools/lto/LTOModule.cpp805
-rw-r--r--tools/lto/LTOModule.h1
-rw-r--r--tools/lto/Makefile13
-rw-r--r--tools/lto/lto.cpp28
-rw-r--r--tools/lto/lto.exports3
-rw-r--r--tools/opt/AnalysisWrappers.cpp22
-rw-r--r--tools/opt/GraphPrinters.cpp40
-rw-r--r--tools/opt/PrintSCC.cpp38
-rw-r--r--tools/opt/opt.cpp139
102 files changed, 3000 insertions, 3429 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index b9c77b1..7ed10e9 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -27,8 +27,10 @@ add_subdirectory(llvm-link)
add_subdirectory(lli)
add_subdirectory(llvm-extract)
+add_subdirectory(llvm-diff)
add_subdirectory(bugpoint)
+add_subdirectory(bugpoint-passes)
add_subdirectory(llvm-bcanalyzer)
add_subdirectory(llvm-stub)
add_subdirectory(edis)
diff --git a/tools/Makefile b/tools/Makefile
index 9bc74fe..aa07a2b 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -15,16 +15,13 @@ OPTIONAL_PARALLEL_DIRS := clang
# NOTE: The tools are organized into five groups of four consisting of one
# large and three small executables. This is done to minimize memory load
# in parallel builds. Please retain this ordering.
-
-# libEnhancedDisassembly must be built ahead of llvm-mc
-# because llvm-mc links against libEnhancedDisassembly
-DIRS := llvm-config edis llvm-mc
+DIRS := llvm-config
PARALLEL_DIRS := opt llvm-as llvm-dis \
llc llvm-ranlib llvm-ar llvm-nm \
llvm-ld llvm-prof llvm-link \
- lli llvm-extract \
+ lli llvm-extract llvm-mc \
bugpoint llvm-bcanalyzer llvm-stub \
- llvmc
+ llvmc llvm-diff
# Let users override the set of tools to build from the command line.
ifdef ONLY_TOOLS
@@ -34,6 +31,7 @@ endif
include $(LEVEL)/Makefile.config
+
# These libraries build as dynamic libraries (.dylib /.so), they can only be
# built if ENABLE_PIC is set.
ifeq ($(ENABLE_PIC),1)
@@ -46,6 +44,16 @@ ifeq ($(ENABLE_PIC),1)
else
PARALLEL_DIRS += lto
endif
+
+ PARALLEL_DIRS += bugpoint-passes
+
+ # The edis library is only supported if ARM and/or X86 are enabled, and if
+ # LLVM is being built PIC on platforms that support dylibs.
+ ifneq ($(DISABLE_EDIS),1)
+ ifneq ($(filter $(TARGETS_TO_BUILD), X86 ARM),)
+ PARALLEL_DIRS += edis
+ endif
+ endif
endif
endif
diff --git a/tools/bugpoint-passes/CMakeLists.txt b/tools/bugpoint-passes/CMakeLists.txt
new file mode 100644
index 0000000..50109a5
--- /dev/null
+++ b/tools/bugpoint-passes/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_llvm_loadable_module( BugpointPasses
+ TestPasses.cpp
+ )
diff --git a/tools/bugpoint-passes/Makefile b/tools/bugpoint-passes/Makefile
new file mode 100644
index 0000000..b4ad3e4
--- /dev/null
+++ b/tools/bugpoint-passes/Makefile
@@ -0,0 +1,23 @@
+##===- tools/bugpoint-passes/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 = BugpointPasses
+LOADABLE_MODULE = 1
+USEDLIBS =
+
+# If we don't need RTTI or EH, there's no reason to export anything
+# from this plugin.
+ifneq ($(REQUIRES_RTTI), 1)
+ifneq ($(REQUIRES_EH), 1)
+EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/bugpoint.exports
+endif
+endif
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/bugpoint/TestPasses.cpp b/tools/bugpoint-passes/TestPasses.cpp
index 900bf63..1535b03 100644
--- a/tools/bugpoint/TestPasses.cpp
+++ b/tools/bugpoint-passes/TestPasses.cpp
@@ -27,7 +27,7 @@ namespace {
class CrashOnCalls : public BasicBlockPass {
public:
static char ID; // Pass ID, replacement for typeid
- CrashOnCalls() : BasicBlockPass(&ID) {}
+ CrashOnCalls() : BasicBlockPass(ID) {}
private:
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
@@ -41,12 +41,12 @@ namespace {
return false;
}
};
+}
- char CrashOnCalls::ID = 0;
- RegisterPass<CrashOnCalls>
+char CrashOnCalls::ID = 0;
+static RegisterPass<CrashOnCalls>
X("bugpoint-crashcalls",
"BugPoint Test Pass - Intentionally crash on CallInsts");
-}
namespace {
/// DeleteCalls - This pass is used to test bugpoint. It intentionally
@@ -54,7 +54,7 @@ namespace {
class DeleteCalls : public BasicBlockPass {
public:
static char ID; // Pass ID, replacement for typeid
- DeleteCalls() : BasicBlockPass(&ID) {}
+ DeleteCalls() : BasicBlockPass(ID) {}
private:
bool runOnBasicBlock(BasicBlock &BB) {
for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
@@ -67,9 +67,9 @@ namespace {
return false;
}
};
+}
- char DeleteCalls::ID = 0;
- RegisterPass<DeleteCalls>
+char DeleteCalls::ID = 0;
+static RegisterPass<DeleteCalls>
Y("bugpoint-deletecalls",
"BugPoint Test Pass - Intentionally 'misoptimize' CallInsts");
-}
diff --git a/tools/bugpoint-passes/bugpoint.exports b/tools/bugpoint-passes/bugpoint.exports
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/bugpoint-passes/bugpoint.exports
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp
index 45a0d4d..6966671 100644
--- a/tools/bugpoint/BugDriver.cpp
+++ b/tools/bugpoint/BugDriver.cpp
@@ -56,22 +56,22 @@ void BugDriver::setNewProgram(Module *M) {
/// getPassesString - Turn a list of passes into a string which indicates the
/// command line options that must be passed to add the passes.
///
-std::string llvm::getPassesString(const std::vector<const PassInfo*> &Passes) {
+std::string llvm::getPassesString(const std::vector<std::string> &Passes) {
std::string Result;
for (unsigned i = 0, e = Passes.size(); i != e; ++i) {
if (i) Result += " ";
Result += "-";
- Result += Passes[i]->getPassArgument();
+ Result += Passes[i];
}
return Result;
}
-BugDriver::BugDriver(const char *toolname, bool as_child, bool find_bugs,
+BugDriver::BugDriver(const char *toolname, bool find_bugs,
unsigned timeout, unsigned memlimit, bool use_valgrind,
LLVMContext& ctxt)
: Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile),
Program(0), Interpreter(0), SafeInterpreter(0), gcc(0),
- run_as_child(as_child), run_find_bugs(find_bugs), Timeout(timeout),
+ run_find_bugs(find_bugs), Timeout(timeout),
MemoryLimit(memlimit), UseValgrind(use_valgrind) {}
BugDriver::~BugDriver() {
@@ -119,15 +119,13 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
Program = ParseInputFile(Filenames[0], Context);
if (Program == 0) return true;
- if (!run_as_child)
- outs() << "Read input file : '" << Filenames[0] << "'\n";
+ outs() << "Read input file : '" << Filenames[0] << "'\n";
for (unsigned i = 1, e = Filenames.size(); i != e; ++i) {
std::auto_ptr<Module> M(ParseInputFile(Filenames[i], Context));
if (M.get() == 0) return true;
- if (!run_as_child)
- outs() << "Linking in input file: '" << Filenames[i] << "'\n";
+ outs() << "Linking in input file: '" << Filenames[i] << "'\n";
std::string ErrorMessage;
if (Linker::LinkModules(Program, M.get(), &ErrorMessage)) {
errs() << ToolName << ": error linking in '" << Filenames[i] << "': "
@@ -136,8 +134,7 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
}
}
- if (!run_as_child)
- outs() << "*** All input ok\n";
+ outs() << "*** All input ok\n";
// All input files read successfully!
return false;
@@ -149,14 +146,6 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
/// variables are set up from command line arguments.
///
bool BugDriver::run(std::string &ErrMsg) {
- // The first thing to do is determine if we're running as a child. If we are,
- // then what to do is very narrow. This form of invocation is only called
- // from the runPasses method to actually run those passes in a child process.
- if (run_as_child) {
- // Execute the passes
- return runPassesAsChild(PassesToRun);
- }
-
if (run_find_bugs) {
// Rearrange the passes and apply them to the program. Repeat this process
// until the user kills the program or we find a bug.
@@ -172,7 +161,7 @@ bool BugDriver::run(std::string &ErrMsg) {
// miscompilation.
if (!PassesToRun.empty()) {
outs() << "Running selected passes on program to test for crash: ";
- if (runPasses(PassesToRun))
+ if (runPasses(Program, PassesToRun))
return debugOptimizerCrash();
}
@@ -211,7 +200,7 @@ bool BugDriver::run(std::string &ErrMsg) {
// matches, then we assume there is a miscompilation bug and try to
// diagnose it.
outs() << "*** Checking the code generator...\n";
- bool Diff = diffProgram("", "", false, &Error);
+ bool Diff = diffProgram(Program, "", "", false, &Error);
if (!Error.empty()) {
errs() << Error;
return debugCodeGeneratorCrash(ErrMsg);
diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h
index 4f6bae5..e48806a 100644
--- a/tools/bugpoint/BugDriver.h
+++ b/tools/bugpoint/BugDriver.h
@@ -47,11 +47,10 @@ class BugDriver {
const char *ToolName; // argv[0] of bugpoint
std::string ReferenceOutputFile; // Name of `good' output file
Module *Program; // The raw program, linked together
- std::vector<const PassInfo*> PassesToRun;
+ std::vector<std::string> PassesToRun;
AbstractInterpreter *Interpreter; // How to run the program
AbstractInterpreter *SafeInterpreter; // To generate reference output, etc.
GCC *gcc;
- bool run_as_child;
bool run_find_bugs;
unsigned Timeout;
unsigned MemoryLimit;
@@ -62,25 +61,24 @@ class BugDriver {
friend class ReduceMisCodegenFunctions;
public:
- BugDriver(const char *toolname, bool as_child, bool find_bugs,
+ BugDriver(const char *toolname, bool find_bugs,
unsigned timeout, unsigned memlimit, bool use_valgrind,
LLVMContext& ctxt);
~BugDriver();
const char *getToolName() const { return ToolName; }
- LLVMContext& getContext() { return Context; }
+ LLVMContext& getContext() const { return Context; }
// Set up methods... these methods are used to copy information about the
// command line arguments into instance variables of BugDriver.
//
bool addSources(const std::vector<std::string> &FileNames);
- template<class It>
- void addPasses(It I, It E) { PassesToRun.insert(PassesToRun.end(), I, E); }
- void setPassesToRun(const std::vector<const PassInfo*> &PTR) {
+ void addPass(std::string p) { PassesToRun.push_back(p); }
+ void setPassesToRun(const std::vector<std::string> &PTR) {
PassesToRun = PTR;
}
- const std::vector<const PassInfo*> &getPassesToRun() const {
+ const std::vector<std::string> &getPassesToRun() const {
return PassesToRun;
}
@@ -132,12 +130,8 @@ public:
/// runPasses - Run all of the passes in the "PassesToRun" list, discard the
/// output, and return true if any of the passes crashed.
- bool runPasses(Module *M = 0) {
- if (M == 0) M = Program;
- std::swap(M, Program);
- bool Result = runPasses(PassesToRun);
- std::swap(M, Program);
- return Result;
+ bool runPasses(Module *M) const {
+ return runPasses(M, PassesToRun);
}
Module *getProgram() const { return Program; }
@@ -169,23 +163,26 @@ public:
/// setting Error if an error occurs. This is used for code generation
/// crash testing.
///
- void compileProgram(Module *M, std::string *Error);
+ void compileProgram(Module *M, std::string *Error) const;
/// executeProgram - This method runs "Program", capturing the output of the
/// program to a file. A recommended filename may be optionally specified.
///
- std::string executeProgram(std::string OutputFilename,
+ std::string executeProgram(const Module *Program,
+ std::string OutputFilename,
std::string Bitcode,
const std::string &SharedObjects,
AbstractInterpreter *AI,
- std::string *Error);
+ std::string *Error) const;
/// executeProgramSafely - Used to create reference output with the "safe"
/// backend, if reference output is not provided. If there is a problem with
/// the code generator (e.g., llc crashes), this will return false and set
/// Error.
///
- std::string executeProgramSafely(std::string OutputFile, std::string *Error);
+ std::string executeProgramSafely(const Module *Program,
+ std::string OutputFile,
+ std::string *Error) const;
/// createReferenceFile - calls compileProgram and then records the output
/// into ReferenceOutputFile. Returns true if reference file created, false
@@ -200,23 +197,24 @@ public:
/// is different, 1 is returned. If there is a problem with the code
/// generator (e.g., llc crashes), this will return -1 and set Error.
///
- bool diffProgram(const std::string &BitcodeFile = "",
+ bool diffProgram(const Module *Program,
+ const std::string &BitcodeFile = "",
const std::string &SharedObj = "",
bool RemoveBitcode = false,
- std::string *Error = 0);
+ std::string *Error = 0) const;
- /// EmitProgressBitcode - This function is used to output the current Program
- /// to a file named "bugpoint-ID.bc".
+ /// EmitProgressBitcode - This function is used to output M to a file named
+ /// "bugpoint-ID.bc".
///
- void EmitProgressBitcode(const std::string &ID, bool NoFlyer = false);
+ void EmitProgressBitcode(const Module *M, const std::string &ID,
+ bool NoFlyer = false) const;
/// deleteInstructionFromProgram - This method clones the current Program and
/// deletes the specified instruction from the cloned module. It then runs a
/// series of cleanup passes (ADCE and SimplifyCFG) to eliminate any code
/// which depends on the value. The modified module is then returned.
///
- Module *deleteInstructionFromProgram(const Instruction *I, unsigned Simp)
- const;
+ Module *deleteInstructionFromProgram(const Instruction *I, unsigned Simp);
/// performFinalCleanups - This method clones the current Program and performs
/// a series of cleanups intended to get rid of extra cruft on the module. If
@@ -243,7 +241,7 @@ public:
/// failure. If AutoDebugCrashes is set to true, then bugpoint will
/// automatically attempt to track down a crashing pass if one exists, and
/// this method will never return null.
- Module *runPassesOn(Module *M, const std::vector<const PassInfo*> &Passes,
+ Module *runPassesOn(Module *M, const std::vector<std::string> &Passes,
bool AutoDebugCrashes = false, unsigned NumExtraArgs = 0,
const char * const *ExtraArgs = NULL);
@@ -256,7 +254,8 @@ public:
/// or failed, unless Quiet is set. ExtraArgs specifies additional arguments
/// to pass to the child bugpoint instance.
///
- bool runPasses(const std::vector<const PassInfo*> &PassesToRun,
+ bool runPasses(Module *Program,
+ const std::vector<std::string> &PassesToRun,
std::string &OutputFilename, bool DeleteOutput = false,
bool Quiet = false, unsigned NumExtraArgs = 0,
const char * const *ExtraArgs = NULL) const;
@@ -268,28 +267,26 @@ public:
/// If the passes did not compile correctly, output the command required to
/// recreate the failure. This returns true if a compiler error is found.
///
- bool runManyPasses(const std::vector<const PassInfo*> &AllPasses,
+ bool runManyPasses(const std::vector<std::string> &AllPasses,
std::string &ErrMsg);
/// writeProgramToFile - This writes the current "Program" to the named
/// bitcode file. If an error occurs, true is returned.
///
- bool writeProgramToFile(const std::string &Filename, Module *M = 0) const;
+ bool writeProgramToFile(const std::string &Filename, const Module *M) const;
private:
/// runPasses - Just like the method above, but this just returns true or
/// false indicating whether or not the optimizer crashed on the specified
/// input (true = crashed).
///
- bool runPasses(const std::vector<const PassInfo*> &PassesToRun,
+ bool runPasses(Module *M,
+ const std::vector<std::string> &PassesToRun,
bool DeleteOutput = true) const {
std::string Filename;
- return runPasses(PassesToRun, Filename, DeleteOutput);
+ return runPasses(M, PassesToRun, Filename, DeleteOutput);
}
- /// runAsChild - The actual "runPasses" guts that runs in a child process.
- int runPassesAsChild(const std::vector<const PassInfo*> &PassesToRun);
-
/// initializeExecutionEnvironment - This method is used to set up the
/// environment for executing LLVM programs.
///
@@ -306,7 +303,7 @@ Module *ParseInputFile(const std::string &InputFilename,
/// getPassesString - Turn a list of passes into a string which indicates the
/// command line options that must be passed to add the passes.
///
-std::string getPassesString(const std::vector<const PassInfo*> &Passes);
+std::string getPassesString(const std::vector<std::string> &Passes);
/// PrintFunctionList - prints out list of problematic functions
///
diff --git a/tools/bugpoint/CMakeLists.txt b/tools/bugpoint/CMakeLists.txt
index 34b759f..e06feb1 100644
--- a/tools/bugpoint/CMakeLists.txt
+++ b/tools/bugpoint/CMakeLists.txt
@@ -9,7 +9,6 @@ add_llvm_tool(bugpoint
FindBugs.cpp
Miscompilation.cpp
OptimizerDriver.cpp
- TestPasses.cpp
ToolRunner.cpp
bugpoint.cpp
)
diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp
index 2d0631c..57dc1c8 100644
--- a/tools/bugpoint/CrashDebugger.cpp
+++ b/tools/bugpoint/CrashDebugger.cpp
@@ -43,7 +43,7 @@ namespace {
}
namespace llvm {
- class ReducePassList : public ListReducer<const PassInfo*> {
+ class ReducePassList : public ListReducer<std::string> {
BugDriver &BD;
public:
ReducePassList(BugDriver &bd) : BD(bd) {}
@@ -52,15 +52,15 @@ namespace llvm {
// running the "Kept" passes fail when run on the output of the "removed"
// passes. If we return true, we update the current module of bugpoint.
//
- virtual TestResult doTest(std::vector<const PassInfo*> &Removed,
- std::vector<const PassInfo*> &Kept,
+ virtual TestResult doTest(std::vector<std::string> &Removed,
+ std::vector<std::string> &Kept,
std::string &Error);
};
}
ReducePassList::TestResult
-ReducePassList::doTest(std::vector<const PassInfo*> &Prefix,
- std::vector<const PassInfo*> &Suffix,
+ReducePassList::doTest(std::vector<std::string> &Prefix,
+ std::vector<std::string> &Suffix,
std::string &Error) {
sys::Path PrefixOutput;
Module *OrigProgram = 0;
@@ -68,7 +68,7 @@ ReducePassList::doTest(std::vector<const PassInfo*> &Prefix,
outs() << "Checking to see if these passes crash: "
<< getPassesString(Prefix) << ": ";
std::string PfxOutput;
- if (BD.runPasses(Prefix, PfxOutput))
+ if (BD.runPasses(BD.getProgram(), Prefix, PfxOutput))
return KeepPrefix;
PrefixOutput.set(PfxOutput);
@@ -86,7 +86,7 @@ ReducePassList::doTest(std::vector<const PassInfo*> &Prefix,
outs() << "Checking to see if these passes crash: "
<< getPassesString(Suffix) << ": ";
- if (BD.runPasses(Suffix)) {
+ if (BD.runPasses(BD.getProgram(), Suffix)) {
delete OrigProgram; // The suffix crashes alone...
return KeepSuffix;
}
@@ -106,10 +106,10 @@ namespace {
///
class ReduceCrashingGlobalVariables : public ListReducer<GlobalVariable*> {
BugDriver &BD;
- bool (*TestFn)(BugDriver &, Module *);
+ bool (*TestFn)(const BugDriver &, Module *);
public:
ReduceCrashingGlobalVariables(BugDriver &bd,
- bool (*testFn)(BugDriver &, Module *))
+ bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
virtual TestResult doTest(std::vector<GlobalVariable*> &Prefix,
@@ -176,10 +176,10 @@ namespace llvm {
///
class ReduceCrashingFunctions : public ListReducer<Function*> {
BugDriver &BD;
- bool (*TestFn)(BugDriver &, Module *);
+ bool (*TestFn)(const BugDriver &, Module *);
public:
ReduceCrashingFunctions(BugDriver &bd,
- bool (*testFn)(BugDriver &, Module *))
+ bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
virtual TestResult doTest(std::vector<Function*> &Prefix,
@@ -249,9 +249,10 @@ namespace {
///
class ReduceCrashingBlocks : public ListReducer<const BasicBlock*> {
BugDriver &BD;
- bool (*TestFn)(BugDriver &, Module *);
+ bool (*TestFn)(const BugDriver &, Module *);
public:
- ReduceCrashingBlocks(BugDriver &bd, bool (*testFn)(BugDriver &, Module *))
+ ReduceCrashingBlocks(BugDriver &bd,
+ bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
virtual TestResult doTest(std::vector<const BasicBlock*> &Prefix,
@@ -311,17 +312,24 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) {
// a "persistent mapping" by turning basic blocks into <function, name> pairs.
// This won't work well if blocks are unnamed, but that is just the risk we
// have to take.
- std::vector<std::pair<Function*, std::string> > BlockInfo;
+ std::vector<std::pair<std::string, std::string> > BlockInfo;
for (SmallPtrSet<BasicBlock*, 8>::iterator I = Blocks.begin(),
E = Blocks.end(); I != E; ++I)
- BlockInfo.push_back(std::make_pair((*I)->getParent(), (*I)->getName()));
+ BlockInfo.push_back(std::make_pair((*I)->getParent()->getName(),
+ (*I)->getName()));
// Now run the CFG simplify pass on the function...
- PassManager Passes;
- Passes.add(createCFGSimplificationPass());
- Passes.add(createVerifierPass());
- Passes.run(*M);
+ std::vector<std::string> Passes;
+ Passes.push_back("simplifycfg");
+ Passes.push_back("verify");
+ Module *New = BD.runPassesOn(M, Passes);
+ delete M;
+ if (!New) {
+ errs() << "simplifycfg failed!\n";
+ exit(1);
+ }
+ M = New;
// Try running on the hacked up program...
if (TestFn(BD, M)) {
@@ -330,8 +338,10 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) {
// Make sure to use basic block pointers that point into the now-current
// module, and that they don't include any deleted blocks.
BBs.clear();
+ const ValueSymbolTable &GST = M->getValueSymbolTable();
for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
- ValueSymbolTable &ST = BlockInfo[i].first->getValueSymbolTable();
+ Function *F = cast<Function>(GST.lookup(BlockInfo[i].first));
+ ValueSymbolTable &ST = F->getValueSymbolTable();
Value* V = ST.lookup(BlockInfo[i].second);
if (V && V->getType() == Type::getLabelTy(V->getContext()))
BBs.push_back(cast<BasicBlock>(V));
@@ -348,10 +358,10 @@ namespace {
///
class ReduceCrashingInstructions : public ListReducer<const Instruction*> {
BugDriver &BD;
- bool (*TestFn)(BugDriver &, Module *);
+ bool (*TestFn)(const BugDriver &, Module *);
public:
- ReduceCrashingInstructions(BugDriver &bd, bool (*testFn)(BugDriver &,
- Module *))
+ ReduceCrashingInstructions(BugDriver &bd,
+ bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
virtual TestResult doTest(std::vector<const Instruction*> &Prefix,
@@ -422,7 +432,8 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*>
/// DebugACrash - Given a predicate that determines whether a component crashes
/// on a program, try to destructively reduce the program while still keeping
/// the predicate true.
-static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *),
+static bool DebugACrash(BugDriver &BD,
+ bool (*TestFn)(const BugDriver &, Module *),
std::string &Error) {
// See if we can get away with nuking some of the global variable initializers
// in the program...
@@ -471,7 +482,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *),
return true;
if (GVs.size() < OldSize)
- BD.EmitProgressBitcode("reduced-global-variables");
+ BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables");
}
}
}
@@ -492,7 +503,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *),
ReduceCrashingFunctions(BD, TestFn).reduceList(Functions, Error);
if (Functions.size() < OldSize)
- BD.EmitProgressBitcode("reduced-function");
+ BD.EmitProgressBitcode(BD.getProgram(), "reduced-function");
}
// Attempt to delete entire basic blocks at a time to speed up
@@ -509,7 +520,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *),
unsigned OldSize = Blocks.size();
ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error);
if (Blocks.size() < OldSize)
- BD.EmitProgressBitcode("reduced-blocks");
+ BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks");
}
// Attempt to delete instructions using bisection. This should help out nasty
@@ -602,12 +613,12 @@ ExitLoops:
}
}
- BD.EmitProgressBitcode("reduced-simplified");
+ BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified");
return false;
}
-static bool TestForOptimizerCrash(BugDriver &BD, Module *M) {
+static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) {
return BD.runPasses(M);
}
@@ -628,14 +639,14 @@ bool BugDriver::debugOptimizerCrash(const std::string &ID) {
<< (PassesToRun.size() == 1 ? ": " : "es: ")
<< getPassesString(PassesToRun) << '\n';
- EmitProgressBitcode(ID);
+ EmitProgressBitcode(Program, ID);
bool Success = DebugACrash(*this, TestForOptimizerCrash, Error);
assert(Error.empty());
return Success;
}
-static bool TestForCodeGenCrash(BugDriver &BD, Module *M) {
+static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) {
std::string Error;
BD.compileProgram(M, &Error);
if (!Error.empty()) {
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp
index 57f12d5..7312484 100644
--- a/tools/bugpoint/ExecutionDriver.cpp
+++ b/tools/bugpoint/ExecutionDriver.cpp
@@ -293,7 +293,7 @@ bool BugDriver::initializeExecutionEnvironment() {
/// setting Error if an error occurs. This is used for code generation
/// crash testing.
///
-void BugDriver::compileProgram(Module *M, std::string *Error) {
+void BugDriver::compileProgram(Module *M, std::string *Error) const {
// Emit the program to a bitcode file...
sys::Path BitcodeFile (OutputPrefix + "-test-program.bc");
std::string ErrMsg;
@@ -320,11 +320,12 @@ void BugDriver::compileProgram(Module *M, std::string *Error) {
/// program to a file, returning the filename of the file. A recommended
/// filename may be optionally specified.
///
-std::string BugDriver::executeProgram(std::string OutputFile,
+std::string BugDriver::executeProgram(const Module *Program,
+ std::string OutputFile,
std::string BitcodeFile,
const std::string &SharedObj,
AbstractInterpreter *AI,
- std::string *Error) {
+ std::string *Error) const {
if (AI == 0) AI = Interpreter;
assert(AI && "Interpreter should have been created already!");
bool CreatedBitcode = false;
@@ -399,9 +400,10 @@ std::string BugDriver::executeProgram(std::string OutputFile,
/// executeProgramSafely - Used to create reference output with the "safe"
/// backend, if reference output is not provided.
///
-std::string BugDriver::executeProgramSafely(std::string OutputFile,
- std::string *Error) {
- return executeProgram(OutputFile, "", "", SafeInterpreter, Error);
+std::string BugDriver::executeProgramSafely(const Module *Program,
+ std::string OutputFile,
+ std::string *Error) const {
+ return executeProgram(Program, OutputFile, "", "", SafeInterpreter, Error);
}
std::string BugDriver::compileSharedObject(const std::string &BitcodeFile,
@@ -440,7 +442,7 @@ bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) {
if (!Error.empty())
return false;
- ReferenceOutputFile = executeProgramSafely(Filename, &Error);
+ ReferenceOutputFile = executeProgramSafely(Program, Filename, &Error);
if (!Error.empty()) {
errs() << Error;
if (Interpreter != SafeInterpreter) {
@@ -460,12 +462,14 @@ bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) {
/// is different, 1 is returned. If there is a problem with the code
/// generator (e.g., llc crashes), this will return -1 and set Error.
///
-bool BugDriver::diffProgram(const std::string &BitcodeFile,
+bool BugDriver::diffProgram(const Module *Program,
+ const std::string &BitcodeFile,
const std::string &SharedObject,
bool RemoveBitcode,
- std::string *ErrMsg) {
+ std::string *ErrMsg) const {
// Execute the program, generating an output file...
- sys::Path Output(executeProgram("", BitcodeFile, SharedObject, 0, ErrMsg));
+ sys::Path Output(executeProgram(Program, "", BitcodeFile, SharedObject, 0,
+ ErrMsg));
if (!ErrMsg->empty())
return false;
diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp
index d5611b5..524f130 100644
--- a/tools/bugpoint/ExtractFunction.cpp
+++ b/tools/bugpoint/ExtractFunction.cpp
@@ -55,13 +55,14 @@ namespace {
/// depends on the value. The modified module is then returned.
///
Module *BugDriver::deleteInstructionFromProgram(const Instruction *I,
- unsigned Simplification) const {
- Module *Result = CloneModule(Program);
+ unsigned Simplification) {
+ // FIXME, use vmap?
+ Module *Clone = CloneModule(Program);
const BasicBlock *PBB = I->getParent();
const Function *PF = PBB->getParent();
- Module::iterator RFI = Result->begin(); // Get iterator to corresponding fn
+ Module::iterator RFI = Clone->begin(); // Get iterator to corresponding fn
std::advance(RFI, std::distance(PF->getParent()->begin(),
Module::const_iterator(PF)));
@@ -79,30 +80,23 @@ Module *BugDriver::deleteInstructionFromProgram(const Instruction *I,
// Remove the instruction from the program.
TheInst->getParent()->getInstList().erase(TheInst);
-
- //writeProgramToFile("current.bc", Result);
-
// Spiff up the output a little bit.
- PassManager Passes;
- // Make sure that the appropriate target data is always used...
- Passes.add(new TargetData(Result));
+ std::vector<std::string> Passes;
- /// FIXME: If this used runPasses() like the methods below, we could get rid
- /// of the -disable-* options!
+ /// Can we get rid of the -disable-* options?
if (Simplification > 1 && !NoDCE)
- Passes.add(createDeadCodeEliminationPass());
+ Passes.push_back("dce");
if (Simplification && !DisableSimplifyCFG)
- Passes.add(createCFGSimplificationPass()); // Delete dead control flow
-
- Passes.add(createVerifierPass());
- Passes.run(*Result);
- return Result;
-}
-
-static const PassInfo *getPI(Pass *P) {
- const PassInfo *PI = P->getPassInfo();
- delete P;
- return PI;
+ Passes.push_back("simplifycfg"); // Delete dead control flow
+
+ Passes.push_back("verify");
+ Module *New = runPassesOn(Clone, Passes);
+ delete Clone;
+ if (!New) {
+ errs() << "Instruction removal failed. Sorry. :( Please report a bug!\n";
+ exit(1);
+ }
+ return New;
}
/// performFinalCleanups - This method clones the current Program and performs
@@ -114,15 +108,15 @@ Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) {
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
I->setLinkage(GlobalValue::ExternalLinkage);
- std::vector<const PassInfo*> CleanupPasses;
- CleanupPasses.push_back(getPI(createGlobalDCEPass()));
+ std::vector<std::string> CleanupPasses;
+ CleanupPasses.push_back("globaldce");
if (MayModifySemantics)
- CleanupPasses.push_back(getPI(createDeadArgHackingPass()));
+ CleanupPasses.push_back("deadarghaX0r");
else
- CleanupPasses.push_back(getPI(createDeadArgEliminationPass()));
+ CleanupPasses.push_back("deadargelim");
- CleanupPasses.push_back(getPI(createDeadTypeEliminationPass()));
+ CleanupPasses.push_back("deadtypeelim");
Module *New = runPassesOn(M, CleanupPasses);
if (New == 0) {
@@ -138,16 +132,14 @@ Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) {
/// function. This returns null if there are no extractable loops in the
/// program or if the loop extractor crashes.
Module *BugDriver::ExtractLoop(Module *M) {
- std::vector<const PassInfo*> LoopExtractPasses;
- LoopExtractPasses.push_back(getPI(createSingleLoopExtractorPass()));
+ std::vector<std::string> LoopExtractPasses;
+ LoopExtractPasses.push_back("loop-extract-single");
Module *NewM = runPassesOn(M, LoopExtractPasses);
if (NewM == 0) {
- Module *Old = swapProgramIn(M);
outs() << "*** Loop extraction failed: ";
- EmitProgressBitcode("loopextraction", true);
+ EmitProgressBitcode(M, "loopextraction", true);
outs() << "*** Sorry. :( Please report a bug!\n";
- swapProgramIn(Old);
return 0;
}
@@ -201,7 +193,7 @@ static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) {
/// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and
/// prune appropriate entries out of M1s list.
static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
- ValueMap<const Value*, Value*> VMap) {
+ ValueMap<const Value*, Value*> &VMap) {
GlobalVariable *GV = M1->getNamedGlobal(GlobalName);
if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() ||
!GV->use_empty()) return;
@@ -327,22 +319,18 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) {
outs() << "*** Basic Block extraction failed!\n";
errs() << "Error creating temporary file: " << ErrMsg << "\n";
- M = swapProgramIn(M);
- EmitProgressBitcode("basicblockextractfail", true);
- swapProgramIn(M);
+ EmitProgressBitcode(M, "basicblockextractfail", true);
return 0;
}
sys::RemoveFileOnSignal(uniqueFilename);
std::string ErrorInfo;
- raw_fd_ostream BlocksToNotExtractFile(uniqueFilename.c_str(), ErrorInfo);
+ tool_output_file BlocksToNotExtractFile(uniqueFilename.c_str(), ErrorInfo);
if (!ErrorInfo.empty()) {
outs() << "*** Basic Block extraction failed!\n";
errs() << "Error writing list of blocks to not extract: " << ErrorInfo
<< "\n";
- M = swapProgramIn(M);
- EmitProgressBitcode("basicblockextractfail", true);
- swapProgramIn(M);
+ EmitProgressBitcode(M, "basicblockextractfail", true);
return 0;
}
for (std::vector<BasicBlock*>::const_iterator I = BBs.begin(), E = BBs.end();
@@ -351,26 +339,31 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
// If the BB doesn't have a name, give it one so we have something to key
// off of.
if (!BB->hasName()) BB->setName("tmpbb");
- BlocksToNotExtractFile << BB->getParent()->getNameStr() << " "
- << BB->getName() << "\n";
+ BlocksToNotExtractFile.os() << BB->getParent()->getNameStr() << " "
+ << BB->getName() << "\n";
+ }
+ BlocksToNotExtractFile.os().close();
+ if (BlocksToNotExtractFile.os().has_error()) {
+ errs() << "Error writing list of blocks to not extract: " << ErrorInfo
+ << "\n";
+ EmitProgressBitcode(M, "basicblockextractfail", true);
+ BlocksToNotExtractFile.os().clear_error();
+ return 0;
}
- BlocksToNotExtractFile.close();
+ BlocksToNotExtractFile.keep();
std::string uniqueFN = "--extract-blocks-file=" + uniqueFilename.str();
const char *ExtraArg = uniqueFN.c_str();
- std::vector<const PassInfo*> PI;
- std::vector<BasicBlock *> EmptyBBs; // This parameter is ignored.
- PI.push_back(getPI(createBlockExtractorPass(EmptyBBs)));
+ std::vector<std::string> PI;
+ PI.push_back("extract-blocks");
Module *Ret = runPassesOn(M, PI, false, 1, &ExtraArg);
uniqueFilename.eraseFromDisk(); // Free disk space
if (Ret == 0) {
outs() << "*** Basic Block extraction failed, please report a bug!\n";
- M = swapProgramIn(M);
- EmitProgressBitcode("basicblockextractfail", true);
- swapProgramIn(M);
+ EmitProgressBitcode(M, "basicblockextractfail", true);
}
return Ret;
}
diff --git a/tools/bugpoint/FindBugs.cpp b/tools/bugpoint/FindBugs.cpp
index 224c717..a291f9f 100644
--- a/tools/bugpoint/FindBugs.cpp
+++ b/tools/bugpoint/FindBugs.cpp
@@ -29,7 +29,7 @@ using namespace llvm;
/// If the passes did not compile correctly, output the command required to
/// recreate the failure. This returns true if a compiler error is found.
///
-bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses,
+bool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses,
std::string &ErrMsg) {
setPassesToRun(AllPasses);
outs() << "Starting bug finding procedure...\n\n";
@@ -58,11 +58,11 @@ bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses,
//
outs() << "Running selected passes on program to test for crash: ";
for(int i = 0, e = PassesToRun.size(); i != e; i++) {
- outs() << "-" << PassesToRun[i]->getPassArgument() << " ";
+ outs() << "-" << PassesToRun[i] << " ";
}
std::string Filename;
- if(runPasses(PassesToRun, Filename, false)) {
+ if(runPasses(Program, PassesToRun, Filename, false)) {
outs() << "\n";
outs() << "Optimizer passes caused failure!\n\n";
debugOptimizerCrash();
@@ -89,7 +89,7 @@ bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses,
// output (created above).
//
outs() << "*** Checking if passes caused miscompliation:\n";
- bool Diff = diffProgram(Filename, "", false, &Error);
+ bool Diff = diffProgram(Program, Filename, "", false, &Error);
if (Error.empty() && Diff) {
outs() << "\n*** diffProgram returned true!\n";
debugMiscompilation(&Error);
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
index 47ac3c5..3f2b696 100644
--- a/tools/bugpoint/Miscompilation.cpp
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -43,13 +43,13 @@ namespace {
cl::desc("Don't extract blocks when searching for miscompilations"),
cl::init(false));
- class ReduceMiscompilingPasses : public ListReducer<const PassInfo*> {
+ class ReduceMiscompilingPasses : public ListReducer<std::string> {
BugDriver &BD;
public:
ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
- virtual TestResult doTest(std::vector<const PassInfo*> &Prefix,
- std::vector<const PassInfo*> &Suffix,
+ virtual TestResult doTest(std::vector<std::string> &Prefix,
+ std::vector<std::string> &Suffix,
std::string &Error);
};
}
@@ -58,8 +58,8 @@ namespace {
/// group, see if they still break the program.
///
ReduceMiscompilingPasses::TestResult
-ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
- std::vector<const PassInfo*> &Suffix,
+ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
+ std::vector<std::string> &Suffix,
std::string &Error) {
// First, run the program with just the Suffix passes. If it is still broken
// with JUST the kept passes, discard the prefix passes.
@@ -67,17 +67,18 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
<< "' compiles correctly: ";
std::string BitcodeResult;
- if (BD.runPasses(Suffix, BitcodeResult, false/*delete*/, true/*quiet*/)) {
+ if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/,
+ true/*quiet*/)) {
errs() << " Error running this sequence of passes"
<< " on the input program!\n";
BD.setPassesToRun(Suffix);
- BD.EmitProgressBitcode("pass-error", false);
+ BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false);
exit(BD.debugOptimizerCrash());
}
// Check to see if the finished program matches the reference output...
- bool Diff = BD.diffProgram(BitcodeResult, "", true /*delete bitcode*/,
- &Error);
+ bool Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "",
+ true /*delete bitcode*/, &Error);
if (!Error.empty())
return InternalError;
if (Diff) {
@@ -104,16 +105,17 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
// kept passes, we can update our bitcode file to include the result of the
// prefix passes, then discard the prefix passes.
//
- if (BD.runPasses(Prefix, BitcodeResult, false/*delete*/, true/*quiet*/)) {
+ if (BD.runPasses(BD.getProgram(), Prefix, BitcodeResult, false/*delete*/,
+ true/*quiet*/)) {
errs() << " Error running this sequence of passes"
<< " on the input program!\n";
BD.setPassesToRun(Prefix);
- BD.EmitProgressBitcode("pass-error", false);
+ BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false);
exit(BD.debugOptimizerCrash());
}
// If the prefix maintains the predicate by itself, only keep the prefix!
- Diff = BD.diffProgram(BitcodeResult, "", false, &Error);
+ Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "", false, &Error);
if (!Error.empty())
return InternalError;
if (Diff) {
@@ -144,16 +146,18 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
<< getPassesString(Prefix) << "' passes: ";
OwningPtr<Module> OriginalInput(BD.swapProgramIn(PrefixOutput.take()));
- if (BD.runPasses(Suffix, BitcodeResult, false/*delete*/, true/*quiet*/)) {
+ if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/,
+ true/*quiet*/)) {
errs() << " Error running this sequence of passes"
<< " on the input program!\n";
BD.setPassesToRun(Suffix);
- BD.EmitProgressBitcode("pass-error", false);
+ BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false);
exit(BD.debugOptimizerCrash());
}
// Run the result...
- Diff = BD.diffProgram(BitcodeResult, "", true /*delete bitcode*/, &Error);
+ Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "",
+ true /*delete bitcode*/, &Error);
if (!Error.empty())
return InternalError;
if (Diff) {
@@ -198,18 +202,20 @@ namespace {
return NoFailure;
}
- int TestFuncs(const std::vector<Function*> &Prefix, std::string &Error);
+ bool TestFuncs(const std::vector<Function*> &Prefix, std::string &Error);
};
}
/// TestMergedProgram - Given two modules, link them together and run the
-/// program, checking to see if the program matches the diff. If the diff
-/// matches, return false, otherwise return true. If the DeleteInputs argument
-/// is set to true then this function deletes both input modules before it
-/// returns.
+/// program, checking to see if the program matches the diff. If there is
+/// an error, return NULL. If not, return the merged module. The Broken argument
+/// will be set to true if the output is different. If the DeleteInputs
+/// argument is set to true then this function deletes both input
+/// modules before it returns.
///
-static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2,
- bool DeleteInputs, std::string &Error) {
+static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2,
+ bool DeleteInputs, std::string &Error,
+ bool &Broken) {
// Link the two portions of the program back to together.
std::string ErrorMsg;
if (!DeleteInputs) {
@@ -223,24 +229,22 @@ static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2,
}
delete M2; // We are done with this module.
- OwningPtr<Module> OldProgram(BD.swapProgramIn(M1));
-
- // Execute the program. If it does not match the expected output, we must
- // return true.
- bool Broken = BD.diffProgram("", "", false, &Error);
+ // Execute the program.
+ Broken = BD.diffProgram(M1, "", "", false, &Error);
if (!Error.empty()) {
- // Delete the linked module & restore the original
- delete BD.swapProgramIn(OldProgram.take());
+ // Delete the linked module
+ delete M1;
+ return NULL;
}
- return Broken;
+ return M1;
}
/// TestFuncs - split functions in a Module into two groups: those that are
/// under consideration for miscompilation vs. those that are not, and test
/// accordingly. Each group of functions becomes a separate Module.
///
-int ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
- std::string &Error) {
+bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
+ std::string &Error) {
// Test to see if the function is misoptimized if we ONLY run it on the
// functions listed in Funcs.
outs() << "Checking to see if the program is misoptimized when "
@@ -250,14 +254,35 @@ int ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
PrintFunctionList(Funcs);
outs() << '\n';
- // Split the module into the two halves of the program we want.
+ // Create a clone for two reasons:
+ // * If the optimization passes delete any function, the deleted function
+ // will be in the clone and Funcs will still point to valid memory
+ // * If the optimization passes use interprocedural information to break
+ // a function, we want to continue with the original function. Otherwise
+ // we can conclude that a function triggers the bug when in fact one
+ // needs a larger set of original functions to do so.
ValueMap<const Value*, Value*> VMap;
+ Module *Clone = CloneModule(BD.getProgram(), VMap);
+ Module *Orig = BD.swapProgramIn(Clone);
+
+ std::vector<Function*> FuncsOnClone;
+ for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
+ Function *F = cast<Function>(VMap[Funcs[i]]);
+ FuncsOnClone.push_back(F);
+ }
+
+ // Split the module into the two halves of the program we want.
+ VMap.clear();
Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap);
- Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, Funcs,
+ Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone,
VMap);
// Run the predicate, note that the predicate will delete both input modules.
- return TestFn(BD, ToOptimize, ToNotOptimize, Error);
+ bool Broken = TestFn(BD, ToOptimize, ToNotOptimize, Error);
+
+ delete BD.swapProgramIn(Orig);
+
+ return Broken;
}
/// DisambiguateGlobalSymbols - Give anonymous global values names.
@@ -307,10 +332,13 @@ static bool ExtractLoops(BugDriver &BD,
// has broken. If something broke, then we'll inform the user and stop
// extraction.
AbstractInterpreter *AI = BD.switchToSafeInterpreter();
- bool Failure = TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize,
- false, Error);
- if (!Error.empty())
+ bool Failure;
+ Module *New = TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize,
+ false, Error, Failure);
+ if (!New)
return false;
+ // Delete the original and set the new program.
+ delete BD.swapProgramIn(New);
if (Failure) {
BD.switchToInterpreter(AI);
@@ -449,18 +477,36 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs,
// Split the module into the two halves of the program we want.
ValueMap<const Value*, Value*> VMap;
+ Module *Clone = CloneModule(BD.getProgram(), VMap);
+ Module *Orig = BD.swapProgramIn(Clone);
+ std::vector<Function*> FuncsOnClone;
+ std::vector<BasicBlock*> BBsOnClone;
+ for (unsigned i = 0, e = FunctionsBeingTested.size(); i != e; ++i) {
+ Function *F = cast<Function>(VMap[FunctionsBeingTested[i]]);
+ FuncsOnClone.push_back(F);
+ }
+ for (unsigned i = 0, e = BBs.size(); i != e; ++i) {
+ BasicBlock *BB = cast<BasicBlock>(VMap[BBs[i]]);
+ BBsOnClone.push_back(BB);
+ }
+ VMap.clear();
+
Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap);
Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
- FunctionsBeingTested,
+ FuncsOnClone,
VMap);
// Try the extraction. If it doesn't work, then the block extractor crashed
// or something, in which case bugpoint can't chase down this possibility.
- if (Module *New = BD.ExtractMappedBlocksFromModule(BBs, ToOptimize)) {
+ if (Module *New = BD.ExtractMappedBlocksFromModule(BBsOnClone, ToOptimize)) {
delete ToOptimize;
- // Run the predicate, not that the predicate will delete both input modules.
- return TestFn(BD, New, ToNotOptimize, Error);
+ // Run the predicate,
+ // note that the predicate will delete both input modules.
+ bool Ret = TestFn(BD, New, ToNotOptimize, Error);
+ delete BD.swapProgramIn(Orig);
+ return Ret;
}
+ delete BD.swapProgramIn(Orig);
delete ToOptimize;
delete ToNotOptimize;
return false;
@@ -655,8 +701,13 @@ static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe,
delete Test;
outs() << " Checking to see if the merged program executes correctly: ";
- bool Broken = TestMergedProgram(BD, Optimized, Safe, true, Error);
- if (Error.empty()) outs() << (Broken ? " nope.\n" : " yup.\n");
+ bool Broken;
+ Module *New = TestMergedProgram(BD, Optimized, Safe, true, Error, Broken);
+ if (New) {
+ outs() << (Broken ? " nope.\n" : " yup.\n");
+ // Delete the original and set the new program.
+ delete BD.swapProgramIn(New);
+ }
return Broken;
}
@@ -678,7 +729,7 @@ void BugDriver::debugMiscompilation(std::string *Error) {
outs() << "\n*** Found miscompiling pass"
<< (getPassesToRun().size() == 1 ? "" : "es") << ": "
<< getPassesString(getPassesToRun()) << '\n';
- EmitProgressBitcode("passinput");
+ EmitProgressBitcode(Program, "passinput");
std::vector<Function *> MiscompiledFunctions =
DebugAMiscompilation(*this, TestOptimizer, *Error);
@@ -694,14 +745,12 @@ void BugDriver::debugMiscompilation(std::string *Error) {
VMap);
outs() << " Non-optimized portion: ";
- ToNotOptimize = swapProgramIn(ToNotOptimize);
- EmitProgressBitcode("tonotoptimize", true);
- setNewProgram(ToNotOptimize); // Delete hacked module.
+ EmitProgressBitcode(ToNotOptimize, "tonotoptimize", true);
+ delete ToNotOptimize; // Delete hacked module.
outs() << " Portion that is input to optimizer: ";
- ToOptimize = swapProgramIn(ToOptimize);
- EmitProgressBitcode("tooptimize");
- setNewProgram(ToOptimize); // Delete hacked module.
+ EmitProgressBitcode(ToOptimize, "tooptimize");
+ delete ToOptimize; // Delete hacked module.
return;
}
@@ -921,7 +970,8 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
// Run the code generator on the `Test' code, loading the shared library.
// The function returns whether or not the new output differs from reference.
- bool Result = BD.diffProgram(TestModuleBC.str(), SharedObject, false, &Error);
+ bool Result = BD.diffProgram(BD.getProgram(), TestModuleBC.str(),
+ SharedObject, false, &Error);
if (!Error.empty())
return false;
@@ -938,7 +988,8 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
///
bool BugDriver::debugCodeGenerator(std::string *Error) {
if ((void*)SafeInterpreter == (void*)Interpreter) {
- std::string Result = executeProgramSafely("bugpoint.safe.out", Error);
+ std::string Result = executeProgramSafely(Program, "bugpoint.safe.out",
+ Error);
if (Error->empty()) {
outs() << "\n*** The \"safe\" i.e. 'known good' backend cannot match "
<< "the reference diff. This may be due to a\n front-end "
diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp
index 3a6149b..3600ca6 100644
--- a/tools/bugpoint/OptimizerDriver.cpp
+++ b/tools/bugpoint/OptimizerDriver.cpp
@@ -27,6 +27,8 @@
#include "llvm/Target/TargetData.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
@@ -51,26 +53,34 @@ namespace {
/// file. If an error occurs, true is returned.
///
bool BugDriver::writeProgramToFile(const std::string &Filename,
- Module *M) const {
+ const Module *M) const {
std::string ErrInfo;
- raw_fd_ostream Out(Filename.c_str(), ErrInfo,
- raw_fd_ostream::F_Binary);
- if (!ErrInfo.empty()) return true;
-
- WriteBitcodeToFile(M ? M : Program, Out);
- return false;
+ tool_output_file Out(Filename.c_str(), ErrInfo,
+ raw_fd_ostream::F_Binary);
+ if (ErrInfo.empty()) {
+ WriteBitcodeToFile(M, Out.os());
+ Out.os().close();
+ if (!Out.os().has_error()) {
+ Out.keep();
+ return false;
+ }
+ }
+ Out.os().clear_error();
+ return true;
}
/// EmitProgressBitcode - This function is used to output the current Program
/// to a file named "bugpoint-ID.bc".
///
-void BugDriver::EmitProgressBitcode(const std::string &ID, bool NoFlyer) {
+void BugDriver::EmitProgressBitcode(const Module *M,
+ const std::string &ID,
+ bool NoFlyer) const {
// Output the input to the current pass to a bitcode file, emit a message
// telling the user how to reproduce it: opt -foo blah.bc
//
std::string Filename = OutputPrefix + "-" + ID + ".bc";
- if (writeProgramToFile(Filename)) {
+ if (writeProgramToFile(Filename, M)) {
errs() << "Error opening file '" << Filename << "' for writing!\n";
return;
}
@@ -83,39 +93,12 @@ void BugDriver::EmitProgressBitcode(const std::string &ID, bool NoFlyer) {
outs() << getPassesString(PassesToRun) << "\n";
}
-int BugDriver::runPassesAsChild(const std::vector<const PassInfo*> &Passes) {
- std::string ErrInfo;
- raw_fd_ostream OutFile(ChildOutput.c_str(), ErrInfo,
- raw_fd_ostream::F_Binary);
- if (!ErrInfo.empty()) {
- errs() << "Error opening bitcode file: " << ChildOutput << "\n";
- return 1;
- }
-
- PassManager PM;
- // Make sure that the appropriate target data is always used...
- PM.add(new TargetData(Program));
-
- for (unsigned i = 0, e = Passes.size(); i != e; ++i) {
- if (Passes[i]->getNormalCtor())
- PM.add(Passes[i]->getNormalCtor()());
- else
- errs() << "Cannot create pass yet: " << Passes[i]->getPassName() << "\n";
- }
- // Check that the module is well formed on completion of optimization
- PM.add(createVerifierPass());
-
- // Write bitcode out to disk as the last step...
- PM.add(createBitcodeWriterPass(OutFile));
-
- // Run all queued passes.
- PM.run(*Program);
-
- return 0;
-}
-
cl::opt<bool> SilencePasses("silence-passes", cl::desc("Suppress output of running passes (both stdout and stderr)"));
+static cl::list<std::string> OptArgs("opt-args", cl::Positional,
+ cl::desc("<opt arguments>..."),
+ cl::ZeroOrMore, cl::PositionalEatsArgs);
+
/// runPasses - Run the specified passes on Program, outputting a bitcode file
/// and writing the filename into OutputFile if successful. If the
/// optimizations fail for some reason (optimizer crashes), return true,
@@ -124,7 +107,8 @@ cl::opt<bool> SilencePasses("silence-passes", cl::desc("Suppress output of runni
/// outs() a single line message indicating whether compilation was successful
/// or failed.
///
-bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
+bool BugDriver::runPasses(Module *Program,
+ const std::vector<std::string> &Passes,
std::string &OutputFilename, bool DeleteOutput,
bool Quiet, unsigned NumExtraArgs,
const char * const *ExtraArgs) const {
@@ -148,39 +132,47 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
}
std::string ErrInfo;
- raw_fd_ostream InFile(inputFilename.c_str(), ErrInfo,
- raw_fd_ostream::F_Binary);
+ tool_output_file InFile(inputFilename.c_str(), ErrInfo,
+ raw_fd_ostream::F_Binary);
if (!ErrInfo.empty()) {
errs() << "Error opening bitcode file: " << inputFilename.str() << "\n";
return 1;
}
- WriteBitcodeToFile(Program, InFile);
- InFile.close();
+ WriteBitcodeToFile(Program, InFile.os());
+ InFile.os().close();
+ if (InFile.os().has_error()) {
+ errs() << "Error writing bitcode file: " << inputFilename.str() << "\n";
+ InFile.os().clear_error();
+ return 1;
+ }
+ InFile.keep();
// setup the child process' arguments
SmallVector<const char*, 8> Args;
- sys::Path tool = sys::Program::FindProgramByName(ToolName);
+ sys::Path tool = FindExecutable("opt", getToolName(), (void*)"opt");
+ std::string Opt = tool.str();
if (UseValgrind) {
Args.push_back("valgrind");
Args.push_back("--error-exitcode=1");
Args.push_back("-q");
Args.push_back(tool.c_str());
} else
- Args.push_back(ToolName);
+ Args.push_back(Opt.c_str());
- Args.push_back("-as-child");
- Args.push_back("-child-output");
+ Args.push_back("-o");
Args.push_back(OutputFilename.c_str());
+ for (unsigned i = 0, e = OptArgs.size(); i != e; ++i)
+ Args.push_back(OptArgs[i].c_str());
std::vector<std::string> pass_args;
for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) {
pass_args.push_back( std::string("-load"));
pass_args.push_back( PluginLoader::getPlugin(i));
}
- for (std::vector<const PassInfo*>::const_iterator I = Passes.begin(),
+ for (std::vector<std::string>::const_iterator I = Passes.begin(),
E = Passes.end(); I != E; ++I )
- pass_args.push_back( std::string("-") + (*I)->getPassArgument() );
+ pass_args.push_back( std::string("-") + (*I) );
for (std::vector<std::string>::const_iterator I = pass_args.begin(),
E = pass_args.end(); I != E; ++I )
Args.push_back(I->c_str());
@@ -189,6 +181,12 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
Args.push_back(*ExtraArgs);
Args.push_back(0);
+ DEBUG(errs() << "\nAbout to run:\t";
+ for (unsigned i = 0, e = Args.size()-1; i != e; ++i)
+ errs() << " " << Args[i];
+ errs() << "\n";
+ );
+
sys::Path prog;
if (UseValgrind)
prog = sys::Program::FindProgramByName("valgrind");
@@ -235,27 +233,22 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
/// module, returning the transformed module on success, or a null pointer on
/// failure.
Module *BugDriver::runPassesOn(Module *M,
- const std::vector<const PassInfo*> &Passes,
+ const std::vector<std::string> &Passes,
bool AutoDebugCrashes, unsigned NumExtraArgs,
const char * const *ExtraArgs) {
- Module *OldProgram = swapProgramIn(M);
std::string BitcodeResult;
- if (runPasses(Passes, BitcodeResult, false/*delete*/, true/*quiet*/,
+ if (runPasses(M, Passes, BitcodeResult, false/*delete*/, true/*quiet*/,
NumExtraArgs, ExtraArgs)) {
if (AutoDebugCrashes) {
errs() << " Error running this sequence of passes"
<< " on the input program!\n";
- delete OldProgram;
- EmitProgressBitcode("pass-error", false);
+ delete swapProgramIn(M);
+ EmitProgressBitcode(M, "pass-error", false);
exit(debugOptimizerCrash());
}
- swapProgramIn(OldProgram);
return 0;
}
- // Restore the current program.
- swapProgramIn(OldProgram);
-
Module *Ret = ParseInputFile(BitcodeResult, Context);
if (Ret == 0) {
errs() << getToolName() << ": Error reading bitcode file '"
diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp
index 3149a7a..36dbe14 100644
--- a/tools/bugpoint/ToolRunner.cpp
+++ b/tools/bugpoint/ToolRunner.cpp
@@ -627,8 +627,8 @@ CBE *AbstractInterpreter::createCBE(const char *Argv0,
// GCC abstraction
//
-static bool IsARMArchitecture(std::vector<std::string> Args) {
- for (std::vector<std::string>::const_iterator
+static bool IsARMArchitecture(std::vector<const char*> Args) {
+ for (std::vector<const char*>::const_iterator
I = Args.begin(), E = Args.end(); I != E; ++I) {
if (StringRef(*I).equals_lower("-arch")) {
++I;
@@ -673,7 +673,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
// explicitly told what architecture it is working on, so we get
// it from gcc flags
if ((TargetTriple.getOS() == Triple::Darwin) &&
- !IsARMArchitecture(ArgsForGCC))
+ !IsARMArchitecture(GCCArgs))
GCCArgs.push_back("-force_cpusubtype_ALL");
}
}
@@ -721,6 +721,10 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
std::vector<const char*> ProgramArgs;
+ // Declared here so that the destructor only runs after
+ // ProgramArgs is used.
+ std::string Exec;
+
if (RemoteClientPath.isEmpty())
ProgramArgs.push_back(OutputBinary.c_str());
else {
@@ -741,7 +745,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
// Full path to the binary. We need to cd to the exec directory because
// there is a dylib there that the exec expects to find in the CWD
char* env_pwd = getenv("PWD");
- std::string Exec = "cd ";
+ Exec = "cd ";
Exec += env_pwd;
Exec += "; ./";
Exec += OutputBinary.c_str();
diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp
index ba5234b..79cf563 100644
--- a/tools/bugpoint/bugpoint.cpp
+++ b/tools/bugpoint/bugpoint.cpp
@@ -29,13 +29,6 @@
#include "llvm/LinkAllVMCore.h"
using namespace llvm;
-// AsChild - Specifies that this invocation of bugpoint is being generated
-// from a parent process. It is not intended to be used by users so the
-// option is hidden.
-static cl::opt<bool>
-AsChild("as-child", cl::desc("Run bugpoint as child process"),
- cl::ReallyHidden);
-
static cl::opt<bool>
FindBugs("find-bugs", cl::desc("Run many different optimization sequences "
"on program to find bugs"), cl::init(false));
@@ -90,8 +83,9 @@ namespace {
AddToDriver(BugDriver &_D) : D(_D) {}
virtual void add(Pass *P) {
- const PassInfo *PI = P->getPassInfo();
- D.addPasses(&PI, &PI + 1);
+ const void *ID = P->getPassID();
+ const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID);
+ D.addPass(PI->getPassArgument());
}
};
}
@@ -110,8 +104,8 @@ int main(int argc, char **argv) {
// If we have an override, set it and then track the triple we want Modules
// to use.
if (!OverrideTriple.empty()) {
- TargetTriple.setTriple(OverrideTriple);
- outs() << "Override triple set to '" << OverrideTriple << "'\n";
+ TargetTriple.setTriple(Triple::normalize(OverrideTriple));
+ outs() << "Override triple set to '" << TargetTriple.getTriple() << "'\n";
}
if (MemoryLimit < 0) {
@@ -123,7 +117,7 @@ int main(int argc, char **argv) {
MemoryLimit = 100;
}
- BugDriver D(argv[0], AsChild, FindBugs, TimeoutValue, MemoryLimit,
+ BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit,
UseValgrind, Context);
if (D.addSources(InputFilenames)) return 1;
@@ -143,7 +137,13 @@ int main(int argc, char **argv) {
/*RunInliner=*/true,
/*VerifyEach=*/false);
- D.addPasses(PassList.begin(), PassList.end());
+
+ for (std::vector<const PassInfo*>::iterator I = PassList.begin(),
+ E = PassList.end();
+ I != E; ++I) {
+ const PassInfo* PI = *I;
+ D.addPass(PI->getPassArgument());
+ }
// Bugpoint has the ability of generating a plethora of core files, so to
// avoid filling up the disk, we prevent it
diff --git a/tools/edis/CMakeLists.txt b/tools/edis/CMakeLists.txt
index f7a199d..2019995 100644
--- a/tools/edis/CMakeLists.txt
+++ b/tools/edis/CMakeLists.txt
@@ -1,22 +1,10 @@
set(LLVM_NO_RTTI 1)
-add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/EDInfo.inc
- COMMAND ${LLVM_TABLEGEN_EXE} -o ${CMAKE_CURRENT_BINARY_DIR}/EDInfo.inc
- -gen-enhanced-disassembly-header ${CMAKE_CURRENT_SOURCE_DIR}/EDInfo.td
- DEPENDS tblgen
- COMMENT "Building enhanced disassembly semantic information header (EDInfo.inc)")
-set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/EDInfo.inc PROPERTIES GENERATED 1)
-
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_llvm_library(EnhancedDisassembly
- EDDisassembler.cpp
- EDInst.cpp
- EDMain.cpp
- EDOperand.cpp
- EDToken.cpp
../../include/llvm-c/EnhancedDisassembly.h
- ${CMAKE_CURRENT_BINARY_DIR}/EDInfo.inc
+ EDMain.cpp
)
set_target_properties(EnhancedDisassembly
diff --git a/tools/edis/EDDisassembler.cpp b/tools/edis/EDDisassembler.cpp
deleted file mode 100644
index 85e41e6..0000000
--- a/tools/edis/EDDisassembler.cpp
+++ /dev/null
@@ -1,407 +0,0 @@
-//===-EDDisassembler.cpp - LLVM Enhanced Disassembler ---------------------===//
-//
-// 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 Enhanced Disassembly library's disassembler class.
-// The disassembler is responsible for vending individual instructions according
-// to a given architecture and disassembly syntax.
-//
-//===----------------------------------------------------------------------===//
-
-#include "EDDisassembler.h"
-#include "EDInst.h"
-
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/MC/EDInstInfo.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDisassembler.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCParser/AsmLexer.h"
-#include "llvm/MC/MCParser/AsmParser.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/MemoryObject.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Target/TargetAsmLexer.h"
-#include "llvm/Target/TargetAsmParser.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/Target/TargetSelect.h"
-
-using namespace llvm;
-
-bool EDDisassembler::sInitialized = false;
-EDDisassembler::DisassemblerMap_t EDDisassembler::sDisassemblers;
-
-struct TripleMap {
- Triple::ArchType Arch;
- const char *String;
-};
-
-static struct TripleMap triplemap[] = {
- { Triple::x86, "i386-unknown-unknown" },
- { Triple::x86_64, "x86_64-unknown-unknown" },
- { Triple::arm, "arm-unknown-unknown" },
- { Triple::thumb, "thumb-unknown-unknown" },
- { Triple::InvalidArch, NULL, }
-};
-
-/// infoFromArch - Returns the TripleMap corresponding to a given architecture,
-/// or NULL if there is an error
-///
-/// @arg arch - The Triple::ArchType for the desired architecture
-static const char *tripleFromArch(Triple::ArchType arch) {
- unsigned int infoIndex;
-
- for (infoIndex = 0; triplemap[infoIndex].String != NULL; ++infoIndex) {
- if (arch == triplemap[infoIndex].Arch)
- return triplemap[infoIndex].String;
- }
-
- return NULL;
-}
-
-/// getLLVMSyntaxVariant - gets the constant to use to get an assembly printer
-/// for the desired assembly syntax, suitable for passing to
-/// Target::createMCInstPrinter()
-///
-/// @arg arch - The target architecture
-/// @arg syntax - The assembly syntax in sd form
-static int getLLVMSyntaxVariant(Triple::ArchType arch,
- EDAssemblySyntax_t syntax) {
- switch (syntax) {
- default:
- return -1;
- // Mappings below from X86AsmPrinter.cpp
- case kEDAssemblySyntaxX86ATT:
- if (arch == Triple::x86 || arch == Triple::x86_64)
- return 0;
- else
- return -1;
- case kEDAssemblySyntaxX86Intel:
- if (arch == Triple::x86 || arch == Triple::x86_64)
- return 1;
- else
- return -1;
- case kEDAssemblySyntaxARMUAL:
- if (arch == Triple::arm || arch == Triple::thumb)
- return 0;
- else
- return -1;
- }
-}
-
-void EDDisassembler::initialize() {
- if (sInitialized)
- return;
-
- sInitialized = true;
-
- InitializeAllTargetInfos();
- InitializeAllTargets();
- InitializeAllAsmPrinters();
- InitializeAllAsmParsers();
- InitializeAllDisassemblers();
-}
-
-#undef BRINGUP_TARGET
-
-EDDisassembler *EDDisassembler::getDisassembler(Triple::ArchType arch,
- EDAssemblySyntax_t syntax) {
- CPUKey key;
- key.Arch = arch;
- key.Syntax = syntax;
-
- EDDisassembler::DisassemblerMap_t::iterator i = sDisassemblers.find(key);
-
- if (i != sDisassemblers.end()) {
- return i->second;
- } else {
- EDDisassembler* sdd = new EDDisassembler(key);
- if (!sdd->valid()) {
- delete sdd;
- return NULL;
- }
-
- sDisassemblers[key] = sdd;
-
- return sdd;
- }
-
- return NULL;
-}
-
-EDDisassembler *EDDisassembler::getDisassembler(StringRef str,
- EDAssemblySyntax_t syntax) {
- Triple triple(str);
-
- return getDisassembler(triple.getArch(), syntax);
-}
-
-EDDisassembler::EDDisassembler(CPUKey &key) :
- Valid(false),
- HasSemantics(false),
- ErrorStream(nulls()),
- Key(key) {
- const char *triple = tripleFromArch(key.Arch);
-
- if (!triple)
- return;
-
- LLVMSyntaxVariant = getLLVMSyntaxVariant(key.Arch, key.Syntax);
-
- if (LLVMSyntaxVariant < 0)
- return;
-
- std::string tripleString(triple);
- std::string errorString;
-
- Tgt = TargetRegistry::lookupTarget(tripleString,
- errorString);
-
- if (!Tgt)
- return;
-
- std::string featureString;
-
- OwningPtr<const TargetMachine>
- targetMachine(Tgt->createTargetMachine(tripleString,
- featureString));
-
- const TargetRegisterInfo *registerInfo = targetMachine->getRegisterInfo();
-
- if (!registerInfo)
- return;
-
- initMaps(*registerInfo);
-
- AsmInfo.reset(Tgt->createAsmInfo(tripleString));
-
- if (!AsmInfo)
- return;
-
- Disassembler.reset(Tgt->createMCDisassembler());
-
- if (!Disassembler)
- return;
-
- InstInfos = Disassembler->getEDInfo();
-
- InstString.reset(new std::string);
- InstStream.reset(new raw_string_ostream(*InstString));
- InstPrinter.reset(Tgt->createMCInstPrinter(LLVMSyntaxVariant, *AsmInfo));
-
- if (!InstPrinter)
- return;
-
- GenericAsmLexer.reset(new AsmLexer(*AsmInfo));
- SpecificAsmLexer.reset(Tgt->createAsmLexer(*AsmInfo));
- SpecificAsmLexer->InstallLexer(*GenericAsmLexer);
-
- initMaps(*targetMachine->getRegisterInfo());
-
- Valid = true;
-}
-
-EDDisassembler::~EDDisassembler() {
- if (!valid())
- return;
-}
-
-namespace {
- /// EDMemoryObject - a subclass of MemoryObject that allows use of a callback
- /// as provided by the sd interface. See MemoryObject.
- class EDMemoryObject : public llvm::MemoryObject {
- private:
- EDByteReaderCallback Callback;
- void *Arg;
- public:
- EDMemoryObject(EDByteReaderCallback callback,
- void *arg) : Callback(callback), Arg(arg) { }
- ~EDMemoryObject() { }
- uint64_t getBase() const { return 0x0; }
- uint64_t getExtent() const { return (uint64_t)-1; }
- int readByte(uint64_t address, uint8_t *ptr) const {
- if (!Callback)
- return -1;
-
- if (Callback(ptr, address, Arg))
- return -1;
-
- return 0;
- }
- };
-}
-
-EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader,
- uint64_t address,
- void *arg) {
- EDMemoryObject memoryObject(byteReader, arg);
-
- MCInst* inst = new MCInst;
- uint64_t byteSize;
-
- if (!Disassembler->getInstruction(*inst,
- byteSize,
- memoryObject,
- address,
- ErrorStream)) {
- delete inst;
- return NULL;
- } else {
- const llvm::EDInstInfo *thisInstInfo;
-
- thisInstInfo = &InstInfos[inst->getOpcode()];
-
- EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo);
- return sdInst;
- }
-}
-
-void EDDisassembler::initMaps(const TargetRegisterInfo &registerInfo) {
- unsigned numRegisters = registerInfo.getNumRegs();
- unsigned registerIndex;
-
- for (registerIndex = 0; registerIndex < numRegisters; ++registerIndex) {
- const char* registerName = registerInfo.get(registerIndex).Name;
-
- RegVec.push_back(registerName);
- RegRMap[registerName] = registerIndex;
- }
-
- switch (Key.Arch) {
- default:
- break;
- case Triple::x86:
- case Triple::x86_64:
- stackPointers.insert(registerIDWithName("SP"));
- stackPointers.insert(registerIDWithName("ESP"));
- stackPointers.insert(registerIDWithName("RSP"));
-
- programCounters.insert(registerIDWithName("IP"));
- programCounters.insert(registerIDWithName("EIP"));
- programCounters.insert(registerIDWithName("RIP"));
- break;
- case Triple::arm:
- case Triple::thumb:
- stackPointers.insert(registerIDWithName("SP"));
-
- programCounters.insert(registerIDWithName("PC"));
- break;
- }
-}
-
-const char *EDDisassembler::nameWithRegisterID(unsigned registerID) const {
- if (registerID >= RegVec.size())
- return NULL;
- else
- return RegVec[registerID].c_str();
-}
-
-unsigned EDDisassembler::registerIDWithName(const char *name) const {
- regrmap_t::const_iterator iter = RegRMap.find(std::string(name));
- if (iter == RegRMap.end())
- return 0;
- else
- return (*iter).second;
-}
-
-bool EDDisassembler::registerIsStackPointer(unsigned registerID) {
- return (stackPointers.find(registerID) != stackPointers.end());
-}
-
-bool EDDisassembler::registerIsProgramCounter(unsigned registerID) {
- return (programCounters.find(registerID) != programCounters.end());
-}
-
-int EDDisassembler::printInst(std::string &str, MCInst &inst) {
- PrinterMutex.acquire();
-
- InstPrinter->printInst(&inst, *InstStream);
- InstStream->flush();
- str = *InstString;
- InstString->clear();
-
- PrinterMutex.release();
-
- return 0;
-}
-
-int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands,
- SmallVectorImpl<AsmToken> &tokens,
- const std::string &str) {
- int ret = 0;
-
- switch (Key.Arch) {
- default:
- return -1;
- case Triple::x86:
- case Triple::x86_64:
- case Triple::arm:
- case Triple::thumb:
- break;
- }
-
- const char *cStr = str.c_str();
- MemoryBuffer *buf = MemoryBuffer::getMemBuffer(cStr, cStr + strlen(cStr));
-
- StringRef instName;
- SMLoc instLoc;
-
- SourceMgr sourceMgr;
- sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over
- MCContext context(*AsmInfo);
- OwningPtr<MCStreamer> streamer(createNullStreamer(context));
- AsmParser genericParser(*Tgt, sourceMgr, context, *streamer, *AsmInfo);
- OwningPtr<TargetAsmParser> TargetParser(Tgt->createAsmParser(genericParser));
-
- AsmToken OpcodeToken = genericParser.Lex();
- AsmToken NextToken = genericParser.Lex(); // consume next token, because specificParser expects us to
-
- if (OpcodeToken.is(AsmToken::Identifier)) {
- instName = OpcodeToken.getString();
- instLoc = OpcodeToken.getLoc();
-
- if (NextToken.isNot(AsmToken::Eof) &&
- TargetParser->ParseInstruction(instName, instLoc, operands))
- ret = -1;
- } else {
- ret = -1;
- }
-
- ParserMutex.acquire();
-
- if (!ret) {
- GenericAsmLexer->setBuffer(buf);
-
- while (SpecificAsmLexer->Lex(),
- SpecificAsmLexer->isNot(AsmToken::Eof) &&
- SpecificAsmLexer->isNot(AsmToken::EndOfStatement)) {
- if (SpecificAsmLexer->is(AsmToken::Error)) {
- ret = -1;
- break;
- }
- tokens.push_back(SpecificAsmLexer->getTok());
- }
- }
-
- ParserMutex.release();
-
- return ret;
-}
-
-int EDDisassembler::llvmSyntaxVariant() const {
- return LLVMSyntaxVariant;
-}
diff --git a/tools/edis/EDDisassembler.h b/tools/edis/EDDisassembler.h
deleted file mode 100644
index 74a260e..0000000
--- a/tools/edis/EDDisassembler.h
+++ /dev/null
@@ -1,256 +0,0 @@
-//===-EDDisassembler.h - LLVM Enhanced Disassembler -------------*- 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 interface for the Enhanced Disassembly library's
-// disassembler class. The disassembler is responsible for vending individual
-// instructions according to a given architecture and disassembly syntax.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef EDDisassembler_
-#define EDDisassembler_
-
-#include "EDInfo.inc"
-
-#include "llvm-c/EnhancedDisassembly.h"
-
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Mutex.h"
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-namespace llvm {
-class AsmLexer;
-class AsmToken;
-class MCContext;
-class MCAsmInfo;
-class MCAsmLexer;
-class AsmParser;
-class TargetAsmLexer;
-class TargetAsmParser;
-class MCDisassembler;
-class MCInstPrinter;
-class MCInst;
-class MCParsedAsmOperand;
-class MCStreamer;
-template <typename T> class SmallVectorImpl;
-class SourceMgr;
-class Target;
-class TargetRegisterInfo;
-
-struct EDInstInfo;
-}
-
-/// EDDisassembler - Encapsulates a disassembler for a single architecture and
-/// disassembly syntax. Also manages the static disassembler registry.
-struct EDDisassembler {
- ////////////////////
- // Static members //
- ////////////////////
-
- /// CPUKey - Encapsulates the descriptor of an architecture/disassembly-syntax
- /// pair
- struct CPUKey {
- /// The architecture type
- llvm::Triple::ArchType Arch;
-
- /// The assembly syntax
- EDAssemblySyntax_t Syntax;
-
- /// operator== - Equality operator
- bool operator==(const CPUKey &key) const {
- return (Arch == key.Arch &&
- Syntax == key.Syntax);
- }
-
- /// operator< - Less-than operator
- bool operator<(const CPUKey &key) const {
- if(Arch > key.Arch)
- return false;
- if(Syntax >= key.Syntax)
- return false;
- return true;
- }
- };
-
- typedef std::map<CPUKey, EDDisassembler*> DisassemblerMap_t;
-
- /// True if the disassembler registry has been initialized; false if not
- static bool sInitialized;
- /// A map from disassembler specifications to disassemblers. Populated
- /// lazily.
- static DisassemblerMap_t sDisassemblers;
-
- /// getDisassembler - Returns the specified disassemble, or NULL on failure
- ///
- /// @arg arch - The desired architecture
- /// @arg syntax - The desired disassembly syntax
- static EDDisassembler *getDisassembler(llvm::Triple::ArchType arch,
- EDAssemblySyntax_t syntax);
-
- /// getDisassembler - Returns the disassembler for a given combination of
- /// CPU type, CPU subtype, and assembly syntax, or NULL on failure
- ///
- /// @arg str - The string representation of the architecture triple, e.g.,
- /// "x86_64-apple-darwin"
- /// @arg syntax - The disassembly syntax for the required disassembler
- static EDDisassembler *getDisassembler(llvm::StringRef str,
- EDAssemblySyntax_t syntax);
-
- /// initialize - Initializes the disassembler registry and the LLVM backend
- static void initialize();
-
- ////////////////////////
- // Per-object members //
- ////////////////////////
-
- /// True only if the object has been successfully initialized
- bool Valid;
- /// True if the disassembler can provide semantic information
- bool HasSemantics;
-
- /// The stream to write errors to
- llvm::raw_ostream &ErrorStream;
-
- /// The architecture/syntax pair for the current architecture
- CPUKey Key;
- /// The LLVM target corresponding to the disassembler
- const llvm::Target *Tgt;
- /// The assembly information for the target architecture
- llvm::OwningPtr<const llvm::MCAsmInfo> AsmInfo;
- /// The disassembler for the target architecture
- llvm::OwningPtr<const llvm::MCDisassembler> Disassembler;
- /// The output string for the instruction printer; must be guarded with
- /// PrinterMutex
- llvm::OwningPtr<std::string> InstString;
- /// The output stream for the disassembler; must be guarded with
- /// PrinterMutex
- llvm::OwningPtr<llvm::raw_string_ostream> InstStream;
- /// The instruction printer for the target architecture; must be guarded with
- /// PrinterMutex when printing
- llvm::OwningPtr<llvm::MCInstPrinter> InstPrinter;
- /// The mutex that guards the instruction printer's printing functions, which
- /// use a shared stream
- llvm::sys::Mutex PrinterMutex;
- /// The array of instruction information provided by the TableGen backend for
- /// the target architecture
- const llvm::EDInstInfo *InstInfos;
- /// The target-specific lexer for use in tokenizing strings, in
- /// target-independent and target-specific portions
- llvm::OwningPtr<llvm::AsmLexer> GenericAsmLexer;
- llvm::OwningPtr<llvm::TargetAsmLexer> SpecificAsmLexer;
- /// The guard for the above
- llvm::sys::Mutex ParserMutex;
- /// The LLVM number used for the target disassembly syntax variant
- int LLVMSyntaxVariant;
-
- typedef std::vector<std::string> regvec_t;
- typedef std::map<std::string, unsigned> regrmap_t;
-
- /// A vector of registers for quick mapping from LLVM register IDs to names
- regvec_t RegVec;
- /// A map of registers for quick mapping from register names to LLVM IDs
- regrmap_t RegRMap;
-
- /// A set of register IDs for aliases of the stack pointer for the current
- /// architecture
- std::set<unsigned> stackPointers;
- /// A set of register IDs for aliases of the program counter for the current
- /// architecture
- std::set<unsigned> programCounters;
-
- /// Constructor - initializes a disassembler with all the necessary objects,
- /// which come pre-allocated from the registry accessor function
- ///
- /// @arg key - the architecture and disassembly syntax for the
- /// disassembler
- EDDisassembler(CPUKey& key);
-
- /// valid - reports whether there was a failure in the constructor.
- bool valid() {
- return Valid;
- }
-
- /// hasSemantics - reports whether the disassembler can provide operands and
- /// tokens.
- bool hasSemantics() {
- return HasSemantics;
- }
-
- ~EDDisassembler();
-
- /// createInst - creates and returns an instruction given a callback and
- /// memory address, or NULL on failure
- ///
- /// @arg byteReader - A callback function that provides machine code bytes
- /// @arg address - The address of the first byte of the instruction,
- /// suitable for passing to byteReader
- /// @arg arg - An opaque argument for byteReader
- EDInst *createInst(EDByteReaderCallback byteReader,
- uint64_t address,
- void *arg);
-
- /// initMaps - initializes regVec and regRMap using the provided register
- /// info
- ///
- /// @arg registerInfo - the register information to use as a source
- void initMaps(const llvm::TargetRegisterInfo &registerInfo);
- /// nameWithRegisterID - Returns the name (owned by the EDDisassembler) of a
- /// register for a given register ID, or NULL on failure
- ///
- /// @arg registerID - the ID of the register to be queried
- const char *nameWithRegisterID(unsigned registerID) const;
- /// registerIDWithName - Returns the ID of a register for a given register
- /// name, or (unsigned)-1 on failure
- ///
- /// @arg name - The name of the register
- unsigned registerIDWithName(const char *name) const;
-
- /// registerIsStackPointer - reports whether a register ID is an alias for the
- /// stack pointer register
- ///
- /// @arg registerID - The LLVM register ID
- bool registerIsStackPointer(unsigned registerID);
- /// registerIsStackPointer - reports whether a register ID is an alias for the
- /// stack pointer register
- ///
- /// @arg registerID - The LLVM register ID
- bool registerIsProgramCounter(unsigned registerID);
-
- /// printInst - prints an MCInst to a string, returning 0 on success, or -1
- /// otherwise
- ///
- /// @arg str - A reference to a string which is filled in with the string
- /// representation of the instruction
- /// @arg inst - A reference to the MCInst to be printed
- int printInst(std::string& str,
- llvm::MCInst& inst);
-
- /// parseInst - extracts operands and tokens from a string for use in
- /// tokenizing the string. Returns 0 on success, or -1 otherwise.
- ///
- /// @arg operands - A reference to a vector that will be filled in with the
- /// parsed operands
- /// @arg tokens - A reference to a vector that will be filled in with the
- /// tokens
- /// @arg str - The string representation of the instruction
- int parseInst(llvm::SmallVectorImpl<llvm::MCParsedAsmOperand*> &operands,
- llvm::SmallVectorImpl<llvm::AsmToken> &tokens,
- const std::string &str);
-
- /// llvmSyntaxVariant - returns the LLVM syntax variant for this disassembler
- int llvmSyntaxVariant() const;
-};
-
-#endif
diff --git a/tools/edis/EDInfo.td b/tools/edis/EDInfo.td
deleted file mode 100644
index bd9ec07..0000000
--- a/tools/edis/EDInfo.td
+++ /dev/null
@@ -1 +0,0 @@
-// Intentionally empty.
diff --git a/tools/edis/EDInst.cpp b/tools/edis/EDInst.cpp
deleted file mode 100644
index c009f0f..0000000
--- a/tools/edis/EDInst.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-//===-EDInst.cpp - LLVM Enhanced Disassembler -----------------------------===//
-//
-// 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 Enhanced Disassembly library's instruction class.
-// The instruction is responsible for vending the string representation,
-// individual tokens, and operands for a single instruction.
-//
-//===----------------------------------------------------------------------===//
-
-#include "EDDisassembler.h"
-#include "EDInst.h"
-#include "EDOperand.h"
-#include "EDToken.h"
-
-#include "llvm/MC/EDInstInfo.h"
-#include "llvm/MC/MCInst.h"
-
-using namespace llvm;
-
-EDInst::EDInst(llvm::MCInst *inst,
- uint64_t byteSize,
- EDDisassembler &disassembler,
- const llvm::EDInstInfo *info) :
- Disassembler(disassembler),
- Inst(inst),
- ThisInstInfo(info),
- ByteSize(byteSize),
- BranchTarget(-1),
- MoveSource(-1),
- MoveTarget(-1) {
- OperandOrder = ThisInstInfo->operandOrders[Disassembler.llvmSyntaxVariant()];
-}
-
-EDInst::~EDInst() {
- unsigned int index;
- unsigned int numOperands = Operands.size();
-
- for (index = 0; index < numOperands; ++index)
- delete Operands[index];
-
- unsigned int numTokens = Tokens.size();
-
- for (index = 0; index < numTokens; ++index)
- delete Tokens[index];
-
- delete Inst;
-}
-
-uint64_t EDInst::byteSize() {
- return ByteSize;
-}
-
-int EDInst::stringify() {
- if (StringifyResult.valid())
- return StringifyResult.result();
-
- if (Disassembler.printInst(String, *Inst))
- return StringifyResult.setResult(-1);
-
- return StringifyResult.setResult(0);
-}
-
-int EDInst::getString(const char*& str) {
- if (stringify())
- return -1;
-
- str = String.c_str();
-
- return 0;
-}
-
-unsigned EDInst::instID() {
- return Inst->getOpcode();
-}
-
-bool EDInst::isBranch() {
- if (ThisInstInfo)
- return
- ThisInstInfo->instructionType == kInstructionTypeBranch ||
- ThisInstInfo->instructionType == kInstructionTypeCall;
- else
- return false;
-}
-
-bool EDInst::isMove() {
- if (ThisInstInfo)
- return ThisInstInfo->instructionType == kInstructionTypeMove;
- else
- return false;
-}
-
-int EDInst::parseOperands() {
- if (ParseResult.valid())
- return ParseResult.result();
-
- if (!ThisInstInfo)
- return ParseResult.setResult(-1);
-
- unsigned int opIndex;
- unsigned int mcOpIndex = 0;
-
- for (opIndex = 0; opIndex < ThisInstInfo->numOperands; ++opIndex) {
- if (isBranch() &&
- (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget)) {
- BranchTarget = opIndex;
- }
- else if (isMove()) {
- if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagSource)
- MoveSource = opIndex;
- else if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget)
- MoveTarget = opIndex;
- }
-
- EDOperand *operand = new EDOperand(Disassembler, *this, opIndex, mcOpIndex);
-
- Operands.push_back(operand);
- }
-
- return ParseResult.setResult(0);
-}
-
-int EDInst::branchTargetID() {
- if (parseOperands())
- return -1;
- return BranchTarget;
-}
-
-int EDInst::moveSourceID() {
- if (parseOperands())
- return -1;
- return MoveSource;
-}
-
-int EDInst::moveTargetID() {
- if (parseOperands())
- return -1;
- return MoveTarget;
-}
-
-int EDInst::numOperands() {
- if (parseOperands())
- return -1;
- return Operands.size();
-}
-
-int EDInst::getOperand(EDOperand *&operand, unsigned int index) {
- if (parseOperands())
- return -1;
-
- if (index >= Operands.size())
- return -1;
-
- operand = Operands[index];
- return 0;
-}
-
-int EDInst::tokenize() {
- if (TokenizeResult.valid())
- return TokenizeResult.result();
-
- if (stringify())
- return TokenizeResult.setResult(-1);
-
- return TokenizeResult.setResult(EDToken::tokenize(Tokens,
- String,
- OperandOrder,
- Disassembler));
-
-}
-
-int EDInst::numTokens() {
- if (tokenize())
- return -1;
- return Tokens.size();
-}
-
-int EDInst::getToken(EDToken *&token, unsigned int index) {
- if (tokenize())
- return -1;
- token = Tokens[index];
- return 0;
-}
-
-#ifdef __BLOCKS__
-int EDInst::visitTokens(EDTokenVisitor_t visitor) {
- if (tokenize())
- return -1;
-
- tokvec_t::iterator iter;
-
- for (iter = Tokens.begin(); iter != Tokens.end(); ++iter) {
- int ret = visitor(*iter);
- if (ret == 1)
- return 0;
- if (ret != 0)
- return -1;
- }
-
- return 0;
-}
-#endif
diff --git a/tools/edis/EDInst.h b/tools/edis/EDInst.h
deleted file mode 100644
index c8a747f..0000000
--- a/tools/edis/EDInst.h
+++ /dev/null
@@ -1,175 +0,0 @@
-//===-EDInst.h - LLVM Enhanced Disassembler ---------------------*- 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 interface for the Enhanced Disassembly library's
-// instruction class. The instruction is responsible for vending the string
-// representation, individual tokens and operands for a single instruction.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef EDInst_
-#define EDInst_
-
-#include "llvm-c/EnhancedDisassembly.h"
-
-#include "llvm/ADT/SmallVector.h"
-
-#include <string>
-#include <vector>
-
-namespace llvm {
- struct EDInstInfo;
-}
-
-/// CachedResult - Encapsulates the result of a function along with the validity
-/// of that result, so that slow functions don't need to run twice
-struct CachedResult {
- /// True if the result has been obtained by executing the function
- bool Valid;
- /// The result last obtained from the function
- int Result;
-
- /// Constructor - Initializes an invalid result
- CachedResult() : Valid(false) { }
- /// valid - Returns true if the result has been obtained by executing the
- /// function and false otherwise
- bool valid() { return Valid; }
- /// result - Returns the result of the function or an undefined value if
- /// valid() is false
- int result() { return Result; }
- /// setResult - Sets the result of the function and declares it valid
- /// returning the result (so that setResult() can be called from inside a
- /// return statement)
- /// @arg result - The result of the function
- int setResult(int result) { Result = result; Valid = true; return result; }
-};
-
-/// EDInst - Encapsulates a single instruction, which can be queried for its
-/// string representation, as well as its operands and tokens
-struct EDInst {
- /// The parent disassembler
- EDDisassembler &Disassembler;
- /// The containing MCInst
- llvm::MCInst *Inst;
- /// The instruction information provided by TableGen for this instruction
- const llvm::EDInstInfo *ThisInstInfo;
- /// The number of bytes for the machine code representation of the instruction
- uint64_t ByteSize;
-
- /// The result of the stringify() function
- CachedResult StringifyResult;
- /// The string representation of the instruction
- std::string String;
- /// The order in which operands from the InstInfo's operand information appear
- /// in String
- const char* OperandOrder;
-
- /// The result of the parseOperands() function
- CachedResult ParseResult;
- typedef llvm::SmallVector<EDOperand*, 5> opvec_t;
- /// The instruction's operands
- opvec_t Operands;
- /// The operand corresponding to the target, if the instruction is a branch
- int BranchTarget;
- /// The operand corresponding to the source, if the instruction is a move
- int MoveSource;
- /// The operand corresponding to the target, if the instruction is a move
- int MoveTarget;
-
- /// The result of the tokenize() function
- CachedResult TokenizeResult;
- typedef std::vector<EDToken*> tokvec_t;
- /// The instruction's tokens
- tokvec_t Tokens;
-
- /// Constructor - initializes an instruction given the output of the LLVM
- /// C++ disassembler
- ///
- /// @arg inst - The MCInst, which will now be owned by this object
- /// @arg byteSize - The size of the consumed instruction, in bytes
- /// @arg disassembler - The parent disassembler
- /// @arg instInfo - The instruction information produced by the table
- /// generator for this instruction
- EDInst(llvm::MCInst *inst,
- uint64_t byteSize,
- EDDisassembler &disassembler,
- const llvm::EDInstInfo *instInfo);
- ~EDInst();
-
- /// byteSize - returns the number of bytes consumed by the machine code
- /// representation of the instruction
- uint64_t byteSize();
- /// instID - returns the LLVM instruction ID of the instruction
- unsigned instID();
-
- /// stringify - populates the String and AsmString members of the instruction,
- /// returning 0 on success or -1 otherwise
- int stringify();
- /// getString - retrieves a pointer to the string representation of the
- /// instructinon, returning 0 on success or -1 otherwise
- ///
- /// @arg str - A reference to a pointer that, on success, is set to point to
- /// the string representation of the instruction; this string is still owned
- /// by the instruction and will be deleted when it is
- int getString(const char *&str);
-
- /// isBranch - Returns true if the instruction is a branch
- bool isBranch();
- /// isMove - Returns true if the instruction is a move
- bool isMove();
-
- /// parseOperands - populates the Operands member of the instruction,
- /// returning 0 on success or -1 otherwise
- int parseOperands();
- /// branchTargetID - returns the ID (suitable for use with getOperand()) of
- /// the target operand if the instruction is a branch, or -1 otherwise
- int branchTargetID();
- /// moveSourceID - returns the ID of the source operand if the instruction
- /// is a move, or -1 otherwise
- int moveSourceID();
- /// moveTargetID - returns the ID of the target operand if the instruction
- /// is a move, or -1 otherwise
- int moveTargetID();
-
- /// numOperands - returns the number of operands available to retrieve, or -1
- /// on error
- int numOperands();
- /// getOperand - retrieves an operand from the instruction's operand list by
- /// index, returning 0 on success or -1 on error
- ///
- /// @arg operand - A reference whose target is pointed at the operand on
- /// success, although the operand is still owned by the EDInst
- /// @arg index - The index of the operand in the instruction
- int getOperand(EDOperand *&operand, unsigned int index);
-
- /// tokenize - populates the Tokens member of the instruction, returning 0 on
- /// success or -1 otherwise
- int tokenize();
- /// numTokens - returns the number of tokens in the instruction, or -1 on
- /// error
- int numTokens();
- /// getToken - retrieves a token from the instruction's token list by index,
- /// returning 0 on success or -1 on error
- ///
- /// @arg token - A reference whose target is pointed at the token on success,
- /// although the token is still owned by the EDInst
- /// @arg index - The index of the token in the instrcutino
- int getToken(EDToken *&token, unsigned int index);
-
-#ifdef __BLOCKS__
- /// visitTokens - Visits each token in turn and applies a block to it,
- /// returning 0 if all blocks are visited and/or the block signals
- /// termination by returning 1; returns -1 on error
- ///
- /// @arg visitor - The visitor block to apply to all tokens.
- int visitTokens(EDTokenVisitor_t visitor);
-#endif
-};
-
-#endif
diff --git a/tools/edis/EDMain.cpp b/tools/edis/EDMain.cpp
index b6ca32f..16855b3 100644
--- a/tools/edis/EDMain.cpp
+++ b/tools/edis/EDMain.cpp
@@ -1,4 +1,4 @@
-//===-EDMain.cpp - LLVM Enhanced Disassembly C API ------------------------===//
+//===-- EDMain.cpp - LLVM Enhanced Disassembly C API ----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,33 +11,46 @@
//
//===----------------------------------------------------------------------===//
-#include "EDDisassembler.h"
-#include "EDInst.h"
-#include "EDOperand.h"
-#include "EDToken.h"
-
+// FIXME: This code isn't layered right, the headers should be moved to
+// include llvm/MC/MCDisassembler or something.
+#include "../../lib/MC/MCDisassembler/EDDisassembler.h"
+#include "../../lib/MC/MCDisassembler/EDInst.h"
+#include "../../lib/MC/MCDisassembler/EDOperand.h"
+#include "../../lib/MC/MCDisassembler/EDToken.h"
#include "llvm-c/EnhancedDisassembly.h"
+using namespace llvm;
int EDGetDisassembler(EDDisassemblerRef *disassembler,
const char *triple,
EDAssemblySyntax_t syntax) {
EDDisassembler::initialize();
- EDDisassemblerRef ret = EDDisassembler::getDisassembler(triple,
- syntax);
+ EDDisassembler::AssemblySyntax Syntax;
+ switch (syntax) {
+ default: assert(0 && "Unknown assembly syntax!");
+ case kEDAssemblySyntaxX86Intel:
+ Syntax = EDDisassembler::kEDAssemblySyntaxX86Intel;
+ break;
+ case kEDAssemblySyntaxX86ATT:
+ Syntax = EDDisassembler::kEDAssemblySyntaxX86ATT;
+ break;
+ case kEDAssemblySyntaxARMUAL:
+ Syntax = EDDisassembler::kEDAssemblySyntaxARMUAL;
+ break;
+ }
+
+ EDDisassemblerRef ret = EDDisassembler::getDisassembler(triple, Syntax);
- if (ret) {
- *disassembler = ret;
- return 0;
- } else {
+ if (!ret)
return -1;
- }
+ *disassembler = ret;
+ return 0;
}
int EDGetRegisterName(const char** regName,
EDDisassemblerRef disassembler,
unsigned regID) {
- const char* name = disassembler->nameWithRegisterID(regID);
+ const char *name = ((EDDisassembler*)disassembler)->nameWithRegisterID(regID);
if (!name)
return -1;
*regName = name;
@@ -46,24 +59,25 @@ int EDGetRegisterName(const char** regName,
int EDRegisterIsStackPointer(EDDisassemblerRef disassembler,
unsigned regID) {
- return disassembler->registerIsStackPointer(regID) ? 1 : 0;
+ return ((EDDisassembler*)disassembler)->registerIsStackPointer(regID) ? 1 : 0;
}
int EDRegisterIsProgramCounter(EDDisassemblerRef disassembler,
unsigned regID) {
- return disassembler->registerIsProgramCounter(regID) ? 1 : 0;
+ return ((EDDisassembler*)disassembler)->registerIsProgramCounter(regID) ? 1:0;
}
unsigned int EDCreateInsts(EDInstRef *insts,
unsigned int count,
EDDisassemblerRef disassembler,
- EDByteReaderCallback byteReader,
+ ::EDByteReaderCallback byteReader,
uint64_t address,
void *arg) {
unsigned int index;
for (index = 0; index < count; ++index) {
- EDInst *inst = disassembler->createInst(byteReader, address, arg);
+ EDInst *inst = ((EDDisassembler*)disassembler)->createInst(byteReader,
+ address, arg);
if (!inst)
return index;
@@ -76,163 +90,143 @@ unsigned int EDCreateInsts(EDInstRef *insts,
}
void EDReleaseInst(EDInstRef inst) {
- delete inst;
+ delete ((EDInst*)inst);
}
int EDInstByteSize(EDInstRef inst) {
- return inst->byteSize();
+ return ((EDInst*)inst)->byteSize();
}
int EDGetInstString(const char **buf,
EDInstRef inst) {
- return inst->getString(*buf);
+ return ((EDInst*)inst)->getString(*buf);
}
int EDInstID(unsigned *instID, EDInstRef inst) {
- *instID = inst->instID();
+ *instID = ((EDInst*)inst)->instID();
return 0;
}
int EDInstIsBranch(EDInstRef inst) {
- return inst->isBranch();
+ return ((EDInst*)inst)->isBranch();
}
int EDInstIsMove(EDInstRef inst) {
- return inst->isMove();
+ return ((EDInst*)inst)->isMove();
}
int EDBranchTargetID(EDInstRef inst) {
- return inst->branchTargetID();
+ return ((EDInst*)inst)->branchTargetID();
}
int EDMoveSourceID(EDInstRef inst) {
- return inst->moveSourceID();
+ return ((EDInst*)inst)->moveSourceID();
}
int EDMoveTargetID(EDInstRef inst) {
- return inst->moveTargetID();
+ return ((EDInst*)inst)->moveTargetID();
}
int EDNumTokens(EDInstRef inst) {
- return inst->numTokens();
+ return ((EDInst*)inst)->numTokens();
}
int EDGetToken(EDTokenRef *token,
EDInstRef inst,
int index) {
- return inst->getToken(*token, index);
+ return ((EDInst*)inst)->getToken(*(EDToken**)token, index);
}
int EDGetTokenString(const char **buf,
EDTokenRef token) {
- return token->getString(*buf);
+ return ((EDToken*)token)->getString(*buf);
}
int EDOperandIndexForToken(EDTokenRef token) {
- return token->operandID();
+ return ((EDToken*)token)->operandID();
}
int EDTokenIsWhitespace(EDTokenRef token) {
- if (token->type() == EDToken::kTokenWhitespace)
- return 1;
- else
- return 0;
+ return ((EDToken*)token)->type() == EDToken::kTokenWhitespace;
}
int EDTokenIsPunctuation(EDTokenRef token) {
- if (token->type() == EDToken::kTokenPunctuation)
- return 1;
- else
- return 0;
+ return ((EDToken*)token)->type() == EDToken::kTokenPunctuation;
}
int EDTokenIsOpcode(EDTokenRef token) {
- if (token->type() == EDToken::kTokenOpcode)
- return 1;
- else
- return 0;
+ return ((EDToken*)token)->type() == EDToken::kTokenOpcode;
}
int EDTokenIsLiteral(EDTokenRef token) {
- if (token->type() == EDToken::kTokenLiteral)
- return 1;
- else
- return 0;
+ return ((EDToken*)token)->type() == EDToken::kTokenLiteral;
}
int EDTokenIsRegister(EDTokenRef token) {
- if (token->type() == EDToken::kTokenRegister)
- return 1;
- else
- return 0;
+ return ((EDToken*)token)->type() == EDToken::kTokenRegister;
}
int EDTokenIsNegativeLiteral(EDTokenRef token) {
- if (token->type() != EDToken::kTokenLiteral)
+ if (((EDToken*)token)->type() != EDToken::kTokenLiteral)
return -1;
- return token->literalSign();
+ return ((EDToken*)token)->literalSign();
}
-int EDLiteralTokenAbsoluteValue(uint64_t *value,
- EDTokenRef token) {
- if (token->type() != EDToken::kTokenLiteral)
+int EDLiteralTokenAbsoluteValue(uint64_t *value, EDTokenRef token) {
+ if (((EDToken*)token)->type() != EDToken::kTokenLiteral)
return -1;
- return token->literalAbsoluteValue(*value);
+ return ((EDToken*)token)->literalAbsoluteValue(*value);
}
int EDRegisterTokenValue(unsigned *registerID,
EDTokenRef token) {
- if (token->type() != EDToken::kTokenRegister)
+ if (((EDToken*)token)->type() != EDToken::kTokenRegister)
return -1;
- return token->registerID(*registerID);
+ return ((EDToken*)token)->registerID(*registerID);
}
int EDNumOperands(EDInstRef inst) {
- return inst->numOperands();
+ return ((EDInst*)inst)->numOperands();
}
int EDGetOperand(EDOperandRef *operand,
EDInstRef inst,
int index) {
- return inst->getOperand(*operand, index);
+ return ((EDInst*)inst)->getOperand(*(EDOperand**)operand, index);
}
int EDOperandIsRegister(EDOperandRef operand) {
- return operand->isRegister();
+ return ((EDOperand*)operand)->isRegister();
}
int EDOperandIsImmediate(EDOperandRef operand) {
- return operand->isImmediate();
+ return ((EDOperand*)operand)->isImmediate();
}
int EDOperandIsMemory(EDOperandRef operand) {
- return operand->isMemory();
+ return ((EDOperand*)operand)->isMemory();
}
-int EDRegisterOperandValue(unsigned *value,
- EDOperandRef operand) {
- if (!operand->isRegister())
+int EDRegisterOperandValue(unsigned *value, EDOperandRef operand) {
+ if (!((EDOperand*)operand)->isRegister())
return -1;
- *value = operand->regVal();
+ *value = ((EDOperand*)operand)->regVal();
return 0;
}
-int EDImmediateOperandValue(uint64_t *value,
- EDOperandRef operand) {
- if (!operand->isImmediate())
+int EDImmediateOperandValue(uint64_t *value, EDOperandRef operand) {
+ if (!((EDOperand*)operand)->isImmediate())
return -1;
- *value = operand->immediateVal();
+ *value = ((EDOperand*)operand)->immediateVal();
return 0;
}
-int EDEvaluateOperand(uint64_t *result,
- EDOperandRef operand,
- EDRegisterReaderCallback regReader,
- void *arg) {
- return operand->evaluate(*result, regReader, arg);
+int EDEvaluateOperand(uint64_t *result, EDOperandRef operand,
+ ::EDRegisterReaderCallback regReader, void *arg) {
+ return ((EDOperand*)operand)->evaluate(*result, regReader, arg);
}
#ifdef __BLOCKS__
@@ -264,15 +258,13 @@ unsigned int EDBlockCreateInsts(EDInstRef *insts,
(void*)&wrapper);
}
-int EDBlockEvaluateOperand(uint64_t *result,
- EDOperandRef operand,
+int EDBlockEvaluateOperand(uint64_t *result, EDOperandRef operand,
EDRegisterBlock_t regBlock) {
- return operand->evaluate(*result, regBlock);
+ return ((EDOperand*)operand)->evaluate(*result, regBlock);
}
-int EDBlockVisitTokens(EDInstRef inst,
- EDTokenVisitor_t visitor) {
- return inst->visitTokens(visitor);
+int EDBlockVisitTokens(EDInstRef inst, ::EDTokenVisitor_t visitor) {
+ return ((EDInst*)inst)->visitTokens((llvm::EDTokenVisitor_t)visitor);
}
#else
diff --git a/tools/edis/EDOperand.cpp b/tools/edis/EDOperand.cpp
deleted file mode 100644
index d63c1c6..0000000
--- a/tools/edis/EDOperand.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-//===-EDOperand.cpp - LLVM Enhanced Disassembler --------------------------===//
-//
-// 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 Enhanced Disassembly library's operand class. The
-// operand is responsible for allowing evaluation given a particular register
-// context.
-//
-//===----------------------------------------------------------------------===//
-
-#include "EDDisassembler.h"
-#include "EDInst.h"
-#include "EDOperand.h"
-
-#include "llvm/MC/EDInstInfo.h"
-#include "llvm/MC/MCInst.h"
-
-using namespace llvm;
-
-EDOperand::EDOperand(const EDDisassembler &disassembler,
- const EDInst &inst,
- unsigned int opIndex,
- unsigned int &mcOpIndex) :
- Disassembler(disassembler),
- Inst(inst),
- OpIndex(opIndex),
- MCOpIndex(mcOpIndex) {
- unsigned int numMCOperands = 0;
-
- if (Disassembler.Key.Arch == Triple::x86 ||
- Disassembler.Key.Arch == Triple::x86_64) {
- uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
-
- switch (operandType) {
- default:
- break;
- case kOperandTypeImmediate:
- numMCOperands = 1;
- break;
- case kOperandTypeRegister:
- numMCOperands = 1;
- break;
- case kOperandTypeX86Memory:
- numMCOperands = 5;
- break;
- case kOperandTypeX86EffectiveAddress:
- numMCOperands = 4;
- break;
- case kOperandTypeX86PCRelative:
- numMCOperands = 1;
- break;
- }
- }
- else if (Disassembler.Key.Arch == Triple::arm ||
- Disassembler.Key.Arch == Triple::thumb) {
- uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
-
- switch (operandType) {
- default:
- case kOperandTypeARMRegisterList:
- break;
- case kOperandTypeImmediate:
- case kOperandTypeRegister:
- case kOperandTypeARMBranchTarget:
- case kOperandTypeARMSoImm:
- case kOperandTypeThumb2SoImm:
- case kOperandTypeARMSoImm2Part:
- case kOperandTypeARMPredicate:
- case kOperandTypeThumbITMask:
- case kOperandTypeThumb2AddrModeImm8Offset:
- case kOperandTypeARMTBAddrMode:
- case kOperandTypeThumb2AddrModeImm8s4Offset:
- numMCOperands = 1;
- break;
- case kOperandTypeThumb2SoReg:
- case kOperandTypeARMAddrMode2Offset:
- case kOperandTypeARMAddrMode3Offset:
- case kOperandTypeARMAddrMode4:
- case kOperandTypeARMAddrMode5:
- case kOperandTypeARMAddrModePC:
- case kOperandTypeThumb2AddrModeImm8:
- case kOperandTypeThumb2AddrModeImm12:
- case kOperandTypeThumb2AddrModeImm8s4:
- case kOperandTypeThumbAddrModeRR:
- case kOperandTypeThumbAddrModeSP:
- numMCOperands = 2;
- break;
- case kOperandTypeARMSoReg:
- case kOperandTypeARMAddrMode2:
- case kOperandTypeARMAddrMode3:
- case kOperandTypeThumb2AddrModeSoReg:
- case kOperandTypeThumbAddrModeS1:
- case kOperandTypeThumbAddrModeS2:
- case kOperandTypeThumbAddrModeS4:
- case kOperandTypeARMAddrMode6Offset:
- numMCOperands = 3;
- break;
- case kOperandTypeARMAddrMode6:
- numMCOperands = 4;
- break;
- }
- }
-
- mcOpIndex += numMCOperands;
-}
-
-EDOperand::~EDOperand() {
-}
-
-int EDOperand::evaluate(uint64_t &result,
- EDRegisterReaderCallback callback,
- void *arg) {
- uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
-
- switch (Disassembler.Key.Arch) {
- default:
- return -1;
- case Triple::x86:
- case Triple::x86_64:
- switch (operandType) {
- default:
- return -1;
- case kOperandTypeImmediate:
- result = Inst.Inst->getOperand(MCOpIndex).getImm();
- return 0;
- case kOperandTypeRegister:
- {
- unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
- return callback(&result, reg, arg);
- }
- case kOperandTypeX86PCRelative:
- {
- int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
-
- uint64_t ripVal;
-
- // TODO fix how we do this
-
- if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
- return -1;
-
- result = ripVal + displacement;
- return 0;
- }
- case kOperandTypeX86Memory:
- case kOperandTypeX86EffectiveAddress:
- {
- unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
- uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
- unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
- int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
- //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
-
- uint64_t addr = 0;
-
- if (baseReg) {
- uint64_t baseVal;
- if (callback(&baseVal, baseReg, arg))
- return -1;
- addr += baseVal;
- }
-
- if (indexReg) {
- uint64_t indexVal;
- if (callback(&indexVal, indexReg, arg))
- return -1;
- addr += (scaleAmount * indexVal);
- }
-
- addr += displacement;
-
- result = addr;
- return 0;
- }
- }
- break;
- case Triple::arm:
- case Triple::thumb:
- switch (operandType) {
- default:
- return -1;
- case kOperandTypeImmediate:
- result = Inst.Inst->getOperand(MCOpIndex).getImm();
- return 0;
- case kOperandTypeRegister:
- {
- unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
- return callback(&result, reg, arg);
- }
- case kOperandTypeARMBranchTarget:
- {
- int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
-
- uint64_t pcVal;
-
- if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
- return -1;
-
- result = pcVal + displacement;
- return 0;
- }
- }
- }
-
- return -1;
-}
-
-int EDOperand::isRegister() {
- return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
-}
-
-unsigned EDOperand::regVal() {
- return Inst.Inst->getOperand(MCOpIndex).getReg();
-}
-
-int EDOperand::isImmediate() {
- return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
-}
-
-uint64_t EDOperand::immediateVal() {
- return Inst.Inst->getOperand(MCOpIndex).getImm();
-}
-
-int EDOperand::isMemory() {
- uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
-
- switch (operandType) {
- default:
- return 0;
- case kOperandTypeX86Memory:
- case kOperandTypeX86PCRelative:
- case kOperandTypeX86EffectiveAddress:
- case kOperandTypeARMSoReg:
- case kOperandTypeARMSoImm:
- case kOperandTypeARMAddrMode2:
- case kOperandTypeARMAddrMode2Offset:
- case kOperandTypeARMAddrMode3:
- case kOperandTypeARMAddrMode3Offset:
- case kOperandTypeARMAddrMode4:
- case kOperandTypeARMAddrMode5:
- case kOperandTypeARMAddrMode6:
- case kOperandTypeARMAddrModePC:
- case kOperandTypeARMBranchTarget:
- case kOperandTypeThumbAddrModeS1:
- case kOperandTypeThumbAddrModeS2:
- case kOperandTypeThumbAddrModeS4:
- case kOperandTypeThumbAddrModeRR:
- case kOperandTypeThumbAddrModeSP:
- case kOperandTypeThumb2SoImm:
- case kOperandTypeThumb2AddrModeImm8:
- case kOperandTypeThumb2AddrModeImm8Offset:
- case kOperandTypeThumb2AddrModeImm12:
- case kOperandTypeThumb2AddrModeSoReg:
- case kOperandTypeThumb2AddrModeImm8s4:
- return 1;
- }
-}
-
-#ifdef __BLOCKS__
-struct RegisterReaderWrapper {
- EDRegisterBlock_t regBlock;
-};
-
-int readerWrapperCallback(uint64_t *value,
- unsigned regID,
- void *arg) {
- struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg;
- return wrapper->regBlock(value, regID);
-}
-
-int EDOperand::evaluate(uint64_t &result,
- EDRegisterBlock_t regBlock) {
- struct RegisterReaderWrapper wrapper;
- wrapper.regBlock = regBlock;
- return evaluate(result,
- readerWrapperCallback,
- (void*)&wrapper);
-}
-#endif
diff --git a/tools/edis/EDOperand.h b/tools/edis/EDOperand.h
deleted file mode 100644
index ad9345b..0000000
--- a/tools/edis/EDOperand.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//===-EDOperand.h - LLVM Enhanced Disassembler ------------------*- 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 interface for the Enhanced Disassembly library's
-// operand class. The operand is responsible for allowing evaluation given a
-// particular register context.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef EDOperand_
-#define EDOperand_
-
-#include "llvm-c/EnhancedDisassembly.h"
-
-/// EDOperand - Encapsulates a single operand, which can be evaluated by the
-/// client
-struct EDOperand {
- /// The parent disassembler
- const EDDisassembler &Disassembler;
- /// The parent instruction
- const EDInst &Inst;
-
- /// The index of the operand in the EDInst
- unsigned int OpIndex;
- /// The index of the first component of the operand in the MCInst
- unsigned int MCOpIndex;
-
- /// Constructor - Initializes an EDOperand
- ///
- /// @arg disassembler - The disassembler responsible for the operand
- /// @arg inst - The instruction containing this operand
- /// @arg opIndex - The index of the operand in inst
- /// @arg mcOpIndex - The index of the operand in the original MCInst
- EDOperand(const EDDisassembler &disassembler,
- const EDInst &inst,
- unsigned int opIndex,
- unsigned int &mcOpIndex);
- ~EDOperand();
-
- /// evaluate - Returns the numeric value of an operand to the extent possible,
- /// returning 0 on success or -1 if there was some problem (such as a
- /// register not being readable)
- ///
- /// @arg result - A reference whose target is filled in with the value of
- /// the operand (the address if it is a memory operand)
- /// @arg callback - A function to call to obtain register values
- /// @arg arg - An opaque argument to pass to callback
- int evaluate(uint64_t &result,
- EDRegisterReaderCallback callback,
- void *arg);
-
- /// isRegister - Returns 1 if the operand is a register or 0 otherwise
- int isRegister();
- /// regVal - Returns the register value.
- unsigned regVal();
-
- /// isImmediate - Returns 1 if the operand is an immediate or 0 otherwise
- int isImmediate();
- /// immediateVal - Returns the immediate value.
- uint64_t immediateVal();
-
- /// isMemory - Returns 1 if the operand is a memory location or 0 otherwise
- int isMemory();
-
-#ifdef __BLOCKS__
- /// evaluate - Like evaluate for a callback, but uses a block instead
- int evaluate(uint64_t &result,
- EDRegisterBlock_t regBlock);
-#endif
-};
-
-#endif
diff --git a/tools/edis/EDToken.cpp b/tools/edis/EDToken.cpp
deleted file mode 100644
index 3bcb0a1..0000000
--- a/tools/edis/EDToken.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-//===-EDToken.cpp - LLVM Enhanced Disassembler ----------------------------===//
-//
-// 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 Enhanced Disassembler library's token class. The
-// token is responsible for vending information about the token, such as its
-// type and logical value.
-//
-//===----------------------------------------------------------------------===//
-
-#include "EDDisassembler.h"
-#include "EDToken.h"
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
-
-using namespace llvm;
-
-EDToken::EDToken(StringRef str,
- enum tokenType type,
- uint64_t localType,
- EDDisassembler &disassembler) :
- Disassembler(disassembler),
- Str(str),
- Type(type),
- LocalType(localType),
- OperandID(-1) {
-}
-
-EDToken::~EDToken() {
-}
-
-void EDToken::makeLiteral(bool sign, uint64_t absoluteValue) {
- Type = kTokenLiteral;
- LiteralSign = sign;
- LiteralAbsoluteValue = absoluteValue;
-}
-
-void EDToken::makeRegister(unsigned registerID) {
- Type = kTokenRegister;
- RegisterID = registerID;
-}
-
-void EDToken::setOperandID(int operandID) {
- OperandID = operandID;
-}
-
-enum EDToken::tokenType EDToken::type() const {
- return Type;
-}
-
-uint64_t EDToken::localType() const {
- return LocalType;
-}
-
-StringRef EDToken::string() const {
- return Str;
-}
-
-int EDToken::operandID() const {
- return OperandID;
-}
-
-int EDToken::literalSign() const {
- if (Type != kTokenLiteral)
- return -1;
- return (LiteralSign ? 1 : 0);
-}
-
-int EDToken::literalAbsoluteValue(uint64_t &value) const {
- if (Type != kTokenLiteral)
- return -1;
- value = LiteralAbsoluteValue;
- return 0;
-}
-
-int EDToken::registerID(unsigned &registerID) const {
- if (Type != kTokenRegister)
- return -1;
- registerID = RegisterID;
- return 0;
-}
-
-int EDToken::tokenize(std::vector<EDToken*> &tokens,
- std::string &str,
- const char *operandOrder,
- EDDisassembler &disassembler) {
- SmallVector<MCParsedAsmOperand*, 5> parsedOperands;
- SmallVector<AsmToken, 10> asmTokens;
-
- if (disassembler.parseInst(parsedOperands, asmTokens, str))
- return -1;
-
- SmallVectorImpl<MCParsedAsmOperand*>::iterator operandIterator;
- unsigned int operandIndex;
- SmallVectorImpl<AsmToken>::iterator tokenIterator;
-
- operandIterator = parsedOperands.begin();
- operandIndex = 0;
-
- bool readOpcode = false;
-
- const char *wsPointer = asmTokens.begin()->getLoc().getPointer();
-
- for (tokenIterator = asmTokens.begin();
- tokenIterator != asmTokens.end();
- ++tokenIterator) {
- SMLoc tokenLoc = tokenIterator->getLoc();
-
- const char *tokenPointer = tokenLoc.getPointer();
-
- if (tokenPointer > wsPointer) {
- unsigned long wsLength = tokenPointer - wsPointer;
-
- EDToken *whitespaceToken = new EDToken(StringRef(wsPointer, wsLength),
- EDToken::kTokenWhitespace,
- 0,
- disassembler);
-
- tokens.push_back(whitespaceToken);
- }
-
- wsPointer = tokenPointer + tokenIterator->getString().size();
-
- while (operandIterator != parsedOperands.end() &&
- tokenLoc.getPointer() >
- (*operandIterator)->getEndLoc().getPointer()) {
- ++operandIterator;
- ++operandIndex;
- }
-
- EDToken *token;
-
- switch (tokenIterator->getKind()) {
- case AsmToken::Identifier:
- if (!readOpcode) {
- token = new EDToken(tokenIterator->getString(),
- EDToken::kTokenOpcode,
- (uint64_t)tokenIterator->getKind(),
- disassembler);
- readOpcode = true;
- break;
- }
- // any identifier that isn't an opcode is mere punctuation; so we fall
- // through
- default:
- token = new EDToken(tokenIterator->getString(),
- EDToken::kTokenPunctuation,
- (uint64_t)tokenIterator->getKind(),
- disassembler);
- break;
- case AsmToken::Integer:
- {
- token = new EDToken(tokenIterator->getString(),
- EDToken::kTokenLiteral,
- (uint64_t)tokenIterator->getKind(),
- disassembler);
-
- int64_t intVal = tokenIterator->getIntVal();
-
- if (intVal < 0)
- token->makeLiteral(true, -intVal);
- else
- token->makeLiteral(false, intVal);
- break;
- }
- case AsmToken::Register:
- {
- token = new EDToken(tokenIterator->getString(),
- EDToken::kTokenLiteral,
- (uint64_t)tokenIterator->getKind(),
- disassembler);
-
- token->makeRegister((unsigned)tokenIterator->getRegVal());
- break;
- }
- }
-
- if (operandIterator != parsedOperands.end() &&
- tokenLoc.getPointer() >=
- (*operandIterator)->getStartLoc().getPointer()) {
- /// operandIndex == 0 means the operand is the instruction (which the
- /// AsmParser treats as an operand but edis does not). We therefore skip
- /// operandIndex == 0 and subtract 1 from all other operand indices.
-
- if (operandIndex > 0)
- token->setOperandID(operandOrder[operandIndex - 1]);
- }
-
- tokens.push_back(token);
- }
-
- return 0;
-}
-
-int EDToken::getString(const char*& buf) {
- if (PermStr.length() == 0) {
- PermStr = Str.str();
- }
- buf = PermStr.c_str();
- return 0;
-}
diff --git a/tools/edis/EDToken.h b/tools/edis/EDToken.h
deleted file mode 100644
index e4ae91f..0000000
--- a/tools/edis/EDToken.h
+++ /dev/null
@@ -1,135 +0,0 @@
-//===-EDToken.h - LLVM Enhanced Disassembler --------------------*- 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 interface for the Enhanced Disassembly library's token
-// class. The token is responsible for vending information about the token,
-// such as its type and logical value.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef EDToken_
-#define EDToken_
-
-#include "llvm-c/EnhancedDisassembly.h"
-#include "llvm/ADT/StringRef.h"
-
-#include <string>
-#include <vector>
-
-/// EDToken - Encapsulates a single token, which can provide a string
-/// representation of itself or interpret itself in various ways, depending
-/// on the token type.
-struct EDToken {
- enum tokenType {
- kTokenWhitespace,
- kTokenOpcode,
- kTokenLiteral,
- kTokenRegister,
- kTokenPunctuation
- };
-
- /// The parent disassembler
- EDDisassembler &Disassembler;
-
- /// The token's string representation
- llvm::StringRef Str;
- /// The token's string representation, but in a form suitable for export
- std::string PermStr;
- /// The type of the token, as exposed through the external API
- enum tokenType Type;
- /// The type of the token, as recorded by the syntax-specific tokenizer
- uint64_t LocalType;
- /// The operand corresponding to the token, or (unsigned int)-1 if not
- /// part of an operand.
- int OperandID;
-
- /// The sign if the token is a literal (1 if negative, 0 otherwise)
- bool LiteralSign;
- /// The absolute value if the token is a literal
- uint64_t LiteralAbsoluteValue;
- /// The LLVM register ID if the token is a register name
- unsigned RegisterID;
-
- /// Constructor - Initializes an EDToken with the information common to all
- /// tokens
- ///
- /// @arg str - The string corresponding to the token
- /// @arg type - The token's type as exposed through the public API
- /// @arg localType - The token's type as recorded by the tokenizer
- /// @arg disassembler - The disassembler responsible for the token
- EDToken(llvm::StringRef str,
- enum tokenType type,
- uint64_t localType,
- EDDisassembler &disassembler);
-
- /// makeLiteral - Adds the information specific to a literal
- /// @arg sign - The sign of the literal (1 if negative, 0
- /// otherwise)
- ///
- /// @arg absoluteValue - The absolute value of the literal
- void makeLiteral(bool sign, uint64_t absoluteValue);
- /// makeRegister - Adds the information specific to a register
- ///
- /// @arg registerID - The LLVM register ID
- void makeRegister(unsigned registerID);
-
- /// setOperandID - Links the token to a numbered operand
- ///
- /// @arg operandID - The operand ID to link to
- void setOperandID(int operandID);
-
- ~EDToken();
-
- /// type - Returns the public type of the token
- enum tokenType type() const;
- /// localType - Returns the tokenizer-specific type of the token
- uint64_t localType() const;
- /// string - Returns the string representation of the token
- llvm::StringRef string() const;
- /// operandID - Returns the operand ID of the token
- int operandID() const;
-
- /// literalSign - Returns the sign of the token
- /// (1 if negative, 0 if positive or unsigned, -1 if it is not a literal)
- int literalSign() const;
- /// literalAbsoluteValue - Retrieves the absolute value of the token, and
- /// returns -1 if the token is not a literal
- /// @arg value - A reference to a value that is filled in with the absolute
- /// value, if it is valid
- int literalAbsoluteValue(uint64_t &value) const;
- /// registerID - Retrieves the register ID of the token, and returns -1 if the
- /// token is not a register
- ///
- /// @arg registerID - A reference to a value that is filled in with the
- /// register ID, if it is valid
- int registerID(unsigned &registerID) const;
-
- /// tokenize - Tokenizes a string using the platform- and syntax-specific
- /// tokenizer, and returns 0 on success (-1 on failure)
- ///
- /// @arg tokens - A vector that will be filled in with pointers to
- /// allocated tokens
- /// @arg str - The string, as outputted by the AsmPrinter
- /// @arg operandOrder - The order of the operands from the operandFlags array
- /// as they appear in str
- /// @arg disassembler - The disassembler for the desired target and
- // assembly syntax
- static int tokenize(std::vector<EDToken*> &tokens,
- std::string &str,
- const char *operandOrder,
- EDDisassembler &disassembler);
-
- /// getString - Directs a character pointer to the string, returning 0 on
- /// success (-1 on failure)
- /// @arg buf - A reference to a pointer that is set to point to the string.
- /// The string is still owned by the token.
- int getString(const char*& buf);
-};
-
-#endif
diff --git a/tools/edis/Makefile b/tools/edis/Makefile
index 0d2e26f..92484bf 100644
--- a/tools/edis/Makefile
+++ b/tools/edis/Makefile
@@ -9,8 +9,8 @@
LEVEL = ../..
LIBRARYNAME = EnhancedDisassembly
-
-BUILT_SOURCES = EDInfo.inc
+LINK_LIBS_IN_SHARED = 1
+SHARED_LIBRARY = 1
EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/EnhancedDisassembly.exports
@@ -19,23 +19,23 @@ EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/EnhancedDisassembly.exports
# early so we can set up LINK_COMPONENTS before including Makefile.rules
include $(LEVEL)/Makefile.config
-ifeq ($(ENABLE_PIC),1)
- ifneq ($(DISABLE_EDIS),1)
- ifneq ($(TARGET_OS), $(filter $(TARGET_OS), Cygwin MingW))
- LINK_LIBS_IN_SHARED = 1
- SHARED_LIBRARY = 1
- endif
- endif
+LINK_COMPONENTS := mcdisassembler
+
+# If the X86 target is enabled, link in the asmprinter and disassembler.
+ifneq ($(filter $(TARGETS_TO_BUILD), X86),)
+LINK_COMPONENTS += x86asmprinter x86disassembler
endif
-LINK_COMPONENTS := $(TARGETS_TO_BUILD) x86asmprinter x86disassembler
+# If the X86 target is enabled, link in the asmprinter and disassembler.
+ifneq ($(filter $(TARGETS_TO_BUILD), ARM),)
+LINK_COMPONENTS += armasmprinter armdisassembler
+endif
include $(LEVEL)/Makefile.common
ifeq ($(HOST_OS),Darwin)
# extra options to override libtool defaults
LLVMLibsOptions := $(LLVMLibsOptions) \
- -avoid-version \
-Wl,-dead_strip
ifdef EDIS_VERSION
@@ -47,14 +47,8 @@ ifeq ($(HOST_OS),Darwin)
DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/')
ifneq ($(DARWIN_VERS),8)
LLVMLibsOptions := $(LLVMLibsOptions) \
- -no-undefined -Wl,-install_name \
+ -Wl,-install_name \
-Wl,"@rpath/lib$(LIBRARYNAME)$(SHLIBEXT)"
endif
endif
-EDInfo.inc: $(TBLGEN)
- $(Echo) "Building semantic information header"
- $(Verb) $(TableGen) -o $(call SYSPATH, $@) -gen-enhanced-disassembly-header /dev/null
-
-clean::
- -$(Verb) $(RM) -f EDInfo.inc
diff --git a/tools/gold/README.txt b/tools/gold/README.txt
index 92ee3d1..a906a90 100644
--- a/tools/gold/README.txt
+++ b/tools/gold/README.txt
@@ -14,8 +14,8 @@ Then build binutils with "make all-gold".
To build the LLVMgold plugin, configure LLVM with the option
--with-binutils-include=/path/to/binutils/src/include/ --enable-pic. To use the
-plugin, run "ld-new --plugin /path/to/libLLVMgold.so".
-Without PIC libLTO and libLLVMgold are not being built (because they would fail
+plugin, run "ld-new --plugin /path/to/LLVMgold.so".
+Without PIC libLTO and LLVMgold are not being built (because they would fail
link on x86-64 with a relocation error: PIC and non-PIC can't be combined).
As an alternative to passing --enable-pic, you can use 'make ENABLE_PIC=1' in
your entire LLVM build.
diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp
index 2d0f5bd..4b58fae 100644
--- a/tools/gold/gold-plugin.cpp
+++ b/tools/gold/gold-plugin.cpp
@@ -66,8 +66,11 @@ namespace options {
static generate_bc generate_bc_file = BC_NO;
static std::string bc_path;
static std::string as_path;
+ static std::vector<std::string> as_args;
static std::vector<std::string> pass_through;
static std::string extra_library_path;
+ static std::string triple;
+ static std::string mcpu;
// Additional options to pass into the code generator.
// Note: This array will contain all plugin options which are not claimed
// as plugin exclusive to pass to the code generator.
@@ -83,6 +86,8 @@ namespace options {
if (opt == "generate-api-file") {
generate_api_file = true;
+ } else if (opt.startswith("mcpu=")) {
+ mcpu = opt.substr(strlen("mcpu="));
} else if (opt.startswith("as=")) {
if (!as_path.empty()) {
(*message)(LDPL_WARNING, "Path to as specified twice. "
@@ -90,11 +95,16 @@ namespace options {
} else {
as_path = opt.substr(strlen("as="));
}
+ } else if (opt.startswith("as-arg=")) {
+ llvm::StringRef item = opt.substr(strlen("as-arg="));
+ as_args.push_back(item.str());
} else if (opt.startswith("extra-library-path=")) {
extra_library_path = opt.substr(strlen("extra_library_path="));
} else if (opt.startswith("pass-through=")) {
llvm::StringRef item = opt.substr(strlen("pass-through="));
pass_through.push_back(item.str());
+ } else if (opt.startswith("mtriple=")) {
+ triple = opt.substr(strlen("mtriple="));
} else if (opt == "emit-llvm") {
generate_bc_file = BC_ONLY;
} else if (opt == "also-emit-llvm") {
@@ -270,6 +280,10 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
lto_get_error_message());
return LDPS_ERR;
}
+
+ if (!options::triple.empty())
+ lto_module_set_target_triple(cf.M, options::triple.c_str());
+
cf.handle = file->handle;
unsigned sym_count = lto_module_get_num_symbols(cf.M);
cf.syms.reserve(sym_count);
@@ -394,6 +408,17 @@ static ld_plugin_status all_symbols_read_hook(void) {
sys::Path p = sys::Program::FindProgramByName(options::as_path);
lto_codegen_set_assembler_path(cg, p.c_str());
}
+ if (!options::as_args.empty()) {
+ std::vector<const char *> as_args_p;
+ for (std::vector<std::string>::iterator I = options::as_args.begin(),
+ E = options::as_args.end(); I != E; ++I) {
+ as_args_p.push_back(I->c_str());
+ }
+ lto_codegen_set_assembler_args(cg, &as_args_p[0], as_args_p.size());
+ }
+ if (!options::mcpu.empty())
+ lto_codegen_set_cpu(cg, options::mcpu.c_str());
+
// Pass through extra options to the code generator.
if (!options::extra.empty()) {
for (std::vector<std::string>::iterator it = options::extra.begin();
@@ -428,15 +453,22 @@ static ld_plugin_status all_symbols_read_hook(void) {
(*message)(LDPL_ERROR, "%s", ErrMsg.c_str());
return LDPS_ERR;
}
- raw_fd_ostream objFile(uniqueObjPath.c_str(), ErrMsg,
- raw_fd_ostream::F_Binary);
+ tool_output_file objFile(uniqueObjPath.c_str(), ErrMsg,
+ raw_fd_ostream::F_Binary);
if (!ErrMsg.empty()) {
(*message)(LDPL_ERROR, "%s", ErrMsg.c_str());
return LDPS_ERR;
}
- objFile.write(buffer, bufsize);
- objFile.close();
+ objFile.os().write(buffer, bufsize);
+ objFile.os().close();
+ if (objFile.os().has_error()) {
+ (*message)(LDPL_ERROR, "Error writing output file '%s'",
+ uniqueObjPath.c_str());
+ objFile.os().clear_error();
+ return LDPS_ERR;
+ }
+ objFile.keep();
lto_codegen_dispose(cg);
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
index 199a1a9..8bcc2d8 100644
--- a/tools/llc/llc.cpp
+++ b/tools/llc/llc.cpp
@@ -18,7 +18,6 @@
#include "llvm/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/IRReader.h"
#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
@@ -76,6 +75,11 @@ MAttrs("mattr",
cl::desc("Target specific attributes (-mattr=help for details)"),
cl::value_desc("a1,+a2,-a3,..."));
+static cl::opt<bool>
+RelaxAll("mc-relax-all",
+ cl::desc("When used with filetype=obj, "
+ "relax all fixups in the emitted object file"));
+
cl::opt<TargetMachine::CodeGenFileType>
FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
cl::desc("Choose a file type (not all types are supported by all targets):"),
@@ -119,87 +123,67 @@ GetFileNameRoot(const std::string &InputFilename) {
return outputFilename;
}
-static formatted_raw_ostream *GetOutputStream(const char *TargetName,
- Triple::OSType OS,
- const char *ProgName) {
- if (OutputFilename != "") {
- if (OutputFilename == "-")
- return new formatted_raw_ostream(outs(),
- formatted_raw_ostream::PRESERVE_STREAM);
-
- // Make sure that the Out file gets unlinked from the disk if we get a
- // SIGINT
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
- std::string error;
- raw_fd_ostream *FDOut =
- new raw_fd_ostream(OutputFilename.c_str(), error,
- raw_fd_ostream::F_Binary);
- if (!error.empty()) {
- errs() << error << '\n';
- delete FDOut;
- return 0;
+static tool_output_file *GetOutputStream(const char *TargetName,
+ Triple::OSType OS,
+ const char *ProgName) {
+ // If we don't yet have an output filename, make one.
+ if (OutputFilename.empty()) {
+ if (InputFilename == "-")
+ OutputFilename = "-";
+ else {
+ OutputFilename = GetFileNameRoot(InputFilename);
+
+ switch (FileType) {
+ default: assert(0 && "Unknown file type");
+ case TargetMachine::CGFT_AssemblyFile:
+ if (TargetName[0] == 'c') {
+ if (TargetName[1] == 0)
+ OutputFilename += ".cbe.c";
+ else if (TargetName[1] == 'p' && TargetName[2] == 'p')
+ OutputFilename += ".cpp";
+ else
+ OutputFilename += ".s";
+ } else
+ OutputFilename += ".s";
+ break;
+ case TargetMachine::CGFT_ObjectFile:
+ if (OS == Triple::Win32)
+ OutputFilename += ".obj";
+ else
+ OutputFilename += ".o";
+ break;
+ case TargetMachine::CGFT_Null:
+ OutputFilename += ".null";
+ break;
+ }
}
- formatted_raw_ostream *Out =
- new formatted_raw_ostream(*FDOut, formatted_raw_ostream::DELETE_STREAM);
-
- return Out;
- }
-
- if (InputFilename == "-") {
- OutputFilename = "-";
- return new formatted_raw_ostream(outs(),
- formatted_raw_ostream::PRESERVE_STREAM);
}
- OutputFilename = GetFileNameRoot(InputFilename);
-
+ // Decide if we need "binary" output.
bool Binary = false;
switch (FileType) {
default: assert(0 && "Unknown file type");
case TargetMachine::CGFT_AssemblyFile:
- if (TargetName[0] == 'c') {
- if (TargetName[1] == 0)
- OutputFilename += ".cbe.c";
- else if (TargetName[1] == 'p' && TargetName[2] == 'p')
- OutputFilename += ".cpp";
- else
- OutputFilename += ".s";
- } else
- OutputFilename += ".s";
break;
case TargetMachine::CGFT_ObjectFile:
- if (OS == Triple::Win32)
- OutputFilename += ".obj";
- else
- OutputFilename += ".o";
- Binary = true;
- break;
case TargetMachine::CGFT_Null:
- OutputFilename += ".null";
Binary = true;
break;
}
- // Make sure that the Out file gets unlinked from the disk if we get a
- // SIGINT
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
+ // Open the file.
std::string error;
unsigned OpenFlags = 0;
if (Binary) OpenFlags |= raw_fd_ostream::F_Binary;
- raw_fd_ostream *FDOut = new raw_fd_ostream(OutputFilename.c_str(), error,
- OpenFlags);
+ tool_output_file *FDOut = new tool_output_file(OutputFilename.c_str(), error,
+ OpenFlags);
if (!error.empty()) {
errs() << error << '\n';
delete FDOut;
return 0;
}
- formatted_raw_ostream *Out =
- new formatted_raw_ostream(*FDOut, formatted_raw_ostream::DELETE_STREAM);
-
- return Out;
+ return FDOut;
}
// main - Entry point for the llc compiler.
@@ -234,7 +218,7 @@ int main(int argc, char **argv) {
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
- mod.setTargetTriple(TargetTriple);
+ mod.setTargetTriple(Triple::normalize(TargetTriple));
Triple TheTriple(mod.getTargetTriple());
if (TheTriple.getTriple().empty())
@@ -290,9 +274,9 @@ int main(int argc, char **argv) {
TargetMachine &Target = *target.get();
// Figure out where we are going to send the output...
- formatted_raw_ostream *Out = GetOutputStream(TheTarget->getName(),
- TheTriple.getOS(), argv[0]);
- if (Out == 0) return 1;
+ OwningPtr<tool_output_file> Out
+ (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]));
+ if (!Out) return 1;
CodeGenOpt::Level OLvl = CodeGenOpt::Default;
switch (OptLevel) {
@@ -306,14 +290,6 @@ int main(int argc, char **argv) {
case '3': OLvl = CodeGenOpt::Aggressive; break;
}
- // Request that addPassesToEmitFile run the Verifier after running
- // passes which modify the IR.
-#ifndef NDEBUG
- bool DisableVerify = false;
-#else
- bool DisableVerify = true;
-#endif
-
// Build up all of the passes that we want to do to the module.
PassManager PM;
@@ -323,27 +299,32 @@ int main(int argc, char **argv) {
else
PM.add(new TargetData(&mod));
- if (!NoVerify)
- PM.add(createVerifierPass());
-
// Override default to generate verbose assembly.
Target.setAsmVerbosityDefault(true);
- // Ask the target to add backend passes as necessary.
- if (Target.addPassesToEmitFile(PM, *Out, FileType, OLvl,
- DisableVerify)) {
- errs() << argv[0] << ": target does not support generation of this"
- << " file type!\n";
- delete Out;
- // And the Out file is empty and useless, so remove it now.
- sys::Path(OutputFilename).eraseFromDisk();
- return 1;
+ if (RelaxAll) {
+ if (FileType != TargetMachine::CGFT_ObjectFile)
+ errs() << argv[0]
+ << ": warning: ignoring -mc-relax-all because filetype != obj";
+ else
+ Target.setMCRelaxAll(true);
}
- PM.run(mod);
+ {
+ formatted_raw_ostream FOS(Out->os());
+
+ // Ask the target to add backend passes as necessary.
+ if (Target.addPassesToEmitFile(PM, FOS, FileType, OLvl, NoVerify)) {
+ errs() << argv[0] << ": target does not support generation of this"
+ << " file type!\n";
+ return 1;
+ }
+
+ PM.run(mod);
+ }
- // Delete the ostream.
- delete Out;
+ // Declare success.
+ Out->keep();
return 0;
}
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index 4e3e07f..4c37780 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -16,6 +16,7 @@
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
#include "llvm/ExecutionEngine/GenericValue.h"
@@ -157,7 +158,7 @@ int main(int argc, char **argv, char * const *envp) {
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
- Mod->setTargetTriple(TargetTriple);
+ Mod->setTargetTriple(Triple::normalize(TargetTriple));
CodeGenOpt::Level OLvl = CodeGenOpt::Default;
switch (OptLevel) {
diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp
index d39d6c8..1eaa4b3 100644
--- a/tools/llvm-as/llvm-as.cpp
+++ b/tools/llvm-as/llvm-as.cpp
@@ -68,22 +68,20 @@ static void WriteOutputFile(const Module *M) {
}
}
- // Make sure that the Out file gets unlinked from the disk if we get a
- // SIGINT.
- if (OutputFilename != "-")
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
std::string ErrorInfo;
- std::auto_ptr<raw_ostream> Out
- (new raw_fd_ostream(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary));
+ OwningPtr<tool_output_file> Out
+ (new tool_output_file(OutputFilename.c_str(), ErrorInfo,
+ raw_fd_ostream::F_Binary));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
exit(1);
}
- if (Force || !CheckBitcodeOutputToConsole(*Out, true))
- WriteBitcodeToFile(M, *Out);
+ if (Force || !CheckBitcodeOutputToConsole(Out->os(), true))
+ WriteBitcodeToFile(M, Out->os());
+
+ // Declare success.
+ Out->keep();
}
int main(int argc, char **argv) {
diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index 732ff11..9c0d675 100644
--- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -46,9 +46,6 @@ using namespace llvm;
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
-static cl::opt<std::string>
- OutputFilename("-o", cl::init("-"), cl::desc("<output file>"));
-
static cl::opt<bool> Dump("dump", cl::desc("Dump low level bitcode trace"));
//===----------------------------------------------------------------------===//
@@ -239,6 +236,8 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
case bitc::FUNC_CODE_INST_VSELECT: return "INST_VSELECT";
case bitc::FUNC_CODE_DEBUG_LOC: return "DEBUG_LOC";
case bitc::FUNC_CODE_DEBUG_LOC_AGAIN: return "DEBUG_LOC_AGAIN";
+ case bitc::FUNC_CODE_INST_CALL2: return "INST_CALL2";
+ case bitc::FUNC_CODE_DEBUG_LOC2: return "DEBUG_LOC2";
}
case bitc::TYPE_SYMTAB_BLOCK_ID:
switch (CodeID) {
@@ -259,13 +258,17 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
case bitc::METADATA_BLOCK_ID:
switch(CodeID) {
default:return 0;
- case bitc::METADATA_STRING: return "MDSTRING";
- case bitc::METADATA_NODE: return "MDNODE";
- case bitc::METADATA_FN_NODE: return "FN_MDNODE";
+ case bitc::METADATA_STRING: return "METADATA_STRING";
+ case bitc::METADATA_NODE: return "METADATA_NODE";
+ case bitc::METADATA_FN_NODE: return "METADATA_FN_NODE";
case bitc::METADATA_NAME: return "METADATA_NAME";
- case bitc::METADATA_NAMED_NODE: return "NAMEDMDNODE";
+ case bitc::METADATA_NAMED_NODE: return "METADATA_NAMED_NODE";
case bitc::METADATA_KIND: return "METADATA_KIND";
case bitc::METADATA_ATTACHMENT: return "METADATA_ATTACHMENT";
+ case bitc::METADATA_NODE2: return "METADATA_NODE2";
+ case bitc::METADATA_FN_NODE2: return "METADATA_FN_NODE2";
+ case bitc::METADATA_NAMED_NODE2: return "METADATA_NAMED_NODE2";
+ case bitc::METADATA_ATTACHMENT2: return "METADATA_ATTACHMENT2";
}
}
}
diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt
index 7a43dba..663cae5 100644
--- a/tools/llvm-config/CMakeLists.txt
+++ b/tools/llvm-config/CMakeLists.txt
@@ -78,7 +78,7 @@ add_custom_command(OUTPUT ${LIBDEPS_TMP}
add_custom_command(OUTPUT ${LIBDEPS}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LIBDEPS_TMP} ${LIBDEPS}
DEPENDS ${LIBDEPS_TMP}
- COMMENT "Updated ${LIBDEPS} because dependencies changed")
+ COMMENT "Updating ${LIBDEPS} if necessary...")
add_custom_command(OUTPUT ${FINAL_LIBDEPS}
COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/find-cycles.pl < ${LIBDEPS} > ${FINAL_LIBDEPS} || ${CMAKE_COMMAND} -E remove -f ${FINAL_LIBDEPS}
diff --git a/tools/llvm-diff/CMakeLists.txt b/tools/llvm-diff/CMakeLists.txt
new file mode 100644
index 0000000..f6d65c9
--- /dev/null
+++ b/tools/llvm-diff/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(LLVM_LINK_COMPONENTS support asmparser bitreader)
+
+add_llvm_tool(llvm-diff
+ llvm-diff.cpp
+ DifferenceEngine.cpp
+ )
diff --git a/tools/llvm-diff/DifferenceEngine.cpp b/tools/llvm-diff/DifferenceEngine.cpp
new file mode 100644
index 0000000..b0a24d0
--- /dev/null
+++ b/tools/llvm-diff/DifferenceEngine.cpp
@@ -0,0 +1,676 @@
+//===-- DifferenceEngine.cpp - Structural function/module comparison ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the implementation of the LLVM difference
+// engine, which structurally compares global values within a module.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DifferenceEngine.h"
+
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/type_traits.h"
+
+#include <utility>
+
+using namespace llvm;
+
+namespace {
+
+/// A priority queue, implemented as a heap.
+template <class T, class Sorter, unsigned InlineCapacity>
+class PriorityQueue {
+ Sorter Precedes;
+ llvm::SmallVector<T, InlineCapacity> Storage;
+
+public:
+ PriorityQueue(const Sorter &Precedes) : Precedes(Precedes) {}
+
+ /// Checks whether the heap is empty.
+ bool empty() const { return Storage.empty(); }
+
+ /// Insert a new value on the heap.
+ void insert(const T &V) {
+ unsigned Index = Storage.size();
+ Storage.push_back(V);
+ if (Index == 0) return;
+
+ T *data = Storage.data();
+ while (true) {
+ unsigned Target = (Index + 1) / 2 - 1;
+ if (!Precedes(data[Index], data[Target])) return;
+ std::swap(data[Index], data[Target]);
+ if (Target == 0) return;
+ Index = Target;
+ }
+ }
+
+ /// Remove the minimum value in the heap. Only valid on a non-empty heap.
+ T remove_min() {
+ assert(!empty());
+ T tmp = Storage[0];
+
+ unsigned NewSize = Storage.size() - 1;
+ if (NewSize) {
+ // Move the slot at the end to the beginning.
+ if (isPodLike<T>::value)
+ Storage[0] = Storage[NewSize];
+ else
+ std::swap(Storage[0], Storage[NewSize]);
+
+ // Bubble the root up as necessary.
+ unsigned Index = 0;
+ while (true) {
+ // With a 1-based index, the children would be Index*2 and Index*2+1.
+ unsigned R = (Index + 1) * 2;
+ unsigned L = R - 1;
+
+ // If R is out of bounds, we're done after this in any case.
+ if (R >= NewSize) {
+ // If L is also out of bounds, we're done immediately.
+ if (L >= NewSize) break;
+
+ // Otherwise, test whether we should swap L and Index.
+ if (Precedes(Storage[L], Storage[Index]))
+ std::swap(Storage[L], Storage[Index]);
+ break;
+ }
+
+ // Otherwise, we need to compare with the smaller of L and R.
+ // Prefer R because it's closer to the end of the array.
+ unsigned IndexToTest = (Precedes(Storage[L], Storage[R]) ? L : R);
+
+ // If Index is >= the min of L and R, then heap ordering is restored.
+ if (!Precedes(Storage[IndexToTest], Storage[Index]))
+ break;
+
+ // Otherwise, keep bubbling up.
+ std::swap(Storage[IndexToTest], Storage[Index]);
+ Index = IndexToTest;
+ }
+ }
+ Storage.pop_back();
+
+ return tmp;
+ }
+};
+
+/// A function-scope difference engine.
+class FunctionDifferenceEngine {
+ DifferenceEngine &Engine;
+
+ /// The current mapping from old local values to new local values.
+ DenseMap<Value*, Value*> Values;
+
+ /// The current mapping from old blocks to new blocks.
+ DenseMap<BasicBlock*, BasicBlock*> Blocks;
+
+ DenseSet<std::pair<Value*, Value*> > TentativeValues;
+
+ unsigned getUnprocPredCount(BasicBlock *Block) const {
+ unsigned Count = 0;
+ for (pred_iterator I = pred_begin(Block), E = pred_end(Block); I != E; ++I)
+ if (!Blocks.count(*I)) Count++;
+ return Count;
+ }
+
+ typedef std::pair<BasicBlock*, BasicBlock*> BlockPair;
+
+ /// A type which sorts a priority queue by the number of unprocessed
+ /// predecessor blocks it has remaining.
+ ///
+ /// This is actually really expensive to calculate.
+ struct QueueSorter {
+ const FunctionDifferenceEngine &fde;
+ explicit QueueSorter(const FunctionDifferenceEngine &fde) : fde(fde) {}
+
+ bool operator()(const BlockPair &Old, const BlockPair &New) {
+ return fde.getUnprocPredCount(Old.first)
+ < fde.getUnprocPredCount(New.first);
+ }
+ };
+
+ /// A queue of unified blocks to process.
+ PriorityQueue<BlockPair, QueueSorter, 20> Queue;
+
+ /// Try to unify the given two blocks. Enqueues them for processing
+ /// if they haven't already been processed.
+ ///
+ /// Returns true if there was a problem unifying them.
+ bool tryUnify(BasicBlock *L, BasicBlock *R) {
+ BasicBlock *&Ref = Blocks[L];
+
+ if (Ref) {
+ if (Ref == R) return false;
+
+ Engine.logf("successor %l cannot be equivalent to %r; "
+ "it's already equivalent to %r")
+ << L << R << Ref;
+ return true;
+ }
+
+ Ref = R;
+ Queue.insert(BlockPair(L, R));
+ return false;
+ }
+
+ /// Unifies two instructions, given that they're known not to have
+ /// structural differences.
+ void unify(Instruction *L, Instruction *R) {
+ DifferenceEngine::Context C(Engine, L, R);
+
+ bool Result = diff(L, R, true, true);
+ assert(!Result && "structural differences second time around?");
+ (void) Result;
+ if (!L->use_empty())
+ Values[L] = R;
+ }
+
+ void processQueue() {
+ while (!Queue.empty()) {
+ BlockPair Pair = Queue.remove_min();
+ diff(Pair.first, Pair.second);
+ }
+ }
+
+ void diff(BasicBlock *L, BasicBlock *R) {
+ DifferenceEngine::Context C(Engine, L, R);
+
+ BasicBlock::iterator LI = L->begin(), LE = L->end();
+ BasicBlock::iterator RI = R->begin(), RE = R->end();
+
+ llvm::SmallVector<std::pair<Instruction*,Instruction*>, 20> TentativePairs;
+
+ do {
+ assert(LI != LE && RI != RE);
+ Instruction *LeftI = &*LI, *RightI = &*RI;
+
+ // If the instructions differ, start the more sophisticated diff
+ // algorithm at the start of the block.
+ if (diff(LeftI, RightI, false, false)) {
+ TentativeValues.clear();
+ return runBlockDiff(L->begin(), R->begin());
+ }
+
+ // Otherwise, tentatively unify them.
+ if (!LeftI->use_empty())
+ TentativeValues.insert(std::make_pair(LeftI, RightI));
+
+ ++LI, ++RI;
+ } while (LI != LE); // This is sufficient: we can't get equality of
+ // terminators if there are residual instructions.
+
+ // Unify everything in the block, non-tentatively this time.
+ TentativeValues.clear();
+ for (LI = L->begin(), RI = R->begin(); LI != LE; ++LI, ++RI)
+ unify(&*LI, &*RI);
+ }
+
+ bool matchForBlockDiff(Instruction *L, Instruction *R);
+ void runBlockDiff(BasicBlock::iterator LI, BasicBlock::iterator RI);
+
+ bool diffCallSites(CallSite L, CallSite R, bool Complain) {
+ // FIXME: call attributes
+ if (!equivalentAsOperands(L.getCalledValue(), R.getCalledValue())) {
+ if (Complain) Engine.log("called functions differ");
+ return true;
+ }
+ if (L.arg_size() != R.arg_size()) {
+ if (Complain) Engine.log("argument counts differ");
+ return true;
+ }
+ for (unsigned I = 0, E = L.arg_size(); I != E; ++I)
+ if (!equivalentAsOperands(L.getArgument(I), R.getArgument(I))) {
+ if (Complain)
+ Engine.logf("arguments %l and %r differ")
+ << L.getArgument(I) << R.getArgument(I);
+ return true;
+ }
+ return false;
+ }
+
+ bool diff(Instruction *L, Instruction *R, bool Complain, bool TryUnify) {
+ // FIXME: metadata (if Complain is set)
+
+ // Different opcodes always imply different operations.
+ if (L->getOpcode() != R->getOpcode()) {
+ if (Complain) Engine.log("different instruction types");
+ return true;
+ }
+
+ if (isa<CmpInst>(L)) {
+ if (cast<CmpInst>(L)->getPredicate()
+ != cast<CmpInst>(R)->getPredicate()) {
+ if (Complain) Engine.log("different predicates");
+ return true;
+ }
+ } else if (isa<CallInst>(L)) {
+ return diffCallSites(CallSite(L), CallSite(R), Complain);
+ } else if (isa<PHINode>(L)) {
+ // FIXME: implement.
+
+ // This is really wierd; type uniquing is broken?
+ if (L->getType() != R->getType()) {
+ if (!L->getType()->isPointerTy() || !R->getType()->isPointerTy()) {
+ if (Complain) Engine.log("different phi types");
+ return true;
+ }
+ }
+ return false;
+
+ // Terminators.
+ } else if (isa<InvokeInst>(L)) {
+ InvokeInst *LI = cast<InvokeInst>(L);
+ InvokeInst *RI = cast<InvokeInst>(R);
+ if (diffCallSites(CallSite(LI), CallSite(RI), Complain))
+ return true;
+
+ if (TryUnify) {
+ tryUnify(LI->getNormalDest(), RI->getNormalDest());
+ tryUnify(LI->getUnwindDest(), RI->getUnwindDest());
+ }
+ return false;
+
+ } else if (isa<BranchInst>(L)) {
+ BranchInst *LI = cast<BranchInst>(L);
+ BranchInst *RI = cast<BranchInst>(R);
+ if (LI->isConditional() != RI->isConditional()) {
+ if (Complain) Engine.log("branch conditionality differs");
+ return true;
+ }
+
+ if (LI->isConditional()) {
+ if (!equivalentAsOperands(LI->getCondition(), RI->getCondition())) {
+ if (Complain) Engine.log("branch conditions differ");
+ return true;
+ }
+ if (TryUnify) tryUnify(LI->getSuccessor(1), RI->getSuccessor(1));
+ }
+ if (TryUnify) tryUnify(LI->getSuccessor(0), RI->getSuccessor(0));
+ return false;
+
+ } else if (isa<SwitchInst>(L)) {
+ SwitchInst *LI = cast<SwitchInst>(L);
+ SwitchInst *RI = cast<SwitchInst>(R);
+ if (!equivalentAsOperands(LI->getCondition(), RI->getCondition())) {
+ if (Complain) Engine.log("switch conditions differ");
+ return true;
+ }
+ if (TryUnify) tryUnify(LI->getDefaultDest(), RI->getDefaultDest());
+
+ bool Difference = false;
+
+ DenseMap<ConstantInt*,BasicBlock*> LCases;
+ for (unsigned I = 1, E = LI->getNumCases(); I != E; ++I)
+ LCases[LI->getCaseValue(I)] = LI->getSuccessor(I);
+ for (unsigned I = 1, E = RI->getNumCases(); I != E; ++I) {
+ ConstantInt *CaseValue = RI->getCaseValue(I);
+ BasicBlock *LCase = LCases[CaseValue];
+ if (LCase) {
+ if (TryUnify) tryUnify(LCase, RI->getSuccessor(I));
+ LCases.erase(CaseValue);
+ } else if (!Difference) {
+ if (Complain)
+ Engine.logf("right switch has extra case %r") << CaseValue;
+ Difference = true;
+ }
+ }
+ if (!Difference)
+ for (DenseMap<ConstantInt*,BasicBlock*>::iterator
+ I = LCases.begin(), E = LCases.end(); I != E; ++I) {
+ if (Complain)
+ Engine.logf("left switch has extra case %l") << I->first;
+ Difference = true;
+ }
+ return Difference;
+ } else if (isa<UnreachableInst>(L)) {
+ return false;
+ }
+
+ if (L->getNumOperands() != R->getNumOperands()) {
+ if (Complain) Engine.log("instructions have different operand counts");
+ return true;
+ }
+
+ for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I) {
+ Value *LO = L->getOperand(I), *RO = R->getOperand(I);
+ if (!equivalentAsOperands(LO, RO)) {
+ if (Complain) Engine.logf("operands %l and %r differ") << LO << RO;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool equivalentAsOperands(Constant *L, Constant *R) {
+ // Use equality as a preliminary filter.
+ if (L == R)
+ return true;
+
+ if (L->getValueID() != R->getValueID())
+ return false;
+
+ // Ask the engine about global values.
+ if (isa<GlobalValue>(L))
+ return Engine.equivalentAsOperands(cast<GlobalValue>(L),
+ cast<GlobalValue>(R));
+
+ // Compare constant expressions structurally.
+ if (isa<ConstantExpr>(L))
+ return equivalentAsOperands(cast<ConstantExpr>(L),
+ cast<ConstantExpr>(R));
+
+ // Nulls of the "same type" don't always actually have the same
+ // type; I don't know why. Just white-list them.
+ if (isa<ConstantPointerNull>(L))
+ return true;
+
+ // Block addresses only match if we've already encountered the
+ // block. FIXME: tentative matches?
+ if (isa<BlockAddress>(L))
+ return Blocks[cast<BlockAddress>(L)->getBasicBlock()]
+ == cast<BlockAddress>(R)->getBasicBlock();
+
+ return false;
+ }
+
+ bool equivalentAsOperands(ConstantExpr *L, ConstantExpr *R) {
+ if (L == R)
+ return true;
+ if (L->getOpcode() != R->getOpcode())
+ return false;
+
+ switch (L->getOpcode()) {
+ case Instruction::ICmp:
+ case Instruction::FCmp:
+ if (L->getPredicate() != R->getPredicate())
+ return false;
+ break;
+
+ case Instruction::GetElementPtr:
+ // FIXME: inbounds?
+ break;
+
+ default:
+ break;
+ }
+
+ if (L->getNumOperands() != R->getNumOperands())
+ return false;
+
+ for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I)
+ if (!equivalentAsOperands(L->getOperand(I), R->getOperand(I)))
+ return false;
+
+ return true;
+ }
+
+ bool equivalentAsOperands(Value *L, Value *R) {
+ // Fall out if the values have different kind.
+ // This possibly shouldn't take priority over oracles.
+ if (L->getValueID() != R->getValueID())
+ return false;
+
+ // Value subtypes: Argument, Constant, Instruction, BasicBlock,
+ // InlineAsm, MDNode, MDString, PseudoSourceValue
+
+ if (isa<Constant>(L))
+ return equivalentAsOperands(cast<Constant>(L), cast<Constant>(R));
+
+ if (isa<Instruction>(L))
+ return Values[L] == R || TentativeValues.count(std::make_pair(L, R));
+
+ if (isa<Argument>(L))
+ return Values[L] == R;
+
+ if (isa<BasicBlock>(L))
+ return Blocks[cast<BasicBlock>(L)] != R;
+
+ // Pretend everything else is identical.
+ return true;
+ }
+
+ // Avoid a gcc warning about accessing 'this' in an initializer.
+ FunctionDifferenceEngine *this_() { return this; }
+
+public:
+ FunctionDifferenceEngine(DifferenceEngine &Engine) :
+ Engine(Engine), Queue(QueueSorter(*this_())) {}
+
+ void diff(Function *L, Function *R) {
+ if (L->arg_size() != R->arg_size())
+ Engine.log("different argument counts");
+
+ // Map the arguments.
+ for (Function::arg_iterator
+ LI = L->arg_begin(), LE = L->arg_end(),
+ RI = R->arg_begin(), RE = R->arg_end();
+ LI != LE && RI != RE; ++LI, ++RI)
+ Values[&*LI] = &*RI;
+
+ tryUnify(&*L->begin(), &*R->begin());
+ processQueue();
+ }
+};
+
+struct DiffEntry {
+ DiffEntry() : Cost(0) {}
+
+ unsigned Cost;
+ llvm::SmallVector<char, 8> Path; // actually of DifferenceEngine::DiffChange
+};
+
+bool FunctionDifferenceEngine::matchForBlockDiff(Instruction *L,
+ Instruction *R) {
+ return !diff(L, R, false, false);
+}
+
+void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart,
+ BasicBlock::iterator RStart) {
+ BasicBlock::iterator LE = LStart->getParent()->end();
+ BasicBlock::iterator RE = RStart->getParent()->end();
+
+ unsigned NL = std::distance(LStart, LE);
+
+ SmallVector<DiffEntry, 20> Paths1(NL+1);
+ SmallVector<DiffEntry, 20> Paths2(NL+1);
+
+ DiffEntry *Cur = Paths1.data();
+ DiffEntry *Next = Paths2.data();
+
+ const unsigned LeftCost = 2;
+ const unsigned RightCost = 2;
+ const unsigned MatchCost = 0;
+
+ assert(TentativeValues.empty());
+
+ // Initialize the first column.
+ for (unsigned I = 0; I != NL+1; ++I) {
+ Cur[I].Cost = I * LeftCost;
+ for (unsigned J = 0; J != I; ++J)
+ Cur[I].Path.push_back(DifferenceEngine::DC_left);
+ }
+
+ for (BasicBlock::iterator RI = RStart; RI != RE; ++RI) {
+ // Initialize the first row.
+ Next[0] = Cur[0];
+ Next[0].Cost += RightCost;
+ Next[0].Path.push_back(DifferenceEngine::DC_right);
+
+ unsigned Index = 1;
+ for (BasicBlock::iterator LI = LStart; LI != LE; ++LI, ++Index) {
+ if (matchForBlockDiff(&*LI, &*RI)) {
+ Next[Index] = Cur[Index-1];
+ Next[Index].Cost += MatchCost;
+ Next[Index].Path.push_back(DifferenceEngine::DC_match);
+ TentativeValues.insert(std::make_pair(&*LI, &*RI));
+ } else if (Next[Index-1].Cost <= Cur[Index].Cost) {
+ Next[Index] = Next[Index-1];
+ Next[Index].Cost += LeftCost;
+ Next[Index].Path.push_back(DifferenceEngine::DC_left);
+ } else {
+ Next[Index] = Cur[Index];
+ Next[Index].Cost += RightCost;
+ Next[Index].Path.push_back(DifferenceEngine::DC_right);
+ }
+ }
+
+ std::swap(Cur, Next);
+ }
+
+ // We don't need the tentative values anymore; everything from here
+ // on out should be non-tentative.
+ TentativeValues.clear();
+
+ SmallVectorImpl<char> &Path = Cur[NL].Path;
+ BasicBlock::iterator LI = LStart, RI = RStart;
+
+ DifferenceEngine::DiffLogBuilder Diff(Engine);
+
+ // Drop trailing matches.
+ while (Path.back() == DifferenceEngine::DC_match)
+ Path.pop_back();
+
+ // Skip leading matches.
+ SmallVectorImpl<char>::iterator
+ PI = Path.begin(), PE = Path.end();
+ while (PI != PE && *PI == DifferenceEngine::DC_match) {
+ unify(&*LI, &*RI);
+ ++PI, ++LI, ++RI;
+ }
+
+ for (; PI != PE; ++PI) {
+ switch (static_cast<DifferenceEngine::DiffChange>(*PI)) {
+ case DifferenceEngine::DC_match:
+ assert(LI != LE && RI != RE);
+ {
+ Instruction *L = &*LI, *R = &*RI;
+ unify(L, R);
+ Diff.addMatch(L, R);
+ }
+ ++LI; ++RI;
+ break;
+
+ case DifferenceEngine::DC_left:
+ assert(LI != LE);
+ Diff.addLeft(&*LI);
+ ++LI;
+ break;
+
+ case DifferenceEngine::DC_right:
+ assert(RI != RE);
+ Diff.addRight(&*RI);
+ ++RI;
+ break;
+ }
+ }
+
+ // Finishing unifying and complaining about the tails of the block,
+ // which should be matches all the way through.
+ while (LI != LE) {
+ assert(RI != RE);
+ unify(&*LI, &*RI);
+ ++LI, ++RI;
+ }
+
+ // If the terminators have different kinds, but one is an invoke and the
+ // other is an unconditional branch immediately following a call, unify
+ // the results and the destinations.
+ TerminatorInst *LTerm = LStart->getParent()->getTerminator();
+ TerminatorInst *RTerm = RStart->getParent()->getTerminator();
+ if (isa<BranchInst>(LTerm) && isa<InvokeInst>(RTerm)) {
+ if (cast<BranchInst>(LTerm)->isConditional()) return;
+ BasicBlock::iterator I = LTerm;
+ if (I == LStart->getParent()->begin()) return;
+ --I;
+ if (!isa<CallInst>(*I)) return;
+ CallInst *LCall = cast<CallInst>(&*I);
+ InvokeInst *RInvoke = cast<InvokeInst>(RTerm);
+ if (!equivalentAsOperands(LCall->getCalledValue(), RInvoke->getCalledValue()))
+ return;
+ if (!LCall->use_empty())
+ Values[LCall] = RInvoke;
+ tryUnify(LTerm->getSuccessor(0), RInvoke->getNormalDest());
+ } else if (isa<InvokeInst>(LTerm) && isa<BranchInst>(RTerm)) {
+ if (cast<BranchInst>(RTerm)->isConditional()) return;
+ BasicBlock::iterator I = RTerm;
+ if (I == RStart->getParent()->begin()) return;
+ --I;
+ if (!isa<CallInst>(*I)) return;
+ CallInst *RCall = cast<CallInst>(I);
+ InvokeInst *LInvoke = cast<InvokeInst>(LTerm);
+ if (!equivalentAsOperands(LInvoke->getCalledValue(), RCall->getCalledValue()))
+ return;
+ if (!LInvoke->use_empty())
+ Values[LInvoke] = RCall;
+ tryUnify(LInvoke->getNormalDest(), RTerm->getSuccessor(0));
+ }
+}
+
+}
+
+void DifferenceEngine::diff(Function *L, Function *R) {
+ Context C(*this, L, R);
+
+ // FIXME: types
+ // FIXME: attributes and CC
+ // FIXME: parameter attributes
+
+ // If both are declarations, we're done.
+ if (L->empty() && R->empty())
+ return;
+ else if (L->empty())
+ log("left function is declaration, right function is definition");
+ else if (R->empty())
+ log("right function is declaration, left function is definition");
+ else
+ FunctionDifferenceEngine(*this).diff(L, R);
+}
+
+void DifferenceEngine::diff(Module *L, Module *R) {
+ StringSet<> LNames;
+ SmallVector<std::pair<Function*,Function*>, 20> Queue;
+
+ for (Module::iterator I = L->begin(), E = L->end(); I != E; ++I) {
+ Function *LFn = &*I;
+ LNames.insert(LFn->getName());
+
+ if (Function *RFn = R->getFunction(LFn->getName()))
+ Queue.push_back(std::make_pair(LFn, RFn));
+ else
+ logf("function %l exists only in left module") << LFn;
+ }
+
+ for (Module::iterator I = R->begin(), E = R->end(); I != E; ++I) {
+ Function *RFn = &*I;
+ if (!LNames.count(RFn->getName()))
+ logf("function %r exists only in right module") << RFn;
+ }
+
+ for (SmallVectorImpl<std::pair<Function*,Function*> >::iterator
+ I = Queue.begin(), E = Queue.end(); I != E; ++I)
+ diff(I->first, I->second);
+}
+
+bool DifferenceEngine::equivalentAsOperands(GlobalValue *L, GlobalValue *R) {
+ if (globalValueOracle) return (*globalValueOracle)(L, R);
+ return L->getName() == R->getName();
+}
diff --git a/tools/llvm-diff/DifferenceEngine.h b/tools/llvm-diff/DifferenceEngine.h
new file mode 100644
index 0000000..6eefb06
--- /dev/null
+++ b/tools/llvm-diff/DifferenceEngine.h
@@ -0,0 +1,179 @@
+//===-- DifferenceEngine.h - Module comparator ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the interface to the LLVM difference engine,
+// which structurally compares functions within a module.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LLVM_DIFFERENCE_ENGINE_H_
+#define _LLVM_DIFFERENCE_ENGINE_H_
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <utility>
+
+namespace llvm {
+ class Function;
+ class GlobalValue;
+ class Instruction;
+ class LLVMContext;
+ class Module;
+ class Twine;
+ class Value;
+
+ /// A class for performing structural comparisons of LLVM assembly.
+ class DifferenceEngine {
+ public:
+ /// A temporary-object class for building up log messages.
+ class LogBuilder {
+ DifferenceEngine &Engine;
+
+ /// The use of a stored StringRef here is okay because
+ /// LogBuilder should be used only as a temporary, and as a
+ /// temporary it will be destructed before whatever temporary
+ /// might be initializing this format.
+ StringRef Format;
+
+ SmallVector<Value*, 4> Arguments;
+
+ public:
+ LogBuilder(DifferenceEngine &Engine, StringRef Format)
+ : Engine(Engine), Format(Format) {}
+
+ LogBuilder &operator<<(Value *V) {
+ Arguments.push_back(V);
+ return *this;
+ }
+
+ ~LogBuilder() {
+ Engine.consumer.logf(*this);
+ }
+
+ StringRef getFormat() const { return Format; }
+
+ unsigned getNumArguments() const { return Arguments.size(); }
+ Value *getArgument(unsigned I) const { return Arguments[I]; }
+ };
+
+ enum DiffChange { DC_match, DC_left, DC_right };
+
+ /// A temporary-object class for building up diff messages.
+ class DiffLogBuilder {
+ typedef std::pair<Instruction*,Instruction*> DiffRecord;
+ SmallVector<DiffRecord, 20> Diff;
+
+ DifferenceEngine &Engine;
+
+ public:
+ DiffLogBuilder(DifferenceEngine &Engine) : Engine(Engine) {}
+ ~DiffLogBuilder() { Engine.consumer.logd(*this); }
+
+ void addMatch(Instruction *L, Instruction *R) {
+ Diff.push_back(DiffRecord(L, R));
+ }
+ void addLeft(Instruction *L) {
+ // HACK: VS 2010 has a bug in the stdlib that requires this.
+ Diff.push_back(DiffRecord(L, DiffRecord::second_type(0)));
+ }
+ void addRight(Instruction *R) {
+ // HACK: VS 2010 has a bug in the stdlib that requires this.
+ Diff.push_back(DiffRecord(DiffRecord::first_type(0), R));
+ }
+
+ unsigned getNumLines() const { return Diff.size(); }
+ DiffChange getLineKind(unsigned I) const {
+ return (Diff[I].first ? (Diff[I].second ? DC_match : DC_left)
+ : DC_right);
+ }
+ Instruction *getLeft(unsigned I) const { return Diff[I].first; }
+ Instruction *getRight(unsigned I) const { return Diff[I].second; }
+ };
+
+ /// The interface for consumers of difference data.
+ struct Consumer {
+ /// Record that a local context has been entered. Left and
+ /// Right are IR "containers" of some sort which are being
+ /// considered for structural equivalence: global variables,
+ /// functions, blocks, instructions, etc.
+ virtual void enterContext(Value *Left, Value *Right) = 0;
+
+ /// Record that a local context has been exited.
+ virtual void exitContext() = 0;
+
+ /// Record a difference within the current context.
+ virtual void log(StringRef Text) = 0;
+
+ /// Record a formatted difference within the current context.
+ virtual void logf(const LogBuilder &Log) = 0;
+
+ /// Record a line-by-line instruction diff.
+ virtual void logd(const DiffLogBuilder &Log) = 0;
+
+ protected:
+ virtual ~Consumer() {}
+ };
+
+ /// A RAII object for recording the current context.
+ struct Context {
+ Context(DifferenceEngine &Engine, Value *L, Value *R) : Engine(Engine) {
+ Engine.consumer.enterContext(L, R);
+ }
+
+ ~Context() {
+ Engine.consumer.exitContext();
+ }
+
+ private:
+ DifferenceEngine &Engine;
+ };
+
+ /// An oracle for answering whether two values are equivalent as
+ /// operands.
+ struct Oracle {
+ virtual bool operator()(Value *L, Value *R) = 0;
+
+ protected:
+ virtual ~Oracle() {}
+ };
+
+ DifferenceEngine(LLVMContext &context, Consumer &consumer)
+ : context(context), consumer(consumer), globalValueOracle(0) {}
+
+ void diff(Module *L, Module *R);
+ void diff(Function *L, Function *R);
+
+ void log(StringRef text) {
+ consumer.log(text);
+ }
+
+ LogBuilder logf(StringRef text) {
+ return LogBuilder(*this, text);
+ }
+
+ /// Installs an oracle to decide whether two global values are
+ /// equivalent as operands. Without an oracle, global values are
+ /// considered equivalent as operands precisely when they have the
+ /// same name.
+ void setGlobalValueOracle(Oracle *oracle) {
+ globalValueOracle = oracle;
+ }
+
+ /// Determines whether two global values are equivalent.
+ bool equivalentAsOperands(GlobalValue *L, GlobalValue *R);
+
+ private:
+ LLVMContext &context;
+ Consumer &consumer;
+ Oracle *globalValueOracle;
+ };
+}
+
+#endif
diff --git a/tools/llvmc/example/Skeleton/plugins/Plugin/Makefile b/tools/llvm-diff/Makefile
index 54f7221..58e49fa 100644
--- a/tools/llvmc/example/Skeleton/plugins/Plugin/Makefile
+++ b/tools/llvm-diff/Makefile
@@ -1,17 +1,17 @@
-##===- llvmc/example/Skeleton/plugins/Plugin/Makefile ------*- Makefile -*-===##
-#
+##===- tools/llvm-diff/Makefile ----------------------------*- Makefile -*-===##
+#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
-#
+#
##===----------------------------------------------------------------------===##
-LEVEL = $(LLVMC_BASE_LEVEL)/../..
-
-# Change this to the name of your plugin.
-LLVMC_PLUGIN = Plugin
+LEVEL = ../..
+TOOLNAME = llvm-diff
+LINK_COMPONENTS := asmparser bitreader
-BUILT_SOURCES = AutoGenerated.inc
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
include $(LEVEL)/Makefile.common
diff --git a/tools/llvm-diff/llvm-diff.cpp b/tools/llvm-diff/llvm-diff.cpp
new file mode 100644
index 0000000..16a990f
--- /dev/null
+++ b/tools/llvm-diff/llvm-diff.cpp
@@ -0,0 +1,331 @@
+//===-- llvm-diff.cpp - Module comparator command-line driver ---*- 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 command-line driver for the difference engine.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DifferenceEngine.h"
+
+#include "llvm/Instructions.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/Type.h"
+#include "llvm/Assembly/Parser.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/SourceMgr.h"
+
+#include <string>
+#include <utility>
+
+
+using namespace llvm;
+
+/// Reads a module from a file. If the filename ends in .ll, it is
+/// interpreted as an assembly file; otherwise, it is interpreted as
+/// bitcode. On error, messages are written to stderr and null is
+/// returned.
+static Module *ReadModule(LLVMContext &Context, StringRef Name) {
+ // LLVM assembly path.
+ if (Name.endswith(".ll")) {
+ SMDiagnostic Diag;
+ Module *M = ParseAssemblyFile(Name, Diag, Context);
+ if (M) return M;
+
+ Diag.Print("llvmdiff", errs());
+ return 0;
+ }
+
+ // Bitcode path.
+ MemoryBuffer *Buffer = MemoryBuffer::getFile(Name);
+
+ // ParseBitcodeFile takes ownership of the buffer if it succeeds.
+ std::string Error;
+ Module *M = ParseBitcodeFile(Buffer, Context, &Error);
+ if (M) return M;
+
+ errs() << "error parsing " << Name << ": " << Error;
+ delete Buffer;
+ return 0;
+}
+
+namespace {
+struct DiffContext {
+ DiffContext(Value *L, Value *R)
+ : L(L), R(R), Differences(false), IsFunction(isa<Function>(L)) {}
+ Value *L;
+ Value *R;
+ bool Differences;
+ bool IsFunction;
+ DenseMap<Value*,unsigned> LNumbering;
+ DenseMap<Value*,unsigned> RNumbering;
+};
+
+void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering) {
+ unsigned IN = 0;
+
+ // Arguments get the first numbers.
+ for (Function::arg_iterator
+ AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI)
+ if (!AI->hasName())
+ Numbering[&*AI] = IN++;
+
+ // Walk the basic blocks in order.
+ for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) {
+ if (!FI->hasName())
+ Numbering[&*FI] = IN++;
+
+ // Walk the instructions in order.
+ for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
+ // void instructions don't get numbers.
+ if (!BI->hasName() && !BI->getType()->isVoidTy())
+ Numbering[&*BI] = IN++;
+ }
+
+ assert(!Numbering.empty() && "asked for numbering but numbering was no-op");
+}
+
+class DiffConsumer : public DifferenceEngine::Consumer {
+private:
+ raw_ostream &out;
+ Module *LModule;
+ Module *RModule;
+ SmallVector<DiffContext, 5> contexts;
+ bool Differences;
+ unsigned Indent;
+
+ void printValue(Value *V, bool isL) {
+ if (V->hasName()) {
+ out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName();
+ return;
+ }
+ if (V->getType()->isVoidTy()) {
+ if (isa<StoreInst>(V)) {
+ out << "store to ";
+ printValue(cast<StoreInst>(V)->getPointerOperand(), isL);
+ } else if (isa<CallInst>(V)) {
+ out << "call to ";
+ printValue(cast<CallInst>(V)->getCalledValue(), isL);
+ } else if (isa<InvokeInst>(V)) {
+ out << "invoke to ";
+ printValue(cast<InvokeInst>(V)->getCalledValue(), isL);
+ } else {
+ out << *V;
+ }
+ return;
+ }
+
+ unsigned N = contexts.size();
+ while (N > 0) {
+ --N;
+ DiffContext &ctxt = contexts[N];
+ if (!ctxt.IsFunction) continue;
+ if (isL) {
+ if (ctxt.LNumbering.empty())
+ ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering);
+ out << '%' << ctxt.LNumbering[V];
+ return;
+ } else {
+ if (ctxt.RNumbering.empty())
+ ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering);
+ out << '%' << ctxt.RNumbering[V];
+ return;
+ }
+ }
+
+ out << "<anonymous>";
+ }
+
+ void header() {
+ if (contexts.empty()) return;
+ for (SmallVectorImpl<DiffContext>::iterator
+ I = contexts.begin(), E = contexts.end(); I != E; ++I) {
+ if (I->Differences) continue;
+ if (isa<Function>(I->L)) {
+ // Extra newline between functions.
+ if (Differences) out << "\n";
+
+ Function *L = cast<Function>(I->L);
+ Function *R = cast<Function>(I->R);
+ if (L->getName() != R->getName())
+ out << "in function " << L->getName()
+ << " / " << R->getName() << ":\n";
+ else
+ out << "in function " << L->getName() << ":\n";
+ } else if (isa<BasicBlock>(I->L)) {
+ BasicBlock *L = cast<BasicBlock>(I->L);
+ BasicBlock *R = cast<BasicBlock>(I->R);
+ if (L->hasName() && R->hasName() && L->getName() == R->getName())
+ out << " in block %" << L->getName() << ":\n";
+ else {
+ out << " in block ";
+ printValue(L, true);
+ out << " / ";
+ printValue(R, false);
+ out << ":\n";
+ }
+ } else if (isa<Instruction>(I->L)) {
+ out << " in instruction ";
+ printValue(I->L, true);
+ out << " / ";
+ printValue(I->R, false);
+ out << ":\n";
+ }
+
+ I->Differences = true;
+ }
+ }
+
+ void indent() {
+ unsigned N = Indent;
+ while (N--) out << ' ';
+ }
+
+public:
+ DiffConsumer(Module *L, Module *R)
+ : out(errs()), LModule(L), RModule(R), Differences(false), Indent(0) {}
+
+ bool hadDifferences() const { return Differences; }
+
+ void enterContext(Value *L, Value *R) {
+ contexts.push_back(DiffContext(L, R));
+ Indent += 2;
+ }
+ void exitContext() {
+ Differences |= contexts.back().Differences;
+ contexts.pop_back();
+ Indent -= 2;
+ }
+
+ void log(StringRef text) {
+ header();
+ indent();
+ out << text << '\n';
+ }
+
+ void logf(const DifferenceEngine::LogBuilder &Log) {
+ header();
+ indent();
+
+ unsigned arg = 0;
+
+ StringRef format = Log.getFormat();
+ while (true) {
+ size_t percent = format.find('%');
+ if (percent == StringRef::npos) {
+ out << format;
+ break;
+ }
+ assert(format[percent] == '%');
+
+ if (percent > 0) out << format.substr(0, percent);
+
+ switch (format[percent+1]) {
+ case '%': out << '%'; break;
+ case 'l': printValue(Log.getArgument(arg++), true); break;
+ case 'r': printValue(Log.getArgument(arg++), false); break;
+ default: llvm_unreachable("unknown format character");
+ }
+
+ format = format.substr(percent+2);
+ }
+
+ out << '\n';
+ }
+
+ void logd(const DifferenceEngine::DiffLogBuilder &Log) {
+ header();
+
+ for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) {
+ indent();
+ switch (Log.getLineKind(I)) {
+ case DifferenceEngine::DC_match:
+ out << " ";
+ Log.getLeft(I)->dump();
+ //printValue(Log.getLeft(I), true);
+ break;
+ case DifferenceEngine::DC_left:
+ out << "< ";
+ Log.getLeft(I)->dump();
+ //printValue(Log.getLeft(I), true);
+ break;
+ case DifferenceEngine::DC_right:
+ out << "> ";
+ Log.getRight(I)->dump();
+ //printValue(Log.getRight(I), false);
+ break;
+ }
+ //out << "\n";
+ }
+ }
+
+};
+}
+
+static void diffGlobal(DifferenceEngine &Engine, Module *L, Module *R,
+ StringRef Name) {
+ // Drop leading sigils from the global name.
+ if (Name.startswith("@")) Name = Name.substr(1);
+
+ Function *LFn = L->getFunction(Name);
+ Function *RFn = R->getFunction(Name);
+ if (LFn && RFn)
+ Engine.diff(LFn, RFn);
+ else if (!LFn && !RFn)
+ errs() << "No function named @" << Name << " in either module\n";
+ else if (!LFn)
+ errs() << "No function named @" << Name << " in left module\n";
+ else
+ errs() << "No function named @" << Name << " in right module\n";
+}
+
+cl::opt<std::string> LeftFilename(cl::Positional,
+ cl::desc("<first file>"),
+ cl::Required);
+cl::opt<std::string> RightFilename(cl::Positional,
+ cl::desc("<second file>"),
+ cl::Required);
+cl::list<std::string> GlobalsToCompare(cl::Positional,
+ cl::desc("<globals to compare>"));
+
+int main(int argc, char **argv) {
+ cl::ParseCommandLineOptions(argc, argv);
+
+ LLVMContext Context;
+
+ // Load both modules. Die if that fails.
+ Module *LModule = ReadModule(Context, LeftFilename);
+ Module *RModule = ReadModule(Context, RightFilename);
+ if (!LModule || !RModule) return 1;
+
+ DiffConsumer Consumer(LModule, RModule);
+ DifferenceEngine Engine(Context, Consumer);
+
+ // If any global names were given, just diff those.
+ if (!GlobalsToCompare.empty()) {
+ for (unsigned I = 0, E = GlobalsToCompare.size(); I != E; ++I)
+ diffGlobal(Engine, LModule, RModule, GlobalsToCompare[I]);
+
+ // Otherwise, diff everything in the module.
+ } else {
+ Engine.diff(LModule, RModule);
+ }
+
+ delete LModule;
+ delete RModule;
+
+ return Consumer.hadDifferences();
+}
diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp
index b8b1a39..9d2d31d 100644
--- a/tools/llvm-dis/llvm-dis.cpp
+++ b/tools/llvm-dis/llvm-dis.cpp
@@ -18,14 +18,16 @@
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
+#include "llvm/Type.h"
#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Assembly/AssemblyAnnotationWriter.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
-#include <memory>
using namespace llvm;
static cl::opt<std::string>
@@ -41,6 +43,29 @@ Force("f", cl::desc("Enable binary output on terminals"));
static cl::opt<bool>
DontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden);
+static cl::opt<bool>
+ShowAnnotations("show-annotations",
+ cl::desc("Add informational comments to the .ll file"));
+
+namespace {
+
+class CommentWriter : public AssemblyAnnotationWriter {
+public:
+ void emitFunctionAnnot(const Function *F,
+ formatted_raw_ostream &OS) {
+ OS << "; [#uses=" << F->getNumUses() << ']'; // Output # uses
+ OS << '\n';
+ }
+ void printInfoComment(const Value &V, formatted_raw_ostream &OS) {
+ if (V.getType()->isVoidTy()) return;
+
+ OS.PadToColumn(50);
+ OS << "; [#uses=" << V.getNumUses() << ']'; // Output # uses
+ }
+};
+
+} // end anon namespace
+
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
@@ -88,23 +113,25 @@ int main(int argc, char **argv) {
}
}
- // Make sure that the Out file gets unlinked from the disk if we get a
- // SIGINT.
- if (OutputFilename != "-")
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
std::string ErrorInfo;
- std::auto_ptr<raw_fd_ostream>
- Out(new raw_fd_ostream(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary));
+ OwningPtr<tool_output_file>
+ Out(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
+ raw_fd_ostream::F_Binary));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
}
+ OwningPtr<AssemblyAnnotationWriter> Annotator;
+ if (ShowAnnotations)
+ Annotator.reset(new CommentWriter());
+
// All that llvm-dis does is write the assembly to a file.
if (!DontPrint)
- *Out << *M;
+ M->print(Out->os(), Annotator.get());
+
+ // Declare success.
+ Out->keep();
return 0;
}
diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp
index e6b5b84..91a59e5 100644
--- a/tools/llvm-extract/llvm-extract.cpp
+++ b/tools/llvm-extract/llvm-extract.cpp
@@ -44,10 +44,6 @@ Force("f", cl::desc("Enable binary output on terminals"));
static cl::opt<bool>
DeleteFn("delete", cl::desc("Delete specified Globals from Module"));
-static cl::opt<bool>
-Relink("relink",
- cl::desc("Turn external linkage for callees of function to delete"));
-
// ExtractFuncs - The functions to extract from the module...
static cl::list<std::string>
ExtractFuncs("func", cl::desc("Specify function to extract"),
@@ -71,9 +67,10 @@ int main(int argc, char **argv) {
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n");
+ // Use lazy loading, since we only care about selected global values.
SMDiagnostic Err;
std::auto_ptr<Module> M;
- M.reset(ParseIRFile(InputFilename, Err, Context));
+ M.reset(getLazyIRFileModule(InputFilename, Err, Context));
if (M.get() == 0) {
Err.Print(argv[0], errs());
@@ -104,36 +101,47 @@ int main(int argc, char **argv) {
GVs.push_back(GV);
}
+ // Materialize requisite global values.
+ for (size_t i = 0, e = GVs.size(); i != e; ++i) {
+ GlobalValue *GV = GVs[i];
+ if (GV->isMaterializable()) {
+ std::string ErrInfo;
+ if (GV->Materialize(&ErrInfo)) {
+ errs() << argv[0] << ": error reading input: " << ErrInfo << "\n";
+ return 1;
+ }
+ }
+ }
+
// In addition to deleting all other functions, we also want to spiff it
// up a little bit. Do this now.
PassManager Passes;
Passes.add(new TargetData(M.get())); // Use correct TargetData
- Passes.add(createGVExtractionPass(GVs, DeleteFn, Relink));
+ Passes.add(createGVExtractionPass(GVs, DeleteFn));
if (!DeleteFn)
Passes.add(createGlobalDCEPass()); // Delete unreachable globals
Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info
Passes.add(createDeadTypeEliminationPass()); // Remove dead types...
Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls
- // Make sure that the Output file gets unlinked from the disk if we get a
- // SIGINT
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
std::string ErrorInfo;
- raw_fd_ostream Out(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary);
+ tool_output_file Out(OutputFilename.c_str(), ErrorInfo,
+ raw_fd_ostream::F_Binary);
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
}
if (OutputAssembly)
- Passes.add(createPrintModulePass(&Out));
- else if (Force || !CheckBitcodeOutputToConsole(Out, true))
- Passes.add(createBitcodeWriterPass(Out));
+ Passes.add(createPrintModulePass(&Out.os()));
+ else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
+ Passes.add(createBitcodeWriterPass(Out.os()));
Passes.run(*M.get());
+ // Declare success.
+ Out.keep();
+
return 0;
}
diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp
index ad6956c..3bbea9d 100644
--- a/tools/llvm-ld/llvm-ld.cpp
+++ b/tools/llvm-ld/llvm-ld.cpp
@@ -145,8 +145,8 @@ static void PrintCommand(const std::vector<const char*> &args) {
std::vector<const char*>::const_iterator I = args.begin(), E = args.end();
for (; I != E; ++I)
if (*I)
- outs() << "'" << *I << "'" << " ";
- outs() << "\n"; outs().flush();
+ errs() << "'" << *I << "'" << " ";
+ errs() << "\n";
}
/// CopyEnv - This function takes an array of environment variables and makes a
@@ -232,17 +232,20 @@ static void RemoveEnv(const char * name, char ** const envp) {
void GenerateBitcode(Module* M, const std::string& FileName) {
if (Verbose)
- outs() << "Generating Bitcode To " << FileName << '\n';
+ errs() << "Generating Bitcode To " << FileName << '\n';
// Create the output file.
std::string ErrorInfo;
- raw_fd_ostream Out(FileName.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary);
- if (!ErrorInfo.empty())
+ tool_output_file Out(FileName.c_str(), ErrorInfo,
+ raw_fd_ostream::F_Binary);
+ if (!ErrorInfo.empty()) {
PrintAndExit(ErrorInfo, M);
+ return;
+ }
// Write it out
- WriteBitcodeToFile(M, Out);
+ WriteBitcodeToFile(M, Out.os());
+ Out.keep();
}
/// GenerateAssembly - generates a native assembly language source file from the
@@ -272,7 +275,7 @@ static int GenerateAssembly(const std::string &OutputFilename,
args.push_back(0);
if (Verbose) {
- outs() << "Generating Assembly With: \n";
+ errs() << "Generating Assembly With: \n";
PrintCommand(args);
}
@@ -294,7 +297,7 @@ static int GenerateCFile(const std::string &OutputFile,
args.push_back(0);
if (Verbose) {
- outs() << "Generating C Source With: \n";
+ errs() << "Generating C Source With: \n";
PrintCommand(args);
}
@@ -391,7 +394,7 @@ static int GenerateNative(const std::string &OutputFilename,
Args.push_back(0);
if (Verbose) {
- outs() << "Generating Native Executable With:\n";
+ errs() << "Generating Native Executable With:\n";
PrintCommand(Args);
}
@@ -406,7 +409,7 @@ static int GenerateNative(const std::string &OutputFilename,
/// bitcode file for the program.
static void EmitShellScript(char **argv, Module *M) {
if (Verbose)
- outs() << "Emitting Shell Script\n";
+ errs() << "Emitting Shell Script\n";
#if defined(_WIN32) || defined(__CYGWIN__)
// Windows doesn't support #!/bin/sh style shell scripts in .exe files. To
// support windows systems, we copy the llvm-stub.exe executable from the
@@ -425,14 +428,14 @@ static void EmitShellScript(char **argv, Module *M) {
// Output the script to start the program...
std::string ErrorInfo;
- raw_fd_ostream Out2(OutputFilename.c_str(), ErrorInfo);
+ tool_output_file Out2(OutputFilename.c_str(), ErrorInfo);
if (!ErrorInfo.empty())
PrintAndExit(ErrorInfo, M);
- Out2 << "#!/bin/sh\n";
+ Out2.os() << "#!/bin/sh\n";
// Allow user to setenv LLVMINTERP if lli is not in their PATH.
- Out2 << "lli=${LLVMINTERP-lli}\n";
- Out2 << "exec $lli \\\n";
+ Out2.os() << "lli=${LLVMINTERP-lli}\n";
+ Out2.os() << "exec $lli \\\n";
// gcc accepts -l<lib> and implicitly searches /lib and /usr/lib.
LibPaths.push_back("/lib");
LibPaths.push_back("/usr/lib");
@@ -463,9 +466,10 @@ static void EmitShellScript(char **argv, Module *M) {
if (FullLibraryPath.isEmpty())
FullLibraryPath = sys::Path::FindLibrary(*i);
if (!FullLibraryPath.isEmpty())
- Out2 << " -load=" << FullLibraryPath.str() << " \\\n";
+ Out2.os() << " -load=" << FullLibraryPath.str() << " \\\n";
}
- Out2 << " " << BitcodeOutputFilename << " ${1+\"$@\"}\n";
+ Out2.os() << " " << BitcodeOutputFilename << " ${1+\"$@\"}\n";
+ Out2.keep();
}
// BuildLinkItems -- This function generates a LinkItemList for the LinkItems
diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp
index f7dad3d..e55d0de 100644
--- a/tools/llvm-link/llvm-link.cpp
+++ b/tools/llvm-link/llvm-link.cpp
@@ -116,19 +116,13 @@ int main(int argc, char **argv) {
if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;
std::string ErrorInfo;
- std::auto_ptr<raw_ostream>
- Out(new raw_fd_ostream(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary));
+ tool_output_file Out(OutputFilename.c_str(), ErrorInfo,
+ raw_fd_ostream::F_Binary);
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
return 1;
}
- // Make sure that the Out file gets unlinked from the disk if we get a
- // SIGINT
- if (OutputFilename != "-")
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
if (verifyModule(*Composite)) {
errs() << argv[0] << ": linked module is broken!\n";
return 1;
@@ -136,9 +130,12 @@ int main(int argc, char **argv) {
if (Verbose) errs() << "Writing bitcode...\n";
if (OutputAssembly) {
- *Out << *Composite;
- } else if (Force || !CheckBitcodeOutputToConsole(*Out, true))
- WriteBitcodeToFile(Composite.get(), *Out);
+ Out.os() << *Composite;
+ } else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
+ WriteBitcodeToFile(Composite.get(), Out.os());
+
+ // Declare success.
+ Out.keep();
return 0;
}
diff --git a/tools/llvm-mc/CMakeLists.txt b/tools/llvm-mc/CMakeLists.txt
index 8b61a4e..805caf4 100644
--- a/tools/llvm-mc/CMakeLists.txt
+++ b/tools/llvm-mc/CMakeLists.txt
@@ -1,5 +1,4 @@
-set( LLVM_USED_LIBS EnhancedDisassembly)
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC MCParser)
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC MCParser MCDisassembler)
add_llvm_tool(llvm-mc
llvm-mc.cpp
diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp
index 37b2cb8..13080b4 100644
--- a/tools/llvm-mc/Disassembler.cpp
+++ b/tools/llvm-mc/Disassembler.cpp
@@ -13,21 +13,21 @@
//===----------------------------------------------------------------------===//
#include "Disassembler.h"
-
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/Triple.h"
+#include "../../lib/MC/MCDisassembler/EDDisassembler.h"
+#include "../../lib/MC/MCDisassembler/EDInst.h"
+#include "../../lib/MC/MCDisassembler/EDOperand.h"
+#include "../../lib/MC/MCDisassembler/EDToken.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/Target/TargetRegistry.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"
-
-#include "llvm-c/EnhancedDisassembly.h"
-
using namespace llvm;
typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy;
@@ -53,7 +53,7 @@ public:
static bool PrintInsts(const MCDisassembler &DisAsm,
MCInstPrinter &Printer, const ByteArrayTy &Bytes,
- SourceMgr &SM) {
+ SourceMgr &SM, raw_ostream &Out) {
// Wrap the vector in a MemoryObject.
VectorMemoryObject memoryObject(Bytes);
@@ -66,8 +66,8 @@ static bool PrintInsts(const MCDisassembler &DisAsm,
if (DisAsm.getInstruction(Inst, Size, memoryObject, Index,
/*REMOVE*/ nulls())) {
- Printer.printInst(&Inst, outs());
- outs() << "\n";
+ Printer.printInst(&Inst, Out);
+ Out << "\n";
} else {
SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
"invalid instruction encoding", "warning");
@@ -127,7 +127,8 @@ static bool ByteArrayFromString(ByteArrayTy &ByteArray,
}
int Disassembler::disassemble(const Target &T, const std::string &Triple,
- MemoryBuffer &Buffer) {
+ MemoryBuffer &Buffer,
+ raw_ostream &Out) {
// Set up disassembler.
OwningPtr<const MCAsmInfo> AsmInfo(T.createAsmInfo(Triple));
@@ -162,7 +163,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,
ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
if (!ByteArray.empty())
- ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM);
+ ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM, Out);
return ErrorOccurred;
}
@@ -179,26 +180,24 @@ static int byteArrayReader(uint8_t *B, uint64_t A, void *Arg) {
}
static int verboseEvaluator(uint64_t *V, unsigned R, void *Arg) {
- EDDisassemblerRef &disassembler = *((EDDisassemblerRef*)Arg);
+ EDDisassembler &disassembler = *(EDDisassembler *)((void **)Arg)[0];
+ raw_ostream &Out = *(raw_ostream *)((void **)Arg)[1];
- const char *regName;
+ if (const char *regName = disassembler.nameWithRegisterID(R))
+ Out << "[" << regName << "/" << R << "]";
- if (!EDGetRegisterName(&regName,
- disassembler,
- R))
- outs() << "[" << regName << "/" << R << "]";
- if (EDRegisterIsStackPointer(disassembler, R))
- outs() << "(sp)";
- if (EDRegisterIsProgramCounter(disassembler, R))
- outs() << "(pc)";
+ if (disassembler.registerIsStackPointer(R))
+ Out << "(sp)";
+ if (disassembler.registerIsProgramCounter(R))
+ Out << "(pc)";
*V = 0;
-
return 0;
}
int Disassembler::disassembleEnhanced(const std::string &TS,
- MemoryBuffer &Buffer) {
+ MemoryBuffer &Buffer,
+ raw_ostream &Out) {
ByteArrayTy ByteArray;
StringRef Str = Buffer.getBuffer();
SourceMgr SM;
@@ -209,10 +208,8 @@ int Disassembler::disassembleEnhanced(const std::string &TS,
return -1;
}
- EDDisassemblerRef disassembler;
-
Triple T(TS);
- EDAssemblySyntax_t AS;
+ EDDisassembler::AssemblySyntax AS;
switch (T.getArch()) {
default:
@@ -220,140 +217,121 @@ int Disassembler::disassembleEnhanced(const std::string &TS,
return -1;
case Triple::arm:
case Triple::thumb:
- AS = kEDAssemblySyntaxARMUAL;
+ AS = EDDisassembler::kEDAssemblySyntaxARMUAL;
break;
case Triple::x86:
case Triple::x86_64:
- AS = kEDAssemblySyntaxX86ATT;
+ AS = EDDisassembler::kEDAssemblySyntaxX86ATT;
break;
}
- if (EDGetDisassembler(&disassembler,
- TS.c_str(),
- AS)) {
- errs() << "error: couldn't get disassembler for " << TS.c_str() << "\n";
+ EDDisassembler::initialize();
+ EDDisassembler *disassembler =
+ EDDisassembler::getDisassembler(TS.c_str(), AS);
+
+ if (disassembler == 0) {
+ errs() << "error: couldn't get disassembler for " << TS << '\n';
return -1;
}
- EDInstRef inst;
-
- if (EDCreateInsts(&inst, 1, disassembler, byteArrayReader, 0,&ByteArray)
- != 1) {
+ EDInst *inst =
+ disassembler->createInst(byteArrayReader, 0, &ByteArray);
+
+ if (inst == 0) {
errs() << "error: Didn't get an instruction\n";
return -1;
}
- int numTokens = EDNumTokens(inst);
-
- if (numTokens < 0) {
- errs() << "error: Couldn't count the instruction's tokens\n";
+ unsigned numTokens = inst->numTokens();
+ if ((int)numTokens < 0) {
+ errs() << "error: couldn't count the instruction's tokens\n";
return -1;
}
- int tokenIndex;
-
- for (tokenIndex = 0; tokenIndex < numTokens; ++tokenIndex) {
- EDTokenRef token;
+ for (unsigned tokenIndex = 0; tokenIndex != numTokens; ++tokenIndex) {
+ EDToken *token;
- if (EDGetToken(&token, inst, tokenIndex)) {
+ if (inst->getToken(token, tokenIndex)) {
errs() << "error: Couldn't get token\n";
return -1;
}
const char *buf;
-
- if (EDGetTokenString(&buf, token)) {
+ if (token->getString(buf)) {
errs() << "error: Couldn't get string for token\n";
return -1;
}
- outs() << "[";
-
- int operandIndex = EDOperandIndexForToken(token);
+ Out << '[';
+ int operandIndex = token->operandID();
if (operandIndex >= 0)
- outs() << operandIndex << "-";
+ Out << operandIndex << "-";
- if (EDTokenIsWhitespace(token)) {
- outs() << "w";
- } else if (EDTokenIsPunctuation(token)) {
- outs() << "p";
- } else if (EDTokenIsOpcode(token)) {
- outs() << "o";
- } else if (EDTokenIsLiteral(token)) {
- outs() << "l";
- } else if (EDTokenIsRegister(token)) {
- outs() << "r";
- } else {
- outs() << "?";
+ switch (token->type()) {
+ default: Out << "?"; break;
+ case EDToken::kTokenWhitespace: Out << "w"; break;
+ case EDToken::kTokenPunctuation: Out << "p"; break;
+ case EDToken::kTokenOpcode: Out << "o"; break;
+ case EDToken::kTokenLiteral: Out << "l"; break;
+ case EDToken::kTokenRegister: Out << "r"; break;
}
- outs() << ":" << buf;
+ Out << ":" << buf;
- if (EDTokenIsLiteral(token)) {
- outs() << "=";
- if (EDTokenIsNegativeLiteral(token))
- outs() << "-";
+ if (token->type() == EDToken::kTokenLiteral) {
+ Out << "=";
+ if (token->literalSign())
+ Out << "-";
uint64_t absoluteValue;
- if (EDLiteralTokenAbsoluteValue(&absoluteValue, token)) {
+ if (token->literalAbsoluteValue(absoluteValue)) {
errs() << "error: Couldn't get the value of a literal token\n";
return -1;
}
- outs() << absoluteValue;
- } else if (EDTokenIsRegister(token)) {
- outs() << "=";
+ Out << absoluteValue;
+ } else if (token->type() == EDToken::kTokenRegister) {
+ Out << "=";
unsigned regID;
- if (EDRegisterTokenValue(&regID, token)) {
+ if (token->registerID(regID)) {
errs() << "error: Couldn't get the ID of a register token\n";
return -1;
}
- outs() << "r" << regID;
+ Out << "r" << regID;
}
- outs() << "]";
+ Out << "]";
}
- outs() << " ";
+ Out << " ";
- if (EDInstIsBranch(inst))
- outs() << "<br> ";
- if (EDInstIsMove(inst))
- outs() << "<mov> ";
+ if (inst->isBranch())
+ Out << "<br> ";
+ if (inst->isMove())
+ Out << "<mov> ";
- int numOperands = EDNumOperands(inst);
+ unsigned numOperands = inst->numOperands();
- if (numOperands < 0) {
+ if ((int)numOperands < 0) {
errs() << "error: Couldn't count operands\n";
return -1;
}
- int operandIndex;
-
- for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
- outs() << operandIndex << ":";
-
- EDOperandRef operand;
+ for (unsigned operandIndex = 0; operandIndex != numOperands; ++operandIndex) {
+ Out << operandIndex << ":";
- if (EDGetOperand(&operand,
- inst,
- operandIndex)) {
- errs() << "error: Couldn't get operand\n";
+ EDOperand *operand;
+ if (inst->getOperand(operand, operandIndex)) {
+ errs() << "error: couldn't get operand\n";
return -1;
}
uint64_t evaluatedResult;
-
- EDEvaluateOperand(&evaluatedResult,
- operand,
- verboseEvaluator,
- &disassembler);
-
- outs() << "=" << evaluatedResult;
-
- outs() << " ";
+ void *Arg[] = { disassembler, &Out };
+ evaluatedResult = operand->evaluate(evaluatedResult, verboseEvaluator, Arg);
+ Out << "=" << evaluatedResult << " ";
}
- outs() << "\n";
+ Out << '\n';
return 0;
}
diff --git a/tools/llvm-mc/Disassembler.h b/tools/llvm-mc/Disassembler.h
index 3da2396..b56f2e9 100644
--- a/tools/llvm-mc/Disassembler.h
+++ b/tools/llvm-mc/Disassembler.h
@@ -21,15 +21,18 @@ namespace llvm {
class Target;
class MemoryBuffer;
+class raw_ostream;
class Disassembler {
public:
static int disassemble(const Target &target,
const std::string &tripleString,
- MemoryBuffer &buffer);
+ MemoryBuffer &buffer,
+ raw_ostream &Out);
static int disassembleEnhanced(const std::string &tripleString,
- MemoryBuffer &buffer);
+ MemoryBuffer &buffer,
+ raw_ostream &Out);
};
} // namespace llvm
diff --git a/tools/llvm-mc/Makefile b/tools/llvm-mc/Makefile
index a127493..934a6e4 100644
--- a/tools/llvm-mc/Makefile
+++ b/tools/llvm-mc/Makefile
@@ -18,9 +18,7 @@ TOOL_NO_EXPORTS = 1
# early so we can set up LINK_COMPONENTS before including Makefile.rules
include $(LEVEL)/Makefile.config
-LINK_COMPONENTS := $(TARGETS_TO_BUILD) MCParser MC support
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) MCDisassembler MCParser MC support
include $(LLVM_SRC_ROOT)/Makefile.rules
-# Using LIBS instead of USEDLIBS to force static linking
-LIBS += $(LLVMLibDir)/libEnhancedDisassembly.a
diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index fc8a1c5..aef0a3d 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/tools/llvm-mc/llvm-mc.cpp
@@ -12,13 +12,13 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/MC/MCParser/AsmLexer.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCParser/AsmParser.h"
#include "llvm/Target/TargetAsmBackend.h"
#include "llvm/Target/TargetAsmParser.h"
#include "llvm/Target/TargetData.h"
@@ -27,6 +27,7 @@
#include "llvm/Target/TargetSelect.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -51,6 +52,10 @@ ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
static cl::opt<bool>
ShowInst("show-inst", cl::desc("Show internal instruction representation"));
+static cl::opt<bool>
+ShowInstOperands("show-inst-operands",
+ cl::desc("Show instructions operands as parsed"));
+
static cl::opt<unsigned>
OutputAsmVariant("output-asm-variant",
cl::desc("Syntax variant to use for output printing"));
@@ -135,6 +140,22 @@ static const Target *GetTarget(const char *ProgName) {
return 0;
}
+static tool_output_file *GetOutputStream() {
+ if (OutputFilename == "")
+ OutputFilename = "-";
+
+ std::string Err;
+ tool_output_file *Out = new tool_output_file(OutputFilename.c_str(), Err,
+ raw_fd_ostream::F_Binary);
+ if (!Err.empty()) {
+ errs() << Err << '\n';
+ delete Out;
+ return 0;
+ }
+
+ return Out;
+}
+
static int AsLexInput(const char *ProgName) {
std::string ErrorMessage;
MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename,
@@ -165,9 +186,13 @@ static int AsLexInput(const char *ProgName) {
assert(MAI && "Unable to create target asm info!");
AsmLexer Lexer(*MAI);
-
+ Lexer.setBuffer(SrcMgr.getMemoryBuffer(0));
+
+ OwningPtr<tool_output_file> Out(GetOutputStream());
+ if (!Out)
+ return 1;
+
bool Error = false;
-
while (Lexer.Lex().isNot(AsmToken::Eof)) {
switch (Lexer.getKind()) {
default:
@@ -178,69 +203,51 @@ static int AsLexInput(const char *ProgName) {
Error = true; // error already printed.
break;
case AsmToken::Identifier:
- outs() << "identifier: " << Lexer.getTok().getString() << '\n';
+ Out->os() << "identifier: " << Lexer.getTok().getString() << '\n';
break;
case AsmToken::String:
- outs() << "string: " << Lexer.getTok().getString() << '\n';
+ Out->os() << "string: " << Lexer.getTok().getString() << '\n';
break;
case AsmToken::Integer:
- outs() << "int: " << Lexer.getTok().getString() << '\n';
+ Out->os() << "int: " << Lexer.getTok().getString() << '\n';
break;
- case AsmToken::Amp: outs() << "Amp\n"; break;
- case AsmToken::AmpAmp: outs() << "AmpAmp\n"; break;
- case AsmToken::Caret: outs() << "Caret\n"; break;
- case AsmToken::Colon: outs() << "Colon\n"; break;
- case AsmToken::Comma: outs() << "Comma\n"; break;
- case AsmToken::Dollar: outs() << "Dollar\n"; break;
- case AsmToken::EndOfStatement: outs() << "EndOfStatement\n"; break;
- case AsmToken::Eof: outs() << "Eof\n"; break;
- case AsmToken::Equal: outs() << "Equal\n"; break;
- case AsmToken::EqualEqual: outs() << "EqualEqual\n"; break;
- case AsmToken::Exclaim: outs() << "Exclaim\n"; break;
- case AsmToken::ExclaimEqual: outs() << "ExclaimEqual\n"; break;
- case AsmToken::Greater: outs() << "Greater\n"; break;
- case AsmToken::GreaterEqual: outs() << "GreaterEqual\n"; break;
- case AsmToken::GreaterGreater: outs() << "GreaterGreater\n"; break;
- case AsmToken::LParen: outs() << "LParen\n"; break;
- case AsmToken::Less: outs() << "Less\n"; break;
- case AsmToken::LessEqual: outs() << "LessEqual\n"; break;
- case AsmToken::LessGreater: outs() << "LessGreater\n"; break;
- case AsmToken::LessLess: outs() << "LessLess\n"; break;
- case AsmToken::Minus: outs() << "Minus\n"; break;
- case AsmToken::Percent: outs() << "Percent\n"; break;
- case AsmToken::Pipe: outs() << "Pipe\n"; break;
- case AsmToken::PipePipe: outs() << "PipePipe\n"; break;
- case AsmToken::Plus: outs() << "Plus\n"; break;
- case AsmToken::RParen: outs() << "RParen\n"; break;
- case AsmToken::Slash: outs() << "Slash\n"; break;
- case AsmToken::Star: outs() << "Star\n"; break;
- case AsmToken::Tilde: outs() << "Tilde\n"; break;
+ case AsmToken::Amp: Out->os() << "Amp\n"; break;
+ case AsmToken::AmpAmp: Out->os() << "AmpAmp\n"; break;
+ case AsmToken::Caret: Out->os() << "Caret\n"; break;
+ case AsmToken::Colon: Out->os() << "Colon\n"; break;
+ case AsmToken::Comma: Out->os() << "Comma\n"; break;
+ case AsmToken::Dollar: Out->os() << "Dollar\n"; break;
+ case AsmToken::EndOfStatement: Out->os() << "EndOfStatement\n"; break;
+ case AsmToken::Eof: Out->os() << "Eof\n"; break;
+ case AsmToken::Equal: Out->os() << "Equal\n"; break;
+ case AsmToken::EqualEqual: Out->os() << "EqualEqual\n"; break;
+ case AsmToken::Exclaim: Out->os() << "Exclaim\n"; break;
+ case AsmToken::ExclaimEqual: Out->os() << "ExclaimEqual\n"; break;
+ case AsmToken::Greater: Out->os() << "Greater\n"; break;
+ case AsmToken::GreaterEqual: Out->os() << "GreaterEqual\n"; break;
+ case AsmToken::GreaterGreater: Out->os() << "GreaterGreater\n"; break;
+ case AsmToken::LParen: Out->os() << "LParen\n"; break;
+ case AsmToken::Less: Out->os() << "Less\n"; break;
+ case AsmToken::LessEqual: Out->os() << "LessEqual\n"; break;
+ case AsmToken::LessGreater: Out->os() << "LessGreater\n"; break;
+ case AsmToken::LessLess: Out->os() << "LessLess\n"; break;
+ case AsmToken::Minus: Out->os() << "Minus\n"; break;
+ case AsmToken::Percent: Out->os() << "Percent\n"; break;
+ case AsmToken::Pipe: Out->os() << "Pipe\n"; break;
+ case AsmToken::PipePipe: Out->os() << "PipePipe\n"; break;
+ case AsmToken::Plus: Out->os() << "Plus\n"; break;
+ case AsmToken::RParen: Out->os() << "RParen\n"; break;
+ case AsmToken::Slash: Out->os() << "Slash\n"; break;
+ case AsmToken::Star: Out->os() << "Star\n"; break;
+ case AsmToken::Tilde: Out->os() << "Tilde\n"; break;
}
}
-
- return Error;
-}
-static formatted_raw_ostream *GetOutputStream() {
- if (OutputFilename == "")
- OutputFilename = "-";
-
- // Make sure that the Out file gets unlinked from the disk if we get a
- // SIGINT.
- if (OutputFilename != "-")
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
- std::string Err;
- raw_fd_ostream *Out = new raw_fd_ostream(OutputFilename.c_str(), Err,
- raw_fd_ostream::F_Binary);
- if (!Err.empty()) {
- errs() << Err << '\n';
- delete Out;
- return 0;
- }
-
- return new formatted_raw_ostream(*Out, formatted_raw_ostream::DELETE_STREAM);
+ // Keep output if no errors.
+ if (Error == 0) Out->keep();
+
+ return Error;
}
static int AssembleInput(const char *ProgName) {
@@ -273,10 +280,6 @@ static int AssembleInput(const char *ProgName) {
assert(MAI && "Unable to create target asm info!");
MCContext Ctx(*MAI);
- formatted_raw_ostream *Out = GetOutputStream();
- if (!Out)
- return 1;
-
// FIXME: We shouldn't need to do this (and link in codegen).
OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(TripleName, ""));
@@ -287,47 +290,52 @@ static int AssembleInput(const char *ProgName) {
return 1;
}
- OwningPtr<MCCodeEmitter> CE;
+ OwningPtr<tool_output_file> Out(GetOutputStream());
+ if (!Out)
+ return 1;
+
+ formatted_raw_ostream FOS(Out->os());
OwningPtr<MCStreamer> Str;
- OwningPtr<TargetAsmBackend> TAB;
if (FileType == OFT_AssemblyFile) {
MCInstPrinter *IP =
TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI);
+ MCCodeEmitter *CE = 0;
if (ShowEncoding)
- CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
- Str.reset(createAsmStreamer(Ctx, *Out,TM->getTargetData()->isLittleEndian(),
- /*asmverbose*/true, IP, CE.get(), ShowInst));
+ CE = TheTarget->createCodeEmitter(*TM, Ctx);
+ Str.reset(createAsmStreamer(Ctx, FOS,
+ TM->getTargetData()->isLittleEndian(),
+ /*asmverbose*/true, IP, CE, ShowInst));
} else if (FileType == OFT_Null) {
Str.reset(createNullStreamer(Ctx));
} else {
assert(FileType == OFT_ObjectFile && "Invalid file type!");
- CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
- TAB.reset(TheTarget->createAsmBackend(TripleName));
+ MCCodeEmitter *CE = TheTarget->createCodeEmitter(*TM, Ctx);
+ TargetAsmBackend *TAB = TheTarget->createAsmBackend(TripleName);
Str.reset(TheTarget->createObjectStreamer(TripleName, Ctx, *TAB,
- *Out, CE.get(), RelaxAll));
+ FOS, CE, RelaxAll));
}
if (EnableLogging) {
Str.reset(createLoggingStreamer(Str.take(), errs()));
}
- AsmParser Parser(*TheTarget, SrcMgr, Ctx, *Str.get(), *MAI);
- OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(Parser));
+ OwningPtr<MCAsmParser> Parser(createMCAsmParser(*TheTarget, SrcMgr, Ctx,
+ *Str.get(), *MAI));
+ OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(*Parser, *TM));
if (!TAP) {
errs() << ProgName
<< ": error: this target does not support assembly parsing.\n";
return 1;
}
- Parser.setTargetParser(*TAP.get());
+ Parser->setShowParsedOperands(ShowInstOperands);
+ Parser->setTargetParser(*TAP.get());
- int Res = Parser.Run(NoInitialTextSection);
- delete Out;
+ int Res = Parser->Run(NoInitialTextSection);
- // Delete output on errors.
- if (Res && OutputFilename != "-")
- sys::Path(OutputFilename).eraseFromDisk();
+ // Keep output if no errors.
+ if (Res == 0) Out->keep();
return Res;
}
@@ -351,10 +359,20 @@ static int DisassembleInput(const char *ProgName, bool Enhanced) {
return 1;
}
+ OwningPtr<tool_output_file> Out(GetOutputStream());
+ if (!Out)
+ return 1;
+
+ int Res;
if (Enhanced)
- return Disassembler::disassembleEnhanced(TripleName, *Buffer);
+ Res = Disassembler::disassembleEnhanced(TripleName, *Buffer, Out->os());
else
- return Disassembler::disassemble(*TheTarget, TripleName, *Buffer);
+ Res = Disassembler::disassemble(*TheTarget, TripleName, *Buffer, Out->os());
+
+ // Keep output if no errors.
+ if (Res == 0) Out->keep();
+
+ return Res;
}
@@ -373,6 +391,7 @@ int main(int argc, char **argv) {
llvm::InitializeAllDisassemblers();
cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
+ TripleName = Triple::normalize(TripleName);
switch (Action) {
default:
diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp
index fd7e7f6..daa8571 100644
--- a/tools/llvm-nm/llvm-nm.cpp
+++ b/tools/llvm-nm/llvm-nm.cpp
@@ -88,10 +88,13 @@ static char TypeCharForSymbol(GlobalValue &GV) {
static void DumpSymbolNameForGlobalValue(GlobalValue &GV) {
// Private linkage and available_externally linkage don't exist in symtab.
- if (GV.hasPrivateLinkage() || GV.hasLinkerPrivateLinkage() ||
- GV.hasLinkerPrivateWeakLinkage() || GV.hasAvailableExternallyLinkage())
+ if (GV.hasPrivateLinkage() ||
+ GV.hasLinkerPrivateLinkage() ||
+ GV.hasLinkerPrivateWeakLinkage() ||
+ GV.hasLinkerPrivateWeakDefAutoLinkage() ||
+ GV.hasAvailableExternallyLinkage())
return;
-
+
const std::string SymbolAddrStr = " "; // Not used yet...
char TypeChar = TypeCharForSymbol(GV);
if ((TypeChar != 'U') && UndefinedOnly)
@@ -145,13 +148,13 @@ static void DumpSymbolNamesFromFile(std::string &Filename) {
Module *Result = 0;
if (Buffer.get())
Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage);
-
+
if (Result) {
DumpSymbolNamesFromModule(Result);
delete Result;
} else
errs() << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
-
+
} else if (aPath.isArchive()) {
std::string ErrMsg;
Archive* archive = Archive::OpenAndLoad(sys::Path(Filename), Context,
@@ -176,7 +179,7 @@ int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
-
+
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
diff --git a/tools/llvm-prof/llvm-prof.cpp b/tools/llvm-prof/llvm-prof.cpp
index 88adeb4..1c63d97 100644
--- a/tools/llvm-prof/llvm-prof.cpp
+++ b/tools/llvm-prof/llvm-prof.cpp
@@ -17,12 +17,13 @@
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
-#include "llvm/Assembly/AsmAnnotationWriter.h"
+#include "llvm/Assembly/AssemblyAnnotationWriter.h"
#include "llvm/Analysis/ProfileInfo.h"
#include "llvm/Analysis/ProfileInfoLoader.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -75,9 +76,10 @@ namespace {
class ProfileAnnotator : public AssemblyAnnotationWriter {
ProfileInfo &PI;
public:
- ProfileAnnotator(ProfileInfo& pi) : PI(pi) {}
+ ProfileAnnotator(ProfileInfo &pi) : PI(pi) {}
- virtual void emitFunctionAnnot(const Function *F, raw_ostream &OS) {
+ virtual void emitFunctionAnnot(const Function *F,
+ formatted_raw_ostream &OS) {
double w = PI.getExecutionCount(F);
if (w != ProfileInfo::MissingValue) {
OS << ";;; %" << F->getName() << " called "<<(unsigned)w
@@ -85,7 +87,7 @@ namespace {
}
}
virtual void emitBasicBlockStartAnnot(const BasicBlock *BB,
- raw_ostream &OS) {
+ formatted_raw_ostream &OS) {
double w = PI.getExecutionCount(BB);
if (w != ProfileInfo::MissingValue) {
if (w != 0) {
@@ -96,7 +98,8 @@ namespace {
}
}
- virtual void emitBasicBlockEndAnnot(const BasicBlock *BB, raw_ostream &OS) {
+ virtual void emitBasicBlockEndAnnot(const BasicBlock *BB,
+ formatted_raw_ostream &OS) {
// Figure out how many times each successor executed.
std::vector<std::pair<ProfileInfo::Edge, double> > SuccCounts;
@@ -128,7 +131,7 @@ namespace {
public:
static char ID; // Class identification, replacement for typeinfo.
explicit ProfileInfoPrinterPass(ProfileInfoLoader &_PIL)
- : ModulePass(&ID), PIL(_PIL) {}
+ : ModulePass(ID), PIL(_PIL) {}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
diff --git a/tools/llvm-shlib/Makefile b/tools/llvm-shlib/Makefile
index ce29bf8..5238130 100644
--- a/tools/llvm-shlib/Makefile
+++ b/tools/llvm-shlib/Makefile
@@ -15,6 +15,17 @@ NO_BUILD_ARCHIVE = 1
LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
+include $(LEVEL)/Makefile.config
+
+ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW))
+ EXPORTED_SYMBOL_FILE = $(ObjDir)/$(LIBRARYNAME).exports
+
+ # It is needed to force static-stdc++.a linked.
+ # FIXME: It should be omitted when configure detects system's stdc++.dll.
+ SHLIB_FRAG_NAMES += stdc++.a.o
+
+endif
+
include $(LEVEL)/Makefile.common
# Include all archives in libLLVM.(so|dylib) except the ones that have
@@ -38,7 +49,6 @@ ifeq ($(HOST_OS),Darwin)
LLVMLibsOptions := $(LLVMLibsOptions) -all_load
# extra options to override libtool defaults
LLVMLibsOptions := $(LLVMLibsOptions) \
- -avoid-version \
-Wl,-dead_strip \
-Wl,-seg1addr -Wl,0xE0000000
@@ -58,3 +68,44 @@ ifeq ($(HOST_OS), Linux)
# Don't allow unresolved symbols.
LLVMLibsOptions += -Wl,--no-undefined
endif
+
+ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW))
+
+SHLIB_STUBS := $(addprefix $(ObjDir)/, $(SHLIB_FRAG_NAMES))
+SHLIB_FRAGS := $(patsubst %.a.o, $(ObjDir)/%.syms.txt, $(LIBRARYNAME).a.o $(SHLIB_FRAG_NAMES))
+LLVMLibsOptions := $(SHLIB_STUBS) $(LLVMLibsOptions)
+
+$(LibName.SO): $(SHLIB_STUBS)
+
+%.syms.txt: %.a.o
+ $(Echo) Collecting global symbols of $(notdir $*)
+ $(Verb) $(NM_PATH) -g $< > $@
+
+$(ObjDir)/$(LIBRARYNAME).exports: $(SHLIB_FRAGS) $(ObjDir)/.dir
+ $(Echo) Generating exports for $(LIBRARYNAME)
+ $(Verb) ($(SED) -n \
+ -e "s/^.* T _\([^.][^.]*\)$$/\1/p" \
+ -e "s/^.* [BDR] _\([^.][^.]*\)$$/\1 DATA/p" \
+ $(SHLIB_FRAGS) \
+ | sort -u) > $@
+
+$(ObjDir)/$(LIBRARYNAME).a.o: $(LLVMLibsPaths) $(ObjDir)/.dir
+ $(Echo) Linking all LLVMLibs together for $(LIBRARYNAME)
+ $(Verb) $(Link) -nostartfiles -Wl,-r -nodefaultlibs -o $@ \
+ -Wl,--whole-archive $(LLVMLibsPaths) \
+ -Wl,--no-whole-archive
+
+$(ObjDir)/stdc++.a.o: $(ObjDir)/.dir
+ $(Echo) Linking all libs together for static libstdc++.a
+ $(Verb) $(Link) -nostartfiles -Wl,-r -nodefaultlibs -o $@ \
+ -Wl,--whole-archive -lstdc++ \
+ -Wl,--no-whole-archive
+# FIXME: workaround to invalidate -lstdc++
+ $(Echo) Making dummy -lstdc++ to lib
+ $(Verb) $(AR) rc $(ToolDir)/libstdc++.dll.a
+# FIXME: Is install-local needed?
+
+clean-local::
+ $(Verb) $(RM) -f $(ToolDir)/libstdc++.dll.a
+
+endif
diff --git a/tools/llvmc/CMakeLists.txt b/tools/llvmc/CMakeLists.txt
index bebaaeb..10ad5d8 100644
--- a/tools/llvmc/CMakeLists.txt
+++ b/tools/llvmc/CMakeLists.txt
@@ -1,4 +1,4 @@
-# add_subdirectory(driver)
+# add_subdirectory(src)
# TODO: support plugins and user-configured builds.
# See ./doc/LLVMC-Reference.rst "Customizing LLVMC: the compilation graph"
diff --git a/tools/llvmc/Makefile b/tools/llvmc/Makefile
index 8f99526..7c03e2a 100644
--- a/tools/llvmc/Makefile
+++ b/tools/llvmc/Makefile
@@ -9,10 +9,10 @@
LEVEL = ../..
-export LLVMC_BASED_DRIVER_NAME = llvmc
-export LLVMC_BUILTIN_PLUGINS = Base Clang
-REQUIRES_RTTI = 1
+DIRS = src
-DIRS = plugins driver
+ifeq ($(BUILD_EXAMPLES),1)
+ OPTIONAL_DIRS += examples
+endif
include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/doc/LLVMC-Reference.rst b/tools/llvmc/doc/LLVMC-Reference.rst
index ca8500d..d160e75 100644
--- a/tools/llvmc/doc/LLVMC-Reference.rst
+++ b/tools/llvmc/doc/LLVMC-Reference.rst
@@ -299,7 +299,7 @@ separate option groups syntactically.
* Possible option types:
- ``switch_option`` - a simple boolean switch without arguments, for example
- ``-O2`` or ``-time``. At most one occurrence is allowed.
+ ``-O2`` or ``-time``. At most one occurrence is allowed by default.
- ``parameter_option`` - option that takes one argument, for example
``-std=c99``. It is also allowed to use spaces instead of the equality
@@ -321,6 +321,13 @@ separate option groups syntactically.
option types, aliases are not allowed to have any properties besides the
aliased option name. Usage example: ``(alias_option "preprocess", "E")``
+ - ``switch_list_option`` - like ``switch_option`` with the ``zero_or_more``
+ property, but remembers how many times the switch was turned on. Useful
+ mostly for forwarding. Example: when ``-foo`` is a switch option (with the
+ ``zero_or_more`` property), the command ``driver -foo -foo`` is forwarded
+ as ``some-tool -foo``, but when ``-foo`` is a switch list, the same command
+ is forwarded as ``some-tool -foo -foo``.
+
* Possible option properties:
diff --git a/tools/llvmc/example/Hello/Hello.cpp b/tools/llvmc/example/Hello/Hello.cpp
deleted file mode 100644
index a7179ea..0000000
--- a/tools/llvmc/example/Hello/Hello.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- Hello.cpp - Example code from "Writing an LLVMC Plugin" ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Test plugin for LLVMC. Shows how to write plugins without using TableGen.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CompilerDriver/CompilationGraph.h"
-#include "llvm/CompilerDriver/Plugin.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace {
-struct MyPlugin : public llvmc::BasePlugin {
-
- void PreprocessOptions() const
- {}
-
- void PopulateLanguageMap(llvmc::LanguageMap&) const
- { outs() << "Hello!\n"; }
-
- void PopulateCompilationGraph(llvmc::CompilationGraph&) const
- {}
-};
-
-static llvmc::RegisterPlugin<MyPlugin> RP("Hello", "Hello World plugin");
-
-}
diff --git a/tools/llvmc/example/Simple/PluginMain.cpp b/tools/llvmc/example/Simple/PluginMain.cpp
deleted file mode 100644
index add8acb..0000000
--- a/tools/llvmc/example/Simple/PluginMain.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "AutoGenerated.inc"
diff --git a/tools/llvmc/example/Skeleton/Makefile b/tools/llvmc/example/Skeleton/Makefile
deleted file mode 100644
index f489abf..0000000
--- a/tools/llvmc/example/Skeleton/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-##===- llvmc/example/Skeleton/Makefile ---------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-# Change this so that $(BASE_LEVEL)/Makefile.common refers to
-# $LLVM_DIR/Makefile.common or $YOUR_LLVM_BASED_PROJECT/Makefile.common.
-export LLVMC_BASE_LEVEL = ../../../..
-
-# Change this to the name of your LLVMC-based driver.
-export LLVMC_BASED_DRIVER_NAME = llvmc-skeleton
-
-# List your plugin names here
-export LLVMC_BUILTIN_PLUGINS = # Plugin
-
-LEVEL = $(LLVMC_BASE_LEVEL)
-
-DIRS = plugins driver
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Skeleton/driver/Makefile b/tools/llvmc/example/Skeleton/driver/Makefile
deleted file mode 100644
index 93e795b..0000000
--- a/tools/llvmc/example/Skeleton/driver/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-##===- llvmc/example/Skeleton/driver/Makefile --------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = $(LLVMC_BASE_LEVEL)/..
-LLVMC_BASED_DRIVER = $(LLVMC_BASED_DRIVER_NAME)
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Skeleton/plugins/Makefile b/tools/llvmc/example/Skeleton/plugins/Makefile
deleted file mode 100644
index fb07f23..0000000
--- a/tools/llvmc/example/Skeleton/plugins/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-##===- llvmc/example/Skeleton/plugins/Makefile -------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = $(LLVMC_BASE_LEVEL)/..
-
-ifneq ($(LLVMC_BUILTIN_PLUGINS),)
-DIRS = $(LLVMC_BUILTIN_PLUGINS)
-endif
-
-export LLVMC_BUILTIN_PLUGIN=1
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Skeleton/plugins/Plugin/PluginMain.cpp b/tools/llvmc/example/Skeleton/plugins/Plugin/PluginMain.cpp
deleted file mode 100644
index add8acb..0000000
--- a/tools/llvmc/example/Skeleton/plugins/Plugin/PluginMain.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "AutoGenerated.inc"
diff --git a/tools/llvmc/example/mcc16/Makefile b/tools/llvmc/example/mcc16/Makefile
deleted file mode 100644
index e94bca2..0000000
--- a/tools/llvmc/example/mcc16/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-##===- llvmc/example/mcc16/Makefile ------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-export LLVMC_BASE_LEVEL = ../../../..
-export LLVMC_BASED_DRIVER_NAME = mcc16
-export LLVMC_BUILTIN_PLUGINS = PIC16Base
-
-LEVEL = $(LLVMC_BASE_LEVEL)
-
-DIRS = plugins driver
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/mcc16/driver/Makefile b/tools/llvmc/example/mcc16/driver/Makefile
deleted file mode 100644
index 670d8bd..0000000
--- a/tools/llvmc/example/mcc16/driver/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-##===- llvmc/example/mcc16/driver/Makefile -----------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = $(LLVMC_BASE_LEVEL)/..
-LLVMC_BASED_DRIVER = $(LLVMC_BASED_DRIVER_NAME)
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/mcc16/plugins/Makefile b/tools/llvmc/example/mcc16/plugins/Makefile
deleted file mode 100644
index fb07f23..0000000
--- a/tools/llvmc/example/mcc16/plugins/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-##===- llvmc/example/Skeleton/plugins/Makefile -------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = $(LLVMC_BASE_LEVEL)/..
-
-ifneq ($(LLVMC_BUILTIN_PLUGINS),)
-DIRS = $(LLVMC_BUILTIN_PLUGINS)
-endif
-
-export LLVMC_BUILTIN_PLUGIN=1
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/Makefile b/tools/llvmc/example/mcc16/plugins/PIC16Base/Makefile
deleted file mode 100644
index 5d785fd..0000000
--- a/tools/llvmc/example/mcc16/plugins/PIC16Base/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-##===- llvmc/example/Skeleton/plugins/Plugin/Makefile ------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = $(LLVMC_BASE_LEVEL)/../..
-
-# Change this to the name of your plugin.
-LLVMC_PLUGIN = PIC16Base
-
-BUILT_SOURCES = AutoGenerated.inc
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/examples/Hello/Hello.cpp b/tools/llvmc/examples/Hello/Hello.cpp
new file mode 100644
index 0000000..71f04fd
--- /dev/null
+++ b/tools/llvmc/examples/Hello/Hello.cpp
@@ -0,0 +1,29 @@
+//===- Hello.cpp - Example code from "Writing an LLVMC Plugin" ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Shows how to write llvmc-based drivers without using TableGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CompilerDriver/AutoGenerated.h"
+#include "llvm/CompilerDriver/Main.inc"
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvmc {
+namespace autogenerated {
+
+int PreprocessOptions () { return 0; }
+
+int PopulateLanguageMap (LanguageMap&) { llvm::outs() << "Hello!\n"; return 0; }
+
+int PopulateCompilationGraph (CompilationGraph&) { return 0; }
+
+}
+}
diff --git a/tools/llvmc/example/Hello/Makefile b/tools/llvmc/examples/Hello/Makefile
index 10325e6..c281be6 100644
--- a/tools/llvmc/example/Hello/Makefile
+++ b/tools/llvmc/examples/Hello/Makefile
@@ -1,4 +1,4 @@
-##===- tools/llvmc/plugins/Hello/Makefile ------------------*- Makefile -*-===##
+##===- tools/llvmc/examples/Hello/Makefile -----------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
@@ -9,6 +9,6 @@
LEVEL = ../../../..
-LLVMC_PLUGIN = Hello
+LLVMC_BASED_DRIVER = Hello
include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Simple/Makefile b/tools/llvmc/examples/Makefile
index d7adb5d..8468e93 100644
--- a/tools/llvmc/example/Simple/Makefile
+++ b/tools/llvmc/examples/Makefile
@@ -1,4 +1,4 @@
-##===- tools/llvmc/plugins/Simple/Makefile -----------------*- Makefile -*-===##
+##===- tools/llvmc/examples/Makefile -----------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
@@ -7,9 +7,8 @@
#
##===----------------------------------------------------------------------===##
-LEVEL = ../../../..
+LEVEL=../../..
-LLVMC_PLUGIN = Simple
-BUILT_SOURCES = AutoGenerated.inc
+PARALLEL_DIRS := Hello Simple mcc16 Skeleton
include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/plugins/Clang/Makefile b/tools/llvmc/examples/Simple/Makefile
index 5e5b88a..c10387c 100644
--- a/tools/llvmc/plugins/Clang/Makefile
+++ b/tools/llvmc/examples/Simple/Makefile
@@ -1,4 +1,4 @@
-##===- tools/llvmc/plugins/Clang/Makefile ------------------*- Makefile -*-===##
+##===- llvmc/examples/Simple/Makefile ----------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
@@ -9,7 +9,7 @@
LEVEL = ../../../..
-LLVMC_PLUGIN = Clang
-BUILT_SOURCES = AutoGenerated.inc
+LLVMC_BASED_DRIVER = Simple
+BUILT_SOURCES = Simple.inc
include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/examples/Simple/Simple.cpp b/tools/llvmc/examples/Simple/Simple.cpp
new file mode 100644
index 0000000..8ac7313
--- /dev/null
+++ b/tools/llvmc/examples/Simple/Simple.cpp
@@ -0,0 +1,2 @@
+#include "llvm/CompilerDriver/Main.inc"
+#include "Simple.inc"
diff --git a/tools/llvmc/example/Simple/Simple.td b/tools/llvmc/examples/Simple/Simple.td
index 87bc385..b47483b 100644
--- a/tools/llvmc/example/Simple/Simple.td
+++ b/tools/llvmc/examples/Simple/Simple.td
@@ -1,4 +1,4 @@
-//===- Simple.td - A simple plugin for LLVMC ------------------------------===//
+//===- Simple.td - A simple LLVMC-based driver ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,19 +7,19 @@
//
//===----------------------------------------------------------------------===//
//
-// A simple LLVMC-based gcc wrapper that shows how to write LLVMC plugins.
+// A simple LLVMC-based gcc wrapper.
//
// To compile, use this command:
//
-// $ cd $LLVMC_DIR/example/Simple
-// $ make
+// $ cd $LLVM_OBJ_DIR/tools/llvmc
+// $ make BUILD_EXAMPLES=1
//
// Run as:
//
-// $ llvmc -load $LLVM_DIR/Release/lib/plugin_llvmc_Simple.so
+// $ $LLVM_OBJ_DIR/$(BuildMode)/bin/Simple
//
// For instructions on how to build your own LLVMC-based driver, see
-// the 'example/Skeleton' directory.
+// the 'examples/Skeleton' directory.
//===----------------------------------------------------------------------===//
include "llvm/CompilerDriver/Common.td"
@@ -28,10 +28,14 @@ def gcc : Tool<
[(in_language "c"),
(out_language "executable"),
(output_suffix "out"),
- (cmd_line "gcc $INFILE -o $OUTFILE"),
- (sink)
+ (command "gcc"),
+ (sink),
+
+ // -o is what is used by default, out_file_option here is included for
+ // instructive purposes.
+ (out_file_option "-o")
]>;
-def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>;
+def LanguageMap : LanguageMap<[(lang_to_suffixes "c", "c")]>;
-def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>;
+def CompilationGraph : CompilationGraph<[(edge "root", "gcc")]>;
diff --git a/tools/llvmc/example/Skeleton/plugins/Plugin/Plugin.td b/tools/llvmc/examples/Skeleton/AutoGenerated.td
index febb9ad..97483ce 100644
--- a/tools/llvmc/example/Skeleton/plugins/Plugin/Plugin.td
+++ b/tools/llvmc/examples/Skeleton/AutoGenerated.td
@@ -1,6 +1,6 @@
-//===- Plugin.td - A skeleton plugin for LLVMC -------------*- tablegen -*-===//
+//===- AutoGenerated.td ------------------------------------*- tablegen -*-===//
//
-// Write the code for your plugin here.
+// Write the TableGen description of your llvmc-based driver here.
//
//===----------------------------------------------------------------------===//
diff --git a/tools/llvmc/examples/Skeleton/Hooks.cpp b/tools/llvmc/examples/Skeleton/Hooks.cpp
new file mode 100644
index 0000000..ddd38f6
--- /dev/null
+++ b/tools/llvmc/examples/Skeleton/Hooks.cpp
@@ -0,0 +1,12 @@
+//===--- Hooks.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hook definitions should go here.
+//
+//===----------------------------------------------------------------------===//
diff --git a/tools/llvmc/driver/Main.cpp b/tools/llvmc/examples/Skeleton/Main.cpp
index b1f5b67..24c7768 100644
--- a/tools/llvmc/driver/Main.cpp
+++ b/tools/llvmc/examples/Skeleton/Main.cpp
@@ -7,8 +7,9 @@
//
//===----------------------------------------------------------------------===//
//
-// Just include CompilerDriver/Main.inc.
+// Just include CompilerDriver/Main.inc and AutoGenerated.inc.
//
//===----------------------------------------------------------------------===//
#include "llvm/CompilerDriver/Main.inc"
+#include "AutoGenerated.inc"
diff --git a/tools/llvmc/examples/Skeleton/Makefile b/tools/llvmc/examples/Skeleton/Makefile
new file mode 100644
index 0000000..41ca823
--- /dev/null
+++ b/tools/llvmc/examples/Skeleton/Makefile
@@ -0,0 +1,20 @@
+##===- llvmc/examples/Skeleton/Makefile --------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open
+# Source License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+# Change this so that $(LEVEL)/Makefile.common refers to
+# $LLVM_OBJ_DIR/Makefile.common or $YOUR_LLVM_BASED_PROJECT/Makefile.common.
+export LEVEL = ../../../..
+
+# Change this to the name of your LLVMC-based driver.
+LLVMC_BASED_DRIVER = llvmc-skeleton
+
+# Change this to the name of .inc file built from your .td file.
+BUILT_SOURCES = AutoGenerated.inc
+
+include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/Skeleton/README b/tools/llvmc/examples/Skeleton/README
index 92216ae..61ff6fb 100644
--- a/tools/llvmc/example/Skeleton/README
+++ b/tools/llvmc/examples/Skeleton/README
@@ -1,6 +1,6 @@
This is a template that can be used to create your own LLVMC-based drivers. Just
copy the `Skeleton` directory to the location of your preference and edit
-`Skeleton/Makefile` and `Skeleton/plugins/Plugin`.
+`Skeleton/Makefile` and `Skeleton/AutoGenerated.inc`.
The build system assumes that your project is based on LLVM.
diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp b/tools/llvmc/examples/mcc16/Hooks.cpp
index 9b2f9fc5..edb91e1 100644
--- a/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp
+++ b/tools/llvmc/examples/mcc16/Hooks.cpp
@@ -1,19 +1,23 @@
-#include "AutoGenerated.inc"
-
#include "llvm/System/Path.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
+#include <string>
namespace llvmc {
extern char *ProgramName;
+
+ namespace autogenerated {
+ extern llvm::cl::opt<std::string> Parameter_p;
+ }
}
-
+using namespace llvm;
+using namespace llvmc;
// Returns the platform specific directory separator via #ifdefs.
-// FIXME: This currently work on linux and windows only. It does not
-// work on other unices.
+// FIXME: This currently work on linux and windows only. It does not
+// work on other unices.
static std::string GetDirSeparator() {
#if __linux__ || __APPLE__
return "/";
@@ -28,14 +32,14 @@ namespace hooks {
std::string
GetLowerCasePartDefine(void) {
std::string Partname;
- if (AutoGeneratedParameter_p.empty()) {
+ if (autogenerated::Parameter_p.empty()) {
Partname = "16f1xxx";
} else {
- Partname = AutoGeneratedParameter_p;
+ Partname = autogenerated::Parameter_p;
}
std::string LowerCase;
- for (unsigned i = 0; i <= Partname.size(); i++) {
+ for (unsigned i = 0; i < Partname.size(); i++) {
LowerCase.push_back(std::tolower(Partname[i]));
}
@@ -45,26 +49,25 @@ GetLowerCasePartDefine(void) {
std::string
GetUpperCasePartDefine(void) {
std::string Partname;
- if (AutoGeneratedParameter_p.empty()) {
+ if (autogenerated::Parameter_p.empty()) {
Partname = "16f1xxx";
} else {
- Partname = AutoGeneratedParameter_p;
+ Partname = autogenerated::Parameter_p;
}
std::string UpperCase;
- for (unsigned i = 0; i <= Partname.size(); i++) {
+ for (unsigned i = 0; i < Partname.size(); i++) {
UpperCase.push_back(std::toupper(Partname[i]));
}
return "__" + UpperCase;
}
-
// Get the dir where c16 executables reside.
std::string GetBinDir() {
- // Construct a Path object from the program name.
+ // Construct a Path object from the program name.
void *P = (void*) (intptr_t) GetBinDir;
- sys::Path ProgramFullPath
+ sys::Path ProgramFullPath
= sys::Path::GetMainExecutable(llvmc::ProgramName, P);
// Get the dir name for the program. It's last component should be 'bin'.
@@ -80,7 +83,7 @@ std::string GetInstallDir() {
// Go one more level up to get the install dir.
std::string InstallDir = BinDirPath.getDirname();
-
+
return InstallDir + GetDirSeparator();
}
diff --git a/tools/llvmc/example/mcc16/driver/Main.cpp b/tools/llvmc/examples/mcc16/Main.cpp
index e66e2f9..55ae912 100644
--- a/tools/llvmc/example/mcc16/driver/Main.cpp
+++ b/tools/llvmc/examples/mcc16/Main.cpp
@@ -13,21 +13,25 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Config/config.h"
#include "llvm/CompilerDriver/BuiltinOptions.h"
-#include "llvm/CompilerDriver/ForceLinkage.h"
+#include "llvm/CompilerDriver/Main.h"
+
#include "llvm/System/Path.h"
+#include "llvm/Config/config.h"
+
#include <iostream>
-namespace llvmc {
- int Main(int argc, char** argv);
-}
+#include "PIC16.inc"
+
+namespace {
// Modify the PACKAGE_VERSION to use build number in top level configure file.
void PIC16VersionPrinter(void) {
std::cout << "MPLAB C16 1.0 " << PACKAGE_VERSION << "\n";
}
+}
+
int main(int argc, char** argv) {
// HACK
@@ -36,7 +40,7 @@ int main(int argc, char** argv) {
Languages.setHiddenFlag(llvm::cl::Hidden);
DryRun.setHiddenFlag(llvm::cl::Hidden);
- llvm::cl::SetVersionPrinter(PIC16VersionPrinter);
+ llvm::cl::SetVersionPrinter(PIC16VersionPrinter);
// Ask for a standard temp dir, but just cache its basename., and delete it.
llvm::sys::Path tempDir;
@@ -49,6 +53,5 @@ int main(int argc, char** argv) {
tempDir = TempDirname;
tempDir.eraseFromDisk(true);
- llvmc::ForceLinkage();
return llvmc::Main(argc, argv);
}
diff --git a/tools/llvmc/plugins/Base/Makefile b/tools/llvmc/examples/mcc16/Makefile
index ebc4335..4409cff 100644
--- a/tools/llvmc/plugins/Base/Makefile
+++ b/tools/llvmc/examples/mcc16/Makefile
@@ -1,4 +1,4 @@
-##===- tools/llvmc/plugins/Base/Makefile -------------------*- Makefile -*-===##
+##===- llvmc/examples/mcc16/Makefile -----------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
@@ -9,7 +9,7 @@
LEVEL = ../../../..
-LLVMC_PLUGIN = Base
-BUILT_SOURCES = AutoGenerated.inc
+LLVMC_BASED_DRIVER = mcc16
+BUILT_SOURCES = PIC16.inc
include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td b/tools/llvmc/examples/mcc16/PIC16.td
index 25149ad..6f04196 100644
--- a/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td
+++ b/tools/llvmc/examples/mcc16/PIC16.td
@@ -1,4 +1,4 @@
-//===- PIC16Base.td - PIC16 toolchain driver ---------------*- tablegen -*-===//
+//===- PIC16.td - PIC16 toolchain driver -------------------*- tablegen -*-===//
//
// A basic driver for the PIC16 toolchain.
//
@@ -202,33 +202,33 @@ def mplink : Tool<[
// Language map
def LanguageMap : LanguageMap<[
- LangToSuffixes<"c", ["c"]>,
- LangToSuffixes<"c-cpp-output", ["i"]>,
- LangToSuffixes<"assembler", ["s"]>,
- LangToSuffixes<"assembler-with-cpp", ["S"]>,
- LangToSuffixes<"llvm-assembler", ["ll"]>,
- LangToSuffixes<"llvm-bitcode", ["bc"]>,
- LangToSuffixes<"object-code", ["o"]>,
- LangToSuffixes<"executable", ["cof"]>
+ (lang_to_suffixes "c", "c"),
+ (lang_to_suffixes "c-cpp-output", "i"),
+ (lang_to_suffixes "assembler", "s"),
+ (lang_to_suffixes "assembler-with-cpp", "S"),
+ (lang_to_suffixes "llvm-assembler", "ll"),
+ (lang_to_suffixes "llvm-bitcode", "bc"),
+ (lang_to_suffixes "object-code", "o"),
+ (lang_to_suffixes "executable", "cof")
]>;
// Compilation graph
def CompilationGraph : CompilationGraph<[
- Edge<"root", "clang_cc">,
- Edge<"root", "llvm_ld">,
- OptionalEdge<"root", "llvm_ld_optimizer", (case
- (switch_on "S"), (inc_weight),
- (switch_on "c"), (inc_weight))>,
- Edge<"root", "gpasm">,
- Edge<"root", "mplink">,
- Edge<"clang_cc", "llvm_ld">,
- OptionalEdge<"clang_cc", "llvm_ld_optimizer", (case
- (switch_on "S"), (inc_weight),
- (switch_on "c"), (inc_weight))>,
- Edge<"llvm_ld", "pic16passes">,
- Edge<"llvm_ld_optimizer", "pic16passes">,
- Edge<"pic16passes", "llc">,
- Edge<"llc", "gpasm">,
- Edge<"gpasm", "mplink">
+ (edge "root", "clang_cc"),
+ (edge "root", "llvm_ld"),
+ (optional_edge "root", "llvm_ld_optimizer",
+ (case (switch_on "S"), (inc_weight),
+ (switch_on "c"), (inc_weight))),
+ (edge "root", "gpasm"),
+ (edge "root", "mplink"),
+ (edge "clang_cc", "llvm_ld"),
+ (optional_edge "clang_cc", "llvm_ld_optimizer",
+ (case (switch_on "S"), (inc_weight),
+ (switch_on "c"), (inc_weight))),
+ (edge "llvm_ld", "pic16passes"),
+ (edge "llvm_ld_optimizer", "pic16passes"),
+ (edge "pic16passes", "llc"),
+ (edge "llc", "gpasm"),
+ (edge "gpasm", "mplink")
]>;
diff --git a/tools/llvmc/example/mcc16/README b/tools/llvmc/examples/mcc16/README
index eeef6a4..6d2b73d 100644
--- a/tools/llvmc/example/mcc16/README
+++ b/tools/llvmc/examples/mcc16/README
@@ -1,5 +1,5 @@
This is a basic compiler driver for the PIC16 toolchain that shows how to create
-your own llvmc-based drivers. It is based on the example/Skeleton template.
+your own llvmc-based drivers. It is based on the examples/Skeleton template.
The PIC16 toolchain looks like this:
diff --git a/tools/llvmc/plugins/Base/PluginMain.cpp b/tools/llvmc/plugins/Base/PluginMain.cpp
deleted file mode 100644
index add8acb..0000000
--- a/tools/llvmc/plugins/Base/PluginMain.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "AutoGenerated.inc"
diff --git a/tools/llvmc/plugins/Clang/PluginMain.cpp b/tools/llvmc/plugins/Clang/PluginMain.cpp
deleted file mode 100644
index add8acb..0000000
--- a/tools/llvmc/plugins/Clang/PluginMain.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "AutoGenerated.inc"
diff --git a/tools/llvmc/plugins/Makefile b/tools/llvmc/plugins/Makefile
deleted file mode 100644
index 37dac6f..0000000
--- a/tools/llvmc/plugins/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-##===- tools/llvmc/plugins/Makefile ------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open
-# Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../..
-
-ifneq ($(LLVMC_BUILTIN_PLUGINS),)
-DIRS = $(LLVMC_BUILTIN_PLUGINS)
-endif
-
-export LLVMC_BUILTIN_PLUGIN=1
-
-include $(LEVEL)/Makefile.common
diff --git a/tools/llvmc/src/AutoGenerated.td b/tools/llvmc/src/AutoGenerated.td
new file mode 100644
index 0000000..8507b1f
--- /dev/null
+++ b/tools/llvmc/src/AutoGenerated.td
@@ -0,0 +1,17 @@
+//===- AutoGenerated.td - LLVMC toolchain descriptions -----*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains compilation graph description used by llvmc.
+//
+//===----------------------------------------------------------------------===//
+
+include "llvm/CompilerDriver/Common.td"
+
+include "Base.td"
+include "Clang.td"
diff --git a/tools/llvmc/plugins/Base/Base.td.in b/tools/llvmc/src/Base.td.in
index a042997..0c4de4c 100644
--- a/tools/llvmc/plugins/Base/Base.td.in
+++ b/tools/llvmc/src/Base.td.in
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-include "llvm/CompilerDriver/Common.td"
// Options
@@ -263,7 +262,7 @@ def llc : Tool<
// Base class for linkers
class llvm_gcc_based_linker <string cmd_prefix, dag on_empty> : Tool<
-[(in_language ["object-code", "static-library"]),
+[(in_language ["object-code", "static-library", "dynamic-library"]),
(out_language "executable"),
(output_suffix "out"),
(command cmd_prefix),
@@ -305,73 +304,79 @@ def llvm_gcc_cpp_linker : llvm_gcc_based_linker<"@LLVMGXXCOMMAND@",
// Language map
-def LanguageMap : LanguageMap<
- [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
- LangToSuffixes<"c++-header", ["hpp"]>,
- LangToSuffixes<"c", ["c"]>,
- LangToSuffixes<"c-header", ["h"]>,
- LangToSuffixes<"c-cpp-output", ["i"]>,
- LangToSuffixes<"objective-c-cpp-output", ["mi"]>,
- LangToSuffixes<"objective-c++", ["mm"]>,
- LangToSuffixes<"objective-c++-header", ["hmm"]>,
- LangToSuffixes<"objective-c", ["m"]>,
- LangToSuffixes<"objective-c-header", ["hm"]>,
- LangToSuffixes<"assembler", ["s"]>,
- LangToSuffixes<"assembler-with-cpp", ["S"]>,
- LangToSuffixes<"llvm-assembler", ["ll"]>,
- LangToSuffixes<"llvm-bitcode", ["bc"]>,
- LangToSuffixes<"object-code", ["o", "*empty*"]>,
- LangToSuffixes<"static-library", ["a", "lib"]>,
- LangToSuffixes<"executable", ["out"]>
- ]>;
+def LanguageMap : LanguageMap<[
+ (lang_to_suffixes "c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]),
+ (lang_to_suffixes "c++-header", "hpp"),
+ (lang_to_suffixes "c", "c"),
+ (lang_to_suffixes "c-header", "h"),
+ (lang_to_suffixes "c-cpp-output", "i"),
+ (lang_to_suffixes "objective-c-cpp-output", "mi"),
+ (lang_to_suffixes "objective-c++", "mm"),
+ (lang_to_suffixes "objective-c++-header", "hmm"),
+ (lang_to_suffixes "objective-c", "m"),
+ (lang_to_suffixes "objective-c-header", "hm"),
+ (lang_to_suffixes "assembler", "s"),
+ (lang_to_suffixes "assembler-with-cpp", "S"),
+ (lang_to_suffixes "llvm-assembler", "ll"),
+ (lang_to_suffixes "llvm-bitcode", "bc"),
+ (lang_to_suffixes "object-code", ["o", "*empty*"]),
+ (lang_to_suffixes "static-library", ["a", "lib"]),
+ (lang_to_suffixes "dynamic-library", ["so", "dylib", "dll"]),
+ (lang_to_suffixes "executable", ["out"])
+]>;
// Compilation graph
def CompilationGraph : CompilationGraph<[
- Edge<"root", "llvm_gcc_c">,
- Edge<"root", "llvm_gcc_assembler">,
- Edge<"root", "llvm_gcc_cpp">,
- Edge<"root", "llvm_gcc_m">,
- Edge<"root", "llvm_gcc_mxx">,
- Edge<"root", "llc">,
+ (edge "root", "llvm_gcc_c"),
+ (edge "root", "llvm_gcc_assembler"),
+ (edge "root", "llvm_gcc_cpp"),
+ (edge "root", "llvm_gcc_m"),
+ (edge "root", "llvm_gcc_mxx"),
+ (edge "root", "llc"),
- Edge<"root", "llvm_gcc_c_pch">,
- Edge<"root", "llvm_gcc_cpp_pch">,
- Edge<"root", "llvm_gcc_m_pch">,
- Edge<"root", "llvm_gcc_mxx_pch">,
+ (edge "root", "llvm_gcc_c_pch"),
+ (edge "root", "llvm_gcc_cpp_pch"),
+ (edge "root", "llvm_gcc_m_pch"),
+ (edge "root", "llvm_gcc_mxx_pch"),
- Edge<"llvm_gcc_c", "llc">,
- Edge<"llvm_gcc_cpp", "llc">,
- Edge<"llvm_gcc_m", "llc">,
- Edge<"llvm_gcc_mxx", "llc">,
- Edge<"llvm_as", "llc">,
+ (edge "llvm_gcc_c", "llc"),
+ (edge "llvm_gcc_cpp", "llc"),
+ (edge "llvm_gcc_m", "llc"),
+ (edge "llvm_gcc_mxx", "llc"),
+ (edge "llvm_as", "llc"),
- OptionalEdge<"root", "llvm_as",
- (case (switch_on "emit-llvm"), (inc_weight))>,
- OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"), (inc_weight))>,
- OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"), (inc_weight))>,
- OptionalEdge<"llvm_gcc_m", "opt", (case (switch_on "opt"), (inc_weight))>,
- OptionalEdge<"llvm_gcc_mxx", "opt", (case (switch_on "opt"), (inc_weight))>,
- OptionalEdge<"llvm_as", "opt", (case (switch_on "opt"), (inc_weight))>,
- Edge<"opt", "llc">,
+ (optional_edge "root", "llvm_as",
+ (case (switch_on "emit-llvm"), (inc_weight))),
+ (optional_edge "llvm_gcc_c", "opt",
+ (case (switch_on "opt"), (inc_weight))),
+ (optional_edge "llvm_gcc_cpp", "opt",
+ (case (switch_on "opt"), (inc_weight))),
+ (optional_edge "llvm_gcc_m", "opt",
+ (case (switch_on "opt"), (inc_weight))),
+ (optional_edge "llvm_gcc_mxx", "opt",
+ (case (switch_on "opt"), (inc_weight))),
+ (optional_edge "llvm_as", "opt",
+ (case (switch_on "opt"), (inc_weight))),
+ (edge "opt", "llc"),
- Edge<"llc", "llvm_gcc_assembler">,
- Edge<"llvm_gcc_assembler", "llvm_gcc_linker">,
- OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker",
+ (edge "llc", "llvm_gcc_assembler"),
+ (edge "llvm_gcc_assembler", "llvm_gcc_linker"),
+ (optional_edge "llvm_gcc_assembler", "llvm_gcc_cpp_linker",
(case
(or (input_languages_contain "c++"),
(input_languages_contain "objective-c++")),
(inc_weight),
(or (parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++")), (inc_weight))>,
+ (parameter_equals "linker", "c++")), (inc_weight))),
- Edge<"root", "llvm_gcc_linker">,
- OptionalEdge<"root", "llvm_gcc_cpp_linker",
+ (edge "root", "llvm_gcc_linker"),
+ (optional_edge "root", "llvm_gcc_cpp_linker",
(case
(or (input_languages_contain "c++"),
(input_languages_contain "objective-c++")),
(inc_weight),
(or (parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++")), (inc_weight))>
- ]>;
+ (parameter_equals "linker", "c++")), (inc_weight)))
+]>;
diff --git a/tools/llvmc/plugins/Clang/Clang.td b/tools/llvmc/src/Clang.td
index 988d9b1..1d75743 100644
--- a/tools/llvmc/plugins/Clang/Clang.td
+++ b/tools/llvmc/src/Clang.td
@@ -1,22 +1,18 @@
-include "llvm/CompilerDriver/Common.td"
+//===- Clang.td - LLVMC toolchain descriptions -------------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains compilation graph description used by llvmc.
+//
+//===----------------------------------------------------------------------===//
-def Priority : PluginPriority<1>;
def Options : OptionList<[
-// Extern options
-(switch_option "E", (extern)),
-(switch_option "S", (extern)),
-(switch_option "c", (extern)),
-(switch_option "fsyntax-only", (extern)),
-(switch_option "emit-llvm", (extern)),
-(switch_option "pthread", (extern)),
-(parameter_list_option "I", (extern)),
-(parameter_list_option "include", (extern)),
-(parameter_list_option "L", (extern)),
-(parameter_list_option "l", (extern)),
-(prefix_list_option "Wa,", (extern)),
-(prefix_list_option "Wl,", (extern)),
-
(switch_option "clang", (help "Use Clang instead of llvm-gcc"))
]>;
@@ -71,31 +67,21 @@ def llvm_ld : Tool<
(join)
]>;
-// Language map
-
-def LanguageMap : LanguageMap<[
- LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
- LangToSuffixes<"c", ["c"]>,
- LangToSuffixes<"objective-c", ["m"]>,
- LangToSuffixes<"c-cpp-output", ["i"]>,
- LangToSuffixes<"objective-c-cpp-output", ["mi"]>
-]>;
-
// Compilation graph
-def CompilationGraph : CompilationGraph<[
- OptionalEdge<"root", "clang_c",
- (case (switch_on "clang"), (inc_weight))>,
- OptionalEdge<"root", "clang_cpp",
- (case (switch_on "clang"), (inc_weight))>,
- OptionalEdge<"root", "clang_objective_c",
- (case (switch_on "clang"), (inc_weight))>,
- OptionalEdge<"root", "clang_objective_cpp",
- (case (switch_on "clang"), (inc_weight))>,
- Edge<"clang_c", "llc">,
- Edge<"clang_cpp", "llc">,
- Edge<"clang_objective_c", "llc">,
- Edge<"clang_objective_cpp", "llc">,
- OptionalEdge<"llc", "as", (case (switch_on "clang"), (inc_weight))>,
- Edge<"as", "llvm_ld">
+def ClangCompilationGraph : CompilationGraph<[
+ (optional_edge "root", "clang_c",
+ (case (switch_on "clang"), (inc_weight))),
+ (optional_edge "root", "clang_cpp",
+ (case (switch_on "clang"), (inc_weight))),
+ (optional_edge "root", "clang_objective_c",
+ (case (switch_on "clang"), (inc_weight))),
+ (optional_edge "root", "clang_objective_cpp",
+ (case (switch_on "clang"), (inc_weight))),
+ (edge "clang_c", "llc"),
+ (edge "clang_cpp", "llc"),
+ (edge "clang_objective_c", "llc"),
+ (edge "clang_objective_cpp", "llc"),
+ (optional_edge "llc", "as", (case (switch_on "clang"), (inc_weight))),
+ (edge "as", "llvm_ld")
]>;
diff --git a/tools/llvmc/plugins/Base/Hooks.cpp b/tools/llvmc/src/Hooks.cpp
index 661a914..661a914 100644
--- a/tools/llvmc/plugins/Base/Hooks.cpp
+++ b/tools/llvmc/src/Hooks.cpp
diff --git a/tools/llvmc/example/Skeleton/driver/Main.cpp b/tools/llvmc/src/Main.cpp
index b1f5b67..9f9c71a 100644
--- a/tools/llvmc/example/Skeleton/driver/Main.cpp
+++ b/tools/llvmc/src/Main.cpp
@@ -7,8 +7,10 @@
//
//===----------------------------------------------------------------------===//
//
-// Just include CompilerDriver/Main.inc.
+// Just include AutoGenerated.inc and CompilerDriver/Main.inc.
//
//===----------------------------------------------------------------------===//
+#include "AutoGenerated.inc"
+
#include "llvm/CompilerDriver/Main.inc"
diff --git a/tools/llvmc/driver/Makefile b/tools/llvmc/src/Makefile
index 2f3104b..f3f3091 100644
--- a/tools/llvmc/driver/Makefile
+++ b/tools/llvmc/src/Makefile
@@ -1,4 +1,4 @@
-##===- tools/llvmc/driver/Makefile -------------------------*- Makefile -*-===##
+##===- tools/llvmc/src/Makefile ----------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
@@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../..
-LLVMC_BASED_DRIVER = $(LLVMC_BASED_DRIVER_NAME)
+LLVMC_BASED_DRIVER = llvmc
+BUILT_SOURCES = AutoGenerated.inc
include $(LEVEL)/Makefile.common
diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp
index 911fddf..671348c 100644
--- a/tools/lto/LTOCodeGenerator.cpp
+++ b/tools/lto/LTOCodeGenerator.cpp
@@ -119,6 +119,11 @@ bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model,
return true;
}
+void LTOCodeGenerator::setCpu(const char* mCpu)
+{
+ _mCpu = mCpu;
+}
+
void LTOCodeGenerator::setAssemblerPath(const char* path)
{
if ( _assemblerPath )
@@ -126,6 +131,14 @@ void LTOCodeGenerator::setAssemblerPath(const char* path)
_assemblerPath = new sys::Path(path);
}
+void LTOCodeGenerator::setAssemblerArgs(const char** args, int nargs)
+{
+ for (int i = 0; i < nargs; ++i) {
+ const char *arg = args[i];
+ _assemblerArgs.push_back(arg);
+ }
+}
+
void LTOCodeGenerator::addMustPreserveSymbol(const char* sym)
{
_mustPreserveSymbols[sym] = 1;
@@ -142,8 +155,8 @@ bool LTOCodeGenerator::writeMergedModules(const char *path,
// create output file
std::string ErrInfo;
- raw_fd_ostream Out(path, ErrInfo,
- raw_fd_ostream::F_Binary);
+ tool_output_file Out(path, ErrInfo,
+ raw_fd_ostream::F_Binary);
if (!ErrInfo.empty()) {
errMsg = "could not open bitcode file for writing: ";
errMsg += path;
@@ -151,16 +164,17 @@ bool LTOCodeGenerator::writeMergedModules(const char *path,
}
// write bitcode to it
- WriteBitcodeToFile(_linker.getModule(), Out);
- Out.close();
+ WriteBitcodeToFile(_linker.getModule(), Out.os());
+ Out.os().close();
- if (Out.has_error()) {
+ if (Out.os().has_error()) {
errMsg = "could not write bitcode file: ";
errMsg += path;
- Out.clear_error();
+ Out.os().clear_error();
return true;
}
+ Out.keep();
return false;
}
@@ -176,11 +190,16 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg)
// generate assembly code
bool genResult = false;
{
- raw_fd_ostream asmFD(uniqueAsmPath.c_str(), errMsg);
- formatted_raw_ostream asmFile(asmFD);
+ tool_output_file asmFile(uniqueAsmPath.c_str(), errMsg);
if (!errMsg.empty())
return NULL;
- genResult = this->generateAssemblyCode(asmFile, errMsg);
+ genResult = this->generateAssemblyCode(asmFile.os(), errMsg);
+ asmFile.os().close();
+ if (asmFile.os().has_error()) {
+ asmFile.os().clear_error();
+ return NULL;
+ }
+ asmFile.keep();
}
if ( genResult ) {
uniqueAsmPath.eraseFromDisk();
@@ -257,6 +276,11 @@ bool LTOCodeGenerator::assemble(const std::string& asmPath,
args.push_back("-c");
args.push_back("-x");
args.push_back("assembler");
+ } else {
+ for (std::vector<std::string>::iterator I = _assemblerArgs.begin(),
+ E = _assemblerArgs.end(); I != E; ++I) {
+ args.push_back(I->c_str());
+ }
}
args.push_back("-o");
args.push_back(objPath.c_str());
@@ -301,7 +325,7 @@ bool LTOCodeGenerator::determineTarget(std::string& errMsg)
// construct LTModule, hand over ownership of module and target
SubtargetFeatures Features;
- Features.getDefaultSubtargetFeatures("" /* cpu */, llvm::Triple(Triple));
+ Features.getDefaultSubtargetFeatures(_mCpu, llvm::Triple(Triple));
std::string FeatureStr = Features.getString();
_target = march->createTargetMachine(Triple, FeatureStr);
}
@@ -343,7 +367,7 @@ void LTOCodeGenerator::applyScopeRestrictions() {
}
/// Optimize merged modules using various IPO passes
-bool LTOCodeGenerator::generateAssemblyCode(formatted_raw_ostream& out,
+bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
std::string& errMsg)
{
if ( this->determineTarget(errMsg) )
@@ -378,7 +402,9 @@ bool LTOCodeGenerator::generateAssemblyCode(formatted_raw_ostream& out,
codeGenPasses->add(new TargetData(*_target->getTargetData()));
- if (_target->addPassesToEmitFile(*codeGenPasses, out,
+ formatted_raw_ostream Out(out);
+
+ if (_target->addPassesToEmitFile(*codeGenPasses, Out,
TargetMachine::CGFT_AssemblyFile,
CodeGenOpt::Aggressive)) {
errMsg = "target file type not supported";
diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h
index cac3b8c..f5b78a6 100644
--- a/tools/lto/LTOCodeGenerator.h
+++ b/tools/lto/LTOCodeGenerator.h
@@ -36,14 +36,16 @@ struct LTOCodeGenerator {
bool addModule(struct LTOModule*, std::string& errMsg);
bool setDebugInfo(lto_debug_model, std::string& errMsg);
bool setCodePICModel(lto_codegen_model, std::string& errMsg);
+ void setCpu(const char *cpu);
void setAssemblerPath(const char* path);
+ void setAssemblerArgs(const char** args, int nargs);
void addMustPreserveSymbol(const char* sym);
bool writeMergedModules(const char* path,
std::string& errMsg);
const void* compile(size_t* length, std::string& errMsg);
void setCodeGenDebugOptions(const char *opts);
private:
- bool generateAssemblyCode(llvm::formatted_raw_ostream& out,
+ bool generateAssemblyCode(llvm::raw_ostream& out,
std::string& errMsg);
bool assemble(const std::string& asmPath,
const std::string& objPath, std::string& errMsg);
@@ -62,6 +64,8 @@ private:
llvm::MemoryBuffer* _nativeObjectFile;
std::vector<const char*> _codegenOptions;
llvm::sys::Path* _assemblerPath;
+ std::string _mCpu;
+ std::vector<std::string> _assemblerArgs;
};
#endif // LTO_CODE_GENERATOR_H
diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp
index 0870205..c7cd585 100644
--- a/tools/lto/LTOModule.cpp
+++ b/tools/lto/LTOModule.cpp
@@ -4,10 +4,10 @@
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
-// This file implements the Link Time Optimization library. This library is
+// This file implements the Link Time Optimization library. This library is
// intended to be used by linker to optimize code at link time.
//
//===----------------------------------------------------------------------===//
@@ -36,490 +36,473 @@
using namespace llvm;
-bool LTOModule::isBitcodeFile(const void* mem, size_t length)
-{
- return llvm::sys::IdentifyFileType((char*)mem, length)
- == llvm::sys::Bitcode_FileType;
+bool LTOModule::isBitcodeFile(const void *mem, size_t length) {
+ return llvm::sys::IdentifyFileType((char*)mem, length)
+ == llvm::sys::Bitcode_FileType;
}
-bool LTOModule::isBitcodeFile(const char* path)
-{
- return llvm::sys::Path(path).isBitcodeFile();
+bool LTOModule::isBitcodeFile(const char *path) {
+ return llvm::sys::Path(path).isBitcodeFile();
}
-bool LTOModule::isBitcodeFileForTarget(const void* mem, size_t length,
- const char* triplePrefix)
-{
- MemoryBuffer* buffer = makeBuffer(mem, length);
- if (!buffer)
- return false;
- return isTargetMatch(buffer, triplePrefix);
+bool LTOModule::isBitcodeFileForTarget(const void *mem, size_t length,
+ const char *triplePrefix) {
+ MemoryBuffer *buffer = makeBuffer(mem, length);
+ if (!buffer)
+ return false;
+ return isTargetMatch(buffer, triplePrefix);
}
-bool LTOModule::isBitcodeFileForTarget(const char* path,
- const char* triplePrefix)
-{
- MemoryBuffer *buffer = MemoryBuffer::getFile(path);
- if (buffer == NULL)
- return false;
- return isTargetMatch(buffer, triplePrefix);
+bool LTOModule::isBitcodeFileForTarget(const char *path,
+ const char *triplePrefix) {
+ MemoryBuffer *buffer = MemoryBuffer::getFile(path);
+ if (buffer == NULL)
+ return false;
+ return isTargetMatch(buffer, triplePrefix);
}
-// takes ownership of buffer
-bool LTOModule::isTargetMatch(MemoryBuffer* buffer, const char* triplePrefix)
-{
- OwningPtr<Module> m(getLazyBitcodeModule(buffer, getGlobalContext()));
- // on success, m owns buffer and both are deleted at end of this method
- if (!m) {
- delete buffer;
- return false;
- }
- std::string actualTarget = m->getTargetTriple();
- return (strncmp(actualTarget.c_str(), triplePrefix,
- strlen(triplePrefix)) == 0);
+// Takes ownership of buffer.
+bool LTOModule::isTargetMatch(MemoryBuffer *buffer, const char *triplePrefix) {
+ OwningPtr<Module> m(getLazyBitcodeModule(buffer, getGlobalContext()));
+ // On success, m owns buffer and both are deleted at end of this method.
+ if (!m) {
+ delete buffer;
+ return false;
+ }
+ std::string actualTarget = m->getTargetTriple();
+ return (strncmp(actualTarget.c_str(), triplePrefix,
+ strlen(triplePrefix)) == 0);
}
-LTOModule::LTOModule(Module* m, TargetMachine* t)
- : _module(m), _target(t), _symbolsParsed(false)
+LTOModule::LTOModule(Module *m, TargetMachine *t)
+ : _module(m), _target(t), _symbolsParsed(false)
{
}
-LTOModule* LTOModule::makeLTOModule(const char* path,
- std::string& errMsg)
-{
- OwningPtr<MemoryBuffer> buffer(MemoryBuffer::getFile(path, &errMsg));
- if (!buffer)
- return NULL;
- return makeLTOModule(buffer.get(), errMsg);
+LTOModule *LTOModule::makeLTOModule(const char *path,
+ std::string &errMsg) {
+ OwningPtr<MemoryBuffer> buffer(MemoryBuffer::getFile(path, &errMsg));
+ if (!buffer)
+ return NULL;
+ return makeLTOModule(buffer.get(), errMsg);
}
-/// makeBuffer - create a MemoryBuffer from a memory range.
-/// MemoryBuffer requires the byte past end of the buffer to be a zero.
-/// We might get lucky and already be that way, otherwise make a copy.
-/// Also if next byte is on a different page, don't assume it is readable.
-MemoryBuffer* LTOModule::makeBuffer(const void* mem, size_t length)
-{
- const char *startPtr = (char*)mem;
- const char *endPtr = startPtr+length;
- if (((uintptr_t)endPtr & (sys::Process::GetPageSize()-1)) == 0 ||
- *endPtr != 0)
- return MemoryBuffer::getMemBufferCopy(StringRef(startPtr, length));
-
- return MemoryBuffer::getMemBuffer(StringRef(startPtr, length));
+/// makeBuffer - Create a MemoryBuffer from a memory range. MemoryBuffer
+/// requires the byte past end of the buffer to be a zero. We might get lucky
+/// and already be that way, otherwise make a copy. Also if next byte is on a
+/// different page, don't assume it is readable.
+MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) {
+ const char *startPtr = (char*)mem;
+ const char *endPtr = startPtr+length;
+ if (((uintptr_t)endPtr & (sys::Process::GetPageSize()-1)) == 0 ||
+ *endPtr != 0)
+ return MemoryBuffer::getMemBufferCopy(StringRef(startPtr, length));
+
+ return MemoryBuffer::getMemBuffer(StringRef(startPtr, length));
}
-LTOModule* LTOModule::makeLTOModule(const void* mem, size_t length,
- std::string& errMsg)
-{
- OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length));
- if (!buffer)
- return NULL;
- return makeLTOModule(buffer.get(), errMsg);
+LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length,
+ std::string &errMsg) {
+ OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length));
+ if (!buffer)
+ return NULL;
+ return makeLTOModule(buffer.get(), errMsg);
}
-LTOModule* LTOModule::makeLTOModule(MemoryBuffer* buffer,
- std::string& errMsg)
-{
- InitializeAllTargets();
-
- // parse bitcode buffer
- OwningPtr<Module> m(ParseBitcodeFile(buffer, getGlobalContext(), &errMsg));
- if (!m)
- return NULL;
-
- std::string Triple = m->getTargetTriple();
- if (Triple.empty())
- Triple = sys::getHostTriple();
-
- // find machine architecture for this module
- const Target* march = TargetRegistry::lookupTarget(Triple, errMsg);
- if (!march)
- return NULL;
-
- // construct LTModule, hand over ownership of module and target
- SubtargetFeatures Features;
- Features.getDefaultSubtargetFeatures("" /* cpu */, llvm::Triple(Triple));
- std::string FeatureStr = Features.getString();
- TargetMachine* target = march->createTargetMachine(Triple, FeatureStr);
- return new LTOModule(m.take(), target);
+LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer,
+ std::string &errMsg) {
+ InitializeAllTargets();
+
+ // parse bitcode buffer
+ OwningPtr<Module> m(ParseBitcodeFile(buffer, getGlobalContext(), &errMsg));
+ if (!m)
+ return NULL;
+
+ std::string Triple = m->getTargetTriple();
+ if (Triple.empty())
+ Triple = sys::getHostTriple();
+
+ // find machine architecture for this module
+ const Target *march = TargetRegistry::lookupTarget(Triple, errMsg);
+ if (!march)
+ return NULL;
+
+ // construct LTModule, hand over ownership of module and target
+ SubtargetFeatures Features;
+ Features.getDefaultSubtargetFeatures("" /* cpu */, llvm::Triple(Triple));
+ std::string FeatureStr = Features.getString();
+ TargetMachine *target = march->createTargetMachine(Triple, FeatureStr);
+ return new LTOModule(m.take(), target);
}
-const char* LTOModule::getTargetTriple()
-{
- return _module->getTargetTriple().c_str();
+const char *LTOModule::getTargetTriple() {
+ return _module->getTargetTriple().c_str();
}
-void LTOModule::addDefinedFunctionSymbol(Function* f, Mangler &mangler)
-{
- // add to list of defined symbols
- addDefinedSymbol(f, mangler, true);
-
- // add external symbols referenced by this function.
- for (Function::iterator b = f->begin(); b != f->end(); ++b) {
- for (BasicBlock::iterator i = b->begin(); i != b->end(); ++i) {
- for (unsigned count = 0, total = i->getNumOperands();
- count != total; ++count) {
- findExternalRefs(i->getOperand(count), mangler);
- }
- }
- }
+void LTOModule::setTargetTriple(const char *triple) {
+ _module->setTargetTriple(triple);
}
-// get string that data pointer points to
-bool LTOModule::objcClassNameFromExpression(Constant* c, std::string& name)
-{
- if (ConstantExpr* ce = dyn_cast<ConstantExpr>(c)) {
- Constant* op = ce->getOperand(0);
- if (GlobalVariable* gvn = dyn_cast<GlobalVariable>(op)) {
- Constant* cn = gvn->getInitializer();
- if (ConstantArray* ca = dyn_cast<ConstantArray>(cn)) {
- if (ca->isCString()) {
- name = ".objc_class_name_" + ca->getAsString();
- return true;
- }
- }
- }
+void LTOModule::addDefinedFunctionSymbol(Function *f, Mangler &mangler) {
+ // add to list of defined symbols
+ addDefinedSymbol(f, mangler, true);
+
+ // add external symbols referenced by this function.
+ for (Function::iterator b = f->begin(); b != f->end(); ++b) {
+ for (BasicBlock::iterator i = b->begin(); i != b->end(); ++i) {
+ for (unsigned count = 0, total = i->getNumOperands();
+ count != total; ++count) {
+ findExternalRefs(i->getOperand(count), mangler);
+ }
}
- return false;
+ }
}
-// parse i386/ppc ObjC class data structure
-void LTOModule::addObjCClass(GlobalVariable* clgv)
-{
- if (ConstantStruct* c = dyn_cast<ConstantStruct>(clgv->getInitializer())) {
- // second slot in __OBJC,__class is pointer to superclass name
- std::string superclassName;
- if (objcClassNameFromExpression(c->getOperand(1), superclassName)) {
- NameAndAttributes info;
- if (_undefines.find(superclassName.c_str()) == _undefines.end()) {
- const char* symbolName = ::strdup(superclassName.c_str());
- info.name = ::strdup(symbolName);
- info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
- // string is owned by _undefines
- _undefines[info.name] = info;
- }
+// Get string that data pointer points to.
+bool LTOModule::objcClassNameFromExpression(Constant *c, std::string &name) {
+ if (ConstantExpr *ce = dyn_cast<ConstantExpr>(c)) {
+ Constant *op = ce->getOperand(0);
+ if (GlobalVariable *gvn = dyn_cast<GlobalVariable>(op)) {
+ Constant *cn = gvn->getInitializer();
+ if (ConstantArray *ca = dyn_cast<ConstantArray>(cn)) {
+ if (ca->isCString()) {
+ name = ".objc_class_name_" + ca->getAsString();
+ return true;
}
- // third slot in __OBJC,__class is pointer to class name
- std::string className;
- if (objcClassNameFromExpression(c->getOperand(2), className)) {
- const char* symbolName = ::strdup(className.c_str());
- NameAndAttributes info;
- info.name = symbolName;
- info.attributes = (lto_symbol_attributes)
- (LTO_SYMBOL_PERMISSIONS_DATA |
- LTO_SYMBOL_DEFINITION_REGULAR |
- LTO_SYMBOL_SCOPE_DEFAULT);
- _symbols.push_back(info);
- _defines[info.name] = 1;
- }
+ }
}
+ }
+ return false;
}
-
-// parse i386/ppc ObjC category data structure
-void LTOModule::addObjCCategory(GlobalVariable* clgv)
-{
- if (ConstantStruct* c = dyn_cast<ConstantStruct>(clgv->getInitializer())) {
- // second slot in __OBJC,__category is pointer to target class name
- std::string targetclassName;
- if (objcClassNameFromExpression(c->getOperand(1), targetclassName)) {
- NameAndAttributes info;
- if (_undefines.find(targetclassName.c_str()) == _undefines.end()) {
- const char* symbolName = ::strdup(targetclassName.c_str());
- info.name = ::strdup(symbolName);
- info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
- // string is owned by _undefines
- _undefines[info.name] = info;
- }
- }
+// Parse i386/ppc ObjC class data structure.
+void LTOModule::addObjCClass(GlobalVariable *clgv) {
+ if (ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer())) {
+ // second slot in __OBJC,__class is pointer to superclass name
+ std::string superclassName;
+ if (objcClassNameFromExpression(c->getOperand(1), superclassName)) {
+ NameAndAttributes info;
+ if (_undefines.find(superclassName.c_str()) == _undefines.end()) {
+ const char *symbolName = ::strdup(superclassName.c_str());
+ info.name = symbolName;
+ info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
+ // string is owned by _undefines
+ _undefines[info.name] = info;
+ }
+ }
+ // third slot in __OBJC,__class is pointer to class name
+ std::string className;
+ if (objcClassNameFromExpression(c->getOperand(2), className)) {
+ const char *symbolName = ::strdup(className.c_str());
+ NameAndAttributes info;
+ info.name = symbolName;
+ info.attributes = (lto_symbol_attributes)
+ (LTO_SYMBOL_PERMISSIONS_DATA |
+ LTO_SYMBOL_DEFINITION_REGULAR |
+ LTO_SYMBOL_SCOPE_DEFAULT);
+ _symbols.push_back(info);
+ _defines[info.name] = 1;
}
+ }
}
-// parse i386/ppc ObjC class list data structure
-void LTOModule::addObjCClassRef(GlobalVariable* clgv)
-{
+// Parse i386/ppc ObjC category data structure.
+void LTOModule::addObjCCategory(GlobalVariable *clgv) {
+ if (ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer())) {
+ // second slot in __OBJC,__category is pointer to target class name
std::string targetclassName;
- if (objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) {
- NameAndAttributes info;
- if (_undefines.find(targetclassName.c_str()) == _undefines.end()) {
- const char* symbolName = ::strdup(targetclassName.c_str());
- info.name = ::strdup(symbolName);
- info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
- // string is owned by _undefines
- _undefines[info.name] = info;
- }
+ if (objcClassNameFromExpression(c->getOperand(1), targetclassName)) {
+ NameAndAttributes info;
+ if (_undefines.find(targetclassName.c_str()) == _undefines.end()) {
+ const char *symbolName = ::strdup(targetclassName.c_str());
+ info.name = symbolName;
+ info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
+ // string is owned by _undefines
+ _undefines[info.name] = info;
+ }
}
+ }
}
-void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler& mangler)
-{
- // add to list of defined symbols
- addDefinedSymbol(v, mangler, false);
-
- // Special case i386/ppc ObjC data structures in magic sections:
- // The issue is that the old ObjC object format did some strange
- // contortions to avoid real linker symbols. For instance, the
- // ObjC class data structure is allocated statically in the executable
- // that defines that class. That data structures contains a pointer to
- // its superclass. But instead of just initializing that part of the
- // struct to the address of its superclass, and letting the static and
- // dynamic linkers do the rest, the runtime works by having that field
- // instead point to a C-string that is the name of the superclass.
- // At runtime the objc initialization updates that pointer and sets
- // it to point to the actual super class. As far as the linker
- // knows it is just a pointer to a string. But then someone wanted the
- // linker to issue errors at build time if the superclass was not found.
- // So they figured out a way in mach-o object format to use an absolute
- // symbols (.objc_class_name_Foo = 0) and a floating reference
- // (.reference .objc_class_name_Bar) to cause the linker into erroring when
- // a class was missing.
- // The following synthesizes the implicit .objc_* symbols for the linker
- // from the ObjC data structures generated by the front end.
- if (v->hasSection() /* && isTargetDarwin */) {
- // special case if this data blob is an ObjC class definition
- if (v->getSection().compare(0, 15, "__OBJC,__class,") == 0) {
- if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
- addObjCClass(gv);
- }
- }
-
- // special case if this data blob is an ObjC category definition
- else if (v->getSection().compare(0, 18, "__OBJC,__category,") == 0) {
- if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
- addObjCCategory(gv);
- }
- }
-
- // special case if this data blob is the list of referenced classes
- else if (v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) {
- if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
- addObjCClassRef(gv);
- }
- }
- }
-
- // add external symbols referenced by this data.
- for (unsigned count = 0, total = v->getNumOperands();
- count != total; ++count) {
- findExternalRefs(v->getOperand(count), mangler);
+// Parse i386/ppc ObjC class list data structure.
+void LTOModule::addObjCClassRef(GlobalVariable *clgv) {
+ std::string targetclassName;
+ if (objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) {
+ NameAndAttributes info;
+ if (_undefines.find(targetclassName.c_str()) == _undefines.end()) {
+ const char *symbolName = ::strdup(targetclassName.c_str());
+ info.name = symbolName;
+ info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
+ // string is owned by _undefines
+ _undefines[info.name] = info;
}
+ }
}
-void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
- bool isFunction)
-{
- // ignore all llvm.* symbols
- if (def->getName().startswith("llvm."))
- return;
-
- // string is owned by _defines
- const char* symbolName = ::strdup(mangler.getNameWithPrefix(def).c_str());
-
- // set alignment part log2() can have rounding errors
- uint32_t align = def->getAlignment();
- uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0;
-
- // set permissions part
- if (isFunction)
- attr |= LTO_SYMBOL_PERMISSIONS_CODE;
- else {
- GlobalVariable* gv = dyn_cast<GlobalVariable>(def);
- if (gv && gv->isConstant())
- attr |= LTO_SYMBOL_PERMISSIONS_RODATA;
- else
- attr |= LTO_SYMBOL_PERMISSIONS_DATA;
- }
-
- // set definition part
- if (def->hasWeakLinkage() || def->hasLinkOnceLinkage()) {
- attr |= LTO_SYMBOL_DEFINITION_WEAK;
- }
- else if (def->hasCommonLinkage()) {
- attr |= LTO_SYMBOL_DEFINITION_TENTATIVE;
+void LTOModule::addDefinedDataSymbol(GlobalValue *v, Mangler &mangler) {
+ // Add to list of defined symbols.
+ addDefinedSymbol(v, mangler, false);
+
+ // Special case i386/ppc ObjC data structures in magic sections:
+ // The issue is that the old ObjC object format did some strange
+ // contortions to avoid real linker symbols. For instance, the
+ // ObjC class data structure is allocated statically in the executable
+ // that defines that class. That data structures contains a pointer to
+ // its superclass. But instead of just initializing that part of the
+ // struct to the address of its superclass, and letting the static and
+ // dynamic linkers do the rest, the runtime works by having that field
+ // instead point to a C-string that is the name of the superclass.
+ // At runtime the objc initialization updates that pointer and sets
+ // it to point to the actual super class. As far as the linker
+ // knows it is just a pointer to a string. But then someone wanted the
+ // linker to issue errors at build time if the superclass was not found.
+ // So they figured out a way in mach-o object format to use an absolute
+ // symbols (.objc_class_name_Foo = 0) and a floating reference
+ // (.reference .objc_class_name_Bar) to cause the linker into erroring when
+ // a class was missing.
+ // The following synthesizes the implicit .objc_* symbols for the linker
+ // from the ObjC data structures generated by the front end.
+ if (v->hasSection() /* && isTargetDarwin */) {
+ // special case if this data blob is an ObjC class definition
+ if (v->getSection().compare(0, 15, "__OBJC,__class,") == 0) {
+ if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) {
+ addObjCClass(gv);
+ }
}
- else {
- attr |= LTO_SYMBOL_DEFINITION_REGULAR;
+
+ // special case if this data blob is an ObjC category definition
+ else if (v->getSection().compare(0, 18, "__OBJC,__category,") == 0) {
+ if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) {
+ addObjCCategory(gv);
+ }
}
-
- // set scope part
- if (def->hasHiddenVisibility())
- attr |= LTO_SYMBOL_SCOPE_HIDDEN;
- else if (def->hasProtectedVisibility())
- attr |= LTO_SYMBOL_SCOPE_PROTECTED;
- else if (def->hasExternalLinkage() || def->hasWeakLinkage()
- || def->hasLinkOnceLinkage() || def->hasCommonLinkage())
- attr |= LTO_SYMBOL_SCOPE_DEFAULT;
- else
- attr |= LTO_SYMBOL_SCOPE_INTERNAL;
- // add to table of symbols
- NameAndAttributes info;
- info.name = symbolName;
- info.attributes = (lto_symbol_attributes)attr;
- _symbols.push_back(info);
- _defines[info.name] = 1;
-}
+ // special case if this data blob is the list of referenced classes
+ else if (v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) {
+ if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) {
+ addObjCClassRef(gv);
+ }
+ }
+ }
-void LTOModule::addAsmGlobalSymbol(const char *name) {
- // only add new define if not already defined
- if (_defines.count(name) == 0)
- return;
-
- // string is owned by _defines
- const char *symbolName = ::strdup(name);
- uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR;
- attr |= LTO_SYMBOL_SCOPE_DEFAULT;
- NameAndAttributes info;
- info.name = symbolName;
- info.attributes = (lto_symbol_attributes)attr;
- _symbols.push_back(info);
- _defines[info.name] = 1;
+ // add external symbols referenced by this data.
+ for (unsigned count = 0, total = v->getNumOperands();
+ count != total; ++count) {
+ findExternalRefs(v->getOperand(count), mangler);
+ }
}
-void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler)
-{
- // ignore all llvm.* symbols
- if (decl->getName().startswith("llvm."))
- return;
- // ignore all aliases
- if (isa<GlobalAlias>(decl))
- return;
+void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler,
+ bool isFunction) {
+ // ignore all llvm.* symbols
+ if (def->getName().startswith("llvm."))
+ return;
- std::string name = mangler.getNameWithPrefix(decl);
+ // string is owned by _defines
+ const char *symbolName = ::strdup(mangler.getNameWithPrefix(def).c_str());
- // we already have the symbol
- if (_undefines.find(name) != _undefines.end())
- return;
+ // set alignment part log2() can have rounding errors
+ uint32_t align = def->getAlignment();
+ uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0;
- NameAndAttributes info;
- // string is owned by _undefines
- info.name = ::strdup(name.c_str());
- if (decl->hasExternalWeakLinkage())
- info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF;
+ // set permissions part
+ if (isFunction)
+ attr |= LTO_SYMBOL_PERMISSIONS_CODE;
+ else {
+ GlobalVariable *gv = dyn_cast<GlobalVariable>(def);
+ if (gv && gv->isConstant())
+ attr |= LTO_SYMBOL_PERMISSIONS_RODATA;
else
- info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
- _undefines[name] = info;
+ attr |= LTO_SYMBOL_PERMISSIONS_DATA;
+ }
+
+ // set definition part
+ if (def->hasWeakLinkage() || def->hasLinkOnceLinkage()) {
+ attr |= LTO_SYMBOL_DEFINITION_WEAK;
+ }
+ else if (def->hasCommonLinkage()) {
+ attr |= LTO_SYMBOL_DEFINITION_TENTATIVE;
+ }
+ else {
+ attr |= LTO_SYMBOL_DEFINITION_REGULAR;
+ }
+
+ // set scope part
+ if (def->hasHiddenVisibility())
+ attr |= LTO_SYMBOL_SCOPE_HIDDEN;
+ else if (def->hasProtectedVisibility())
+ attr |= LTO_SYMBOL_SCOPE_PROTECTED;
+ else if (def->hasExternalLinkage() || def->hasWeakLinkage()
+ || def->hasLinkOnceLinkage() || def->hasCommonLinkage())
+ attr |= LTO_SYMBOL_SCOPE_DEFAULT;
+ else
+ attr |= LTO_SYMBOL_SCOPE_INTERNAL;
+
+ // add to table of symbols
+ NameAndAttributes info;
+ info.name = symbolName;
+ info.attributes = (lto_symbol_attributes)attr;
+ _symbols.push_back(info);
+ _defines[info.name] = 1;
}
+void LTOModule::addAsmGlobalSymbol(const char *name) {
+ // only add new define if not already defined
+ if (_defines.count(name))
+ return;
+
+ // string is owned by _defines
+ const char *symbolName = ::strdup(name);
+ uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR;
+ attr |= LTO_SYMBOL_SCOPE_DEFAULT;
+ NameAndAttributes info;
+ info.name = symbolName;
+ info.attributes = (lto_symbol_attributes)attr;
+ _symbols.push_back(info);
+ _defines[info.name] = 1;
+}
+void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl,
+ Mangler &mangler) {
+ // ignore all llvm.* symbols
+ if (decl->getName().startswith("llvm."))
+ return;
+
+ // ignore all aliases
+ if (isa<GlobalAlias>(decl))
+ return;
+
+ std::string name = mangler.getNameWithPrefix(decl);
+
+ // we already have the symbol
+ if (_undefines.find(name) != _undefines.end())
+ return;
+
+ NameAndAttributes info;
+ // string is owned by _undefines
+ info.name = ::strdup(name.c_str());
+ if (decl->hasExternalWeakLinkage())
+ info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF;
+ else
+ info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
+ _undefines[name] = info;
+}
-// Find external symbols referenced by VALUE. This is a recursive function.
-void LTOModule::findExternalRefs(Value* value, Mangler &mangler) {
-
- if (GlobalValue* gv = dyn_cast<GlobalValue>(value)) {
- if (!gv->hasExternalLinkage())
- addPotentialUndefinedSymbol(gv, mangler);
- // If this is a variable definition, do not recursively process
- // initializer. It might contain a reference to this variable
- // and cause an infinite loop. The initializer will be
- // processed in addDefinedDataSymbol().
- return;
- }
- // GlobalValue, even with InternalLinkage type, may have operands with
- // ExternalLinkage type. Do not ignore these operands.
- if (Constant* c = dyn_cast<Constant>(value)) {
- // Handle ConstantExpr, ConstantStruct, ConstantArry etc.
- for (unsigned i = 0, e = c->getNumOperands(); i != e; ++i)
- findExternalRefs(c->getOperand(i), mangler);
- }
+
+// Find external symbols referenced by VALUE. This is a recursive function.
+void LTOModule::findExternalRefs(Value *value, Mangler &mangler) {
+ if (GlobalValue *gv = dyn_cast<GlobalValue>(value)) {
+ if (!gv->hasExternalLinkage())
+ addPotentialUndefinedSymbol(gv, mangler);
+ // If this is a variable definition, do not recursively process
+ // initializer. It might contain a reference to this variable
+ // and cause an infinite loop. The initializer will be
+ // processed in addDefinedDataSymbol().
+ return;
+ }
+
+ // GlobalValue, even with InternalLinkage type, may have operands with
+ // ExternalLinkage type. Do not ignore these operands.
+ if (Constant *c = dyn_cast<Constant>(value)) {
+ // Handle ConstantExpr, ConstantStruct, ConstantArry etc.
+ for (unsigned i = 0, e = c->getNumOperands(); i != e; ++i)
+ findExternalRefs(c->getOperand(i), mangler);
+ }
}
-void LTOModule::lazyParseSymbols()
-{
- if (!_symbolsParsed) {
- _symbolsParsed = true;
-
- // Use mangler to add GlobalPrefix to names to match linker names.
- MCContext Context(*_target->getMCAsmInfo());
- Mangler mangler(Context, *_target->getTargetData());
-
- // add functions
- for (Module::iterator f = _module->begin(); f != _module->end(); ++f) {
- if (f->isDeclaration())
- addPotentialUndefinedSymbol(f, mangler);
- else
- addDefinedFunctionSymbol(f, mangler);
- }
-
- // add data
- for (Module::global_iterator v = _module->global_begin(),
- e = _module->global_end(); v != e; ++v) {
- if (v->isDeclaration())
- addPotentialUndefinedSymbol(v, mangler);
- else
- addDefinedDataSymbol(v, mangler);
- }
+void LTOModule::lazyParseSymbols() {
+ if (_symbolsParsed)
+ return;
- // add asm globals
- const std::string &inlineAsm = _module->getModuleInlineAsm();
- const std::string glbl = ".globl";
- std::string asmSymbolName;
- std::string::size_type pos = inlineAsm.find(glbl, 0);
- while (pos != std::string::npos) {
- // eat .globl
- pos = pos + 6;
-
- // skip white space between .globl and symbol name
- std::string::size_type pbegin = inlineAsm.find_first_not_of(' ', pos);
- if (pbegin == std::string::npos)
- break;
-
- // find end-of-line
- std::string::size_type pend = inlineAsm.find_first_of('\n', pbegin);
- if (pend == std::string::npos)
- break;
-
- asmSymbolName.assign(inlineAsm, pbegin, pend - pbegin);
- addAsmGlobalSymbol(asmSymbolName.c_str());
-
- // search next .globl
- pos = inlineAsm.find(glbl, pend);
- }
+ _symbolsParsed = true;
- // make symbols for all undefines
- for (StringMap<NameAndAttributes>::iterator it=_undefines.begin();
- it != _undefines.end(); ++it) {
- // if this symbol also has a definition, then don't make an undefine
- // because it is a tentative definition
- if (_defines.count(it->getKey()) == 0) {
- NameAndAttributes info = it->getValue();
- _symbols.push_back(info);
- }
- }
- }
+ // Use mangler to add GlobalPrefix to names to match linker names.
+ MCContext Context(*_target->getMCAsmInfo());
+ Mangler mangler(Context, *_target->getTargetData());
+
+ // add functions
+ for (Module::iterator f = _module->begin(); f != _module->end(); ++f) {
+ if (f->isDeclaration())
+ addPotentialUndefinedSymbol(f, mangler);
+ else
+ addDefinedFunctionSymbol(f, mangler);
+ }
+
+ // add data
+ for (Module::global_iterator v = _module->global_begin(),
+ e = _module->global_end(); v != e; ++v) {
+ if (v->isDeclaration())
+ addPotentialUndefinedSymbol(v, mangler);
+ else
+ addDefinedDataSymbol(v, mangler);
+ }
+
+ // add asm globals
+ const std::string &inlineAsm = _module->getModuleInlineAsm();
+ const std::string glbl = ".globl";
+ std::string asmSymbolName;
+ std::string::size_type pos = inlineAsm.find(glbl, 0);
+ while (pos != std::string::npos) {
+ // eat .globl
+ pos = pos + 6;
+
+ // skip white space between .globl and symbol name
+ std::string::size_type pbegin = inlineAsm.find_first_not_of(' ', pos);
+ if (pbegin == std::string::npos)
+ break;
+
+ // find end-of-line
+ std::string::size_type pend = inlineAsm.find_first_of('\n', pbegin);
+ if (pend == std::string::npos)
+ break;
+
+ asmSymbolName.assign(inlineAsm, pbegin, pend - pbegin);
+ addAsmGlobalSymbol(asmSymbolName.c_str());
+
+ // search next .globl
+ pos = inlineAsm.find(glbl, pend);
+ }
+
+ // make symbols for all undefines
+ for (StringMap<NameAndAttributes>::iterator it=_undefines.begin();
+ it != _undefines.end(); ++it) {
+ // if this symbol also has a definition, then don't make an undefine
+ // because it is a tentative definition
+ if (_defines.count(it->getKey()) == 0) {
+ NameAndAttributes info = it->getValue();
+ _symbols.push_back(info);
+ }
+ }
}
-uint32_t LTOModule::getSymbolCount()
-{
- lazyParseSymbols();
- return _symbols.size();
+uint32_t LTOModule::getSymbolCount() {
+ lazyParseSymbols();
+ return _symbols.size();
}
-lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index)
-{
- lazyParseSymbols();
- if (index < _symbols.size())
- return _symbols[index].attributes;
- else
- return lto_symbol_attributes(0);
+lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index) {
+ lazyParseSymbols();
+ if (index < _symbols.size())
+ return _symbols[index].attributes;
+ else
+ return lto_symbol_attributes(0);
}
-const char* LTOModule::getSymbolName(uint32_t index)
-{
- lazyParseSymbols();
- if (index < _symbols.size())
- return _symbols[index].name;
- else
- return NULL;
+const char *LTOModule::getSymbolName(uint32_t index) {
+ lazyParseSymbols();
+ if (index < _symbols.size())
+ return _symbols[index].name;
+ else
+ return NULL;
}
diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h
index 7f475d4..a19acc0 100644
--- a/tools/lto/LTOModule.h
+++ b/tools/lto/LTOModule.h
@@ -55,6 +55,7 @@ struct LTOModule {
std::string& errMsg);
const char* getTargetTriple();
+ void setTargetTriple(const char*);
uint32_t getSymbolCount();
lto_symbol_attributes getSymbolAttributes(uint32_t index);
const char* getSymbolName(uint32_t index);
diff --git a/tools/lto/Makefile b/tools/lto/Makefile
index 8d57333..e157a4c 100644
--- a/tools/lto/Makefile
+++ b/tools/lto/Makefile
@@ -25,15 +25,22 @@ LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader bitwriter
include $(LEVEL)/Makefile.common
ifeq ($(HOST_OS),Darwin)
+ # Special hack to allow libLTO to have an offset version number.
+ ifdef LLVM_LTO_VERSION_OFFSET
+ LTO_LIBRARY_VERSION := $(shell expr $(LLVM_SUBMIT_VERSION) + \
+ $(LLVM_LTO_VERSION_OFFSET))
+ else
+ LTO_LIBRARY_VERSION := $(LLVM_SUBMIT_VERSION)
+ endif
+
# set dylib internal version number to llvmCore submission number
ifdef LLVM_SUBMIT_VERSION
LLVMLibsOptions := $(LLVMLibsOptions) -Wl,-current_version \
- -Wl,$(LLVM_SUBMIT_VERSION).$(LLVM_SUBMIT_SUBVERSION) \
+ -Wl,$(LTO_LIBRARY_VERSION).$(LLVM_SUBMIT_SUBVERSION) \
-Wl,-compatibility_version -Wl,1
endif
# extra options to override libtool defaults
LLVMLibsOptions := $(LLVMLibsOptions) \
- -avoid-version \
-Wl,-dead_strip \
-Wl,-seg1addr -Wl,0xE0000000
@@ -41,7 +48,7 @@ ifeq ($(HOST_OS),Darwin)
DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/')
ifneq ($(DARWIN_VERS),8)
LLVMLibsOptions := $(LLVMLibsOptions) \
- -no-undefined -Wl,-install_name \
+ -Wl,-install_name \
-Wl,"@executable_path/../lib/lib$(LIBRARYNAME)$(SHLIBEXT)"
endif
endif
diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp
index cc841bd..3d7ef0a 100644
--- a/tools/lto/lto.cpp
+++ b/tools/lto/lto.cpp
@@ -120,6 +120,14 @@ const char* lto_module_get_target_triple(lto_module_t mod)
return mod->getTargetTriple();
}
+//
+// sets triple string with which the object will be codegened.
+//
+void lto_module_set_target_triple(lto_module_t mod, const char *triple)
+{
+ return mod->setTargetTriple(triple);
+}
+
//
// returns the number of symbols in the object module
@@ -142,7 +150,7 @@ const char* lto_module_get_symbol_name(lto_module_t mod, uint32_t index)
// returns the attributes of the ith symbol in the object module
//
lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
- uint32_t index)
+ uint32_t index)
{
return mod->getSymbolAttributes(index);
}
@@ -203,6 +211,14 @@ bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model)
}
//
+// sets the cpu to generate code for
+//
+void lto_codegen_set_cpu(lto_code_gen_t cg, const char* cpu)
+{
+ return cg->setCpu(cpu);
+}
+
+//
// sets the path to the assembler tool
//
void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path)
@@ -210,6 +226,16 @@ void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path)
cg->setAssemblerPath(path);
}
+
+//
+// sets extra arguments that libLTO should pass to the assembler
+//
+void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char** args,
+ int nargs)
+{
+ cg->setAssemblerArgs(args, nargs);
+}
+
//
// adds to a list of all global symbols that must exist in the final
// generated code. If a function is not listed there, it might be
diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports
index 9011cf6..4dbf760 100644
--- a/tools/lto/lto.exports
+++ b/tools/lto/lto.exports
@@ -6,6 +6,7 @@ lto_module_get_num_symbols
lto_module_get_symbol_attribute
lto_module_get_symbol_name
lto_module_get_target_triple
+lto_module_set_target_triple
lto_module_is_object_file
lto_module_is_object_file_for_target
lto_module_is_object_file_in_memory
@@ -20,4 +21,6 @@ lto_codegen_set_debug_model
lto_codegen_set_pic_model
lto_codegen_write_merged_modules
lto_codegen_debug_options
+lto_codegen_set_assembler_args
lto_codegen_set_assembler_path
+lto_codegen_set_cpu
diff --git a/tools/opt/AnalysisWrappers.cpp b/tools/opt/AnalysisWrappers.cpp
index f548d00..a2b57bb 100644
--- a/tools/opt/AnalysisWrappers.cpp
+++ b/tools/opt/AnalysisWrappers.cpp
@@ -31,7 +31,7 @@ namespace {
/// or handle in alias analyses.
struct ExternalFunctionsPassedConstants : public ModulePass {
static char ID; // Pass ID, replacement for typeid
- ExternalFunctionsPassedConstants() : ModulePass(&ID) {}
+ ExternalFunctionsPassedConstants() : ModulePass(ID) {}
virtual bool runOnModule(Module &M) {
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
if (!I->isDeclaration()) continue;
@@ -42,8 +42,8 @@ namespace {
Instruction *User = dyn_cast<Instruction>(*UI);
if (!User) continue;
- CallSite CS = CallSite::get(User);
- if (!CS.getInstruction()) continue;
+ CallSite CS(cast<Value>(User));
+ if (!CS) continue;
for (CallSite::arg_iterator AI = CS.arg_begin(),
E = CS.arg_end(); AI != E; ++AI) {
@@ -66,15 +66,17 @@ namespace {
AU.setPreservesAll();
}
};
+}
- char ExternalFunctionsPassedConstants::ID = 0;
- RegisterPass<ExternalFunctionsPassedConstants>
+char ExternalFunctionsPassedConstants::ID = 0;
+static RegisterPass<ExternalFunctionsPassedConstants>
P1("print-externalfnconstants",
"Print external fn callsites passed constants");
+namespace {
struct CallGraphPrinter : public ModulePass {
static char ID; // Pass ID, replacement for typeid
- CallGraphPrinter() : ModulePass(&ID) {}
+ CallGraphPrinter() : ModulePass(ID) {}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
@@ -85,8 +87,8 @@ namespace {
return false;
}
};
-
- char CallGraphPrinter::ID = 0;
- RegisterPass<CallGraphPrinter>
- P2("print-callgraph", "Print a call graph");
}
+
+char CallGraphPrinter::ID = 0;
+static RegisterPass<CallGraphPrinter>
+ P2("print-callgraph", "Print a call graph");
diff --git a/tools/opt/GraphPrinters.cpp b/tools/opt/GraphPrinters.cpp
index e7c6d1e..9de7d6a 100644
--- a/tools/opt/GraphPrinters.cpp
+++ b/tools/opt/GraphPrinters.cpp
@@ -28,13 +28,19 @@ static void WriteGraphToFile(raw_ostream &O, const std::string &GraphName,
std::string Filename = GraphName + ".dot";
O << "Writing '" << Filename << "'...";
std::string ErrInfo;
- raw_fd_ostream F(Filename.c_str(), ErrInfo);
-
- if (ErrInfo.empty())
- WriteGraph(F, GT);
- else
- O << " error opening file for writing!";
- O << "\n";
+ tool_output_file F(Filename.c_str(), ErrInfo);
+
+ if (ErrInfo.empty()) {
+ WriteGraph(F.os(), GT);
+ F.os().close();
+ if (!F.os().has_error()) {
+ O << "\n";
+ F.keep();
+ return;
+ }
+ }
+ O << " error opening file for writing!\n";
+ F.os().clear_error();
}
@@ -65,7 +71,7 @@ namespace llvm {
namespace {
struct CallGraphPrinter : public ModulePass {
static char ID; // Pass ID, replacement for typeid
- CallGraphPrinter() : ModulePass(&ID) {}
+ CallGraphPrinter() : ModulePass(ID) {}
virtual bool runOnModule(Module &M) {
WriteGraphToFile(llvm::errs(), "callgraph", &getAnalysis<CallGraph>());
@@ -79,12 +85,12 @@ namespace {
AU.setPreservesAll();
}
};
-
- char CallGraphPrinter::ID = 0;
- RegisterPass<CallGraphPrinter> P2("dot-callgraph",
- "Print Call Graph to 'dot' file");
}
+char CallGraphPrinter::ID = 0;
+static RegisterPass<CallGraphPrinter> P2("dot-callgraph",
+ "Print Call Graph to 'dot' file");
+
//===----------------------------------------------------------------------===//
// DomInfoPrinter Pass
//===----------------------------------------------------------------------===//
@@ -93,7 +99,7 @@ namespace {
class DomInfoPrinter : public FunctionPass {
public:
static char ID; // Pass identification, replacement for typeid
- DomInfoPrinter() : FunctionPass(&ID) {}
+ DomInfoPrinter() : FunctionPass(ID) {}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
@@ -110,8 +116,8 @@ namespace {
return false;
}
};
-
- char DomInfoPrinter::ID = 0;
- static RegisterPass<DomInfoPrinter>
- DIP("print-dom-info", "Dominator Info Printer", true, true);
}
+
+char DomInfoPrinter::ID = 0;
+static RegisterPass<DomInfoPrinter>
+DIP("print-dom-info", "Dominator Info Printer", true, true);
diff --git a/tools/opt/PrintSCC.cpp b/tools/opt/PrintSCC.cpp
index ea486ca..533f49e 100644
--- a/tools/opt/PrintSCC.cpp
+++ b/tools/opt/PrintSCC.cpp
@@ -36,7 +36,7 @@ using namespace llvm;
namespace {
struct CFGSCC : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
- CFGSCC() : FunctionPass(&ID) {}
+ CFGSCC() : FunctionPass(ID) {}
bool runOnFunction(Function& func);
void print(raw_ostream &O, const Module* = 0) const { }
@@ -48,7 +48,7 @@ namespace {
struct CallGraphSCC : public ModulePass {
static char ID; // Pass identification, replacement for typeid
- CallGraphSCC() : ModulePass(&ID) {}
+ CallGraphSCC() : ModulePass(ID) {}
// run - Print out SCCs in the call graph for the specified module.
bool runOnModule(Module &M);
@@ -61,30 +61,30 @@ namespace {
AU.addRequired<CallGraph>();
}
};
+}
- char CFGSCC::ID = 0;
- RegisterPass<CFGSCC>
- Y("print-cfg-sccs", "Print SCCs of each function CFG");
+char CFGSCC::ID = 0;
+static RegisterPass<CFGSCC>
+Y("print-cfg-sccs", "Print SCCs of each function CFG");
- char CallGraphSCC::ID = 0;
- RegisterPass<CallGraphSCC>
- Z("print-callgraph-sccs", "Print SCCs of the Call Graph");
-}
+char CallGraphSCC::ID = 0;
+static RegisterPass<CallGraphSCC>
+Z("print-callgraph-sccs", "Print SCCs of the Call Graph");
bool CFGSCC::runOnFunction(Function &F) {
unsigned sccNum = 0;
- outs() << "SCCs for Function " << F.getName() << " in PostOrder:";
+ errs() << "SCCs for Function " << F.getName() << " in PostOrder:";
for (scc_iterator<Function*> SCCI = scc_begin(&F),
E = scc_end(&F); SCCI != E; ++SCCI) {
std::vector<BasicBlock*> &nextSCC = *SCCI;
- outs() << "\nSCC #" << ++sccNum << " : ";
+ errs() << "\nSCC #" << ++sccNum << " : ";
for (std::vector<BasicBlock*>::const_iterator I = nextSCC.begin(),
E = nextSCC.end(); I != E; ++I)
- outs() << (*I)->getName() << ", ";
+ errs() << (*I)->getName() << ", ";
if (nextSCC.size() == 1 && SCCI.hasLoop())
- outs() << " (Has self-loop).";
+ errs() << " (Has self-loop).";
}
- outs() << "\n";
+ errs() << "\n";
return true;
}
@@ -94,19 +94,19 @@ bool CFGSCC::runOnFunction(Function &F) {
bool CallGraphSCC::runOnModule(Module &M) {
CallGraphNode* rootNode = getAnalysis<CallGraph>().getRoot();
unsigned sccNum = 0;
- outs() << "SCCs for the program in PostOrder:";
+ errs() << "SCCs for the program in PostOrder:";
for (scc_iterator<CallGraphNode*> SCCI = scc_begin(rootNode),
E = scc_end(rootNode); SCCI != E; ++SCCI) {
const std::vector<CallGraphNode*> &nextSCC = *SCCI;
- outs() << "\nSCC #" << ++sccNum << " : ";
+ errs() << "\nSCC #" << ++sccNum << " : ";
for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(),
E = nextSCC.end(); I != E; ++I)
- outs() << ((*I)->getFunction() ? (*I)->getFunction()->getNameStr()
+ errs() << ((*I)->getFunction() ? (*I)->getFunction()->getNameStr()
: std::string("external node")) << ", ";
if (nextSCC.size() == 1 && SCCI.hasLoop())
- outs() << " (Has self-loop).";
+ errs() << " (Has self-loop).";
}
- outs() << "\n";
+ errs() << "\n";
return true;
}
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 0878737..d837185 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -53,7 +53,7 @@ InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
static cl::opt<std::string>
OutputFilename("o", cl::desc("Override output filename"),
- cl::value_desc("filename"), cl::init("-"));
+ cl::value_desc("filename"));
static cl::opt<bool>
Force("f", cl::desc("Enable binary output on terminals"));
@@ -138,17 +138,19 @@ namespace {
struct CallGraphSCCPassPrinter : public CallGraphSCCPass {
static char ID;
const PassInfo *PassToPrint;
- CallGraphSCCPassPrinter(const PassInfo *PI) :
- CallGraphSCCPass(&ID), PassToPrint(PI) {}
+ raw_ostream &Out;
+ CallGraphSCCPassPrinter(const PassInfo *PI, raw_ostream &out) :
+ CallGraphSCCPass(ID), PassToPrint(PI), Out(out) {}
virtual bool runOnSCC(CallGraphSCC &SCC) {
if (!Quiet) {
- outs() << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+ Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
Function *F = (*I)->getFunction();
if (F)
- getAnalysisID<Pass>(PassToPrint).print(outs(), F->getParent());
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out,
+ F->getParent());
}
}
// Get and print pass...
@@ -158,7 +160,7 @@ struct CallGraphSCCPassPrinter : public CallGraphSCCPass {
virtual const char *getPassName() const { return "'Pass' Printer"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint);
+ AU.addRequiredID(PassToPrint->getTypeInfo());
AU.setPreservesAll();
}
};
@@ -168,13 +170,14 @@ char CallGraphSCCPassPrinter::ID = 0;
struct ModulePassPrinter : public ModulePass {
static char ID;
const PassInfo *PassToPrint;
- ModulePassPrinter(const PassInfo *PI) : ModulePass(&ID),
- PassToPrint(PI) {}
+ raw_ostream &Out;
+ ModulePassPrinter(const PassInfo *PI, raw_ostream &out)
+ : ModulePass(ID), PassToPrint(PI), Out(out) {}
virtual bool runOnModule(Module &M) {
if (!Quiet) {
- outs() << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
- getAnalysisID<Pass>(PassToPrint).print(outs(), &M);
+ Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out, &M);
}
// Get and print pass...
@@ -184,7 +187,7 @@ struct ModulePassPrinter : public ModulePass {
virtual const char *getPassName() const { return "'Pass' Printer"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint);
+ AU.addRequiredID(PassToPrint->getTypeInfo());
AU.setPreservesAll();
}
};
@@ -192,24 +195,26 @@ struct ModulePassPrinter : public ModulePass {
char ModulePassPrinter::ID = 0;
struct FunctionPassPrinter : public FunctionPass {
const PassInfo *PassToPrint;
+ raw_ostream &Out;
static char ID;
- FunctionPassPrinter(const PassInfo *PI) : FunctionPass(&ID),
- PassToPrint(PI) {}
+ FunctionPassPrinter(const PassInfo *PI, raw_ostream &out)
+ : FunctionPass(ID), PassToPrint(PI), Out(out) {}
virtual bool runOnFunction(Function &F) {
if (!Quiet) {
- outs() << "Printing analysis '" << PassToPrint->getPassName()
- << "' for function '" << F.getName() << "':\n";
+ Out << "Printing analysis '" << PassToPrint->getPassName()
+ << "' for function '" << F.getName() << "':\n";
}
// Get and print pass...
- getAnalysisID<Pass>(PassToPrint).print(outs(), F.getParent());
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out,
+ F.getParent());
return false;
}
virtual const char *getPassName() const { return "FunctionPass Printer"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint);
+ AU.addRequiredID(PassToPrint->getTypeInfo());
AU.setPreservesAll();
}
};
@@ -219,13 +224,14 @@ char FunctionPassPrinter::ID = 0;
struct LoopPassPrinter : public LoopPass {
static char ID;
const PassInfo *PassToPrint;
- LoopPassPrinter(const PassInfo *PI) :
- LoopPass(&ID), PassToPrint(PI) {}
+ raw_ostream &Out;
+ LoopPassPrinter(const PassInfo *PI, raw_ostream &out) :
+ LoopPass(ID), PassToPrint(PI), Out(out) {}
virtual bool runOnLoop(Loop *L, LPPassManager &LPM) {
if (!Quiet) {
- outs() << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
- getAnalysisID<Pass>(PassToPrint).print(outs(),
+ Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out,
L->getHeader()->getParent()->getParent());
}
// Get and print pass...
@@ -235,7 +241,7 @@ struct LoopPassPrinter : public LoopPass {
virtual const char *getPassName() const { return "'Pass' Printer"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint);
+ AU.addRequiredID(PassToPrint->getTypeInfo());
AU.setPreservesAll();
}
};
@@ -244,25 +250,27 @@ char LoopPassPrinter::ID = 0;
struct BasicBlockPassPrinter : public BasicBlockPass {
const PassInfo *PassToPrint;
+ raw_ostream &Out;
static char ID;
- BasicBlockPassPrinter(const PassInfo *PI)
- : BasicBlockPass(&ID), PassToPrint(PI) {}
+ BasicBlockPassPrinter(const PassInfo *PI, raw_ostream &out)
+ : BasicBlockPass(ID), PassToPrint(PI), Out(out) {}
virtual bool runOnBasicBlock(BasicBlock &BB) {
if (!Quiet) {
- outs() << "Printing Analysis info for BasicBlock '" << BB.getName()
- << "': Pass " << PassToPrint->getPassName() << ":\n";
+ Out << "Printing Analysis info for BasicBlock '" << BB.getName()
+ << "': Pass " << PassToPrint->getPassName() << ":\n";
}
// Get and print pass...
- getAnalysisID<Pass>(PassToPrint).print(outs(), BB.getParent()->getParent());
+ getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out,
+ BB.getParent()->getParent());
return false;
}
virtual const char *getPassName() const { return "BasicBlockPass Printer"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PassToPrint);
+ AU.addRequiredID(PassToPrint->getTypeInfo());
AU.setPreservesAll();
}
};
@@ -351,6 +359,11 @@ void AddStandardLinkPasses(PassManagerBase &PM) {
int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal();
llvm::PrettyStackTraceProgram X(argc, argv);
+
+ if (AnalyzeOnly && NoOutput) {
+ errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n";
+ return 1;
+ }
// Enable debug stream buffering.
EnableDebugBuffering = true;
@@ -377,35 +390,22 @@ int main(int argc, char **argv) {
}
// Figure out what stream we are supposed to write to...
- raw_ostream *Out = 0;
- bool DeleteStream = false;
- if (!NoOutput && !AnalyzeOnly) {
- if (OutputFilename == "-") {
- // Print to stdout.
- Out = &outs();
- // If we're printing a bitcode file, switch stdout to binary mode.
- // FIXME: This switches outs() globally, not just for the bitcode output.
- if (!OutputAssembly)
- sys::Program::ChangeStdoutToBinary();
- } else {
- if (NoOutput || AnalyzeOnly) {
- errs() << "WARNING: The -o (output filename) option is ignored when\n"
- "the --disable-output or --analyze options are used.\n";
- } else {
- // Make sure that the Output file gets unlinked from the disk if we get
- // a SIGINT.
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
- std::string ErrorInfo;
- Out = new raw_fd_ostream(OutputFilename.c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary);
- if (!ErrorInfo.empty()) {
- errs() << ErrorInfo << '\n';
- delete Out;
- return 1;
- }
- DeleteStream = true;
- }
+ OwningPtr<tool_output_file> Out;
+ if (NoOutput) {
+ if (!OutputFilename.empty())
+ errs() << "WARNING: The -o (output filename) option is ignored when\n"
+ "the --disable-output option is used.\n";
+ } else {
+ // Default to standard output.
+ if (OutputFilename.empty())
+ OutputFilename = "-";
+
+ std::string ErrorInfo;
+ Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo,
+ raw_fd_ostream::F_Binary));
+ if (!ErrorInfo.empty()) {
+ errs() << ErrorInfo << '\n';
+ return 1;
}
}
@@ -413,7 +413,7 @@ int main(int argc, char **argv) {
// console, print out a warning message and refuse to do it. We don't
// impress anyone by spewing tons of binary goo to a terminal.
if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly)
- if (CheckBitcodeOutputToConsole(*Out, !Quiet))
+ if (CheckBitcodeOutputToConsole(Out->os(), !Quiet))
NoOutput = true;
// Create a PassManager to hold and optimize the collection of passes we are
@@ -489,19 +489,19 @@ int main(int argc, char **argv) {
if (AnalyzeOnly) {
switch (Kind) {
case PT_BasicBlock:
- Passes.add(new BasicBlockPassPrinter(PassInf));
+ Passes.add(new BasicBlockPassPrinter(PassInf, Out->os()));
break;
case PT_Loop:
- Passes.add(new LoopPassPrinter(PassInf));
+ Passes.add(new LoopPassPrinter(PassInf, Out->os()));
break;
case PT_Function:
- Passes.add(new FunctionPassPrinter(PassInf));
+ Passes.add(new FunctionPassPrinter(PassInf, Out->os()));
break;
case PT_CallGraphSCC:
- Passes.add(new CallGraphSCCPassPrinter(PassInf));
+ Passes.add(new CallGraphSCCPassPrinter(PassInf, Out->os()));
break;
default:
- Passes.add(new ModulePassPrinter(PassInf));
+ Passes.add(new ModulePassPrinter(PassInf, Out->os()));
break;
}
}
@@ -538,19 +538,20 @@ int main(int argc, char **argv) {
if (!NoVerify && !VerifyEach)
Passes.add(createVerifierPass());
- // Write bitcode or assembly out to disk or outs() as the last step...
+ // Write bitcode or assembly to the output as the last step...
if (!NoOutput && !AnalyzeOnly) {
if (OutputAssembly)
- Passes.add(createPrintModulePass(Out));
+ Passes.add(createPrintModulePass(&Out->os()));
else
- Passes.add(createBitcodeWriterPass(*Out));
+ Passes.add(createBitcodeWriterPass(Out->os()));
}
// Now that we have all of the passes ready, run them.
Passes.run(*M.get());
- // Delete the raw_fd_ostream.
- if (DeleteStream)
- delete Out;
+ // Declare success.
+ if (!NoOutput)
+ Out->keep();
+
return 0;
}
OpenPOWER on IntegriCloud