summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-10-14 17:57:32 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-10-14 17:57:32 +0000
commitcd749a9c07f1de2fb8affde90537efa4bc3e7c54 (patch)
treeb21f6de4e08b89bb7931806bab798fc2a5e3a686 /tools
parent72621d11de5b873f1695f391eb95f0b336c3d2d4 (diff)
downloadFreeBSD-src-cd749a9c07f1de2fb8affde90537efa4bc3e7c54.zip
FreeBSD-src-cd749a9c07f1de2fb8affde90537efa4bc3e7c54.tar.gz
Update llvm to r84119.
Diffstat (limited to 'tools')
-rw-r--r--tools/CMakeLists.txt17
-rw-r--r--tools/Makefile4
-rw-r--r--tools/bugpoint/BugDriver.cpp83
-rw-r--r--tools/bugpoint/BugDriver.h6
-rw-r--r--tools/bugpoint/CrashDebugger.cpp78
-rw-r--r--tools/bugpoint/ExecutionDriver.cpp120
-rw-r--r--tools/bugpoint/ExtractFunction.cpp61
-rw-r--r--tools/bugpoint/FindBugs.cpp36
-rw-r--r--tools/bugpoint/ListReducer.h14
-rw-r--r--tools/bugpoint/Miscompilation.cpp327
-rw-r--r--tools/bugpoint/OptimizerDriver.cpp127
-rw-r--r--tools/bugpoint/ToolRunner.cpp301
-rw-r--r--tools/bugpoint/ToolRunner.h21
-rw-r--r--tools/bugpoint/bugpoint.cpp75
-rw-r--r--tools/gold/Makefile5
-rw-r--r--tools/gold/gold-plugin.cpp5
-rw-r--r--tools/llc/CMakeLists.txt2
-rw-r--r--tools/llc/Makefile2
-rw-r--r--tools/llc/llc.cpp204
-rw-r--r--tools/lli/lli.cpp53
-rw-r--r--tools/llvm-ar/llvm-ar.cpp39
-rw-r--r--tools/llvm-as/llvm-as.cpp129
-rw-r--r--tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp370
-rw-r--r--tools/llvm-config/CMakeLists.txt36
-rw-r--r--tools/llvm-config/llvm-config.in.in31
-rw-r--r--tools/llvm-dis/llvm-dis.cpp144
-rw-r--r--tools/llvm-extract/CMakeLists.txt2
-rw-r--r--tools/llvm-extract/Makefile2
-rw-r--r--tools/llvm-extract/llvm-extract.cpp67
-rw-r--r--tools/llvm-ld/Optimize.cpp6
-rw-r--r--tools/llvm-ld/llvm-ld.cpp103
-rw-r--r--tools/llvm-link/CMakeLists.txt2
-rw-r--r--tools/llvm-link/Makefile2
-rw-r--r--tools/llvm-link/llvm-link.cpp100
-rw-r--r--tools/llvm-mc/AsmCond.h40
-rw-r--r--tools/llvm-mc/AsmLexer.cpp185
-rw-r--r--tools/llvm-mc/AsmLexer.h95
-rw-r--r--tools/llvm-mc/AsmParser.cpp1477
-rw-r--r--tools/llvm-mc/AsmParser.h162
-rw-r--r--tools/llvm-mc/CMakeLists.txt4
-rw-r--r--tools/llvm-mc/Makefile11
-rw-r--r--tools/llvm-mc/llvm-mc.cpp235
-rw-r--r--tools/llvm-nm/llvm-nm.cpp48
-rw-r--r--tools/llvm-prof/llvm-prof.cpp329
-rw-r--r--tools/llvm-ranlib/llvm-ranlib.cpp9
-rw-r--r--tools/llvm-stub/llvm-stub.c5
-rw-r--r--tools/llvmc/doc/LLVMC-Reference.rst42
-rw-r--r--tools/llvmc/example/Hello/Hello.cpp5
-rw-r--r--tools/llvmc/example/mcc16/driver/Main.cpp27
-rw-r--r--tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td6
-rw-r--r--tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp18
-rw-r--r--tools/llvmc/plugins/Base/Base.td.in32
-rw-r--r--tools/lto/LTOCodeGenerator.cpp136
-rw-r--r--tools/lto/LTOCodeGenerator.h4
-rw-r--r--tools/lto/LTOModule.cpp129
-rw-r--r--tools/lto/Makefile2
-rw-r--r--tools/lto/lto.cpp8
-rw-r--r--tools/opt/AnalysisWrappers.cpp45
-rw-r--r--tools/opt/CMakeLists.txt2
-rw-r--r--tools/opt/GraphPrinters.cpp8
-rw-r--r--tools/opt/Makefile2
-rw-r--r--tools/opt/PrintSCC.cpp28
-rw-r--r--tools/opt/opt.cpp201
63 files changed, 3606 insertions, 2263 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 1273c25..8b5d77e 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -2,10 +2,13 @@
# large and three small executables. This is done to minimize memory load
# in parallel builds. Please retain this ordering.
-# FIXME: We don't yet have the ability to build llvm-config with CMake
-# based on explicit dependencies.
-if (FALSE)
- add_subdirectory(llvm-config)
+if( NOT WIN32 OR MSYS OR CYGWIN )
+ # It is useful to build llvm-config before the other tools, so we
+ # have a fresh LibDeps.txt for regenerating the hard-coded library
+ # dependencies. llvm-config/CMakeLists.txt takes care of this but we
+ # must keep llvm-config as the first entry on the list of tools to
+ # be built.
+ add_subdirectory(llvm-config)
endif()
add_subdirectory(opt)
@@ -23,11 +26,7 @@ add_subdirectory(llvm-prof)
add_subdirectory(llvm-link)
add_subdirectory(lli)
-# gccas and gccld are deprecated:
-# add_subdirectory(gccas)
-# add_subdirectory(gccld)
add_subdirectory(llvm-extract)
-add_subdirectory(llvm-db)
add_subdirectory(bugpoint)
add_subdirectory(llvm-bcanalyzer)
@@ -37,3 +36,5 @@ add_subdirectory(llvmc)
if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/clang/CMakeLists.txt )
add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/clang )
endif( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/clang/CMakeLists.txt )
+
+set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} PARENT_SCOPE)
diff --git a/tools/Makefile b/tools/Makefile
index 4f0f54b..0340c7f 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,7 +19,7 @@ DIRS := llvm-config
PARALLEL_DIRS := opt llvm-as llvm-dis \
llc llvm-ranlib llvm-ar llvm-nm \
llvm-ld llvm-prof llvm-link \
- lli gccas gccld llvm-extract llvm-db \
+ lli llvm-extract \
bugpoint llvm-bcanalyzer llvm-stub \
llvm-mc llvmc
@@ -39,7 +39,7 @@ ifeq ($(ENABLE_PIC),1)
endif
# No support for lto / gold on windows targets
-ifeq ($(OS), $(filter $(OS), Cygwin MingW))
+ifeq ($(TARGET_OS), $(filter $(TARGET_OS), Cygwin MingW))
DIRS := $(filter-out lto gold, $(DIRS))
endif
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp
index aab5072..abf5d8e 100644
--- a/tools/bugpoint/BugDriver.cpp
+++ b/tools/bugpoint/BugDriver.cpp
@@ -18,17 +18,20 @@
#include "llvm/Linker.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
-#include "llvm/Assembly/Parser.h"
-#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/IRReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
-#include <iostream>
+#include "llvm/System/Host.h"
#include <memory>
using namespace llvm;
+namespace llvm {
+ Triple TargetTriple;
+}
+
// Anonymous namespace to define command line options for debugging.
//
namespace {
@@ -78,17 +81,25 @@ BugDriver::BugDriver(const char *toolname, bool as_child, bool find_bugs,
///
Module *llvm::ParseInputFile(const std::string &Filename,
LLVMContext& Ctxt) {
- std::auto_ptr<MemoryBuffer> Buffer(MemoryBuffer::getFileOrSTDIN(Filename));
- Module *Result = 0;
- if (Buffer.get())
- Result = ParseBitcodeFile(Buffer.get(), Ctxt);
-
SMDiagnostic Err;
- if (!Result && !(Result = ParseAssemblyFile(Filename, Err, Ctxt))) {
- Err.Print("bugpoint", errs());
- Result = 0;
+ Module *Result = ParseIRFile(Filename, Err, Ctxt);
+ if (!Result)
+ Err.Print("bugpoint", errs());
+
+ // If we don't have an override triple, use the first one to configure
+ // bugpoint, or use the host triple if none provided.
+ if (Result) {
+ if (TargetTriple.getTriple().empty()) {
+ Triple TheTriple(Result->getTargetTriple());
+
+ if (TheTriple.getTriple().empty())
+ TheTriple.setTriple(sys::getHostTriple());
+
+ TargetTriple.setTriple(TheTriple.getTriple());
+ }
+
+ Result->setTargetTriple(TargetTriple.getTriple()); // override the triple
}
-
return Result;
}
@@ -107,28 +118,28 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
if (Program == 0) return true;
if (!run_as_child)
- std::cout << "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)
- std::cout << "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)) {
- std::cerr << ToolName << ": error linking in '" << Filenames[i] << "': "
- << ErrorMessage << '\n';
+ errs() << ToolName << ": error linking in '" << Filenames[i] << "': "
+ << ErrorMessage << '\n';
return true;
}
}
} catch (const std::string &Error) {
- std::cerr << ToolName << ": error reading input '" << Error << "'\n";
+ errs() << ToolName << ": error reading input '" << Error << "'\n";
return true;
}
if (!run_as_child)
- std::cout << "*** All input ok\n";
+ outs() << "*** All input ok\n";
// All input files read successfully!
return false;
@@ -162,7 +173,7 @@ bool BugDriver::run() {
// file, then we know the compiler didn't crash, so try to diagnose a
// miscompilation.
if (!PassesToRun.empty()) {
- std::cout << "Running selected passes on program to test for crash: ";
+ outs() << "Running selected passes on program to test for crash: ";
if (runPasses(PassesToRun))
return debugOptimizerCrash();
}
@@ -171,12 +182,12 @@ bool BugDriver::run() {
if (initializeExecutionEnvironment()) return true;
// Test to see if we have a code generator crash.
- std::cout << "Running the code generator to test for a crash: ";
+ outs() << "Running the code generator to test for a crash: ";
try {
compileProgram(Program);
- std::cout << '\n';
+ outs() << '\n';
} catch (ToolExecutionError &TEE) {
- std::cout << TEE.what();
+ outs() << TEE.what();
return debugCodeGeneratorCrash();
}
@@ -187,7 +198,7 @@ bool BugDriver::run() {
//
bool CreatedOutput = false;
if (ReferenceOutputFile.empty()) {
- std::cout << "Generating reference output from raw program: ";
+ outs() << "Generating reference output from raw program: ";
if(!createReferenceFile(Program)){
return debugCodeGeneratorCrash();
}
@@ -197,28 +208,28 @@ bool BugDriver::run() {
// Make sure the reference output file gets deleted on exit from this
// function, if appropriate.
sys::Path ROF(ReferenceOutputFile);
- FileRemover RemoverInstance(ROF, CreatedOutput);
+ FileRemover RemoverInstance(ROF, CreatedOutput && !SaveTemps);
// Diff the output of the raw program against the reference output. If it
// matches, then we assume there is a miscompilation bug and try to
// diagnose it.
- std::cout << "*** Checking the code generator...\n";
+ outs() << "*** Checking the code generator...\n";
try {
if (!diffProgram()) {
- std::cout << "\n*** Debugging miscompilation!\n";
+ outs() << "\n*** Output matches: Debugging miscompilation!\n";
return debugMiscompilation();
}
} catch (ToolExecutionError &TEE) {
- std::cerr << TEE.what();
+ errs() << TEE.what();
return debugCodeGeneratorCrash();
}
- std::cout << "\n*** Input program does not match reference diff!\n";
- std::cout << "Debugging code generator problem!\n";
+ outs() << "\n*** Input program does not match reference diff!\n";
+ outs() << "Debugging code generator problem!\n";
try {
return debugCodeGenerator();
} catch (ToolExecutionError &TEE) {
- std::cerr << TEE.what();
+ errs() << TEE.what();
return debugCodeGeneratorCrash();
}
}
@@ -227,18 +238,18 @@ void llvm::PrintFunctionList(const std::vector<Function*> &Funcs) {
unsigned NumPrint = Funcs.size();
if (NumPrint > 10) NumPrint = 10;
for (unsigned i = 0; i != NumPrint; ++i)
- std::cout << " " << Funcs[i]->getName();
+ outs() << " " << Funcs[i]->getName();
if (NumPrint < Funcs.size())
- std::cout << "... <" << Funcs.size() << " total>";
- std::cout << std::flush;
+ outs() << "... <" << Funcs.size() << " total>";
+ outs().flush();
}
void llvm::PrintGlobalVariableList(const std::vector<GlobalVariable*> &GVs) {
unsigned NumPrint = GVs.size();
if (NumPrint > 10) NumPrint = 10;
for (unsigned i = 0; i != NumPrint; ++i)
- std::cout << " " << GVs[i]->getName();
+ outs() << " " << GVs[i]->getName();
if (NumPrint < GVs.size())
- std::cout << "... <" << GVs.size() << " total>";
- std::cout << std::flush;
+ outs() << "... <" << GVs.size() << " total>";
+ outs().flush();
}
diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h
index d637c24..db35c85 100644
--- a/tools/bugpoint/BugDriver.h
+++ b/tools/bugpoint/BugDriver.h
@@ -44,7 +44,7 @@ extern bool BugpointIsInterrupted;
class BugDriver {
LLVMContext& Context;
- const std::string ToolName; // Name of bugpoint
+ 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;
@@ -64,7 +64,7 @@ public:
BugDriver(const char *toolname, bool as_child, bool find_bugs,
unsigned timeout, unsigned memlimit, LLVMContext& ctxt);
- const std::string &getToolName() const { return ToolName; }
+ const char *getToolName() const { return ToolName; }
LLVMContext& getContext() { return Context; }
@@ -248,7 +248,7 @@ public:
/// optimizations fail for some reason (optimizer crashes), return true,
/// otherwise return false. If DeleteOutput is set to true, the bitcode is
/// deleted on success, and the filename string is undefined. This prints to
- /// cout a single line message indicating whether compilation was successful
+ /// outs() a single line message indicating whether compilation was successful
/// or failed, unless Quiet is set. ExtraArgs specifies additional arguments
/// to pass to the child bugpoint instance.
///
diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp
index 9697b34..b348a08 100644
--- a/tools/bugpoint/CrashDebugger.cpp
+++ b/tools/bugpoint/CrashDebugger.cpp
@@ -28,7 +28,6 @@
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/CommandLine.h"
-#include <fstream>
#include <set>
using namespace llvm;
@@ -64,8 +63,8 @@ ReducePassList::doTest(std::vector<const PassInfo*> &Prefix,
sys::Path PrefixOutput;
Module *OrigProgram = 0;
if (!Prefix.empty()) {
- std::cout << "Checking to see if these passes crash: "
- << getPassesString(Prefix) << ": ";
+ outs() << "Checking to see if these passes crash: "
+ << getPassesString(Prefix) << ": ";
std::string PfxOutput;
if (BD.runPasses(Prefix, PfxOutput))
return KeepPrefix;
@@ -73,17 +72,17 @@ ReducePassList::doTest(std::vector<const PassInfo*> &Prefix,
PrefixOutput.set(PfxOutput);
OrigProgram = BD.Program;
- BD.Program = ParseInputFile(PrefixOutput.toString(), BD.getContext());
+ BD.Program = ParseInputFile(PrefixOutput.str(), BD.getContext());
if (BD.Program == 0) {
- std::cerr << BD.getToolName() << ": Error reading bitcode file '"
- << PrefixOutput << "'!\n";
+ errs() << BD.getToolName() << ": Error reading bitcode file '"
+ << PrefixOutput.str() << "'!\n";
exit(1);
}
PrefixOutput.eraseFromDisk();
}
- std::cout << "Checking to see if these passes crash: "
- << getPassesString(Suffix) << ": ";
+ outs() << "Checking to see if these passes crash: "
+ << getPassesString(Suffix) << ": ";
if (BD.runPasses(Suffix)) {
delete OrigProgram; // The suffix crashes alone...
@@ -142,9 +141,9 @@ ReduceCrashingGlobalVariables::TestGlobalVariables(
GVSet.insert(CMGV);
}
- std::cout << "Checking for crash with only these global variables: ";
+ outs() << "Checking for crash with only these global variables: ";
PrintGlobalVariableList(GVs);
- std::cout << ": ";
+ outs() << ": ";
// Loop over and delete any global variables which we aren't supposed to be
// playing with...
@@ -216,9 +215,9 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
Functions.insert(CMF);
}
- std::cout << "Checking for crash with only these functions: ";
+ outs() << "Checking for crash with only these functions: ";
PrintFunctionList(Funcs);
- std::cout << ": ";
+ outs() << ": ";
// Loop over and delete any functions which we aren't supposed to be playing
// with...
@@ -276,14 +275,14 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) {
for (unsigned i = 0, e = BBs.size(); i != e; ++i)
Blocks.insert(cast<BasicBlock>(ValueMap[BBs[i]]));
- std::cout << "Checking for crash with only these blocks:";
+ outs() << "Checking for crash with only these blocks:";
unsigned NumPrint = Blocks.size();
if (NumPrint > 10) NumPrint = 10;
for (unsigned i = 0, e = NumPrint; i != e; ++i)
- std::cout << " " << BBs[i]->getName();
+ outs() << " " << BBs[i]->getName();
if (NumPrint < Blocks.size())
- std::cout << "... <" << Blocks.size() << " total>";
- std::cout << ": ";
+ outs() << "... <" << Blocks.size() << " total>";
+ outs() << ": ";
// Loop over and delete any hack up any blocks that are not listed...
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
@@ -298,12 +297,13 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) {
if (isa<StructType>(BBTerm->getType()))
BBTerm->replaceAllUsesWith(UndefValue::get(BBTerm->getType()));
- else if (BB->getTerminator()->getType() != Type::VoidTy)
+ else if (BB->getTerminator()->getType() !=
+ Type::getVoidTy(BB->getContext()))
BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));
// Replace the old terminator instruction.
BB->getInstList().pop_back();
- new UnreachableInst(BB);
+ new UnreachableInst(BB->getContext(), BB);
}
// The CFG Simplifier pass may delete one of the basic blocks we are
@@ -333,7 +333,7 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) {
for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
ValueSymbolTable &ST = BlockInfo[i].first->getValueSymbolTable();
Value* V = ST.lookup(BlockInfo[i].second);
- if (V && V->getType() == Type::LabelTy)
+ if (V && V->getType() == Type::getLabelTy(V->getContext()))
BBs.push_back(cast<BasicBlock>(V));
}
return true;
@@ -380,18 +380,18 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*>
Instructions.insert(cast<Instruction>(ValueMap[Insts[i]]));
}
- std::cout << "Checking for crash with only " << Instructions.size();
+ outs() << "Checking for crash with only " << Instructions.size();
if (Instructions.size() == 1)
- std::cout << " instruction: ";
+ outs() << " instruction: ";
else
- std::cout << " instructions: ";
+ outs() << " instructions: ";
for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI)
for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI)
for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) {
Instruction *Inst = I++;
if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst)) {
- if (Inst->getType() != Type::VoidTy)
+ if (Inst->getType() != Type::getVoidTy(Inst->getContext()))
Inst->replaceAllUsesWith(UndefValue::get(Inst->getType()));
Inst->eraseFromParent();
}
@@ -443,13 +443,13 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
delete M; // No change made...
} else {
// See if the program still causes a crash...
- std::cout << "\nChecking to see if we can delete global inits: ";
+ outs() << "\nChecking to see if we can delete global inits: ";
if (TestFn(BD, M)) { // Still crashes?
BD.setNewProgram(M);
- std::cout << "\n*** Able to remove all global initializers!\n";
+ outs() << "\n*** Able to remove all global initializers!\n";
} else { // No longer crashes?
- std::cout << " - Removing all global inits hides problem!\n";
+ outs() << " - Removing all global inits hides problem!\n";
delete M;
std::vector<GlobalVariable*> GVs;
@@ -460,7 +460,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
GVs.push_back(I);
if (GVs.size() > 1 && !BugpointIsInterrupted) {
- std::cout << "\n*** Attempting to reduce the number of global "
+ outs() << "\n*** Attempting to reduce the number of global "
<< "variables in the testcase\n";
unsigned OldSize = GVs.size();
@@ -481,7 +481,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
Functions.push_back(I);
if (Functions.size() > 1 && !BugpointIsInterrupted) {
- std::cout << "\n*** Attempting to reduce the number of functions "
+ outs() << "\n*** Attempting to reduce the number of functions "
"in the testcase\n";
unsigned OldSize = Functions.size();
@@ -530,8 +530,8 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
do {
if (BugpointIsInterrupted) break;
--Simplification;
- std::cout << "\n*** Attempting to reduce testcase by deleting instruc"
- << "tions: Simplification Level #" << Simplification << '\n';
+ outs() << "\n*** Attempting to reduce testcase by deleting instruc"
+ << "tions: Simplification Level #" << Simplification << '\n';
// Now that we have deleted the functions that are unnecessary for the
// program, try to remove instructions that are not necessary to cause the
@@ -559,7 +559,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
} else {
if (BugpointIsInterrupted) goto ExitLoops;
- std::cout << "Checking instruction: " << *I;
+ outs() << "Checking instruction: " << *I;
Module *M = BD.deleteInstructionFromProgram(I, Simplification);
// Find out if the pass still crashes on this pass...
@@ -586,7 +586,7 @@ ExitLoops:
// Try to clean up the testcase by running funcresolve and globaldce...
if (!BugpointIsInterrupted) {
- std::cout << "\n*** Attempting to perform final cleanups: ";
+ outs() << "\n*** Attempting to perform final cleanups: ";
Module *M = CloneModule(BD.getProgram());
M = BD.performFinalCleanups(M, true);
@@ -612,15 +612,15 @@ static bool TestForOptimizerCrash(BugDriver &BD, Module *M) {
/// out exactly which pass is crashing.
///
bool BugDriver::debugOptimizerCrash(const std::string &ID) {
- std::cout << "\n*** Debugging optimizer crash!\n";
+ outs() << "\n*** Debugging optimizer crash!\n";
// Reduce the list of passes which causes the optimizer to crash...
if (!BugpointIsInterrupted)
ReducePassList(*this).reduceList(PassesToRun);
- std::cout << "\n*** Found crashing pass"
- << (PassesToRun.size() == 1 ? ": " : "es: ")
- << getPassesString(PassesToRun) << '\n';
+ outs() << "\n*** Found crashing pass"
+ << (PassesToRun.size() == 1 ? ": " : "es: ")
+ << getPassesString(PassesToRun) << '\n';
EmitProgressBitcode(ID);
@@ -630,10 +630,10 @@ bool BugDriver::debugOptimizerCrash(const std::string &ID) {
static bool TestForCodeGenCrash(BugDriver &BD, Module *M) {
try {
BD.compileProgram(M);
- std::cerr << '\n';
+ errs() << '\n';
return false;
} catch (ToolExecutionError &) {
- std::cerr << "<crash>\n";
+ errs() << "<crash>\n";
return true; // Tool is still crashing.
}
}
@@ -642,7 +642,7 @@ static bool TestForCodeGenCrash(BugDriver &BD, Module *M) {
/// crashes on an input. It attempts to reduce the input as much as possible
/// while still causing the code generator to crash.
bool BugDriver::debugCodeGeneratorCrash() {
- std::cerr << "*** Debugging code generator crash!\n";
+ errs() << "*** Debugging code generator crash!\n";
return DebugACrash(*this, TestForCodeGenCrash);
}
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp
index 640fe28..feda331 100644
--- a/tools/bugpoint/ExecutionDriver.cpp
+++ b/tools/bugpoint/ExecutionDriver.cpp
@@ -18,8 +18,8 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/raw_ostream.h"
#include <fstream>
-#include <iostream>
using namespace llvm;
@@ -56,19 +56,19 @@ namespace {
cl::opt<OutputType>
SafeInterpreterSel(cl::desc("Specify \"safe\" i.e. known-good backend:"),
- cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"),
- clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"),
- clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"),
- clEnumValN(Custom, "safe-run-custom",
- "Use -exec-command to define a command to execute "
- "the bitcode. Useful for cross-compilation."),
- clEnumValEnd),
+ cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"),
+ clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"),
+ clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"),
+ clEnumValN(Custom, "safe-run-custom",
+ "Use -exec-command to define a command to execute "
+ "the bitcode. Useful for cross-compilation."),
+ clEnumValEnd),
cl::init(AutoPick));
cl::opt<std::string>
SafeInterpreterPath("safe-path",
- cl::desc("Specify the path to the \"safe\" backend program"),
- cl::init(""));
+ cl::desc("Specify the path to the \"safe\" backend program"),
+ cl::init(""));
cl::opt<bool>
AppendProgramExitCode("append-exit-code",
@@ -100,6 +100,10 @@ namespace llvm {
cl::list<std::string>
InputArgv("args", cl::Positional, cl::desc("<program arguments>..."),
cl::ZeroOrMore, cl::PositionalEatsArgs);
+
+ cl::opt<std::string>
+ OutputPrefix("output-prefix", cl::init("bugpoint"),
+ cl::desc("Prefix to use for outputs (default: 'bugpoint')"));
}
namespace {
@@ -126,7 +130,7 @@ namespace {
/// environment for executing LLVM programs.
///
bool BugDriver::initializeExecutionEnvironment() {
- std::cout << "Initializing execution environment: ";
+ outs() << "Initializing execution environment: ";
// Create an instance of the AbstractInterpreter interface as specified on
// the command line
@@ -178,17 +182,16 @@ bool BugDriver::initializeExecutionEnvironment() {
&ToolArgv, &GCCToolArgv);
break;
case Custom:
- Interpreter = AbstractInterpreter::createCustom(getToolName(), Message,
- CustomExecCommand);
+ Interpreter = AbstractInterpreter::createCustom(Message, CustomExecCommand);
break;
default:
Message = "Sorry, this back-end is not supported by bugpoint right now!\n";
break;
}
if (!Interpreter)
- std::cerr << Message;
+ errs() << Message;
else // Display informational messages on stdout instead of stderr
- std::cout << Message;
+ outs() << Message;
std::string Path = SafeInterpreterPath;
if (Path.empty())
@@ -201,7 +204,7 @@ bool BugDriver::initializeExecutionEnvironment() {
InterpreterSel == CBE_bug) {
SafeInterpreterSel = RunLLC;
SafeToolArgs.push_back("--relocation-model=pic");
- SafeInterpreter = AbstractInterpreter::createLLC(Path, Message,
+ SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
&SafeToolArgs,
&GCCToolArgv);
}
@@ -211,7 +214,7 @@ bool BugDriver::initializeExecutionEnvironment() {
InterpreterSel == LLC_Safe) {
SafeInterpreterSel = RunLLC;
SafeToolArgs.push_back("--relocation-model=pic");
- SafeInterpreter = AbstractInterpreter::createLLC(Path, Message,
+ SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
&SafeToolArgs,
&GCCToolArgv);
}
@@ -222,7 +225,7 @@ bool BugDriver::initializeExecutionEnvironment() {
if (!SafeInterpreter &&
InterpreterSel != RunCBE) {
SafeInterpreterSel = RunCBE;
- SafeInterpreter = AbstractInterpreter::createCBE(Path, Message,
+ SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message,
&SafeToolArgs,
&GCCToolArgv);
}
@@ -231,7 +234,7 @@ bool BugDriver::initializeExecutionEnvironment() {
InterpreterSel != RunJIT) {
SafeInterpreterSel = RunLLC;
SafeToolArgs.push_back("--relocation-model=pic");
- SafeInterpreter = AbstractInterpreter::createLLC(Path, Message,
+ SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
&SafeToolArgs,
&GCCToolArgv);
}
@@ -242,17 +245,17 @@ bool BugDriver::initializeExecutionEnvironment() {
break;
case RunLLC:
SafeToolArgs.push_back("--relocation-model=pic");
- SafeInterpreter = AbstractInterpreter::createLLC(Path, Message,
+ SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
&SafeToolArgs,
&GCCToolArgv);
break;
case RunCBE:
- SafeInterpreter = AbstractInterpreter::createCBE(Path, Message,
+ SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message,
&SafeToolArgs,
&GCCToolArgv);
break;
case Custom:
- SafeInterpreter = AbstractInterpreter::createCustom(Path, Message,
+ SafeInterpreter = AbstractInterpreter::createCustom(Message,
CustomExecCommand);
break;
default:
@@ -260,10 +263,10 @@ bool BugDriver::initializeExecutionEnvironment() {
"\"safe\" backend right now!\n";
break;
}
- if (!SafeInterpreter) { std::cout << Message << "\nExiting.\n"; exit(1); }
+ if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); }
- gcc = GCC::create(getToolName(), Message, &GCCToolArgv);
- if (!gcc) { std::cout << Message << "\nExiting.\n"; exit(1); }
+ gcc = GCC::create(Message, &GCCToolArgv);
+ if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); }
// If there was an error creating the selected interpreter, quit with error.
return Interpreter == 0;
@@ -275,24 +278,24 @@ bool BugDriver::initializeExecutionEnvironment() {
///
void BugDriver::compileProgram(Module *M) {
// Emit the program to a bitcode file...
- sys::Path BitcodeFile ("bugpoint-test-program.bc");
+ sys::Path BitcodeFile (OutputPrefix + "-test-program.bc");
std::string ErrMsg;
if (BitcodeFile.makeUnique(true,&ErrMsg)) {
- std::cerr << ToolName << ": Error making unique filename: " << ErrMsg
- << "\n";
+ errs() << ToolName << ": Error making unique filename: " << ErrMsg
+ << "\n";
exit(1);
}
- if (writeProgramToFile(BitcodeFile.toString(), M)) {
- std::cerr << ToolName << ": Error emitting bitcode to file '"
- << BitcodeFile << "'!\n";
+ if (writeProgramToFile(BitcodeFile.str(), M)) {
+ errs() << ToolName << ": Error emitting bitcode to file '"
+ << BitcodeFile.str() << "'!\n";
exit(1);
}
// Remove the temporary bitcode file when we are done.
- FileRemover BitcodeFileRemover(BitcodeFile);
+ FileRemover BitcodeFileRemover(BitcodeFile, !SaveTemps);
// Actually compile the program!
- Interpreter->compileProgram(BitcodeFile.toString());
+ Interpreter->compileProgram(BitcodeFile.str());
}
@@ -311,17 +314,17 @@ std::string BugDriver::executeProgram(std::string OutputFile,
std::string ErrMsg;
if (BitcodeFile.empty()) {
// Emit the program to a bitcode file...
- sys::Path uniqueFilename("bugpoint-test-program.bc");
+ sys::Path uniqueFilename(OutputPrefix + "-test-program.bc");
if (uniqueFilename.makeUnique(true, &ErrMsg)) {
- std::cerr << ToolName << ": Error making unique filename: "
- << ErrMsg << "!\n";
+ errs() << ToolName << ": Error making unique filename: "
+ << ErrMsg << "!\n";
exit(1);
}
- BitcodeFile = uniqueFilename.toString();
+ BitcodeFile = uniqueFilename.str();
if (writeProgramToFile(BitcodeFile, Program)) {
- std::cerr << ToolName << ": Error emitting bitcode to file '"
- << BitcodeFile << "'!\n";
+ errs() << ToolName << ": Error emitting bitcode to file '"
+ << BitcodeFile << "'!\n";
exit(1);
}
CreatedBitcode = true;
@@ -329,18 +332,18 @@ std::string BugDriver::executeProgram(std::string OutputFile,
// Remove the temporary bitcode file when we are done.
sys::Path BitcodePath (BitcodeFile);
- FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode);
+ FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode && !SaveTemps);
- if (OutputFile.empty()) OutputFile = "bugpoint-execution-output";
+ if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output";
// Check to see if this is a valid output filename...
sys::Path uniqueFile(OutputFile);
if (uniqueFile.makeUnique(true, &ErrMsg)) {
- std::cerr << ToolName << ": Error making unique filename: "
- << ErrMsg << "\n";
+ errs() << ToolName << ": Error making unique filename: "
+ << ErrMsg << "\n";
exit(1);
}
- OutputFile = uniqueFile.toString();
+ OutputFile = uniqueFile.str();
// Figure out which shared objects to run, if any.
std::vector<std::string> SharedObjs(AdditionalSOs);
@@ -352,10 +355,10 @@ std::string BugDriver::executeProgram(std::string OutputFile,
Timeout, MemoryLimit);
if (RetVal == -1) {
- std::cerr << "<timeout>";
+ errs() << "<timeout>";
static bool FirstTimeout = true;
if (FirstTimeout) {
- std::cout << "\n"
+ outs() << "\n"
"*** Program execution timed out! This mechanism is designed to handle\n"
" programs stuck in infinite loops gracefully. The -timeout option\n"
" can be used to change the timeout threshold or disable it completely\n"
@@ -395,7 +398,7 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile) {
GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile);
std::string SharedObjectFile;
- if (gcc->MakeSharedObject(OutputFile.toString(), FT,
+ if (gcc->MakeSharedObject(OutputFile.str(), FT,
SharedObjectFile, AdditionalLinkerArgs))
exit(1);
@@ -418,14 +421,14 @@ bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) {
}
try {
ReferenceOutputFile = executeProgramSafely(Filename);
- std::cout << "\nReference output is: " << ReferenceOutputFile << "\n\n";
+ outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n";
} catch (ToolExecutionError &TEE) {
- std::cerr << TEE.what();
+ errs() << TEE.what();
if (Interpreter != SafeInterpreter) {
- std::cerr << "*** There is a bug running the \"safe\" backend. Either"
- << " debug it (for example with the -run-cbe bugpoint option,"
- << " if CBE is being used as the \"safe\" backend), or fix the"
- << " error some other way.\n";
+ errs() << "*** There is a bug running the \"safe\" backend. Either"
+ << " debug it (for example with the -run-cbe bugpoint option,"
+ << " if CBE is being used as the \"safe\" backend), or fix the"
+ << " error some other way.\n";
}
return false;
}
@@ -449,17 +452,18 @@ bool BugDriver::diffProgram(const std::string &BitcodeFile,
std::string Error;
bool FilesDifferent = false;
if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile),
- sys::Path(Output.toString()),
+ sys::Path(Output.str()),
AbsTolerance, RelTolerance, &Error)) {
if (Diff == 2) {
- std::cerr << "While diffing output: " << Error << '\n';
+ errs() << "While diffing output: " << Error << '\n';
exit(1);
}
FilesDifferent = true;
}
-
- // Remove the generated output.
- Output.eraseFromDisk();
+ else {
+ // Remove the generated output if there are no differences.
+ Output.eraseFromDisk();
+ }
// Remove the bitcode file if we are supposed to.
if (RemoveBitcode)
diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp
index e4affbb..918d6a6a 100644
--- a/tools/bugpoint/ExtractFunction.cpp
+++ b/tools/bugpoint/ExtractFunction.cpp
@@ -15,10 +15,12 @@
#include "BugDriver.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Verifier.h"
+#include "llvm/Assembly/Writer.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Cloning.h"
@@ -27,15 +29,15 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/System/Signals.h"
#include <set>
-#include <fstream>
-#include <iostream>
using namespace llvm;
namespace llvm {
bool DisableSimplifyCFG = false;
+ extern cl::opt<std::string> OutputPrefix;
} // End llvm namespace
namespace {
@@ -73,7 +75,7 @@ Module *BugDriver::deleteInstructionFromProgram(const Instruction *I,
// If this instruction produces a value, replace any users with null values
if (isa<StructType>(TheInst->getType()))
TheInst->replaceAllUsesWith(UndefValue::get(TheInst->getType()));
- else if (TheInst->getType() != Type::VoidTy)
+ else if (TheInst->getType() != Type::getVoidTy(I->getContext()))
TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType()));
// Remove the instruction from the program.
@@ -125,7 +127,7 @@ Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) {
Module *New = runPassesOn(M, CleanupPasses);
if (New == 0) {
- std::cerr << "Final cleanups failed. Sorry. :( Please report a bug!\n";
+ errs() << "Final cleanups failed. Sorry. :( Please report a bug!\n";
return M;
}
delete M;
@@ -143,9 +145,9 @@ Module *BugDriver::ExtractLoop(Module *M) {
Module *NewM = runPassesOn(M, LoopExtractPasses);
if (NewM == 0) {
Module *Old = swapProgramIn(M);
- std::cout << "*** Loop extraction failed: ";
+ outs() << "*** Loop extraction failed: ";
EmitProgressBitcode("loopextraction", true);
- std::cout << "*** Sorry. :( Please report a bug!\n";
+ outs() << "*** Sorry. :( Please report a bug!\n";
swapProgramIn(Old);
return 0;
}
@@ -184,9 +186,11 @@ static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) {
std::vector<Constant*> ArrayElts;
for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
std::vector<Constant*> Elts;
- Elts.push_back(ConstantInt::get(Type::Int32Ty, TorList[i].second));
+ Elts.push_back(ConstantInt::get(
+ Type::getInt32Ty(TorList[i].first->getContext()), TorList[i].second));
Elts.push_back(TorList[i].first);
- ArrayElts.push_back(ConstantStruct::get(Elts));
+ ArrayElts.push_back(ConstantStruct::get(TorList[i].first->getContext(),
+ Elts, false));
}
return ConstantArray::get(ArrayType::get(ArrayElts[0]->getType(),
ArrayElts.size()),
@@ -236,8 +240,9 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
GV->eraseFromParent();
if (!M1Tors.empty()) {
Constant *M1Init = GetTorInit(M1Tors);
- new GlobalVariable(M1Init->getType(), false, GlobalValue::AppendingLinkage,
- M1Init, GlobalName, M1);
+ new GlobalVariable(*M1, M1Init->getType(), false,
+ GlobalValue::AppendingLinkage,
+ M1Init, GlobalName);
}
GV = M2->getNamedGlobal(GlobalName);
@@ -247,8 +252,9 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
GV->eraseFromParent();
if (!M2Tors.empty()) {
Constant *M2Init = GetTorInit(M2Tors);
- new GlobalVariable(M2Init->getType(), false, GlobalValue::AppendingLinkage,
- M2Init, GlobalName, M2);
+ new GlobalVariable(*M2, M2Init->getType(), false,
+ GlobalValue::AppendingLinkage,
+ M2Init, GlobalName);
}
}
@@ -266,8 +272,8 @@ llvm::SplitFunctionsOutOfModule(Module *M,
I->setLinkage(GlobalValue::ExternalLinkage);
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
I != E; ++I) {
- if (I->hasName() && *I->getNameStart() == '\01')
- I->setName(I->getNameStart()+1, I->getNameLen()-1);
+ if (I->hasName() && I->getName()[0] == '\01')
+ I->setName(I->getName().substr(1));
I->setLinkage(GlobalValue::ExternalLinkage);
}
@@ -283,9 +289,9 @@ llvm::SplitFunctionsOutOfModule(Module *M,
std::set<Function *> TestFunctions;
for (unsigned i = 0, e = F.size(); i != e; ++i) {
Function *TNOF = cast<Function>(ValueMap[F[i]]);
- DEBUG(std::cerr << "Removing function ");
- DEBUG(WriteAsOperand(std::cerr, TNOF, false));
- DEBUG(std::cerr << "\n");
+ DEBUG(errs() << "Removing function ");
+ DEBUG(WriteAsOperand(errs(), TNOF, false));
+ DEBUG(errs() << "\n");
TestFunctions.insert(cast<Function>(NewValueMap[TNOF]));
DeleteFunctionBody(TNOF); // Function is now external in this module!
}
@@ -319,11 +325,11 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
Module *M) {
char *ExtraArg = NULL;
- sys::Path uniqueFilename("bugpoint-extractblocks");
+ sys::Path uniqueFilename(OutputPrefix + "-extractblocks");
std::string ErrMsg;
if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) {
- std::cout << "*** Basic Block extraction failed!\n";
- std::cerr << "Error creating temporary file: " << ErrMsg << "\n";
+ outs() << "*** Basic Block extraction failed!\n";
+ errs() << "Error creating temporary file: " << ErrMsg << "\n";
M = swapProgramIn(M);
EmitProgressBitcode("basicblockextractfail", true);
swapProgramIn(M);
@@ -331,11 +337,12 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
}
sys::RemoveFileOnSignal(uniqueFilename);
- std::ofstream BlocksToNotExtractFile(uniqueFilename.c_str());
- if (!BlocksToNotExtractFile) {
- std::cout << "*** Basic Block extraction failed!\n";
- std::cerr << "Error writing list of blocks to not extract: " << ErrMsg
- << "\n";
+ std::string ErrorInfo;
+ raw_fd_ostream 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);
@@ -347,7 +354,7 @@ 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()->getName() << " "
+ BlocksToNotExtractFile << BB->getParent()->getNameStr() << " "
<< BB->getName() << "\n";
}
BlocksToNotExtractFile.close();
@@ -366,7 +373,7 @@ Module *BugDriver::ExtractMappedBlocksFromModule(const
free(ExtraArg);
if (Ret == 0) {
- std::cout << "*** Basic Block extraction failed, please report a bug!\n";
+ outs() << "*** Basic Block extraction failed, please report a bug!\n";
M = swapProgramIn(M);
EmitProgressBitcode("basicblockextractfail", true);
swapProgramIn(M);
diff --git a/tools/bugpoint/FindBugs.cpp b/tools/bugpoint/FindBugs.cpp
index e42cce4..2c11d29 100644
--- a/tools/bugpoint/FindBugs.cpp
+++ b/tools/bugpoint/FindBugs.cpp
@@ -17,9 +17,9 @@
#include "BugDriver.h"
#include "ToolRunner.h"
#include "llvm/Pass.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <ctime>
-#include <iostream>
using namespace llvm;
/// runManyPasses - Take the specified pass list and create different
@@ -31,14 +31,14 @@ using namespace llvm;
///
bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) {
setPassesToRun(AllPasses);
- std::cout << "Starting bug finding procedure...\n\n";
+ outs() << "Starting bug finding procedure...\n\n";
// Creating a reference output if necessary
if (initializeExecutionEnvironment()) return false;
- std::cout << "\n";
+ outs() << "\n";
if (ReferenceOutputFile.empty()) {
- std::cout << "Generating reference output from raw program: \n";
+ outs() << "Generating reference output from raw program: \n";
if (!createReferenceFile(Program))
return false;
}
@@ -55,31 +55,31 @@ bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) {
//
// Step 2: Run optimizer passes on the program and check for success.
//
- std::cout << "Running selected passes on program to test for crash: ";
+ outs() << "Running selected passes on program to test for crash: ";
for(int i = 0, e = PassesToRun.size(); i != e; i++) {
- std::cout << "-" << PassesToRun[i]->getPassArgument( )<< " ";
+ outs() << "-" << PassesToRun[i]->getPassArgument( )<< " ";
}
std::string Filename;
if(runPasses(PassesToRun, Filename, false)) {
- std::cout << "\n";
- std::cout << "Optimizer passes caused failure!\n\n";
+ outs() << "\n";
+ outs() << "Optimizer passes caused failure!\n\n";
debugOptimizerCrash();
return true;
} else {
- std::cout << "Combination " << num << " optimized successfully!\n";
+ outs() << "Combination " << num << " optimized successfully!\n";
}
//
// Step 3: Compile the optimized code.
//
- std::cout << "Running the code generator to test for a crash: ";
+ outs() << "Running the code generator to test for a crash: ";
try {
compileProgram(Program);
- std::cout << '\n';
+ outs() << '\n';
} catch (ToolExecutionError &TEE) {
- std::cout << "\n*** compileProgram threw an exception: ";
- std::cout << TEE.what();
+ outs() << "\n*** compileProgram threw an exception: ";
+ outs() << TEE.what();
return debugCodeGeneratorCrash();
}
@@ -87,24 +87,24 @@ bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) {
// Step 4: Run the program and compare its output to the reference
// output (created above).
//
- std::cout << "*** Checking if passes caused miscompliation:\n";
+ outs() << "*** Checking if passes caused miscompliation:\n";
try {
if (diffProgram(Filename, "", false)) {
- std::cout << "\n*** diffProgram returned true!\n";
+ outs() << "\n*** diffProgram returned true!\n";
debugMiscompilation();
return true;
} else {
- std::cout << "\n*** diff'd output matches!\n";
+ outs() << "\n*** diff'd output matches!\n";
}
} catch (ToolExecutionError &TEE) {
- std::cerr << TEE.what();
+ errs() << TEE.what();
debugCodeGeneratorCrash();
return true;
}
sys::Path(Filename).eraseFromDisk();
- std::cout << "\n\n";
+ outs() << "\n\n";
num++;
} //end while
diff --git a/tools/bugpoint/ListReducer.h b/tools/bugpoint/ListReducer.h
index de3f389..8036d1f 100644
--- a/tools/bugpoint/ListReducer.h
+++ b/tools/bugpoint/ListReducer.h
@@ -15,8 +15,8 @@
#ifndef BUGPOINT_LIST_REDUCER_H
#define BUGPOINT_LIST_REDUCER_H
+#include "llvm/Support/raw_ostream.h"
#include <vector>
-#include <iostream>
#include <cstdlib>
#include <algorithm>
@@ -58,7 +58,7 @@ struct ListReducer {
case KeepSuffix:
// cannot be reached!
- std::cerr << "bugpoint ListReducer internal error: selected empty set.\n";
+ errs() << "bugpoint ListReducer internal error: selected empty set.\n";
abort();
case NoFailure:
@@ -77,7 +77,7 @@ Backjump:
while (MidTop > 1) { // Binary split reduction loop
// Halt if the user presses ctrl-c.
if (BugpointIsInterrupted) {
- std::cerr << "\n\n*** Reduction Interrupted, cleaning up...\n\n";
+ errs() << "\n\n*** Reduction Interrupted, cleaning up...\n\n";
return true;
}
@@ -88,7 +88,7 @@ Backjump:
NumOfIterationsWithoutProgress > MaxIterations) {
std::vector<ElTy> ShuffledList(TheList);
std::random_shuffle(ShuffledList.begin(), ShuffledList.end());
- std::cerr << "\n\n*** Testing shuffled set...\n\n";
+ errs() << "\n\n*** Testing shuffled set...\n\n";
// Check that random shuffle doesn't loose the bug
if (doTest(ShuffledList, empty) == KeepPrefix) {
// If the bug is still here, use the shuffled list.
@@ -97,10 +97,10 @@ Backjump:
// Must increase the shuffling treshold to avoid the small
// probability of inifinite looping without making progress.
MaxIterations += 2;
- std::cerr << "\n\n*** Shuffling does not hide the bug...\n\n";
+ errs() << "\n\n*** Shuffling does not hide the bug...\n\n";
} else {
ShufflingEnabled = false; // Disable shuffling further on
- std::cerr << "\n\n*** Shuffling hides the bug...\n\n";
+ errs() << "\n\n*** Shuffling hides the bug...\n\n";
}
NumOfIterationsWithoutProgress = 0;
}
@@ -160,7 +160,7 @@ Backjump:
for (unsigned i = 1; i < TheList.size()-1; ++i) { // Check interior elts
if (BugpointIsInterrupted) {
- std::cerr << "\n\n*** Reduction Interrupted, cleaning up...\n\n";
+ errs() << "\n\n*** Reduction Interrupted, cleaning up...\n\n";
return true;
}
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
index b3260e1..a591417 100644
--- a/tools/bugpoint/Miscompilation.cpp
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -14,6 +14,7 @@
#include "BugDriver.h"
#include "ListReducer.h"
+#include "ToolRunner.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
@@ -29,6 +30,7 @@
using namespace llvm;
namespace llvm {
+ extern cl::opt<std::string> OutputPrefix;
extern cl::list<std::string> InputArgv;
}
@@ -37,6 +39,10 @@ namespace {
DisableLoopExtraction("disable-loop-extraction",
cl::desc("Don't extract loops when searching for miscompilations"),
cl::init(false));
+ static llvm::cl::opt<bool>
+ DisableBlockExtraction("disable-block-extraction",
+ cl::desc("Don't extract blocks when searching for miscompilations"),
+ cl::init(false));
class ReduceMiscompilingPasses : public ListReducer<const PassInfo*> {
BugDriver &BD;
@@ -56,36 +62,36 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
std::vector<const PassInfo*> &Suffix) {
// First, run the program with just the Suffix passes. If it is still broken
// with JUST the kept passes, discard the prefix passes.
- std::cout << "Checking to see if '" << getPassesString(Suffix)
- << "' compile correctly: ";
+ outs() << "Checking to see if '" << getPassesString(Suffix)
+ << "' compiles correctly: ";
std::string BitcodeResult;
if (BD.runPasses(Suffix, BitcodeResult, false/*delete*/, true/*quiet*/)) {
- std::cerr << " Error running this sequence of passes"
- << " on the input program!\n";
+ errs() << " Error running this sequence of passes"
+ << " on the input program!\n";
BD.setPassesToRun(Suffix);
BD.EmitProgressBitcode("pass-error", false);
exit(BD.debugOptimizerCrash());
}
-
+
// Check to see if the finished program matches the reference output...
if (BD.diffProgram(BitcodeResult, "", true /*delete bitcode*/)) {
- std::cout << " nope.\n";
+ outs() << " nope.\n";
if (Suffix.empty()) {
- std::cerr << BD.getToolName() << ": I'm confused: the test fails when "
- << "no passes are run, nondeterministic program?\n";
+ errs() << BD.getToolName() << ": I'm confused: the test fails when "
+ << "no passes are run, nondeterministic program?\n";
exit(1);
}
return KeepSuffix; // Miscompilation detected!
}
- std::cout << " yup.\n"; // No miscompilation!
+ outs() << " yup.\n"; // No miscompilation!
if (Prefix.empty()) return NoFailure;
// Next, see if the program is broken if we run the "prefix" passes first,
// then separately run the "kept" passes.
- std::cout << "Checking to see if '" << getPassesString(Prefix)
- << "' compile correctly: ";
+ outs() << "Checking to see if '" << getPassesString(Prefix)
+ << "' compiles correctly: ";
// If it is not broken with the kept passes, it's possible that the prefix
// passes must be run before the kept passes to break it. If the program
@@ -94,8 +100,8 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
// prefix passes, then discard the prefix passes.
//
if (BD.runPasses(Prefix, BitcodeResult, false/*delete*/, true/*quiet*/)) {
- std::cerr << " Error running this sequence of passes"
- << " on the input program!\n";
+ errs() << " Error running this sequence of passes"
+ << " on the input program!\n";
BD.setPassesToRun(Prefix);
BD.EmitProgressBitcode("pass-error", false);
exit(BD.debugOptimizerCrash());
@@ -103,19 +109,19 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
// If the prefix maintains the predicate by itself, only keep the prefix!
if (BD.diffProgram(BitcodeResult)) {
- std::cout << " nope.\n";
+ outs() << " nope.\n";
sys::Path(BitcodeResult).eraseFromDisk();
return KeepPrefix;
}
- std::cout << " yup.\n"; // No miscompilation!
+ outs() << " yup.\n"; // No miscompilation!
// Ok, so now we know that the prefix passes work, try running the suffix
// passes on the result of the prefix passes.
//
Module *PrefixOutput = ParseInputFile(BitcodeResult, BD.getContext());
if (PrefixOutput == 0) {
- std::cerr << BD.getToolName() << ": Error reading bitcode file '"
- << BitcodeResult << "'!\n";
+ errs() << BD.getToolName() << ": Error reading bitcode file '"
+ << BitcodeResult << "'!\n";
exit(1);
}
sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk
@@ -124,14 +130,14 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
if (Suffix.empty())
return NoFailure;
- std::cout << "Checking to see if '" << getPassesString(Suffix)
+ outs() << "Checking to see if '" << getPassesString(Suffix)
<< "' passes compile correctly after the '"
<< getPassesString(Prefix) << "' passes: ";
Module *OriginalInput = BD.swapProgramIn(PrefixOutput);
if (BD.runPasses(Suffix, BitcodeResult, false/*delete*/, true/*quiet*/)) {
- std::cerr << " Error running this sequence of passes"
- << " on the input program!\n";
+ errs() << " Error running this sequence of passes"
+ << " on the input program!\n";
BD.setPassesToRun(Suffix);
BD.EmitProgressBitcode("pass-error", false);
exit(BD.debugOptimizerCrash());
@@ -139,13 +145,13 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
// Run the result...
if (BD.diffProgram(BitcodeResult, "", true/*delete bitcode*/)) {
- std::cout << " nope.\n";
+ outs() << " nope.\n";
delete OriginalInput; // We pruned down the original input...
return KeepSuffix;
}
// Otherwise, we must not be running the bad pass anymore.
- std::cout << " yup.\n"; // No miscompilation!
+ outs() << " yup.\n"; // No miscompilation!
delete BD.swapProgramIn(OriginalInput); // Restore orig program & free test
return NoFailure;
}
@@ -187,8 +193,8 @@ static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2,
M2 = CloneModule(M2);
}
if (Linker::LinkModules(M1, M2, &ErrorMsg)) {
- std::cerr << BD.getToolName() << ": Error linking modules together:"
- << ErrorMsg << '\n';
+ errs() << BD.getToolName() << ": Error linking modules together:"
+ << ErrorMsg << '\n';
exit(1);
}
delete M2; // We are done with this module.
@@ -212,12 +218,12 @@ static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2,
bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*>&Funcs){
// Test to see if the function is misoptimized if we ONLY run it on the
// functions listed in Funcs.
- std::cout << "Checking to see if the program is misoptimized when "
- << (Funcs.size()==1 ? "this function is" : "these functions are")
- << " run through the pass"
- << (BD.getPassesToRun().size() == 1 ? "" : "es") << ":";
+ outs() << "Checking to see if the program is misoptimized when "
+ << (Funcs.size()==1 ? "this function is" : "these functions are")
+ << " run through the pass"
+ << (BD.getPassesToRun().size() == 1 ? "" : "es") << ":";
PrintFunctionList(Funcs);
- std::cout << '\n';
+ outs() << '\n';
// Split the module into the two halves of the program we want.
DenseMap<const Value*, Value*> ValueMap;
@@ -241,12 +247,18 @@ static void DisambiguateGlobalSymbols(Module *M) {
Mangler Mang(*M);
// Agree with the CBE on symbol naming
Mang.markCharUnacceptable('.');
- Mang.setPreserveAsmNames(true);
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
- I != E; ++I)
- I->setName(Mang.getValueName(I));
- for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
- I->setName(Mang.getValueName(I));
+ I != E; ++I) {
+ // Don't mangle asm names.
+ if (!I->hasName() || I->getName()[0] != 1)
+ I->setName(Mang.getMangledName(I));
+ }
+ for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
+ // Don't mangle asm names or intrinsics.
+ if ((!I->hasName() || I->getName()[0] != 1) &&
+ I->getIntrinsicID() == 0)
+ I->setName(Mang.getMangledName(I));
+ }
}
/// ExtractLoops - Given a reduced list of functions that still exposed the bug,
@@ -274,7 +286,7 @@ static bool ExtractLoops(BugDriver &BD,
return MadeChange;
}
- std::cerr << "Extracted a loop from the breaking portion of the program.\n";
+ errs() << "Extracted a loop from the breaking portion of the program.\n";
// Bugpoint is intentionally not very trusting of LLVM transformations. In
// particular, we're not going to assume that the loop extractor works, so
@@ -286,16 +298,19 @@ static bool ExtractLoops(BugDriver &BD,
BD.switchToInterpreter(AI);
// Merged program doesn't work anymore!
- std::cerr << " *** ERROR: Loop extraction broke the program. :("
- << " Please report a bug!\n";
- std::cerr << " Continuing on with un-loop-extracted version.\n";
-
- BD.writeProgramToFile("bugpoint-loop-extract-fail-tno.bc", ToNotOptimize);
- BD.writeProgramToFile("bugpoint-loop-extract-fail-to.bc", ToOptimize);
- BD.writeProgramToFile("bugpoint-loop-extract-fail-to-le.bc",
+ errs() << " *** ERROR: Loop extraction broke the program. :("
+ << " Please report a bug!\n";
+ errs() << " Continuing on with un-loop-extracted version.\n";
+
+ BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc",
+ ToNotOptimize);
+ BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc",
+ ToOptimize);
+ BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc",
ToOptimizeLoopExtracted);
- std::cerr << "Please submit the bugpoint-loop-extract-fail-*.bc files.\n";
+ errs() << "Please submit the "
+ << OutputPrefix << "-loop-extract-fail-*.bc files.\n";
delete ToOptimize;
delete ToNotOptimize;
delete ToOptimizeLoopExtracted;
@@ -304,12 +319,12 @@ static bool ExtractLoops(BugDriver &BD,
delete ToOptimize;
BD.switchToInterpreter(AI);
- std::cout << " Testing after loop extraction:\n";
+ outs() << " Testing after loop extraction:\n";
// Clone modules, the tester function will free them.
Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted);
Module *TNOBackup = CloneModule(ToNotOptimize);
if (!TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize)) {
- std::cout << "*** Loop extraction masked the problem. Undoing.\n";
+ outs() << "*** Loop extraction masked the problem. Undoing.\n";
// If the program is not still broken, then loop extraction did something
// that masked the error. Stop loop extraction now.
delete TOLEBackup;
@@ -319,7 +334,7 @@ static bool ExtractLoops(BugDriver &BD,
ToOptimizeLoopExtracted = TOLEBackup;
ToNotOptimize = TNOBackup;
- std::cout << "*** Loop extraction successful!\n";
+ outs() << "*** Loop extraction successful!\n";
std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions;
for (Module::iterator I = ToOptimizeLoopExtracted->begin(),
@@ -334,8 +349,8 @@ static bool ExtractLoops(BugDriver &BD,
// extract another loop.
std::string ErrorMsg;
if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)){
- std::cerr << BD.getToolName() << ": Error linking modules together:"
- << ErrorMsg << '\n';
+ errs() << BD.getToolName() << ": Error linking modules together:"
+ << ErrorMsg << '\n';
exit(1);
}
delete ToOptimizeLoopExtracted;
@@ -388,16 +403,16 @@ namespace {
bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs) {
// Test to see if the function is misoptimized if we ONLY run it on the
// functions listed in Funcs.
- std::cout << "Checking to see if the program is misoptimized when all ";
+ outs() << "Checking to see if the program is misoptimized when all ";
if (!BBs.empty()) {
- std::cout << "but these " << BBs.size() << " blocks are extracted: ";
+ outs() << "but these " << BBs.size() << " blocks are extracted: ";
for (unsigned i = 0, e = BBs.size() < 10 ? BBs.size() : 10; i != e; ++i)
- std::cout << BBs[i]->getName() << " ";
- if (BBs.size() > 10) std::cout << "...";
+ outs() << BBs[i]->getName() << " ";
+ if (BBs.size() > 10) outs() << "...";
} else {
- std::cout << "blocks are extracted.";
+ outs() << "blocks are extracted.";
}
- std::cout << '\n';
+ outs() << '\n';
// Split the module into the two halves of the program we want.
DenseMap<const Value*, Value*> ValueMap;
@@ -457,7 +472,7 @@ static bool ExtractBlocks(BugDriver &BD,
Module *Extracted = BD.ExtractMappedBlocksFromModule(Blocks, ToExtract);
if (Extracted == 0) {
// Weird, extraction should have worked.
- std::cerr << "Nondeterministic problem extracting blocks??\n";
+ errs() << "Nondeterministic problem extracting blocks??\n";
delete ProgClone;
delete ToExtract;
return false;
@@ -476,8 +491,8 @@ static bool ExtractBlocks(BugDriver &BD,
std::string ErrorMsg;
if (Linker::LinkModules(ProgClone, Extracted, &ErrorMsg)) {
- std::cerr << BD.getToolName() << ": Error linking modules together:"
- << ErrorMsg << '\n';
+ errs() << BD.getToolName() << ": Error linking modules together:"
+ << ErrorMsg << '\n';
exit(1);
}
delete Extracted;
@@ -520,11 +535,11 @@ DebugAMiscompilation(BugDriver &BD,
if (!BugpointIsInterrupted)
ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions);
- std::cout << "\n*** The following function"
- << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
- << " being miscompiled: ";
+ outs() << "\n*** The following function"
+ << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
+ << " being miscompiled: ";
PrintFunctionList(MiscompiledFunctions);
- std::cout << '\n';
+ outs() << '\n';
// See if we can rip any loops out of the miscompiled functions and still
// trigger the problem.
@@ -543,14 +558,14 @@ DebugAMiscompilation(BugDriver &BD,
if (!BugpointIsInterrupted)
ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions);
- std::cout << "\n*** The following function"
- << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
- << " being miscompiled: ";
+ outs() << "\n*** The following function"
+ << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
+ << " being miscompiled: ";
PrintFunctionList(MiscompiledFunctions);
- std::cout << '\n';
+ outs() << '\n';
}
- if (!BugpointIsInterrupted &&
+ if (!BugpointIsInterrupted && !DisableBlockExtraction &&
ExtractBlocks(BD, TestFn, MiscompiledFunctions)) {
// Okay, we extracted some blocks and the problem still appears. See if we
// can eliminate some of the created functions from being candidates.
@@ -563,11 +578,11 @@ DebugAMiscompilation(BugDriver &BD,
// Do the reduction...
ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions);
- std::cout << "\n*** The following function"
- << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
- << " being miscompiled: ";
+ outs() << "\n*** The following function"
+ << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
+ << " being miscompiled: ";
PrintFunctionList(MiscompiledFunctions);
- std::cout << '\n';
+ outs() << '\n';
}
return MiscompiledFunctions;
@@ -580,15 +595,15 @@ DebugAMiscompilation(BugDriver &BD,
static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe) {
// Run the optimization passes on ToOptimize, producing a transformed version
// of the functions being tested.
- std::cout << " Optimizing functions being tested: ";
+ outs() << " Optimizing functions being tested: ";
Module *Optimized = BD.runPassesOn(Test, BD.getPassesToRun(),
/*AutoDebugCrashes*/true);
- std::cout << "done.\n";
+ outs() << "done.\n";
delete Test;
- std::cout << " Checking to see if the merged program executes correctly: ";
+ outs() << " Checking to see if the merged program executes correctly: ";
bool Broken = TestMergedProgram(BD, Optimized, Safe, true);
- std::cout << (Broken ? " nope.\n" : " yup.\n");
+ outs() << (Broken ? " nope.\n" : " yup.\n");
return Broken;
}
@@ -601,33 +616,33 @@ bool BugDriver::debugMiscompilation() {
// Make sure something was miscompiled...
if (!BugpointIsInterrupted)
if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun)) {
- std::cerr << "*** Optimized program matches reference output! No problem"
- << " detected...\nbugpoint can't help you with your problem!\n";
+ errs() << "*** Optimized program matches reference output! No problem"
+ << " detected...\nbugpoint can't help you with your problem!\n";
return false;
}
- std::cout << "\n*** Found miscompiling pass"
- << (getPassesToRun().size() == 1 ? "" : "es") << ": "
- << getPassesString(getPassesToRun()) << '\n';
+ outs() << "\n*** Found miscompiling pass"
+ << (getPassesToRun().size() == 1 ? "" : "es") << ": "
+ << getPassesString(getPassesToRun()) << '\n';
EmitProgressBitcode("passinput");
std::vector<Function*> MiscompiledFunctions =
DebugAMiscompilation(*this, TestOptimizer);
// Output a bunch of bitcode files for the user...
- std::cout << "Outputting reduced bitcode files which expose the problem:\n";
+ outs() << "Outputting reduced bitcode files which expose the problem:\n";
DenseMap<const Value*, Value*> ValueMap;
Module *ToNotOptimize = CloneModule(getProgram(), ValueMap);
Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
MiscompiledFunctions,
ValueMap);
- std::cout << " Non-optimized portion: ";
+ outs() << " Non-optimized portion: ";
ToNotOptimize = swapProgramIn(ToNotOptimize);
EmitProgressBitcode("tonotoptimize", true);
setNewProgram(ToNotOptimize); // Delete hacked module.
- std::cout << " Portion that is input to optimizer: ";
+ outs() << " Portion that is input to optimizer: ";
ToOptimize = swapProgramIn(ToOptimize);
EmitProgressBitcode("tooptimize");
setNewProgram(ToOptimize); // Delete hacked module.
@@ -672,12 +687,12 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
}
// Call the old main function and return its result
- BasicBlock *BB = BasicBlock::Create("entry", newMain);
+ BasicBlock *BB = BasicBlock::Create(Safe->getContext(), "entry", newMain);
CallInst *call = CallInst::Create(oldMainProto, args.begin(), args.end(),
"", BB);
// If the type of old function wasn't void, return value of call
- ReturnInst::Create(call, BB);
+ ReturnInst::Create(Safe->getContext(), call, BB);
}
// The second nasty issue we must deal with in the JIT is that the Safe
@@ -689,8 +704,9 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
// Prototype: void *getPointerToNamedFunction(const char* Name)
Constant *resolverFunc =
Safe->getOrInsertFunction("getPointerToNamedFunction",
- PointerType::getUnqual(Type::Int8Ty),
- PointerType::getUnqual(Type::Int8Ty), (Type *)0);
+ Type::getInt8PtrTy(Safe->getContext()),
+ Type::getInt8PtrTy(Safe->getContext()),
+ (Type *)0);
// Use the function we just added to get addresses of functions we need.
for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) {
@@ -701,18 +717,20 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
// Don't forward functions which are external in the test module too.
if (TestFn && !TestFn->isDeclaration()) {
// 1. Add a string constant with its name to the global file
- Constant *InitArray = ConstantArray::get(F->getName());
+ Constant *InitArray = ConstantArray::get(F->getContext(), F->getName());
GlobalVariable *funcName =
- new GlobalVariable(InitArray->getType(), true /*isConstant*/,
+ new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/,
GlobalValue::InternalLinkage, InitArray,
- F->getName() + "_name", Safe);
+ F->getName() + "_name");
// 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an
// sbyte* so it matches the signature of the resolver function.
// GetElementPtr *funcName, ulong 0, ulong 0
- std::vector<Constant*> GEPargs(2,Constant::getNullValue(Type::Int32Ty));
- Value *GEP = ConstantExpr::getGetElementPtr(funcName, &GEPargs[0], 2);
+ std::vector<Constant*> GEPargs(2,
+ Constant::getNullValue(Type::getInt32Ty(F->getContext())));
+ Value *GEP =
+ ConstantExpr::getGetElementPtr(funcName, &GEPargs[0], 2);
std::vector<Value*> ResolverArgs;
ResolverArgs.push_back(GEP);
@@ -722,8 +740,9 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
// Create a new global to hold the cached function pointer.
Constant *NullPtr = ConstantPointerNull::get(F->getType());
GlobalVariable *Cache =
- new GlobalVariable(F->getType(), false,GlobalValue::InternalLinkage,
- NullPtr,F->getName()+".fpcache", F->getParent());
+ new GlobalVariable(*F->getParent(), F->getType(),
+ false, GlobalValue::InternalLinkage,
+ NullPtr,F->getName()+".fpcache");
// Construct a new stub function that will re-route calls to F
const FunctionType *FuncTy = F->getFunctionType();
@@ -731,14 +750,17 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
GlobalValue::InternalLinkage,
F->getName() + "_wrapper",
F->getParent());
- BasicBlock *EntryBB = BasicBlock::Create("entry", FuncWrapper);
- BasicBlock *DoCallBB = BasicBlock::Create("usecache", FuncWrapper);
- BasicBlock *LookupBB = BasicBlock::Create("lookupfp", FuncWrapper);
+ BasicBlock *EntryBB = BasicBlock::Create(F->getContext(),
+ "entry", FuncWrapper);
+ BasicBlock *DoCallBB = BasicBlock::Create(F->getContext(),
+ "usecache", FuncWrapper);
+ BasicBlock *LookupBB = BasicBlock::Create(F->getContext(),
+ "lookupfp", FuncWrapper);
// Check to see if we already looked up the value.
Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB);
- Value *IsNull = new ICmpInst(ICmpInst::ICMP_EQ, CachedVal,
- NullPtr, "isNull", EntryBB);
+ Value *IsNull = new ICmpInst(*EntryBB, ICmpInst::ICMP_EQ, CachedVal,
+ NullPtr, "isNull");
BranchInst::Create(LookupBB, DoCallBB, IsNull, EntryBB);
// Resolve the call to function F via the JIT API:
@@ -770,13 +792,13 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
Args.push_back(i);
// Pass on the arguments to the real function, return its result
- if (F->getReturnType() == Type::VoidTy) {
+ if (F->getReturnType() == Type::getVoidTy(F->getContext())) {
CallInst::Create(FuncPtr, Args.begin(), Args.end(), "", DoCallBB);
- ReturnInst::Create(DoCallBB);
+ ReturnInst::Create(F->getContext(), DoCallBB);
} else {
CallInst *Call = CallInst::Create(FuncPtr, Args.begin(), Args.end(),
"retval", DoCallBB);
- ReturnInst::Create(Call, DoCallBB);
+ ReturnInst::Create(F->getContext(),Call, DoCallBB);
}
// Use the wrapper function instead of the old function
@@ -787,7 +809,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
}
if (verifyModule(*Test) || verifyModule(*Safe)) {
- std::cerr << "Bugpoint has a bug, which corrupted a module!!\n";
+ errs() << "Bugpoint has a bug, which corrupted a module!!\n";
abort();
}
}
@@ -804,12 +826,13 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) {
sys::Path TestModuleBC("bugpoint.test.bc");
std::string ErrMsg;
if (TestModuleBC.makeUnique(true, &ErrMsg)) {
- std::cerr << BD.getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ errs() << BD.getToolName() << "Error making unique filename: "
+ << ErrMsg << "\n";
exit(1);
}
- if (BD.writeProgramToFile(TestModuleBC.toString(), Test)) {
- std::cerr << "Error writing bitcode to `" << TestModuleBC << "'\nExiting.";
+ if (BD.writeProgramToFile(TestModuleBC.str(), Test)) {
+ errs() << "Error writing bitcode to `" << TestModuleBC.str()
+ << "'\nExiting.";
exit(1);
}
delete Test;
@@ -817,26 +840,27 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) {
// Make the shared library
sys::Path SafeModuleBC("bugpoint.safe.bc");
if (SafeModuleBC.makeUnique(true, &ErrMsg)) {
- std::cerr << BD.getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ errs() << BD.getToolName() << "Error making unique filename: "
+ << ErrMsg << "\n";
exit(1);
}
- if (BD.writeProgramToFile(SafeModuleBC.toString(), Safe)) {
- std::cerr << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
+ if (BD.writeProgramToFile(SafeModuleBC.str(), Safe)) {
+ errs() << "Error writing bitcode to `" << SafeModuleBC.str()
+ << "'\nExiting.";
exit(1);
}
- std::string SharedObject = BD.compileSharedObject(SafeModuleBC.toString());
+ std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str());
delete 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.
- int Result = BD.diffProgram(TestModuleBC.toString(), SharedObject, false);
+ int Result = BD.diffProgram(TestModuleBC.str(), SharedObject, false);
if (Result)
- std::cerr << ": still failing!\n";
+ errs() << ": still failing!\n";
else
- std::cerr << ": didn't fail.\n";
+ errs() << ": didn't fail.\n";
TestModuleBC.eraseFromDisk();
SafeModuleBC.eraseFromDisk();
sys::Path(SharedObject).eraseFromDisk();
@@ -850,14 +874,14 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) {
bool BugDriver::debugCodeGenerator() {
if ((void*)SafeInterpreter == (void*)Interpreter) {
std::string Result = executeProgramSafely("bugpoint.safe.out");
- std::cout << "\n*** The \"safe\" i.e. 'known good' backend cannot match "
- << "the reference diff. This may be due to a\n front-end "
- << "bug or a bug in the original program, but this can also "
- << "happen if bugpoint isn't running the program with the "
- << "right flags or input.\n I left the result of executing "
- << "the program with the \"safe\" backend in this file for "
- << "you: '"
- << Result << "'.\n";
+ outs() << "\n*** The \"safe\" i.e. 'known good' backend cannot match "
+ << "the reference diff. This may be due to a\n front-end "
+ << "bug or a bug in the original program, but this can also "
+ << "happen if bugpoint isn't running the program with the "
+ << "right flags or input.\n I left the result of executing "
+ << "the program with the \"safe\" backend in this file for "
+ << "you: '"
+ << Result << "'.\n";
return true;
}
@@ -876,13 +900,14 @@ bool BugDriver::debugCodeGenerator() {
sys::Path TestModuleBC("bugpoint.test.bc");
std::string ErrMsg;
if (TestModuleBC.makeUnique(true, &ErrMsg)) {
- std::cerr << getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ errs() << getToolName() << "Error making unique filename: "
+ << ErrMsg << "\n";
exit(1);
}
- if (writeProgramToFile(TestModuleBC.toString(), ToCodeGen)) {
- std::cerr << "Error writing bitcode to `" << TestModuleBC << "'\nExiting.";
+ if (writeProgramToFile(TestModuleBC.str(), ToCodeGen)) {
+ errs() << "Error writing bitcode to `" << TestModuleBC.str()
+ << "'\nExiting.";
exit(1);
}
delete ToCodeGen;
@@ -890,43 +915,45 @@ bool BugDriver::debugCodeGenerator() {
// Make the shared library
sys::Path SafeModuleBC("bugpoint.safe.bc");
if (SafeModuleBC.makeUnique(true, &ErrMsg)) {
- std::cerr << getToolName() << "Error making unique filename: "
- << ErrMsg << "\n";
+ errs() << getToolName() << "Error making unique filename: "
+ << ErrMsg << "\n";
exit(1);
}
- if (writeProgramToFile(SafeModuleBC.toString(), ToNotCodeGen)) {
- std::cerr << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
+ if (writeProgramToFile(SafeModuleBC.str(), ToNotCodeGen)) {
+ errs() << "Error writing bitcode to `" << SafeModuleBC.str()
+ << "'\nExiting.";
exit(1);
}
- std::string SharedObject = compileSharedObject(SafeModuleBC.toString());
+ std::string SharedObject = compileSharedObject(SafeModuleBC.str());
delete ToNotCodeGen;
- std::cout << "You can reproduce the problem with the command line: \n";
+ outs() << "You can reproduce the problem with the command line: \n";
if (isExecutingJIT()) {
- std::cout << " lli -load " << SharedObject << " " << TestModuleBC;
+ outs() << " lli -load " << SharedObject << " " << TestModuleBC.str();
} else {
- std::cout << " llc -f " << TestModuleBC << " -o " << TestModuleBC<< ".s\n";
- std::cout << " gcc " << SharedObject << " " << TestModuleBC
- << ".s -o " << TestModuleBC << ".exe";
+ outs() << " llc -f " << TestModuleBC.str() << " -o " << TestModuleBC.str()
+ << ".s\n";
+ outs() << " gcc " << SharedObject << " " << TestModuleBC.str()
+ << ".s -o " << TestModuleBC.str() << ".exe";
#if defined (HAVE_LINK_R)
- std::cout << " -Wl,-R.";
+ outs() << " -Wl,-R.";
#endif
- std::cout << "\n";
- std::cout << " " << TestModuleBC << ".exe";
+ outs() << "\n";
+ outs() << " " << TestModuleBC.str() << ".exe";
}
for (unsigned i=0, e = InputArgv.size(); i != e; ++i)
- std::cout << " " << InputArgv[i];
- std::cout << '\n';
- std::cout << "The shared object was created with:\n llc -march=c "
- << SafeModuleBC << " -o temporary.c\n"
- << " gcc -xc temporary.c -O2 -o " << SharedObject
-#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
- << " -G" // Compile a shared library, `-G' for Sparc
-#else
- << " -fPIC -shared" // `-shared' for Linux/X86, maybe others
-#endif
- << " -fno-strict-aliasing\n";
+ outs() << " " << InputArgv[i];
+ outs() << '\n';
+ outs() << "The shared object was created with:\n llc -march=c "
+ << SafeModuleBC.str() << " -o temporary.c\n"
+ << " gcc -xc temporary.c -O2 -o " << SharedObject;
+ if (TargetTriple.getArch() == Triple::sparc)
+ outs() << " -G"; // Compile a shared library, `-G' for Sparc
+ else
+ outs() << " -fPIC -shared"; // `-shared' for Linux/X86, maybe others
+
+ outs() << " -fno-strict-aliasing\n";
return false;
}
diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp
index 741be24..9f712e0 100644
--- a/tools/bugpoint/OptimizerDriver.cpp
+++ b/tools/bugpoint/OptimizerDriver.cpp
@@ -27,10 +27,9 @@
#include "llvm/Target/TargetData.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Streams.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
-#include "llvm/Config/alloca.h"
#define DONT_GET_PLUGIN_LOADER_OPTION
#include "llvm/Support/PluginLoader.h"
@@ -38,6 +37,9 @@
#include <fstream>
using namespace llvm;
+namespace llvm {
+ extern cl::opt<std::string> OutputPrefix;
+}
namespace {
// ChildOutput - This option captures the name of the child output file that
@@ -52,10 +54,10 @@ namespace {
///
bool BugDriver::writeProgramToFile(const std::string &Filename,
Module *M) const {
- std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
- std::ios::binary;
- std::ofstream Out(Filename.c_str(), io_mode);
- if (!Out.good()) return true;
+ 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;
@@ -69,26 +71,26 @@ void BugDriver::EmitProgressBitcode(const std::string &ID, bool NoFlyer) {
// 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 = "bugpoint-" + ID + ".bc";
+ std::string Filename = OutputPrefix + "-" + ID + ".bc";
if (writeProgramToFile(Filename)) {
- cerr << "Error opening file '" << Filename << "' for writing!\n";
+ errs() << "Error opening file '" << Filename << "' for writing!\n";
return;
}
- cout << "Emitted bitcode to '" << Filename << "'\n";
+ outs() << "Emitted bitcode to '" << Filename << "'\n";
if (NoFlyer || PassesToRun.empty()) return;
- cout << "\n*** You can reproduce the problem with: ";
- cout << "opt " << Filename << " ";
- cout << getPassesString(PassesToRun) << "\n";
+ outs() << "\n*** You can reproduce the problem with: ";
+ if (UseValgrind) outs() << "valgrind ";
+ outs() << "opt " << Filename << " ";
+ outs() << getPassesString(PassesToRun) << "\n";
}
int BugDriver::runPassesAsChild(const std::vector<const PassInfo*> &Passes) {
-
- std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
- std::ios::binary;
- std::ofstream OutFile(ChildOutput.c_str(), io_mode);
- if (!OutFile.good()) {
- cerr << "Error opening bitcode file: " << ChildOutput << "\n";
+ 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;
}
@@ -100,13 +102,13 @@ int BugDriver::runPassesAsChild(const std::vector<const PassInfo*> &Passes) {
if (Passes[i]->getNormalCtor())
PM.add(Passes[i]->getNormalCtor()());
else
- cerr << "Cannot create pass yet: " << Passes[i]->getPassName() << "\n";
+ 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));
+ PM.add(createBitcodeWriterPass(OutFile));
// Run all queued passes.
PM.run(*Program);
@@ -121,58 +123,58 @@ cl::opt<bool> SilencePasses("silence-passes", cl::desc("Suppress output of runni
/// optimizations fail for some reason (optimizer crashes), return true,
/// otherwise return false. If DeleteOutput is set to true, the bitcode is
/// deleted on success, and the filename string is undefined. This prints to
-/// cout a single line message indicating whether compilation was successful or
-/// failed.
+/// outs() a single line message indicating whether compilation was successful
+/// or failed.
///
bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
std::string &OutputFilename, bool DeleteOutput,
bool Quiet, unsigned NumExtraArgs,
const char * const *ExtraArgs) const {
// setup the output file name
- cout << std::flush;
- sys::Path uniqueFilename("bugpoint-output.bc");
+ outs().flush();
+ sys::Path uniqueFilename(OutputPrefix + "-output.bc");
std::string ErrMsg;
if (uniqueFilename.makeUnique(true, &ErrMsg)) {
- cerr << getToolName() << ": Error making unique filename: "
- << ErrMsg << "\n";
+ errs() << getToolName() << ": Error making unique filename: "
+ << ErrMsg << "\n";
return(1);
}
- OutputFilename = uniqueFilename.toString();
+ OutputFilename = uniqueFilename.str();
// set up the input file name
- sys::Path inputFilename("bugpoint-input.bc");
+ sys::Path inputFilename(OutputPrefix + "-input.bc");
if (inputFilename.makeUnique(true, &ErrMsg)) {
- cerr << getToolName() << ": Error making unique filename: "
- << ErrMsg << "\n";
+ errs() << getToolName() << ": Error making unique filename: "
+ << ErrMsg << "\n";
return(1);
}
- std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
- std::ios::binary;
- std::ofstream InFile(inputFilename.c_str(), io_mode);
- if (!InFile.good()) {
- cerr << "Error opening bitcode file: " << inputFilename << "\n";
- return(1);
+
+ std::string ErrInfo;
+ raw_fd_ostream 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();
// setup the child process' arguments
- const char** args = (const char**)
- alloca(sizeof(const char*) *
- (Passes.size()+13+2*PluginLoader::getNumPlugins()+NumExtraArgs));
- int n = 0;
+ SmallVector<const char*, 8> Args;
sys::Path tool = sys::Program::FindProgramByName(ToolName);
if (UseValgrind) {
- args[n++] = "valgrind";
- args[n++] = "--error-exitcode=1";
- args[n++] = "-q";
- args[n++] = tool.c_str();
+ Args.push_back("valgrind");
+ Args.push_back("--error-exitcode=1");
+ Args.push_back("-q");
+ Args.push_back(tool.c_str());
} else
- args[n++] = ToolName.c_str();
+ Args.push_back(ToolName);
- args[n++] = "-as-child";
- args[n++] = "-child-output";
- args[n++] = OutputFilename.c_str();
+ Args.push_back("-as-child");
+ Args.push_back("-child-output");
+ Args.push_back(OutputFilename.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"));
@@ -183,11 +185,11 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
pass_args.push_back( std::string("-") + (*I)->getPassArgument() );
for (std::vector<std::string>::const_iterator I = pass_args.begin(),
E = pass_args.end(); I != E; ++I )
- args[n++] = I->c_str();
- args[n++] = inputFilename.c_str();
+ Args.push_back(I->c_str());
+ Args.push_back(inputFilename.c_str());
for (unsigned i = 0; i < NumExtraArgs; ++i)
- args[n++] = *ExtraArgs;
- args[n++] = 0;
+ Args.push_back(*ExtraArgs);
+ Args.push_back(0);
sys::Path prog;
if (UseValgrind)
@@ -199,7 +201,8 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
sys::Path Nowhere;
const sys::Path *Redirects[3] = {0, &Nowhere, &Nowhere};
- int result = sys::Program::ExecuteAndWait(prog, args, 0, (SilencePasses ? Redirects : 0),
+ int result = sys::Program::ExecuteAndWait(prog, Args.data(), 0,
+ (SilencePasses ? Redirects : 0),
Timeout, MemoryLimit, &ErrMsg);
// If we are supposed to delete the bitcode file or if the passes crashed,
@@ -212,17 +215,17 @@ bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
if (!Quiet) {
if (result == 0)
- cout << "Success!\n";
+ outs() << "Success!\n";
else if (result > 0)
- cout << "Exited with error code '" << result << "'\n";
+ outs() << "Exited with error code '" << result << "'\n";
else if (result < 0) {
if (result == -1)
- cout << "Execute failed: " << ErrMsg << "\n";
+ outs() << "Execute failed: " << ErrMsg << "\n";
else
- cout << "Crashed with signal #" << abs(result) << "\n";
+ outs() << "Crashed with signal #" << abs(result) << "\n";
}
if (result & 0x01000000)
- cout << "Dumped core\n";
+ outs() << "Dumped core\n";
}
// Was the child successful?
@@ -242,8 +245,8 @@ Module *BugDriver::runPassesOn(Module *M,
if (runPasses(Passes, BitcodeResult, false/*delete*/, true/*quiet*/,
NumExtraArgs, ExtraArgs)) {
if (AutoDebugCrashes) {
- cerr << " Error running this sequence of passes"
- << " on the input program!\n";
+ errs() << " Error running this sequence of passes"
+ << " on the input program!\n";
delete OldProgram;
EmitProgressBitcode("pass-error", false);
exit(debugOptimizerCrash());
@@ -257,8 +260,8 @@ Module *BugDriver::runPassesOn(Module *M,
Module *Ret = ParseInputFile(BitcodeResult, Context);
if (Ret == 0) {
- cerr << getToolName() << ": Error reading bitcode file '"
- << BitcodeResult << "'!\n";
+ errs() << getToolName() << ": Error reading bitcode file '"
+ << BitcodeResult << "'!\n";
exit(1);
}
sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk
diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp
index 978e60b..4551d41 100644
--- a/tools/bugpoint/ToolRunner.cpp
+++ b/tools/bugpoint/ToolRunner.cpp
@@ -13,16 +13,22 @@
#define DEBUG_TYPE "toolrunner"
#include "ToolRunner.h"
-#include "llvm/Config/config.h" // for HAVE_LINK_R
#include "llvm/System/Program.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h" // for HAVE_LINK_R
#include <fstream>
#include <sstream>
-#include <iostream>
using namespace llvm;
+namespace llvm {
+ cl::opt<bool>
+ SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files"));
+}
+
namespace {
cl::opt<std::string>
RemoteClient("remote-client",
@@ -33,6 +39,10 @@ namespace {
cl::desc("Remote execution (rsh/ssh) host"));
cl::opt<std::string>
+ RemotePort("remote-port",
+ cl::desc("Remote execution (rsh/ssh) port"));
+
+ cl::opt<std::string>
RemoteUser("remote-user",
cl::desc("Remote execution (rsh/ssh) user id"));
@@ -43,8 +53,8 @@ namespace {
ToolExecutionError::~ToolExecutionError() throw() { }
-/// RunProgramWithTimeout - This function provides an alternate interface to the
-/// sys::Program::ExecuteAndWait interface.
+/// RunProgramWithTimeout - This function provides an alternate interface
+/// to the sys::Program::ExecuteAndWait interface.
/// @see sys:Program::ExecuteAndWait
static int RunProgramWithTimeout(const sys::Path &ProgramPath,
const char **Args,
@@ -57,20 +67,74 @@ static int RunProgramWithTimeout(const sys::Path &ProgramPath,
redirects[0] = &StdInFile;
redirects[1] = &StdOutFile;
redirects[2] = &StdErrFile;
-
- if (0) {
- std::cerr << "RUN:";
+
+#if 0 // For debug purposes
+ {
+ errs() << "RUN:";
for (unsigned i = 0; Args[i]; ++i)
- std::cerr << " " << Args[i];
- std::cerr << "\n";
+ errs() << " " << Args[i];
+ errs() << "\n";
}
+#endif
return
sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects,
NumSeconds, MemoryLimit);
}
+/// RunProgramRemotelyWithTimeout - This function runs the given program
+/// remotely using the given remote client and the sys::Program::ExecuteAndWait.
+/// Returns the remote program exit code or reports a remote client error if it
+/// fails. Remote client is required to return 255 if it failed or program exit
+/// code otherwise.
+/// @see sys:Program::ExecuteAndWait
+static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath,
+ const char **Args,
+ const sys::Path &StdInFile,
+ const sys::Path &StdOutFile,
+ const sys::Path &StdErrFile,
+ unsigned NumSeconds = 0,
+ unsigned MemoryLimit = 0) {
+ const sys::Path* redirects[3];
+ redirects[0] = &StdInFile;
+ redirects[1] = &StdOutFile;
+ redirects[2] = &StdErrFile;
+
+#if 0 // For debug purposes
+ {
+ errs() << "RUN:";
+ for (unsigned i = 0; Args[i]; ++i)
+ errs() << " " << Args[i];
+ errs() << "\n";
+ }
+#endif
+ // Run the program remotely with the remote client
+ int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args,
+ 0, redirects, NumSeconds, MemoryLimit);
+
+ // Has the remote client fail?
+ if (255 == ReturnCode) {
+ std::ostringstream OS;
+ OS << "\nError running remote client:\n ";
+ for (const char **Arg = Args; *Arg; ++Arg)
+ OS << " " << *Arg;
+ OS << "\n";
+
+ // The error message is in the output file, let's print it out from there.
+ std::ifstream ErrorFile(StdOutFile.c_str());
+ if (ErrorFile) {
+ std::copy(std::istreambuf_iterator<char>(ErrorFile),
+ std::istreambuf_iterator<char>(),
+ std::ostreambuf_iterator<char>(OS));
+ ErrorFile.close();
+ }
+
+ throw ToolExecutionError(OS.str());
+ }
+
+ return ReturnCode;
+}
static void ProcessFailure(sys::Path ProgPath, const char** Args) {
std::ostringstream OS;
@@ -83,7 +147,7 @@ static void ProcessFailure(sys::Path ProgPath, const char** Args) {
sys::Path ErrorFilename("bugpoint.program_error_messages");
std::string ErrMsg;
if (ErrorFilename.makeUnique(true, &ErrMsg)) {
- std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+ errs() << "Error making unique filename: " << ErrMsg << "\n";
exit(1);
}
RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename,
@@ -154,11 +218,11 @@ int LLI::ExecuteProgram(const std::string &Bitcode,
LLIArgs.push_back(Args[i].c_str());
LLIArgs.push_back(0);
- std::cout << "<lli>" << std::flush;
- DEBUG(std::cerr << "\nAbout to run:\t";
+ outs() << "<lli>"; outs().flush();
+ DEBUG(errs() << "\nAbout to run:\t";
for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i)
- std::cerr << " " << LLIArgs[i];
- std::cerr << "\n";
+ errs() << " " << LLIArgs[i];
+ errs() << "\n";
);
return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0],
sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
@@ -166,10 +230,11 @@ int LLI::ExecuteProgram(const std::string &Bitcode,
}
// LLI create method - Try to find the LLI executable
-AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath,
+AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0,
std::string &Message,
const std::vector<std::string> *ToolArgs) {
- std::string LLIPath = FindExecutable("lli", ProgPath).toString();
+ std::string LLIPath =
+ FindExecutable("lli", Argv0, (void *)(intptr_t)&createLLI).str();
if (!LLIPath.empty()) {
Message = "Found lli: " + LLIPath + "\n";
return new LLI(LLIPath, ToolArgs);
@@ -236,7 +301,6 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode,
// Custom execution environment create method, takes the execution command
// as arguments
AbstractInterpreter *AbstractInterpreter::createCustom(
- const std::string &ProgramPath,
std::string &Message,
const std::string &ExecCommandLine) {
@@ -270,7 +334,7 @@ AbstractInterpreter *AbstractInterpreter::createCustom(
pos = ExecCommandLine.find_first_of(delimiters, lastPos);
}
- std::string CmdPath = FindExecutable(Command, ProgramPath).toString();
+ std::string CmdPath = sys::Program::FindProgramByName(Command).str();
if (CmdPath.empty()) {
Message =
std::string("Cannot find '") + Command +
@@ -291,7 +355,7 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode,
sys::Path uniqueFile(Bitcode+".llc.s");
std::string ErrMsg;
if (uniqueFile.makeUnique(true, &ErrMsg)) {
- std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+ errs() << "Error making unique filename: " << ErrMsg << "\n";
exit(1);
}
OutputAsmFile = uniqueFile;
@@ -304,15 +368,14 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode,
LLCArgs.push_back ("-o");
LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file
- LLCArgs.push_back ("-f"); // Overwrite as necessary...
LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode
LLCArgs.push_back (0);
- std::cout << "<llc>" << std::flush;
- DEBUG(std::cerr << "\nAbout to run:\t";
+ outs() << "<llc>"; outs().flush();
+ DEBUG(errs() << "\nAbout to run:\t";
for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
- std::cerr << " " << LLCArgs[i];
- std::cerr << "\n";
+ errs() << " " << LLCArgs[i];
+ errs() << "\n";
);
if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0],
sys::Path(), sys::Path(), sys::Path()))
@@ -338,34 +401,35 @@ int LLC::ExecuteProgram(const std::string &Bitcode,
sys::Path OutputAsmFile;
OutputCode(Bitcode, OutputAsmFile);
- FileRemover OutFileRemover(OutputAsmFile);
+ FileRemover OutFileRemover(OutputAsmFile, !SaveTemps);
std::vector<std::string> GCCArgs(ArgsForGCC);
GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end());
GCCArgs.insert(GCCArgs.end(), gccArgs.begin(), gccArgs.end());
// Assuming LLC worked, compile the result with GCC and run it.
- return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile,
+ return gcc->ExecuteProgram(OutputAsmFile.str(), Args, GCC::AsmFile,
InputFile, OutputFile, GCCArgs,
Timeout, MemoryLimit);
}
/// createLLC - Try to find the LLC executable
///
-LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath,
+LLC *AbstractInterpreter::createLLC(const char *Argv0,
std::string &Message,
const std::vector<std::string> *Args,
const std::vector<std::string> *GCCArgs) {
- std::string LLCPath = FindExecutable("llc", ProgramPath).toString();
+ std::string LLCPath =
+ FindExecutable("llc", Argv0, (void *)(intptr_t)&createLLC).str();
if (LLCPath.empty()) {
Message = "Cannot find `llc' in executable directory or PATH!\n";
return 0;
}
Message = "Found llc: " + LLCPath + "\n";
- GCC *gcc = GCC::create(ProgramPath, Message, GCCArgs);
+ GCC *gcc = GCC::create(Message, GCCArgs);
if (!gcc) {
- std::cerr << Message << "\n";
+ errs() << Message << "\n";
exit(1);
}
return new LLC(LLCPath, gcc, Args, GCCArgs);
@@ -425,13 +489,13 @@ int JIT::ExecuteProgram(const std::string &Bitcode,
JITArgs.push_back(Args[i].c_str());
JITArgs.push_back(0);
- std::cout << "<jit>" << std::flush;
- DEBUG(std::cerr << "\nAbout to run:\t";
+ outs() << "<jit>"; outs().flush();
+ DEBUG(errs() << "\nAbout to run:\t";
for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i)
- std::cerr << " " << JITArgs[i];
- std::cerr << "\n";
+ errs() << " " << JITArgs[i];
+ errs() << "\n";
);
- DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n");
+ DEBUG(errs() << "\nSending output to " << OutputFile << "\n");
return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0],
sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
Timeout, MemoryLimit);
@@ -439,9 +503,10 @@ int JIT::ExecuteProgram(const std::string &Bitcode,
/// createJIT - Try to find the LLI executable
///
-AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath,
+AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0,
std::string &Message, const std::vector<std::string> *Args) {
- std::string LLIPath = FindExecutable("lli", ProgPath).toString();
+ std::string LLIPath =
+ FindExecutable("lli", Argv0, (void *)(intptr_t)&createJIT).str();
if (!LLIPath.empty()) {
Message = "Found lli: " + LLIPath + "\n";
return new JIT(LLIPath, Args);
@@ -456,7 +521,7 @@ GCC::FileType CBE::OutputCode(const std::string &Bitcode,
sys::Path uniqueFile(Bitcode+".cbe.c");
std::string ErrMsg;
if (uniqueFile.makeUnique(true, &ErrMsg)) {
- std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+ errs() << "Error making unique filename: " << ErrMsg << "\n";
exit(1);
}
OutputCFile = uniqueFile;
@@ -474,11 +539,11 @@ GCC::FileType CBE::OutputCode(const std::string &Bitcode,
LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode
LLCArgs.push_back (0);
- std::cout << "<cbe>" << std::flush;
- DEBUG(std::cerr << "\nAbout to run:\t";
+ outs() << "<cbe>"; outs().flush();
+ DEBUG(errs() << "\nAbout to run:\t";
for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
- std::cerr << " " << LLCArgs[i];
- std::cerr << "\n";
+ errs() << " " << LLCArgs[i];
+ errs() << "\n";
);
if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(),
sys::Path()))
@@ -503,33 +568,34 @@ int CBE::ExecuteProgram(const std::string &Bitcode,
sys::Path OutputCFile;
OutputCode(Bitcode, OutputCFile);
- FileRemover CFileRemove(OutputCFile);
+ FileRemover CFileRemove(OutputCFile, !SaveTemps);
std::vector<std::string> GCCArgs(ArgsForGCC);
GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end());
- return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile,
+ return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile,
InputFile, OutputFile, GCCArgs,
Timeout, MemoryLimit);
}
/// createCBE - Try to find the 'llc' executable
///
-CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath,
+CBE *AbstractInterpreter::createCBE(const char *Argv0,
std::string &Message,
const std::vector<std::string> *Args,
const std::vector<std::string> *GCCArgs) {
- sys::Path LLCPath = FindExecutable("llc", ProgramPath);
+ sys::Path LLCPath =
+ FindExecutable("llc", Argv0, (void *)(intptr_t)&createCBE);
if (LLCPath.isEmpty()) {
Message =
"Cannot find `llc' in executable directory or PATH!\n";
return 0;
}
- Message = "Found llc: " + LLCPath.toString() + "\n";
- GCC *gcc = GCC::create(ProgramPath, Message, GCCArgs);
+ Message = "Found llc: " + LLCPath.str() + "\n";
+ GCC *gcc = GCC::create(Message, GCCArgs);
if (!gcc) {
- std::cerr << Message << "\n";
+ errs() << Message << "\n";
exit(1);
}
return new CBE(LLCPath, gcc, Args);
@@ -538,6 +604,23 @@ CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath,
//===---------------------------------------------------------------------===//
// GCC abstraction
//
+
+static bool
+IsARMArchitecture(std::vector<std::string> Args)
+{
+ for (std::vector<std::string>::const_iterator
+ I = Args.begin(), E = Args.end(); I != E; ++I) {
+ if (!StringsEqualNoCase(*I, "-arch")) {
+ ++I;
+ if ((I != E) && !StringsEqualNoCase(I->c_str(), "arm", strlen("arm"))) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
int GCC::ExecuteProgram(const std::string &ProgramFile,
const std::vector<std::string> &Args,
FileType fileType,
@@ -561,9 +644,13 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
GCCArgs.push_back("-fno-strict-aliasing");
} else {
GCCArgs.push_back("assembler");
-#ifdef __APPLE__
- GCCArgs.push_back("-force_cpusubtype_ALL");
-#endif
+
+ // For ARM architectures we don't want this flag. bugpoint isn't
+ // explicitly told what architecture it is working on, so we get
+ // it from gcc flags
+ if ((TargetTriple.getOS() == Triple::Darwin) &&
+ !IsARMArchitecture(ArgsForGCC))
+ GCCArgs.push_back("-force_cpusubtype_ALL");
}
GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename...
GCCArgs.push_back("-x");
@@ -572,7 +659,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
sys::Path OutputBinary (ProgramFile+".gcc.exe");
std::string ErrMsg;
if (OutputBinary.makeUnique(true, &ErrMsg)) {
- std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+ errs() << "Error making unique filename: " << ErrMsg << "\n";
exit(1);
}
GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
@@ -589,16 +676,15 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
#if defined (HAVE_LINK_R)
GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files
#endif
-#ifdef __sparc__
- GCCArgs.push_back("-mcpu=v9");
-#endif
+ if (TargetTriple.getArch() == Triple::sparc)
+ GCCArgs.push_back("-mcpu=v9");
GCCArgs.push_back(0); // NULL terminator
- std::cout << "<gcc>" << std::flush;
- DEBUG(std::cerr << "\nAbout to run:\t";
+ outs() << "<gcc>"; outs().flush();
+ DEBUG(errs() << "\nAbout to run:\t";
for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
- std::cerr << " " << GCCArgs[i];
- std::cerr << "\n";
+ errs() << " " << GCCArgs[i];
+ errs() << "\n";
);
if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
sys::Path())) {
@@ -613,12 +699,20 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
else {
ProgramArgs.push_back(RemoteClientPath.c_str());
ProgramArgs.push_back(RemoteHost.c_str());
- ProgramArgs.push_back("-l");
- ProgramArgs.push_back(RemoteUser.c_str());
+ if (!RemoteUser.empty()) {
+ ProgramArgs.push_back("-l");
+ ProgramArgs.push_back(RemoteUser.c_str());
+ }
+ if (!RemotePort.empty()) {
+ ProgramArgs.push_back("-p");
+ ProgramArgs.push_back(RemotePort.c_str());
+ }
if (!RemoteExtra.empty()) {
ProgramArgs.push_back(RemoteExtra.c_str());
}
+ // 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 += env_pwd;
@@ -633,23 +727,26 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
ProgramArgs.push_back(0); // NULL terminator
// Now that we have a binary, run it!
- std::cout << "<program>" << std::flush;
- DEBUG(std::cerr << "\nAbout to run:\t";
+ outs() << "<program>"; outs().flush();
+ DEBUG(errs() << "\nAbout to run:\t";
for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i)
- std::cerr << " " << ProgramArgs[i];
- std::cerr << "\n";
+ errs() << " " << ProgramArgs[i];
+ errs() << "\n";
);
- FileRemover OutputBinaryRemover(OutputBinary);
+ FileRemover OutputBinaryRemover(OutputBinary, !SaveTemps);
- if (RemoteClientPath.isEmpty())
+ if (RemoteClientPath.isEmpty()) {
+ DEBUG(errs() << "<run locally>";);
return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
Timeout, MemoryLimit);
- else
- return RunProgramWithTimeout(sys::Path(RemoteClientPath), &ProgramArgs[0],
- sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
- Timeout, MemoryLimit);
+ } else {
+ outs() << "<run remotely>"; outs().flush();
+ return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath),
+ &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile),
+ sys::Path(OutputFile), Timeout, MemoryLimit);
+ }
}
int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
@@ -658,10 +755,10 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT);
std::string ErrMsg;
if (uniqueFilename.makeUnique(true, &ErrMsg)) {
- std::cerr << "Error making unique filename: " << ErrMsg << "\n";
+ errs() << "Error making unique filename: " << ErrMsg << "\n";
exit(1);
}
- OutputFile = uniqueFilename.toString();
+ OutputFile = uniqueFilename.str();
std::vector<const char*> GCCArgs;
@@ -678,27 +775,27 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
GCCArgs.push_back(InputFile.c_str()); // Specify the input filename.
GCCArgs.push_back("-x");
GCCArgs.push_back("none");
-#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
- GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc
-#elif defined(__APPLE__)
- // link all source files into a single module in data segment, rather than
- // generating blocks. dynamic_lookup requires that you set
- // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for
- // bugpoint to just pass that in the environment of GCC.
- GCCArgs.push_back("-single_module");
- GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC
- GCCArgs.push_back("-undefined");
- GCCArgs.push_back("dynamic_lookup");
-#else
- GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others
-#endif
+ if (TargetTriple.getArch() == Triple::sparc)
+ GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc
+ else if (TargetTriple.getOS() == Triple::Darwin) {
+ // link all source files into a single module in data segment, rather than
+ // generating blocks. dynamic_lookup requires that you set
+ // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for
+ // bugpoint to just pass that in the environment of GCC.
+ GCCArgs.push_back("-single_module");
+ GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC
+ GCCArgs.push_back("-undefined");
+ GCCArgs.push_back("dynamic_lookup");
+ } else
+ GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others
+
+ if ((TargetTriple.getArch() == Triple::alpha) ||
+ (TargetTriple.getArch() == Triple::x86_64))
+ GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC
+
+ if (TargetTriple.getArch() == Triple::sparc)
+ GCCArgs.push_back("-mcpu=v9");
-#if defined(__ia64__) || defined(__alpha__) || defined(__amd64__)
- GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC
-#endif
-#ifdef __sparc__
- GCCArgs.push_back("-mcpu=v9");
-#endif
GCCArgs.push_back("-o");
GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename.
GCCArgs.push_back("-O2"); // Optimize the program a bit.
@@ -715,11 +812,11 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
- std::cout << "<gcc>" << std::flush;
- DEBUG(std::cerr << "\nAbout to run:\t";
+ outs() << "<gcc>"; outs().flush();
+ DEBUG(errs() << "\nAbout to run:\t";
for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
- std::cerr << " " << GCCArgs[i];
- std::cerr << "\n";
+ errs() << " " << GCCArgs[i];
+ errs() << "\n";
);
if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
sys::Path())) {
@@ -731,9 +828,9 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
/// create - Try to find the `gcc' executable
///
-GCC *GCC::create(const std::string &ProgramPath, std::string &Message,
+GCC *GCC::create(std::string &Message,
const std::vector<std::string> *Args) {
- sys::Path GCCPath = FindExecutable("gcc", ProgramPath);
+ sys::Path GCCPath = sys::Program::FindProgramByName("gcc");
if (GCCPath.isEmpty()) {
Message = "Cannot find `gcc' in executable directory or PATH!\n";
return 0;
@@ -741,8 +838,8 @@ GCC *GCC::create(const std::string &ProgramPath, std::string &Message,
sys::Path RemoteClientPath;
if (!RemoteClient.empty())
- RemoteClientPath = FindExecutable(RemoteClient.c_str(), ProgramPath);
+ RemoteClientPath = sys::Program::FindProgramByName(RemoteClient);
- Message = "Found gcc: " + GCCPath.toString() + "\n";
+ Message = "Found gcc: " + GCCPath.str() + "\n";
return new GCC(GCCPath, RemoteClientPath, Args);
}
diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h
index 721f66c..39b0bbf 100644
--- a/tools/bugpoint/ToolRunner.h
+++ b/tools/bugpoint/ToolRunner.h
@@ -17,12 +17,18 @@
#ifndef BUGPOINT_TOOLRUNNER_H
#define BUGPOINT_TOOLRUNNER_H
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/SystemUtils.h"
+#include "llvm/System/Path.h"
#include <exception>
#include <vector>
namespace llvm {
+extern cl::opt<bool> SaveTemps;
+extern Triple TargetTriple;
+
class CBE;
class LLC;
@@ -54,7 +60,7 @@ class GCC {
public:
enum FileType { AsmFile, CFile };
- static GCC *create(const std::string &ProgramPath, std::string &Message,
+ static GCC *create(std::string &Message,
const std::vector<std::string> *Args);
/// ExecuteProgram - Execute the program specified by "ProgramFile" (which is
@@ -90,23 +96,20 @@ public:
///
class AbstractInterpreter {
public:
- static CBE *createCBE(const std::string &ProgramPath, std::string &Message,
+ static CBE *createCBE(const char *Argv0, std::string &Message,
const std::vector<std::string> *Args = 0,
const std::vector<std::string> *GCCArgs = 0);
- static LLC *createLLC(const std::string &ProgramPath, std::string &Message,
+ static LLC *createLLC(const char *Argv0, std::string &Message,
const std::vector<std::string> *Args = 0,
const std::vector<std::string> *GCCArgs = 0);
- static AbstractInterpreter* createLLI(const std::string &ProgramPath,
- std::string &Message,
+ static AbstractInterpreter* createLLI(const char *Argv0, std::string &Message,
const std::vector<std::string> *Args=0);
- static AbstractInterpreter* createJIT(const std::string &ProgramPath,
- std::string &Message,
+ static AbstractInterpreter* createJIT(const char *Argv0, std::string &Message,
const std::vector<std::string> *Args=0);
- static AbstractInterpreter* createCustom(const std::string &ProgramPath,
- std::string &Message,
+ static AbstractInterpreter* createCustom(std::string &Message,
const std::string &ExecCommandLine);
diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp
index 3365b22..565f3f9 100644
--- a/tools/bugpoint/bugpoint.cpp
+++ b/tools/bugpoint/bugpoint.cpp
@@ -22,10 +22,10 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/StandardPasses.h"
#include "llvm/System/Process.h"
#include "llvm/System/Signals.h"
#include "llvm/LinkAllVMCore.h"
-#include <iostream>
using namespace llvm;
// AsChild - Specifies that this invocation of bugpoint is being generated
@@ -58,6 +58,17 @@ MemoryLimit("mlimit", cl::init(100), cl::value_desc("MBytes"),
static cl::list<const PassInfo*, bool, PassNameParser>
PassList(cl::desc("Passes available:"), cl::ZeroOrMore);
+static cl::opt<bool>
+StandardCompileOpts("std-compile-opts",
+ cl::desc("Include the standard compile time optimizations"));
+
+static cl::opt<bool>
+StandardLinkOpts("std-link-opts",
+ cl::desc("Include the standard link time optimizations"));
+
+static cl::opt<std::string>
+OverrideTriple("mtriple", cl::desc("Override target triple for module"));
+
/// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
bool llvm::BugpointIsInterrupted = false;
@@ -65,6 +76,20 @@ static void BugpointInterruptFunction() {
BugpointIsInterrupted = true;
}
+// Hack to capture a pass list.
+namespace {
+ class AddToDriver : public PassManager {
+ BugDriver &D;
+ public:
+ AddToDriver(BugDriver &_D) : D(_D) {}
+
+ virtual void add(Pass *P) {
+ const PassInfo *PI = P->getPassInfo();
+ D.addPasses(&PI, &PI + 1);
+ }
+ };
+}
+
int main(int argc, char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal();
llvm::PrettyStackTraceProgram X(argc, argv);
@@ -75,9 +100,33 @@ int main(int argc, char **argv) {
" for more information.\n");
sys::SetInterruptFunction(BugpointInterruptFunction);
- LLVMContext Context;
+ LLVMContext& Context = getGlobalContext();
+ // 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";
+ }
+
BugDriver D(argv[0], AsChild, FindBugs, TimeoutValue, MemoryLimit, Context);
if (D.addSources(InputFilenames)) return 1;
+
+ AddToDriver PM(D);
+ if (StandardCompileOpts) {
+ createStandardModulePasses(&PM, 3,
+ /*OptimizeSize=*/ false,
+ /*UnitAtATime=*/ true,
+ /*UnrollLoops=*/ true,
+ /*SimplifyLibCalls=*/ true,
+ /*HaveExceptions=*/ true,
+ createFunctionInliningPass());
+ }
+
+ if (StandardLinkOpts)
+ createStandardLTOPasses(&PM, /*Internalize=*/true,
+ /*RunInliner=*/true,
+ /*VerifyEach=*/false);
+
D.addPasses(PassList.begin(), PassList.end());
// Bugpoint has the ability of generating a plethora of core files, so to
@@ -87,20 +136,20 @@ int main(int argc, char **argv) {
try {
return D.run();
} catch (ToolExecutionError &TEE) {
- std::cerr << "Tool execution error: " << TEE.what() << '\n';
+ errs() << "Tool execution error: " << TEE.what() << '\n';
} catch (const std::string& msg) {
- std::cerr << argv[0] << ": " << msg << "\n";
- } catch (const std::bad_alloc &e) {
- std::cerr << "Oh no, a bugpoint process ran out of memory!\n"
- "To increase the allocation limits for bugpoint child\n"
- "processes, use the -mlimit option.\n";
+ errs() << argv[0] << ": " << msg << "\n";
+ } catch (const std::bad_alloc&) {
+ errs() << "Oh no, a bugpoint process ran out of memory!\n"
+ "To increase the allocation limits for bugpoint child\n"
+ "processes, use the -mlimit option.\n";
} catch (const std::exception &e) {
- std::cerr << "Whoops, a std::exception leaked out of bugpoint: "
- << e.what() << "\n"
- << "This is a bug in bugpoint!\n";
+ errs() << "Whoops, a std::exception leaked out of bugpoint: "
+ << e.what() << "\n"
+ << "This is a bug in bugpoint!\n";
} catch (...) {
- std::cerr << "Whoops, an exception leaked out of bugpoint. "
- << "This is a bug in bugpoint!\n";
+ errs() << "Whoops, an exception leaked out of bugpoint. "
+ << "This is a bug in bugpoint!\n";
}
return 1;
}
diff --git a/tools/gold/Makefile b/tools/gold/Makefile
index 65e99bf..7bac4ec 100644
--- a/tools/gold/Makefile
+++ b/tools/gold/Makefile
@@ -8,7 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../..
-LIBRARYNAME = LLVMgold
+LIBRARYNAME = libLLVMgold
# Include this here so we can get the configuration of the targets
# that have been configured for construction. We have to do this
@@ -18,8 +18,9 @@ include $(LEVEL)/Makefile.config
LINK_LIBS_IN_SHARED=1
SHARED_LIBRARY = 1
BUILD_ARCHIVE = 0
+LOADABLE_MODULE = 1
-LINK_COMPONENTS :=
+LINK_COMPONENTS := support system
LIBS += -llto
# Because off_t is used in the public API, the largefile parts are required for
diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp
index 146c53f..6520617 100644
--- a/tools/gold/gold-plugin.cpp
+++ b/tools/gold/gold-plugin.cpp
@@ -362,8 +362,9 @@ ld_plugin_status all_symbols_read_hook(void) {
(*message)(LDPL_ERROR, "%s", ErrMsg.c_str());
return LDPS_ERR;
}
- raw_fd_ostream *objFile = new raw_fd_ostream(uniqueObjPath.c_str(), true,
- ErrMsg);
+ raw_fd_ostream *objFile =
+ new raw_fd_ostream(uniqueObjPath.c_str(), ErrMsg,
+ raw_fd_ostream::F_Binary);
if (!ErrMsg.empty()) {
delete objFile;
(*message)(LDPL_ERROR, "%s", ErrMsg.c_str());
diff --git a/tools/llc/CMakeLists.txt b/tools/llc/CMakeLists.txt
index e98b5a2..683f298 100644
--- a/tools/llc/CMakeLists.txt
+++ b/tools/llc/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader)
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader asmparser)
add_llvm_tool(llc
llc.cpp
diff --git a/tools/llc/Makefile b/tools/llc/Makefile
index 8514040..7319aad 100644
--- a/tools/llc/Makefile
+++ b/tools/llc/Makefile
@@ -15,7 +15,7 @@ TOOLNAME = llc
# early so we can set up LINK_COMPONENTS before including Makefile.rules
include $(LEVEL)/Makefile.config
-LINK_COMPONENTS := $(TARGETS_TO_BUILD) bitreader
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) bitreader asmparser
include $(LLVM_SRC_ROOT)/Makefile.rules
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
index ae03c1e..b94e5fb 100644
--- a/tools/llc/llc.cpp
+++ b/tools/llc/llc.cpp
@@ -13,35 +13,35 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/CodeGen/FileWriters.h"
-#include "llvm/CodeGen/LinkAllCodegenComponents.h"
-#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
-#include "llvm/Target/SubtargetFeature.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetMachineRegistry.h"
-#include "llvm/Transforms/Scalar.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#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/FileWriters.h"
+#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
+#include "llvm/CodeGen/LinkAllCodegenComponents.h"
+#include "llvm/CodeGen/ObjectCodeEmitter.h"
+#include "llvm/Config/config.h"
+#include "llvm/LinkAllVMCore.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"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/RegistryParser.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Analysis/Verifier.h"
+#include "llvm/System/Host.h"
#include "llvm/System/Signals.h"
-#include "llvm/Config/config.h"
-#include "llvm/LinkAllVMCore.h"
+#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetSelect.h"
-#include <fstream>
-#include <iostream>
+#include "llvm/Transforms/Scalar.h"
#include <memory>
using namespace llvm;
@@ -55,7 +55,8 @@ InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
-static cl::opt<bool> Force("f", cl::desc("Overwrite output files"));
+static cl::opt<bool>
+Force("f", cl::desc("Enable binary output on terminals"));
// Determine optimization level.
static cl::opt<char>
@@ -69,9 +70,8 @@ OptLevel("O",
static cl::opt<std::string>
TargetTriple("mtriple", cl::desc("Override target triple for module"));
-static cl::opt<const TargetMachineRegistry::entry*, false,
- RegistryParser<TargetMachine> >
-MArch("march", cl::desc("Architecture to generate code for:"));
+static cl::opt<std::string>
+MArch("march", cl::desc("Architecture to generate code for (see --version)"));
static cl::opt<std::string>
MCPU("mcpu",
@@ -119,7 +119,9 @@ GetFileNameRoot(const std::string &InputFilename) {
std::string outputFilename;
int Len = IFN.length();
if ((Len > 2) &&
- IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') {
+ IFN[Len-3] == '.' &&
+ ((IFN[Len-2] == 'b' && IFN[Len-1] == 'c') ||
+ (IFN[Len-2] == 'l' && IFN[Len-1] == 'l'))) {
outputFilename = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/
} else {
outputFilename = IFN;
@@ -127,37 +129,34 @@ GetFileNameRoot(const std::string &InputFilename) {
return outputFilename;
}
-static raw_ostream *GetOutputStream(const char *ProgName) {
+static formatted_raw_ostream *GetOutputStream(const char *TargetName,
+ const char *ProgName) {
if (OutputFilename != "") {
if (OutputFilename == "-")
- return &outs();
-
- // Specified an output filename?
- if (!Force && std::ifstream(OutputFilename.c_str())) {
- // If force is not specified, make sure not to overwrite a file!
- std::cerr << ProgName << ": error opening '" << OutputFilename
- << "': file exists!\n"
- << "Use -f command line argument to force output\n";
- return 0;
- }
+ return &fouts();
+
// 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_ostream *Out = new raw_fd_ostream(OutputFilename.c_str(), true, error);
+ raw_fd_ostream *FDOut =
+ new raw_fd_ostream(OutputFilename.c_str(), error,
+ raw_fd_ostream::F_Binary);
if (!error.empty()) {
- std::cerr << error << '\n';
- delete Out;
+ errs() << error << '\n';
+ delete FDOut;
return 0;
}
+ formatted_raw_ostream *Out =
+ new formatted_raw_ostream(*FDOut, formatted_raw_ostream::DELETE_STREAM);
return Out;
}
if (InputFilename == "-") {
OutputFilename = "-";
- return &outs();
+ return &fouts();
}
OutputFilename = GetFileNameRoot(InputFilename);
@@ -165,10 +164,10 @@ static raw_ostream *GetOutputStream(const char *ProgName) {
bool Binary = false;
switch (FileType) {
case TargetMachine::AssemblyFile:
- if (MArch->Name[0] == 'c') {
- if (MArch->Name[1] == 0)
+ if (TargetName[0] == 'c') {
+ if (TargetName[1] == 0)
OutputFilename += ".cbe.c";
- else if (MArch->Name[1] == 'p' && MArch->Name[2] == 'p')
+ else if (TargetName[1] == 'p' && TargetName[2] == 'p')
OutputFilename += ".cpp";
else
OutputFilename += ".s";
@@ -185,26 +184,24 @@ static raw_ostream *GetOutputStream(const char *ProgName) {
break;
}
- if (!Force && std::ifstream(OutputFilename.c_str())) {
- // If force is not specified, make sure not to overwrite a file!
- std::cerr << ProgName << ": error opening '" << OutputFilename
- << "': file exists!\n"
- << "Use -f command line argument to force output\n";
- return 0;
- }
-
// 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_ostream *Out = new raw_fd_ostream(OutputFilename.c_str(), Binary, 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);
if (!error.empty()) {
- std::cerr << error << '\n';
- delete Out;
+ errs() << error << '\n';
+ delete FDOut;
return 0;
}
+ formatted_raw_ostream *Out =
+ new formatted_raw_ostream(*FDOut, formatted_raw_ostream::DELETE_STREAM);
+
return Out;
}
@@ -213,24 +210,22 @@ static raw_ostream *GetOutputStream(const char *ProgName) {
int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
- cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
+ // Initialize targets first, so that --version shows registered targets.
InitializeAllTargets();
InitializeAllAsmPrinters();
+
+ cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
// Load the module to be compiled...
- std::string ErrorMessage;
+ SMDiagnostic Err;
std::auto_ptr<Module> M;
- std::auto_ptr<MemoryBuffer> Buffer(
- MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage));
- if (Buffer.get())
- M.reset(ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage));
+ M.reset(ParseIRFile(InputFilename, Err, Context));
if (M.get() == 0) {
- std::cerr << argv[0] << ": bitcode didn't read correctly.\n";
- std::cerr << "Reason: " << ErrorMessage << "\n";
+ Err.Print(argv[0], errs());
return 1;
}
Module &mod = *M.get();
@@ -239,15 +234,40 @@ int main(int argc, char **argv) {
if (!TargetTriple.empty())
mod.setTargetTriple(TargetTriple);
- // Allocate target machine. First, check whether the user has
- // explicitly specified an architecture to compile for.
- if (MArch == 0) {
+ Triple TheTriple(mod.getTargetTriple());
+ if (TheTriple.getTriple().empty())
+ TheTriple.setTriple(sys::getHostTriple());
+
+ // Allocate target machine. First, check whether the user has explicitly
+ // specified an architecture to compile for. If so we have to look it up by
+ // name, because it might be a backend that has no mapping to a target triple.
+ const Target *TheTarget = 0;
+ if (!MArch.empty()) {
+ for (TargetRegistry::iterator it = TargetRegistry::begin(),
+ ie = TargetRegistry::end(); it != ie; ++it) {
+ if (MArch == it->getName()) {
+ TheTarget = &*it;
+ break;
+ }
+ }
+
+ if (!TheTarget) {
+ errs() << argv[0] << ": error: invalid target '" << MArch << "'.\n";
+ return 1;
+ }
+
+ // Adjust the triple to match (if known), otherwise stick with the
+ // module/host triple.
+ Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch);
+ if (Type != Triple::UnknownArch)
+ TheTriple.setArch(Type);
+ } else {
std::string Err;
- MArch = TargetMachineRegistry::getClosestStaticTargetForModule(mod, Err);
- if (MArch == 0) {
- std::cerr << argv[0] << ": error auto-selecting target for module '"
- << Err << "'. Please use the -march option to explicitly "
- << "pick a target.\n";
+ TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Err);
+ if (TheTarget == 0) {
+ errs() << argv[0] << ": error auto-selecting target for module '"
+ << Err << "'. Please use the -march option to explicitly "
+ << "pick a target.\n";
return 1;
}
}
@@ -262,18 +282,19 @@ int main(int argc, char **argv) {
FeaturesStr = Features.getString();
}
- std::auto_ptr<TargetMachine> target(MArch->CtorFn(mod, FeaturesStr));
+ std::auto_ptr<TargetMachine>
+ target(TheTarget->createTargetMachine(TheTriple.getTriple(), FeaturesStr));
assert(target.get() && "Could not allocate target machine!");
TargetMachine &Target = *target.get();
// Figure out where we are going to send the output...
- raw_ostream *Out = GetOutputStream(argv[0]);
+ formatted_raw_ostream *Out = GetOutputStream(TheTarget->getName(), argv[0]);
if (Out == 0) return 1;
CodeGenOpt::Level OLvl = CodeGenOpt::Default;
switch (OptLevel) {
default:
- std::cerr << argv[0] << ": invalid optimization level.\n";
+ errs() << argv[0] << ": invalid optimization level.\n";
return 1;
case ' ': break;
case '0': OLvl = CodeGenOpt::None; break;
@@ -286,15 +307,21 @@ int main(int argc, char **argv) {
// used by strange things like the C backend.
if (Target.WantsWholeFile()) {
PassManager PM;
- PM.add(new TargetData(*Target.getTargetData()));
+
+ // Add the target data from the target machine, if it exists, or the module.
+ if (const TargetData *TD = Target.getTargetData())
+ PM.add(new TargetData(*TD));
+ else
+ PM.add(new TargetData(&mod));
+
if (!NoVerify)
PM.add(createVerifierPass());
// Ask the target to add backend passes as necessary.
if (Target.addPassesToEmitWholeFile(PM, *Out, FileType, OLvl)) {
- std::cerr << argv[0] << ": target does not support generation of this"
- << " file type!\n";
- if (Out != &outs()) delete Out;
+ errs() << argv[0] << ": target does not support generation of this"
+ << " file type!\n";
+ if (Out != &fouts()) delete Out;
// And the Out file is empty and useless, so remove it now.
sys::Path(OutputFilename).eraseFromDisk();
return 1;
@@ -304,7 +331,12 @@ int main(int argc, char **argv) {
// Build up all of the passes that we want to do to the module.
ExistingModuleProvider Provider(M.release());
FunctionPassManager Passes(&Provider);
- Passes.add(new TargetData(*Target.getTargetData()));
+
+ // Add the target data from the target machine, if it exists, or the module.
+ if (const TargetData *TD = Target.getTargetData())
+ Passes.add(new TargetData(*TD));
+ else
+ Passes.add(new TargetData(&mod));
#ifndef NDEBUG
if (!NoVerify)
@@ -312,7 +344,7 @@ int main(int argc, char **argv) {
#endif
// Ask the target to add backend passes as necessary.
- MachineCodeEmitter *MCE = 0;
+ ObjectCodeEmitter *OCE = 0;
// Override default to generate verbose assembly.
Target.setAsmVerbosityDefault(true);
@@ -322,26 +354,26 @@ int main(int argc, char **argv) {
assert(0 && "Invalid file model!");
return 1;
case FileModel::Error:
- std::cerr << argv[0] << ": target does not support generation of this"
- << " file type!\n";
- if (Out != &outs()) delete Out;
+ errs() << argv[0] << ": target does not support generation of this"
+ << " file type!\n";
+ if (Out != &fouts()) delete Out;
// And the Out file is empty and useless, so remove it now.
sys::Path(OutputFilename).eraseFromDisk();
return 1;
case FileModel::AsmFile:
break;
case FileModel::MachOFile:
- MCE = AddMachOWriter(Passes, *Out, Target);
+ OCE = AddMachOWriter(Passes, *Out, Target);
break;
case FileModel::ElfFile:
- MCE = AddELFWriter(Passes, *Out, Target);
+ OCE = AddELFWriter(Passes, *Out, Target);
break;
}
- if (Target.addPassesToEmitFileFinish(Passes, MCE, OLvl)) {
- std::cerr << argv[0] << ": target does not support generation of this"
- << " file type!\n";
- if (Out != &outs()) delete Out;
+ if (Target.addPassesToEmitFileFinish(Passes, OCE, OLvl)) {
+ errs() << argv[0] << ": target does not support generation of this"
+ << " file type!\n";
+ if (Out != &fouts()) delete Out;
// And the Out file is empty and useless, so remove it now.
sys::Path(OutputFilename).eraseFromDisk();
return 1;
@@ -364,7 +396,7 @@ int main(int argc, char **argv) {
}
// Delete the ostream if it's not a stdout stream
- if (Out != &outs()) delete Out;
+ if (Out != &fouts()) delete Out;
return 0;
}
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index a01b0d6..e5c1070 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -28,10 +28,10 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Process.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/TargetSelect.h"
-#include <iostream>
#include <cerrno>
using namespace llvm;
@@ -94,8 +94,13 @@ int main(int argc, char **argv, char * const *envp) {
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
atexit(do_shutdown); // Call llvm_shutdown() on exit.
+
+ // If we have a native target, initialize it to ensure it is linked in and
+ // usable by the JIT.
+ InitializeNativeTarget();
+
cl::ParseCommandLineOptions(argc, argv,
"llvm interpreter & dynamic compiler\n");
@@ -112,8 +117,8 @@ int main(int argc, char **argv, char * const *envp) {
}
if (!MP) {
- std::cerr << argv[0] << ": error loading program '" << InputFile << "': "
- << ErrorMsg << "\n";
+ errs() << argv[0] << ": error loading program '" << InputFile << "': "
+ << ErrorMsg << "\n";
exit(1);
}
@@ -121,11 +126,17 @@ int main(int argc, char **argv, char * const *envp) {
Module *Mod = NoLazyCompilation
? MP->materializeModule(&ErrorMsg) : MP->getModule();
if (!Mod) {
- std::cerr << argv[0] << ": bitcode didn't read correctly.\n";
- std::cerr << "Reason: " << ErrorMsg << "\n";
+ errs() << argv[0] << ": bitcode didn't read correctly.\n";
+ errs() << "Reason: " << ErrorMsg << "\n";
exit(1);
}
+ EngineBuilder builder(MP);
+ builder.setErrorStr(&ErrorMsg);
+ builder.setEngineKind(ForceInterpreter
+ ? EngineKind::Interpreter
+ : EngineKind::JIT);
+
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
Mod->setTargetTriple(TargetTriple);
@@ -133,7 +144,7 @@ int main(int argc, char **argv, char * const *envp) {
CodeGenOpt::Level OLvl = CodeGenOpt::Default;
switch (OptLevel) {
default:
- std::cerr << argv[0] << ": invalid optimization level.\n";
+ errs() << argv[0] << ": invalid optimization level.\n";
return 1;
case ' ': break;
case '0': OLvl = CodeGenOpt::None; break;
@@ -141,18 +152,19 @@ int main(int argc, char **argv, char * const *envp) {
case '2': OLvl = CodeGenOpt::Default; break;
case '3': OLvl = CodeGenOpt::Aggressive; break;
}
-
- // If we have a native target, initialize it to ensure it is linked in and
- // usable by the JIT.
- InitializeNativeTarget();
-
- EE = ExecutionEngine::create(MP, ForceInterpreter, &ErrorMsg, OLvl);
- if (!EE && !ErrorMsg.empty()) {
- std::cerr << argv[0] << ":error creating EE: " << ErrorMsg << "\n";
+ builder.setOptLevel(OLvl);
+
+ EE = builder.create();
+ if (!EE) {
+ if (!ErrorMsg.empty())
+ errs() << argv[0] << ": error creating EE: " << ErrorMsg << "\n";
+ else
+ errs() << argv[0] << ": unknown error creating EE!\n";
exit(1);
}
EE->RegisterJITEventListener(createMacOSJITEventListener());
+ EE->RegisterJITEventListener(createOProfileJITEventListener());
if (NoLazyCompilation)
EE->DisableLazyCompilation();
@@ -178,14 +190,15 @@ int main(int argc, char **argv, char * const *envp) {
//
Function *EntryFn = Mod->getFunction(EntryFunc);
if (!EntryFn) {
- std::cerr << '\'' << EntryFunc << "\' function not found in module.\n";
+ errs() << '\'' << EntryFunc << "\' function not found in module.\n";
return -1;
}
// If the program doesn't explicitly call exit, we will need the Exit
// function later on to make an explicit call, so get the function now.
- Constant *Exit = Mod->getOrInsertFunction("exit", Type::VoidTy,
- Type::Int32Ty, NULL);
+ Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context),
+ Type::getInt32Ty(Context),
+ NULL);
// Reset errno to zero on entry to main.
errno = 0;
@@ -215,10 +228,10 @@ int main(int argc, char **argv, char * const *envp) {
ResultGV.IntVal = APInt(32, Result);
Args.push_back(ResultGV);
EE->runFunction(ExitF, Args);
- std::cerr << "ERROR: exit(" << Result << ") returned!\n";
+ errs() << "ERROR: exit(" << Result << ") returned!\n";
abort();
} else {
- std::cerr << "ERROR: exit defined with wrong prototype!\n";
+ errs() << "ERROR: exit defined with wrong prototype!\n";
abort();
}
}
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index fe58db1..021a369 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -18,11 +18,13 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <memory>
+#include <fstream>
using namespace llvm;
// Option for compatibility with AIX, not used but must allow it to be present.
@@ -363,7 +365,7 @@ bool doPrint(std::string* ErrMsg) {
continue;
if (Verbose)
- std::cout << "Printing " << I->getPath().toString() << "\n";
+ std::cout << "Printing " << I->getPath().str() << "\n";
unsigned len = I->getSize();
std::cout.write(data, len);
@@ -421,11 +423,10 @@ doDisplayTable(std::string* ErrMsg) {
std::cout << " " << std::setw(4) << I->getUser();
std::cout << "/" << std::setw(4) << I->getGroup();
std::cout << " " << std::setw(8) << I->getSize();
- std::cout << " " << std::setw(20) <<
- I->getModTime().toString().substr(4);
- std::cout << " " << I->getPath().toString() << "\n";
+ std::cout << " " << std::setw(20) << I->getModTime().str().substr(4);
+ std::cout << " " << I->getPath().str() << "\n";
} else {
- std::cout << I->getPath().toString() << "\n";
+ std::cout << I->getPath().str() << "\n";
}
}
}
@@ -527,7 +528,7 @@ doMove(std::string* ErrMsg) {
if (AddBefore || InsertBefore || AddAfter) {
for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end();
I != E; ++I ) {
- if (RelPos == I->getPath().toString()) {
+ if (RelPos == I->getPath().str()) {
if (AddAfter) {
moveto_spot = I;
moveto_spot++;
@@ -615,7 +616,7 @@ doReplaceOrInsert(std::string* ErrMsg) {
std::set<sys::Path>::iterator found = remaining.end();
for (std::set<sys::Path>::iterator RI = remaining.begin(),
RE = remaining.end(); RI != RE; ++RI ) {
- std::string compare(RI->toString());
+ std::string compare(RI->str());
if (TruncateNames && compare.length() > 15) {
const char* nm = compare.c_str();
unsigned len = compare.length();
@@ -628,7 +629,7 @@ doReplaceOrInsert(std::string* ErrMsg) {
len = 15;
compare.assign(nm,len);
}
- if (compare == I->getPath().toString()) {
+ if (compare == I->getPath().str()) {
found = RI;
break;
}
@@ -660,9 +661,9 @@ doReplaceOrInsert(std::string* ErrMsg) {
}
// Determine if this is the place where we should insert
- if ((AddBefore || InsertBefore) && (RelPos == I->getPath().toString()))
+ if ((AddBefore || InsertBefore) && RelPos == I->getPath().str())
insert_spot = I;
- else if (AddAfter && (RelPos == I->getPath().toString())) {
+ else if (AddAfter && RelPos == I->getPath().str()) {
insert_spot = I;
insert_spot++;
}
@@ -691,7 +692,7 @@ int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Have the command line options parsed and handle things
@@ -718,15 +719,15 @@ int main(int argc, char **argv) {
if (!ArchivePath.exists()) {
// Produce a warning if we should and we're creating the archive
if (!Create)
- std::cerr << argv[0] << ": creating " << ArchivePath.toString() << "\n";
+ errs() << argv[0] << ": creating " << ArchivePath.str() << "\n";
TheArchive = Archive::CreateEmpty(ArchivePath, Context);
TheArchive->writeToDisk();
} else {
std::string Error;
TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error);
if (TheArchive == 0) {
- std::cerr << argv[0] << ": error loading '" << ArchivePath << "': "
- << Error << "!\n";
+ errs() << argv[0] << ": error loading '" << ArchivePath.str() << "': "
+ << Error << "!\n";
return 1;
}
}
@@ -749,27 +750,27 @@ int main(int argc, char **argv) {
case DisplayTable: haveError = doDisplayTable(&ErrMsg); break;
case Extract: haveError = doExtract(&ErrMsg); break;
case NoOperation:
- std::cerr << argv[0] << ": No operation was selected.\n";
+ errs() << argv[0] << ": No operation was selected.\n";
break;
}
if (haveError) {
- std::cerr << argv[0] << ": " << ErrMsg << "\n";
+ errs() << argv[0] << ": " << ErrMsg << "\n";
return 1;
}
} catch (const char*msg) {
// These errors are usage errors, thrown only by the various checks in the
// code above.
- std::cerr << argv[0] << ": " << msg << "\n\n";
+ errs() << argv[0] << ": " << msg << "\n\n";
cl::PrintHelpMessage();
exitCode = 1;
} catch (const std::string& msg) {
// These errors are thrown by LLVM libraries (e.g. lib System) and represent
// a more serious error so we bump the exitCode and don't print the usage.
- std::cerr << argv[0] << ": " << msg << "\n";
+ errs() << argv[0] << ": " << msg << "\n";
exitCode = 2;
} catch (...) {
// This really shouldn't happen, but just in case ....
- std::cerr << argv[0] << ": An unexpected unknown exception occurred.\n";
+ errs() << argv[0] << ": An unexpected unknown exception occurred.\n";
exitCode = 3;
}
diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp
index eccabd5..d510297 100644
--- a/tools/llvm-as/llvm-as.cpp
+++ b/tools/llvm-as/llvm-as.cpp
@@ -24,12 +24,9 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/Streams.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
-#include <fstream>
-#include <iostream>
#include <memory>
using namespace llvm;
@@ -41,7 +38,7 @@ OutputFilename("o", cl::desc("Override output filename"),
cl::value_desc("filename"));
static cl::opt<bool>
-Force("f", cl::desc("Overwrite output files"));
+Force("f", cl::desc("Enable binary output on terminals"));
static cl::opt<bool>
DisableOutput("disable-output", cl::desc("Disable output"), cl::init(false));
@@ -57,96 +54,64 @@ int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm .ll -> .bc assembler\n");
- int exitCode = 0;
- std::ostream *Out = 0;
- try {
- // Parse the file now...
- SMDiagnostic Err;
- std::auto_ptr<Module> M(ParseAssemblyFile(InputFilename, Err, Context));
- if (M.get() == 0) {
- Err.Print(argv[0], errs());
- return 1;
- }
+ // Parse the file now...
+ SMDiagnostic Err;
+ std::auto_ptr<Module> M(ParseAssemblyFile(InputFilename, Err, Context));
+ if (M.get() == 0) {
+ Err.Print(argv[0], errs());
+ return 1;
+ }
- if (!DisableVerify) {
- std::string Err;
- if (verifyModule(*M.get(), ReturnStatusAction, &Err)) {
- cerr << argv[0]
+ if (!DisableVerify) {
+ std::string Err;
+ if (verifyModule(*M.get(), ReturnStatusAction, &Err)) {
+ errs() << argv[0]
<< ": assembly parsed, but does not verify as correct!\n";
- cerr << Err;
- return 1;
- }
- }
+ errs() << Err;
+ return 1;
+ }
+ }
- if (DumpAsm) cerr << "Here's the assembly:\n" << *M.get();
-
- if (OutputFilename != "") { // Specified an output filename?
- if (OutputFilename != "-") { // Not stdout?
- if (!Force && std::ifstream(OutputFilename.c_str())) {
- // If force is not specified, make sure not to overwrite a file!
- cerr << argv[0] << ": error opening '" << OutputFilename
- << "': file exists!\n"
- << "Use -f command line argument to force output\n";
- return 1;
- }
- Out = new std::ofstream(OutputFilename.c_str(), std::ios::out |
- std::ios::trunc | std::ios::binary);
- } else { // Specified stdout
- // FIXME: cout is not binary!
- Out = &std::cout;
- }
+ if (DumpAsm) errs() << "Here's the assembly:\n" << *M.get();
+
+ // Infer the output filename if needed.
+ if (OutputFilename.empty()) {
+ if (InputFilename == "-") {
+ OutputFilename = "-";
} else {
- if (InputFilename == "-") {
- OutputFilename = "-";
- Out = &std::cout;
+ std::string IFN = InputFilename;
+ int Len = IFN.length();
+ if (IFN[Len-3] == '.' && IFN[Len-2] == 'l' && IFN[Len-1] == 'l') {
+ // Source ends in .ll
+ OutputFilename = std::string(IFN.begin(), IFN.end()-3);
} else {
- std::string IFN = InputFilename;
- int Len = IFN.length();
- if (IFN[Len-3] == '.' && IFN[Len-2] == 'l' && IFN[Len-1] == 'l') {
- // Source ends in .ll
- OutputFilename = std::string(IFN.begin(), IFN.end()-3);
- } else {
- OutputFilename = IFN; // Append a .bc to it
- }
- OutputFilename += ".bc";
-
- if (!Force && std::ifstream(OutputFilename.c_str())) {
- // If force is not specified, make sure not to overwrite a file!
- cerr << argv[0] << ": error opening '" << OutputFilename
- << "': file exists!\n"
- << "Use -f command line argument to force output\n";
- return 1;
- }
-
- Out = new std::ofstream(OutputFilename.c_str(), std::ios::out |
- std::ios::trunc | std::ios::binary);
- // Make sure that the Out file gets unlinked from the disk if we get a
- // SIGINT
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+ OutputFilename = IFN; // Append a .bc to it
}
+ OutputFilename += ".bc";
}
+ }
- if (!Out->good()) {
- cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
- return 1;
- }
-
- if (!DisableOutput)
- if (Force || !CheckBitcodeOutputToConsole(Out,true))
- WriteBitcodeToFile(M.get(), *Out);
- } catch (const std::string& msg) {
- cerr << argv[0] << ": " << msg << "\n";
- exitCode = 1;
- } catch (...) {
- cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
- exitCode = 1;
+ // 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));
+ if (!ErrorInfo.empty()) {
+ errs() << ErrorInfo << '\n';
+ return 1;
}
- if (Out != &std::cout) delete Out;
- return exitCode;
+ if (!DisableOutput)
+ if (Force || !CheckBitcodeOutputToConsole(*Out, true))
+ WriteBitcodeToFile(M.get(), *Out);
+ return 0;
}
diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index b401a21..6d5b2b51 100644
--- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -20,7 +20,7 @@
// produces on std::out a summary of the bitcode file that shows various
// statistics about the contents of the file. By default this information is
// detailed and contains information about individual bitcode blocks and the
-// functions in the module.
+// functions in the module.
// The tool is also able to print a bitcode file in a straight forward text
// format that shows the containment and relationships of the information in
// the bitcode file (-dump option).
@@ -32,13 +32,14 @@
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Format.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 <cstdio>
#include <map>
-#include <fstream>
-#include <iostream>
#include <algorithm>
using namespace llvm;
@@ -62,7 +63,7 @@ NonSymbolic("non-symbolic",
cl::desc("Emit numberic info in dump even if"
" symbolic info is available"));
-/// CurStreamType - If we can sniff the flavor of this stream, we can produce
+/// CurStreamType - If we can sniff the flavor of this stream, we can produce
/// better dump info.
static enum {
UnknownBitstream,
@@ -80,26 +81,28 @@ static const char *GetBlockName(unsigned BlockID,
return "BLOCKINFO_BLOCK";
return 0;
}
-
+
// Check to see if we have a blockinfo record for this block, with a name.
if (const BitstreamReader::BlockInfo *Info =
StreamFile.getBlockInfo(BlockID)) {
if (!Info->Name.empty())
return Info->Name.c_str();
}
-
-
+
+
if (CurStreamType != LLVMIRBitstream) return 0;
-
+
switch (BlockID) {
- default: return 0;
- case bitc::MODULE_BLOCK_ID: return "MODULE_BLOCK";
- case bitc::PARAMATTR_BLOCK_ID: return "PARAMATTR_BLOCK";
- case bitc::TYPE_BLOCK_ID: return "TYPE_BLOCK";
- case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK";
- case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK";
- case bitc::TYPE_SYMTAB_BLOCK_ID: return "TYPE_SYMTAB";
- case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB";
+ default: return 0;
+ case bitc::MODULE_BLOCK_ID: return "MODULE_BLOCK";
+ case bitc::PARAMATTR_BLOCK_ID: return "PARAMATTR_BLOCK";
+ case bitc::TYPE_BLOCK_ID: return "TYPE_BLOCK";
+ case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK";
+ case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK";
+ case bitc::TYPE_SYMTAB_BLOCK_ID: return "TYPE_SYMTAB";
+ case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB";
+ case bitc::METADATA_BLOCK_ID: return "METADATA_BLOCK";
+ case bitc::METADATA_ATTACHMENT_ID: return "METADATA_ATTACHMENT_BLOCK";
}
}
@@ -119,7 +122,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
}
return 0;
}
-
+
// Check to see if we have a blockinfo record for this record, with a name.
if (const BitstreamReader::BlockInfo *Info =
StreamFile.getBlockInfo(BlockID)) {
@@ -127,10 +130,10 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
if (Info->RecordNames[i].first == CodeID)
return Info->RecordNames[i].second.c_str();
}
-
-
+
+
if (CurStreamType != LLVMIRBitstream) return 0;
-
+
switch (BlockID) {
default: return 0;
case bitc::MODULE_BLOCK_ID:
@@ -173,67 +176,67 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
case bitc::TYPE_CODE_PPC_FP128: return "PPC_FP128";
case bitc::TYPE_CODE_METADATA: return "METADATA";
}
-
+
case bitc::CONSTANTS_BLOCK_ID:
switch (CodeID) {
default: return 0;
- case bitc::CST_CODE_SETTYPE: return "SETTYPE";
- case bitc::CST_CODE_NULL: return "NULL";
- case bitc::CST_CODE_UNDEF: return "UNDEF";
- case bitc::CST_CODE_INTEGER: return "INTEGER";
- case bitc::CST_CODE_WIDE_INTEGER: return "WIDE_INTEGER";
- case bitc::CST_CODE_FLOAT: return "FLOAT";
- case bitc::CST_CODE_AGGREGATE: return "AGGREGATE";
- case bitc::CST_CODE_STRING: return "STRING";
- case bitc::CST_CODE_CSTRING: return "CSTRING";
- case bitc::CST_CODE_CE_BINOP: return "CE_BINOP";
- case bitc::CST_CODE_CE_CAST: return "CE_CAST";
- case bitc::CST_CODE_CE_GEP: return "CE_GEP";
- case bitc::CST_CODE_CE_SELECT: return "CE_SELECT";
- case bitc::CST_CODE_CE_EXTRACTELT: return "CE_EXTRACTELT";
- case bitc::CST_CODE_CE_INSERTELT: return "CE_INSERTELT";
- case bitc::CST_CODE_CE_SHUFFLEVEC: return "CE_SHUFFLEVEC";
- case bitc::CST_CODE_CE_CMP: return "CE_CMP";
- case bitc::CST_CODE_INLINEASM: return "INLINEASM";
- case bitc::CST_CODE_CE_SHUFVEC_EX: return "CE_SHUFVEC_EX";
- case bitc::CST_CODE_MDSTRING: return "MDSTRING";
- case bitc::CST_CODE_MDNODE: return "MDNODE";
- }
+ case bitc::CST_CODE_SETTYPE: return "SETTYPE";
+ case bitc::CST_CODE_NULL: return "NULL";
+ case bitc::CST_CODE_UNDEF: return "UNDEF";
+ case bitc::CST_CODE_INTEGER: return "INTEGER";
+ case bitc::CST_CODE_WIDE_INTEGER: return "WIDE_INTEGER";
+ case bitc::CST_CODE_FLOAT: return "FLOAT";
+ case bitc::CST_CODE_AGGREGATE: return "AGGREGATE";
+ case bitc::CST_CODE_STRING: return "STRING";
+ case bitc::CST_CODE_CSTRING: return "CSTRING";
+ case bitc::CST_CODE_CE_BINOP: return "CE_BINOP";
+ case bitc::CST_CODE_CE_CAST: return "CE_CAST";
+ case bitc::CST_CODE_CE_GEP: return "CE_GEP";
+ case bitc::CST_CODE_CE_INBOUNDS_GEP: return "CE_INBOUNDS_GEP";
+ case bitc::CST_CODE_CE_SELECT: return "CE_SELECT";
+ case bitc::CST_CODE_CE_EXTRACTELT: return "CE_EXTRACTELT";
+ case bitc::CST_CODE_CE_INSERTELT: return "CE_INSERTELT";
+ case bitc::CST_CODE_CE_SHUFFLEVEC: return "CE_SHUFFLEVEC";
+ case bitc::CST_CODE_CE_CMP: return "CE_CMP";
+ case bitc::CST_CODE_INLINEASM: return "INLINEASM";
+ case bitc::CST_CODE_CE_SHUFVEC_EX: return "CE_SHUFVEC_EX";
+ }
case bitc::FUNCTION_BLOCK_ID:
switch (CodeID) {
default: return 0;
case bitc::FUNC_CODE_DECLAREBLOCKS: return "DECLAREBLOCKS";
-
- case bitc::FUNC_CODE_INST_BINOP: return "INST_BINOP";
- case bitc::FUNC_CODE_INST_CAST: return "INST_CAST";
- case bitc::FUNC_CODE_INST_GEP: return "INST_GEP";
- case bitc::FUNC_CODE_INST_SELECT: return "INST_SELECT";
- case bitc::FUNC_CODE_INST_EXTRACTELT: return "INST_EXTRACTELT";
- case bitc::FUNC_CODE_INST_INSERTELT: return "INST_INSERTELT";
- case bitc::FUNC_CODE_INST_SHUFFLEVEC: return "INST_SHUFFLEVEC";
- case bitc::FUNC_CODE_INST_CMP: return "INST_CMP";
-
- case bitc::FUNC_CODE_INST_RET: return "INST_RET";
- case bitc::FUNC_CODE_INST_BR: return "INST_BR";
- case bitc::FUNC_CODE_INST_SWITCH: return "INST_SWITCH";
- case bitc::FUNC_CODE_INST_INVOKE: return "INST_INVOKE";
- case bitc::FUNC_CODE_INST_UNWIND: return "INST_UNWIND";
- case bitc::FUNC_CODE_INST_UNREACHABLE: return "INST_UNREACHABLE";
-
- case bitc::FUNC_CODE_INST_PHI: return "INST_PHI";
- case bitc::FUNC_CODE_INST_MALLOC: return "INST_MALLOC";
- case bitc::FUNC_CODE_INST_FREE: return "INST_FREE";
- case bitc::FUNC_CODE_INST_ALLOCA: return "INST_ALLOCA";
- case bitc::FUNC_CODE_INST_LOAD: return "INST_LOAD";
- case bitc::FUNC_CODE_INST_STORE: return "INST_STORE";
- case bitc::FUNC_CODE_INST_CALL: return "INST_CALL";
- case bitc::FUNC_CODE_INST_VAARG: return "INST_VAARG";
- case bitc::FUNC_CODE_INST_STORE2: return "INST_STORE2";
- case bitc::FUNC_CODE_INST_GETRESULT: return "INST_GETRESULT";
- case bitc::FUNC_CODE_INST_EXTRACTVAL: return "INST_EXTRACTVAL";
- case bitc::FUNC_CODE_INST_INSERTVAL: return "INST_INSERTVAL";
- case bitc::FUNC_CODE_INST_CMP2: return "INST_CMP2";
- case bitc::FUNC_CODE_INST_VSELECT: return "INST_VSELECT";
+
+ case bitc::FUNC_CODE_INST_BINOP: return "INST_BINOP";
+ case bitc::FUNC_CODE_INST_CAST: return "INST_CAST";
+ case bitc::FUNC_CODE_INST_GEP: return "INST_GEP";
+ case bitc::FUNC_CODE_INST_INBOUNDS_GEP: return "INST_INBOUNDS_GEP";
+ case bitc::FUNC_CODE_INST_SELECT: return "INST_SELECT";
+ case bitc::FUNC_CODE_INST_EXTRACTELT: return "INST_EXTRACTELT";
+ case bitc::FUNC_CODE_INST_INSERTELT: return "INST_INSERTELT";
+ case bitc::FUNC_CODE_INST_SHUFFLEVEC: return "INST_SHUFFLEVEC";
+ case bitc::FUNC_CODE_INST_CMP: return "INST_CMP";
+
+ case bitc::FUNC_CODE_INST_RET: return "INST_RET";
+ case bitc::FUNC_CODE_INST_BR: return "INST_BR";
+ case bitc::FUNC_CODE_INST_SWITCH: return "INST_SWITCH";
+ case bitc::FUNC_CODE_INST_INVOKE: return "INST_INVOKE";
+ case bitc::FUNC_CODE_INST_UNWIND: return "INST_UNWIND";
+ case bitc::FUNC_CODE_INST_UNREACHABLE: return "INST_UNREACHABLE";
+
+ case bitc::FUNC_CODE_INST_PHI: return "INST_PHI";
+ case bitc::FUNC_CODE_INST_MALLOC: return "INST_MALLOC";
+ case bitc::FUNC_CODE_INST_FREE: return "INST_FREE";
+ case bitc::FUNC_CODE_INST_ALLOCA: return "INST_ALLOCA";
+ case bitc::FUNC_CODE_INST_LOAD: return "INST_LOAD";
+ case bitc::FUNC_CODE_INST_STORE: return "INST_STORE";
+ case bitc::FUNC_CODE_INST_CALL: return "INST_CALL";
+ case bitc::FUNC_CODE_INST_VAARG: return "INST_VAARG";
+ case bitc::FUNC_CODE_INST_STORE2: return "INST_STORE2";
+ case bitc::FUNC_CODE_INST_GETRESULT: return "INST_GETRESULT";
+ case bitc::FUNC_CODE_INST_EXTRACTVAL: return "INST_EXTRACTVAL";
+ case bitc::FUNC_CODE_INST_INSERTVAL: return "INST_INSERTVAL";
+ case bitc::FUNC_CODE_INST_CMP2: return "INST_CMP2";
+ case bitc::FUNC_CODE_INST_VSELECT: return "INST_VSELECT";
}
case bitc::TYPE_SYMTAB_BLOCK_ID:
switch (CodeID) {
@@ -246,6 +249,20 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
case bitc::VST_CODE_ENTRY: return "ENTRY";
case bitc::VST_CODE_BBENTRY: return "BBENTRY";
}
+ case bitc::METADATA_ATTACHMENT_ID:
+ switch(CodeID) {
+ default:return 0;
+ case bitc::METADATA_ATTACHMENT: return "METADATA_ATTACHMENT";
+ }
+ 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_NAME: return "METADATA_NAME";
+ case bitc::METADATA_NAMED_NODE: return "NAMEDMDNODE";
+ case bitc::METADATA_KIND: return "METADATA_KIND";
+ }
}
}
@@ -253,30 +270,30 @@ struct PerRecordStats {
unsigned NumInstances;
unsigned NumAbbrev;
uint64_t TotalBits;
-
+
PerRecordStats() : NumInstances(0), NumAbbrev(0), TotalBits(0) {}
};
struct PerBlockIDStats {
/// NumInstances - This the number of times this block ID has been seen.
unsigned NumInstances;
-
+
/// NumBits - The total size in bits of all of these blocks.
uint64_t NumBits;
-
+
/// NumSubBlocks - The total number of blocks these blocks contain.
unsigned NumSubBlocks;
-
+
/// NumAbbrevs - The total number of abbreviations.
unsigned NumAbbrevs;
-
- /// NumRecords - The total number of records these blocks contain, and the
+
+ /// NumRecords - The total number of records these blocks contain, and the
/// number that are abbreviated.
unsigned NumRecords, NumAbbreviatedRecords;
-
+
/// CodeFreq - Keep track of the number of times we see each code.
std::vector<PerRecordStats> CodeFreq;
-
+
PerBlockIDStats()
: NumInstances(0), NumBits(0),
NumSubBlocks(0), NumAbbrevs(0), NumRecords(0), NumAbbreviatedRecords(0) {}
@@ -289,7 +306,7 @@ static std::map<unsigned, PerBlockIDStats> BlockIDStats;
/// Error - All bitcode analysis errors go through this function, making this a
/// good place to breakpoint if debugging.
static bool Error(const std::string &Err) {
- std::cerr << Err << "\n";
+ errs() << Err << "\n";
return true;
}
@@ -301,38 +318,38 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
// Get the statistics for this BlockID.
PerBlockIDStats &BlockStats = BlockIDStats[BlockID];
-
+
BlockStats.NumInstances++;
-
+
// BLOCKINFO is a special part of the stream.
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
- if (Dump) std::cerr << Indent << "<BLOCKINFO_BLOCK/>\n";
+ if (Dump) errs() << Indent << "<BLOCKINFO_BLOCK/>\n";
if (Stream.ReadBlockInfoBlock())
return Error("Malformed BlockInfoBlock");
uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
BlockStats.NumBits += BlockBitEnd-BlockBitStart;
return false;
}
-
+
unsigned NumWords = 0;
if (Stream.EnterSubBlock(BlockID, &NumWords))
return Error("Malformed block record");
const char *BlockName = 0;
if (Dump) {
- std::cerr << Indent << "<";
+ errs() << Indent << "<";
if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader())))
- std::cerr << BlockName;
+ errs() << BlockName;
else
- std::cerr << "UnknownBlock" << BlockID;
-
+ errs() << "UnknownBlock" << BlockID;
+
if (NonSymbolic && BlockName)
- std::cerr << " BlockID=" << BlockID;
-
- std::cerr << " NumWords=" << NumWords
- << " BlockCodeSize=" << Stream.GetAbbrevIDWidth() << ">\n";
+ errs() << " BlockID=" << BlockID;
+
+ errs() << " NumWords=" << NumWords
+ << " BlockCodeSize=" << Stream.GetAbbrevIDWidth() << ">\n";
}
-
+
SmallVector<uint64_t, 64> Record;
// Read all the records for this block.
@@ -341,7 +358,7 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
return Error("Premature end of bitstream");
uint64_t RecordStartBit = Stream.GetCurrentBitNo();
-
+
// Read the code for this record.
unsigned AbbrevID = Stream.ReadCode();
switch (AbbrevID) {
@@ -351,21 +368,21 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
BlockStats.NumBits += BlockBitEnd-BlockBitStart;
if (Dump) {
- std::cerr << Indent << "</";
+ errs() << Indent << "</";
if (BlockName)
- std::cerr << BlockName << ">\n";
+ errs() << BlockName << ">\n";
else
- std::cerr << "UnknownBlock" << BlockID << ">\n";
+ errs() << "UnknownBlock" << BlockID << ">\n";
}
return false;
- }
+ }
case bitc::ENTER_SUBBLOCK: {
uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
if (ParseBlock(Stream, IndentLevel+1))
return true;
++BlockStats.NumSubBlocks;
uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
-
+
// Don't include subblock sizes in the size of this block.
BlockBitStart += SubBlockBitEnd-SubBlockBitStart;
break;
@@ -380,13 +397,13 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
++BlockStats.NumRecords;
if (AbbrevID != bitc::UNABBREV_RECORD)
++BlockStats.NumAbbreviatedRecords;
-
+
const char *BlobStart = 0;
unsigned BlobLen = 0;
unsigned Code = Stream.ReadRecord(AbbrevID, Record, BlobStart, BlobLen);
-
-
+
+
// Increment the # occurrences of this code.
if (BlockStats.CodeFreq.size() <= Code)
BlockStats.CodeFreq.resize(Code+1);
@@ -395,43 +412,43 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
Stream.GetCurrentBitNo()-RecordStartBit;
if (AbbrevID != bitc::UNABBREV_RECORD)
BlockStats.CodeFreq[Code].NumAbbrev++;
-
+
if (Dump) {
- std::cerr << Indent << " <";
+ errs() << Indent << " <";
if (const char *CodeName =
GetCodeName(Code, BlockID, *Stream.getBitStreamReader()))
- std::cerr << CodeName;
+ errs() << CodeName;
else
- std::cerr << "UnknownCode" << Code;
+ errs() << "UnknownCode" << Code;
if (NonSymbolic &&
GetCodeName(Code, BlockID, *Stream.getBitStreamReader()))
- std::cerr << " codeid=" << Code;
+ errs() << " codeid=" << Code;
if (AbbrevID != bitc::UNABBREV_RECORD)
- std::cerr << " abbrevid=" << AbbrevID;
+ errs() << " abbrevid=" << AbbrevID;
for (unsigned i = 0, e = Record.size(); i != e; ++i)
- std::cerr << " op" << i << "=" << (int64_t)Record[i];
-
- std::cerr << "/>";
-
+ errs() << " op" << i << "=" << (int64_t)Record[i];
+
+ errs() << "/>";
+
if (BlobStart) {
- std::cerr << " blob data = ";
+ errs() << " blob data = ";
bool BlobIsPrintable = true;
for (unsigned i = 0; i != BlobLen; ++i)
if (!isprint(BlobStart[i])) {
BlobIsPrintable = false;
break;
}
-
+
if (BlobIsPrintable)
- std::cerr << "'" << std::string(BlobStart, BlobStart+BlobLen) <<"'";
+ errs() << "'" << std::string(BlobStart, BlobStart+BlobLen) <<"'";
else
- std::cerr << "unprintable, " << BlobLen << " bytes.";
+ errs() << "unprintable, " << BlobLen << " bytes.";
}
-
- std::cerr << "\n";
+
+ errs() << "\n";
}
-
+
break;
}
}
@@ -453,23 +470,23 @@ static int AnalyzeBitcode() {
if (MemBuf == 0)
return Error("Error reading '" + InputFilename + "'.");
-
+
if (MemBuf->getBufferSize() & 3)
return Error("Bitcode stream should be a multiple of 4 bytes in length");
-
+
unsigned char *BufPtr = (unsigned char *)MemBuf->getBufferStart();
unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize();
-
+
// If we have a wrapper header, parse it and ignore the non-bc file contents.
// The magic number is 0x0B17C0DE stored in little endian.
if (isBitcodeWrapper(BufPtr, EndBufPtr))
if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr))
return Error("Invalid bitcode wrapper header");
-
+
BitstreamReader StreamFile(BufPtr, EndBufPtr);
BitstreamCursor Stream(StreamFile);
StreamFile.CollectBlockInfoNames();
-
+
// Read the stream signature.
char Signature[6];
Signature[0] = Stream.Read(8);
@@ -478,7 +495,7 @@ static int AnalyzeBitcode() {
Signature[3] = Stream.Read(4);
Signature[4] = Stream.Read(4);
Signature[5] = Stream.Read(4);
-
+
// Autodetect the file contents, if it is one we know.
CurStreamType = UnknownBitstream;
if (Signature[0] == 'B' && Signature[1] == 'C' &&
@@ -487,71 +504,72 @@ static int AnalyzeBitcode() {
CurStreamType = LLVMIRBitstream;
unsigned NumTopBlocks = 0;
-
+
// Parse the top-level structure. We only allow blocks at the top-level.
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
if (Code != bitc::ENTER_SUBBLOCK)
return Error("Invalid record at top-level");
-
+
if (ParseBlock(Stream, 0))
return true;
++NumTopBlocks;
}
-
- if (Dump) std::cerr << "\n\n";
-
+
+ if (Dump) errs() << "\n\n";
+
uint64_t BufferSizeBits = (EndBufPtr-BufPtr)*CHAR_BIT;
// Print a summary of the read file.
- std::cerr << "Summary of " << InputFilename << ":\n";
- std::cerr << " Total size: ";
+ errs() << "Summary of " << InputFilename << ":\n";
+ errs() << " Total size: ";
PrintSize(BufferSizeBits);
- std::cerr << "\n";
- std::cerr << " Stream type: ";
+ errs() << "\n";
+ errs() << " Stream type: ";
switch (CurStreamType) {
default: assert(0 && "Unknown bitstream type");
- case UnknownBitstream: std::cerr << "unknown\n"; break;
- case LLVMIRBitstream: std::cerr << "LLVM IR\n"; break;
+ case UnknownBitstream: errs() << "unknown\n"; break;
+ case LLVMIRBitstream: errs() << "LLVM IR\n"; break;
}
- std::cerr << " # Toplevel Blocks: " << NumTopBlocks << "\n";
- std::cerr << "\n";
+ errs() << " # Toplevel Blocks: " << NumTopBlocks << "\n";
+ errs() << "\n";
// Emit per-block stats.
- std::cerr << "Per-block Summary:\n";
+ errs() << "Per-block Summary:\n";
for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
E = BlockIDStats.end(); I != E; ++I) {
- std::cerr << " Block ID #" << I->first;
+ errs() << " Block ID #" << I->first;
if (const char *BlockName = GetBlockName(I->first, StreamFile))
- std::cerr << " (" << BlockName << ")";
- std::cerr << ":\n";
-
+ errs() << " (" << BlockName << ")";
+ errs() << ":\n";
+
const PerBlockIDStats &Stats = I->second;
- std::cerr << " Num Instances: " << Stats.NumInstances << "\n";
- std::cerr << " Total Size: ";
+ errs() << " Num Instances: " << Stats.NumInstances << "\n";
+ errs() << " Total Size: ";
PrintSize(Stats.NumBits);
- std::cerr << "\n";
- std::cerr << " % of file: "
- << Stats.NumBits/(double)BufferSizeBits*100 << "\n";
+ errs() << "\n";
+ double pct = (Stats.NumBits * 100.0) / BufferSizeBits;
+ errs() << " Percent of file: " << format("%2.4f%%", pct) << "\n";
if (Stats.NumInstances > 1) {
- std::cerr << " Average Size: ";
+ errs() << " Average Size: ";
PrintSize(Stats.NumBits/(double)Stats.NumInstances);
- std::cerr << "\n";
- std::cerr << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"
- << Stats.NumSubBlocks/(double)Stats.NumInstances << "\n";
- std::cerr << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"
- << Stats.NumAbbrevs/(double)Stats.NumInstances << "\n";
- std::cerr << " Tot/Avg Records: " << Stats.NumRecords << "/"
- << Stats.NumRecords/(double)Stats.NumInstances << "\n";
+ errs() << "\n";
+ errs() << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"
+ << Stats.NumSubBlocks/(double)Stats.NumInstances << "\n";
+ errs() << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"
+ << Stats.NumAbbrevs/(double)Stats.NumInstances << "\n";
+ errs() << " Tot/Avg Records: " << Stats.NumRecords << "/"
+ << Stats.NumRecords/(double)Stats.NumInstances << "\n";
} else {
- std::cerr << " Num SubBlocks: " << Stats.NumSubBlocks << "\n";
- std::cerr << " Num Abbrevs: " << Stats.NumAbbrevs << "\n";
- std::cerr << " Num Records: " << Stats.NumRecords << "\n";
+ errs() << " Num SubBlocks: " << Stats.NumSubBlocks << "\n";
+ errs() << " Num Abbrevs: " << Stats.NumAbbrevs << "\n";
+ errs() << " Num Records: " << Stats.NumRecords << "\n";
+ }
+ if (Stats.NumRecords) {
+ double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords;
+ errs() << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n";
}
- if (Stats.NumRecords)
- std::cerr << " % Abbrev Recs: " << (Stats.NumAbbreviatedRecords/
- (double)Stats.NumRecords)*100 << "\n";
- std::cerr << "\n";
-
+ errs() << "\n";
+
// Print a histogram of the codes we see.
if (!NoHistogram && !Stats.CodeFreq.empty()) {
std::vector<std::pair<unsigned, unsigned> > FreqPairs; // <freq,code>
@@ -560,29 +578,29 @@ static int AnalyzeBitcode() {
FreqPairs.push_back(std::make_pair(Freq, i));
std::stable_sort(FreqPairs.begin(), FreqPairs.end());
std::reverse(FreqPairs.begin(), FreqPairs.end());
-
- std::cerr << "\tRecord Histogram:\n";
+
+ errs() << "\tRecord Histogram:\n";
fprintf(stderr, "\t\t Count # Bits %% Abv Record Kind\n");
for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) {
const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second];
-
+
fprintf(stderr, "\t\t%7d %9llu ", RecStats.NumInstances,
(unsigned long long)RecStats.TotalBits);
-
+
if (RecStats.NumAbbrev)
fprintf(stderr, "%7.2f ",
(double)RecStats.NumAbbrev/RecStats.NumInstances*100);
else
fprintf(stderr, " ");
-
- if (const char *CodeName =
+
+ if (const char *CodeName =
GetCodeName(FreqPairs[i].second, I->first, StreamFile))
fprintf(stderr, "%s\n", CodeName);
else
fprintf(stderr, "UnknownCode%d\n", FreqPairs[i].second);
}
- std::cerr << "\n";
-
+ errs() << "\n";
+
}
}
return 0;
@@ -595,6 +613,6 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm-bcanalyzer file analyzer\n");
-
+
return AnalyzeBitcode();
}
diff --git a/tools/llvm-config/CMakeLists.txt b/tools/llvm-config/CMakeLists.txt
index 2cfd6bb..7638f3c 100644
--- a/tools/llvm-config/CMakeLists.txt
+++ b/tools/llvm-config/CMakeLists.txt
@@ -1,5 +1,6 @@
include(TestBigEndian)
+include(FindPerl)
if( NOT PERL_FOUND )
message(FATAL_ERROR "Perl required but not found!")
endif( NOT PERL_FOUND )
@@ -7,6 +8,8 @@ endif( NOT PERL_FOUND )
set(PERL ${PERL_EXECUTABLE})
set(VERSION PACKAGE_VERSION)
set(PREFIX ${LLVM_BINARY_DIR}) # TODO: Root for `make install'.
+set(abs_top_srcdir ${LLVM_MAIN_SRC_DIR})
+set(abs_top_builddir ${LLVM_BINARY_DIR})
execute_process(COMMAND date
OUTPUT_VARIABLE LLVM_CONFIGTIME
OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -26,7 +29,7 @@ endif( IS_BIG_ENDIAN )
set(SHLIBEXT ${LTDL_SHLIB_EXT})
#EXEEXT already set.
set(OS "${CMAKE_SYSTEM}")
-set(ARCH "X86") # TODO: This gives "i686" in Linux: "${CMAKE_SYSTEM_PROCESSOR}")
+set(ARCH "${LLVM_NATIVE_ARCH}")
get_system_libs(LLVM_SYSTEM_LIBS_LIST)
foreach(l ${LLVM_SYSTEM_LIBS_LIST})
@@ -103,7 +106,6 @@ add_custom_command(OUTPUT ${LLVM_CONFIG}
COMMAND ${CMAKE_COMMAND} -E remove -f temp.sed
COMMAND cat ${FINAL_LIBDEPS} >> ${LLVM_CONFIG}
COMMAND chmod +x ${LLVM_CONFIG}
- COMMAND cd ${CMAKE_BINARY_DIR} && ${CMAKE_COMMAND} -U HAVE_LLVM_CONFIG -D LLVM_BINARY_DIR="${LLVM_BINARY_DIR}" ${CMAKE_SOURCE_DIR}
DEPENDS ${FINAL_LIBDEPS} ${LLVM_CONFIG_IN}
COMMENT "Building llvm-config script."
)
@@ -113,7 +115,37 @@ add_custom_target(llvm-config.target ALL
add_dependencies(llvm-config.target ${llvm_lib_targets})
+# Make sure that llvm-config builds before the llvm tools, so we have
+# LibDeps.txt and can use it for updating the hard-coded library
+# dependencies on cmake/modules/LLVMLibDeps.cmake when the tools'
+# build fail due to outdated dependencies:
+set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} llvm-config.target)
+
install(FILES ${LLVM_CONFIG}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
DESTINATION bin)
+
+
+# Regeneration of library dependencies.
+
+# See the comments at the end of cmake/modules/LLVMConfig.cmake for
+# notes and guidelines.
+
+set(LLVMLibDeps ${LLVM_MAIN_SRC_DIR}/cmake/modules/LLVMLibDeps.cmake)
+set(LLVMLibDeps_TMP ${CMAKE_CURRENT_BINARY_DIR}/LLVMLibDeps.cmake.tmp)
+
+add_custom_command(OUTPUT ${LLVMLibDeps_TMP}
+ COMMAND sed -e s'@\\.a@@g' -e s'@\\.so@@g' -e 's@libLLVM@LLVM@g' -e 's@: @ @' -e 's@\\\(.*\\\)@set\(MSVC_LIB_DEPS_\\1\)@' ${FINAL_LIBDEPS} > ${LLVMLibDeps_TMP}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LLVMLibDeps_TMP} ${LLVMLibDeps}
+ DEPENDS ${FINAL_LIBDEPS}
+ COMMENT "Updating cmake library dependencies file ${LLVMLibDeps}"
+ )
+
+if( LLVM_TARGETS_TO_BUILD STREQUAL LLVM_ALL_TARGETS )
+ add_custom_target(llvmlibdeps.target ALL DEPENDS ${LLVMLibDeps_TMP})
+ add_dependencies(llvmlibdeps.target llvm-config.target)
+ set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} llvmlibdeps.target)
+endif()
+
+set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} PARENT_SCOPE)
diff --git a/tools/llvm-config/llvm-config.in.in b/tools/llvm-config/llvm-config.in.in
index 36b5112..7f93f16 100644
--- a/tools/llvm-config/llvm-config.in.in
+++ b/tools/llvm-config/llvm-config.in.in
@@ -26,17 +26,6 @@ my $PREFIX = q{@LLVM_PREFIX@};
my $LLVM_CONFIGTIME = q{@LLVM_CONFIGTIME@};
my $LLVM_SRC_ROOT = q{@abs_top_srcdir@};
my $LLVM_OBJ_ROOT = q{@abs_top_builddir@};
-my $LLVM_ON_WIN32 = q{@LLVM_ON_WIN32@};
-my $LLVM_ON_UNIX = q{@LLVM_ON_UNIX@};
-my $LLVMGCCDIR = q{@LLVMGCCDIR@};
-my $LLVMGCC = q{@LLVMGCC@};
-my $LLVMGXX = q{@LLVMGXX@};
-my $LLVMGCC_VERSION = q{@LLVMGCC_VERSION@};
-my $LLVMGCC_MAJVERS = q{@LLVMGCC_MAJVERS@};
-my $ENDIAN = q{@ENDIAN@};
-my $SHLIBEXT = q{@SHLIBEXT@};
-my $EXEEXT = q{@EXEEXT@};
-my $OS = q{@OS@};
my $ARCH = lc(q{@ARCH@});
my $TARGET_TRIPLE = q{@target@};
my $TARGETS_TO_BUILD = q{@TARGETS_TO_BUILD@};
@@ -81,12 +70,15 @@ $ABS_OBJ_ROOT = `cd $ABS_OBJ_ROOT; $PWD` if (-d $ABS_OBJ_ROOT);
chomp($ABS_OBJ_ROOT);
my $INCLUDEDIR = "$ABS_RUN_DIR/include";
+my $INCLUDEOPTION = "-I$INCLUDEDIR";
my $LIBDIR = "$ABS_RUN_DIR/lib";
my $BINDIR = "$ABS_RUN_DIR/bin";
if ($ABS_RUN_DIR eq $ABS_OBJ_ROOT) {
# If we are running out of the build directory, the include dir is in the
# srcdir.
$INCLUDEDIR = "$LLVM_SRC_ROOT/include";
+ # We need include files from both the srcdir and objdir.
+ $INCLUDEOPTION = "-I$INCLUDEDIR -I$LLVM_OBJ_ROOT/include"
} else {
# If installed, ignore the prefix the tree was configured with, use the
# current prefix.
@@ -120,11 +112,11 @@ foreach my $arg (@ARGV) {
} elsif ($arg eq "--libdir") {
$has_opt = 1; print "$LIBDIR\n";
} elsif ($arg eq "--cppflags") {
- $has_opt = 1; print "-I$INCLUDEDIR $CPPFLAGS\n";
+ $has_opt = 1; print "$INCLUDEOPTION $CPPFLAGS\n";
} elsif ($arg eq "--cflags") {
- $has_opt = 1; print "-I$INCLUDEDIR $CFLAGS\n";
+ $has_opt = 1; print "$INCLUDEOPTION $CFLAGS\n";
} elsif ($arg eq "--cxxflags") {
- $has_opt = 1; print "-I$INCLUDEDIR $CXXFLAGS\n";
+ $has_opt = 1; print "$INCLUDEOPTION $CXXFLAGS\n";
} elsif ($arg eq "--ldflags") {
$has_opt = 1; print "-L$LIBDIR $LDFLAGS $SYSTEM_LIBS\n";
} elsif ($arg eq "--libs") {
@@ -330,7 +322,16 @@ sub build_name_map {
foreach my $target (@TARGETS_BUILT) {
# FIXME: Temporary, until we don't switch all targets
if (defined $NAME_MAP{$target.'asmprinter'}) {
- $NAME_MAP{$target} = [$target.'asmprinter', $target.'codegen']
+ $NAME_MAP{$target} = [$target.'info',
+ $target.'asmprinter',
+ $target.'codegen']
+ } else {
+ $NAME_MAP{$target} = [$target.'info',
+ $NAME_MAP{$target}[0]]
+ }
+
+ if (defined $NAME_MAP{$target.'asmparser'}) {
+ push @{$NAME_MAP{$target}},$target.'asmparser'
}
}
diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp
index 901c8e9..b8b1a39 100644
--- a/tools/llvm-dis/llvm-dis.cpp
+++ b/tools/llvm-dis/llvm-dis.cpp
@@ -18,18 +18,13 @@
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
-#include "llvm/PassManager.h"
#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Streams.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
-#include <iostream>
-#include <fstream>
#include <memory>
using namespace llvm;
@@ -41,7 +36,7 @@ OutputFilename("o", cl::desc("Override output filename"),
cl::value_desc("filename"));
static cl::opt<bool>
-Force("f", cl::desc("Overwrite output files"));
+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);
@@ -51,95 +46,66 @@ int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
- try {
- cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
-
- std::ostream *Out = &std::cout; // Default to printing to stdout.
- std::string ErrorMessage;
-
- std::auto_ptr<Module> M;
-
- if (MemoryBuffer *Buffer
- = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)) {
- M.reset(ParseBitcodeFile(Buffer, Context, &ErrorMessage));
- delete Buffer;
- }
+
+
+ cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
+
+ std::string ErrorMessage;
+ std::auto_ptr<Module> M;
+
+ if (MemoryBuffer *Buffer
+ = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)) {
+ M.reset(ParseBitcodeFile(Buffer, Context, &ErrorMessage));
+ delete Buffer;
+ }
- if (M.get() == 0) {
- cerr << argv[0] << ": ";
- if (ErrorMessage.size())
- cerr << ErrorMessage << "\n";
- else
- cerr << "bitcode didn't read correctly.\n";
- return 1;
- }
-
- if (DontPrint) {
- // Just use stdout. We won't actually print anything on it.
- } else if (OutputFilename != "") { // Specified an output filename?
- if (OutputFilename != "-") { // Not stdout?
- if (!Force && std::ifstream(OutputFilename.c_str())) {
- // If force is not specified, make sure not to overwrite a file!
- cerr << argv[0] << ": error opening '" << OutputFilename
- << "': file exists! Sending to standard output.\n";
- } else {
- Out = new std::ofstream(OutputFilename.c_str());
- }
- }
+ if (M.get() == 0) {
+ errs() << argv[0] << ": ";
+ if (ErrorMessage.size())
+ errs() << ErrorMessage << "\n";
+ else
+ errs() << "bitcode didn't read correctly.\n";
+ return 1;
+ }
+
+ // Just use stdout. We won't actually print anything on it.
+ if (DontPrint)
+ OutputFilename = "-";
+
+ if (OutputFilename.empty()) { // Unspecified output, infer it.
+ if (InputFilename == "-") {
+ OutputFilename = "-";
} else {
- if (InputFilename == "-") {
- OutputFilename = "-";
- } else {
- std::string IFN = InputFilename;
- int Len = IFN.length();
- if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') {
- // Source ends in .bc
- OutputFilename = std::string(IFN.begin(), IFN.end()-3)+".ll";
- } else {
- OutputFilename = IFN+".ll";
- }
-
- if (!Force && std::ifstream(OutputFilename.c_str())) {
- // If force is not specified, make sure not to overwrite a file!
- cerr << argv[0] << ": error opening '" << OutputFilename
- << "': file exists! Sending to standard output.\n";
- } else {
- Out = new std::ofstream(OutputFilename.c_str());
-
- // Make sure that the Out file gets unlinked from the disk if we get a
- // SIGINT
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
- }
- }
- }
-
- if (!Out->good()) {
- cerr << argv[0] << ": error opening " << OutputFilename
- << ": sending to stdout instead!\n";
- Out = &std::cout;
- }
-
- // All that llvm-dis does is write the assembly to a file.
- if (!DontPrint) {
- PassManager Passes;
- raw_os_ostream L(*Out);
- Passes.add(createPrintModulePass(&L));
- Passes.run(*M.get());
+ const std::string &IFN = InputFilename;
+ int Len = IFN.length();
+ // If the source ends in .bc, strip it off.
+ if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c')
+ OutputFilename = std::string(IFN.begin(), IFN.end()-3)+".ll";
+ else
+ OutputFilename = IFN+".ll";
}
+ }
- if (Out != &std::cout) {
- ((std::ofstream*)Out)->close();
- delete Out;
- }
- return 0;
- } catch (const std::string& msg) {
- cerr << argv[0] << ": " << msg << "\n";
- } catch (...) {
- cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
+ // 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));
+ if (!ErrorInfo.empty()) {
+ errs() << ErrorInfo << '\n';
+ return 1;
}
- return 1;
+ // All that llvm-dis does is write the assembly to a file.
+ if (!DontPrint)
+ *Out << *M;
+
+ return 0;
}
diff --git a/tools/llvm-extract/CMakeLists.txt b/tools/llvm-extract/CMakeLists.txt
index 88e9343..a4e3266 100644
--- a/tools/llvm-extract/CMakeLists.txt
+++ b/tools/llvm-extract/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_LINK_COMPONENTS ipo bitreader bitwriter)
+set(LLVM_LINK_COMPONENTS asmparser ipo bitreader bitwriter)
add_llvm_tool(llvm-extract
llvm-extract.cpp
diff --git a/tools/llvm-extract/Makefile b/tools/llvm-extract/Makefile
index 2ef8841..5672aa3 100644
--- a/tools/llvm-extract/Makefile
+++ b/tools/llvm-extract/Makefile
@@ -10,7 +10,7 @@
LEVEL = ../..
TOOLNAME = llvm-extract
-LINK_COMPONENTS := ipo bitreader bitwriter
+LINK_COMPONENTS := ipo bitreader bitwriter asmparser
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp
index af0cf07..517244f 100644
--- a/tools/llvm-extract/llvm-extract.cpp
+++ b/tools/llvm-extract/llvm-extract.cpp
@@ -15,17 +15,19 @@
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
+#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/IRReader.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/SystemUtils.h"
#include "llvm/System/Signals.h"
-#include <iostream>
#include <memory>
-#include <fstream>
using namespace llvm;
// InputFilename - The filename to read from.
@@ -38,7 +40,7 @@ OutputFilename("o", cl::desc("Specify output filename"),
cl::value_desc("filename"), cl::init("-"));
static cl::opt<bool>
-Force("f", cl::desc("Overwrite output files"));
+Force("f", cl::desc("Enable binary output on terminals"));
static cl::opt<bool>
DeleteFn("delete", cl::desc("Delete specified Globals from Module"));
@@ -57,28 +59,25 @@ static cl::opt<std::string>
ExtractGlobal("glob", cl::desc("Specify global to extract"), cl::init(""),
cl::value_desc("global"));
+static cl::opt<bool>
+OutputAssembly("S",
+ cl::desc("Write output as LLVM assembly"), cl::Hidden);
+
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n");
+ SMDiagnostic Err;
std::auto_ptr<Module> M;
-
- MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename);
- if (Buffer == 0) {
- cerr << argv[0] << ": Error reading file '" + InputFilename + "'\n";
- return 1;
- } else {
- M.reset(ParseBitcodeFile(Buffer, Context));
- }
- delete Buffer;
-
+ M.reset(ParseIRFile(InputFilename, Err, Context));
+
if (M.get() == 0) {
- cerr << argv[0] << ": bitcode didn't read correctly.\n";
+ Err.Print(argv[0], errs());
return 1;
}
@@ -91,8 +90,8 @@ int main(int argc, char **argv) {
Function *F = M.get()->getFunction(ExtractFunc);
if (F == 0 && G == 0) {
- cerr << argv[0] << ": program doesn't contain function named '"
- << ExtractFunc << "' or a global named '" << ExtractGlobal << "'!\n";
+ errs() << argv[0] << ": program doesn't contain function named '"
+ << ExtractFunc << "' or a global named '" << ExtractGlobal << "'!\n";
return 1;
}
@@ -111,28 +110,24 @@ int main(int argc, char **argv) {
Passes.add(createDeadTypeEliminationPass()); // Remove dead types...
Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls
- std::ostream *Out = 0;
-
- if (OutputFilename != "-") { // Not stdout?
- if (!Force && std::ifstream(OutputFilename.c_str())) {
- // If force is not specified, make sure not to overwrite a file!
- cerr << argv[0] << ": error opening '" << OutputFilename
- << "': file exists!\n"
- << "Use -f command line argument to force output\n";
- return 1;
- }
- std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
- std::ios::binary;
- Out = new std::ofstream(OutputFilename.c_str(), io_mode);
- } else { // Specified stdout
- // FIXME: cout is not binary!
- Out = &std::cout;
+ // 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);
+ if (!ErrorInfo.empty()) {
+ errs() << ErrorInfo << '\n';
+ return 1;
}
- Passes.add(CreateBitcodeWriterPass(*Out));
+ if (OutputAssembly)
+ Passes.add(createPrintModulePass(&Out));
+ else if (Force || !CheckBitcodeOutputToConsole(Out, true))
+ Passes.add(createBitcodeWriterPass(Out));
+
Passes.run(*M.get());
- if (Out != &std::cout)
- delete Out;
return 0;
}
diff --git a/tools/llvm-ld/Optimize.cpp b/tools/llvm-ld/Optimize.cpp
index e466895..6143dc8 100644
--- a/tools/llvm-ld/Optimize.cpp
+++ b/tools/llvm-ld/Optimize.cpp
@@ -18,6 +18,7 @@
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/StandardPasses.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
@@ -25,7 +26,6 @@
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/PluginLoader.h"
-#include <iostream>
using namespace llvm;
// Pass Name Options as generated by the PassNameParser
@@ -109,8 +109,8 @@ void Optimize(Module* M) {
if (Opt->getNormalCtor())
addPass(Passes, Opt->getNormalCtor()());
else
- std::cerr << "llvm-ld: cannot create pass: " << Opt->getPassName()
- << "\n";
+ errs() << "llvm-ld: cannot create pass: " << Opt->getPassName()
+ << "\n";
}
// The user's passes may leave cruft around. Clean up after them them but
diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp
index 2b9d255..ef3c250 100644
--- a/tools/llvm-ld/llvm-ld.cpp
+++ b/tools/llvm-ld/llvm-ld.cpp
@@ -12,7 +12,7 @@
// Additionally, this program outputs a shell script that is used to invoke LLI
// to execute the program. In this manner, the generated executable (a.out for
// example), is directly executable, whereas the bitcode file actually lives in
-// the a.out.bc file generated by this program. Also, Force is on by default.
+// the a.out.bc file generated by this program.
//
// Note that if someone (or a script) deletes the executable program generated,
// the .bc file will be left around. Considering that this is a temporary hack,
@@ -29,21 +29,24 @@
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Streams.h"
#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
#include "llvm/Config/config.h"
-#include <fstream>
#include <memory>
#include <cstring>
using namespace llvm;
+// Rightly this should go in a header file but it just seems such a waste.
+namespace llvm {
+extern void Optimize(Module*);
+}
+
// Input/Output Options
static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
cl::desc("<input bitcode files>"));
@@ -52,6 +55,10 @@ static cl::opt<std::string> OutputFilename("o", cl::init("a.out"),
cl::desc("Override output filename"),
cl::value_desc("filename"));
+static cl::opt<std::string> BitcodeOutputFilename("b", cl::init(""),
+ cl::desc("Override bitcode output filename"),
+ cl::value_desc("filename"));
+
static cl::opt<bool> Verbose("v",
cl::desc("Print information about actions taken"));
@@ -124,7 +131,7 @@ static std::string progname;
/// Message - The message to print to standard error.
///
static void PrintAndExit(const std::string &Message, int errcode = 1) {
- cerr << progname << ": " << Message << "\n";
+ errs() << progname << ": " << Message << "\n";
llvm_shutdown();
exit(errcode);
}
@@ -133,8 +140,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)
- cout << "'" << *I << "'" << " ";
- cout << "\n" << std::flush;
+ outs() << "'" << *I << "'" << " ";
+ outs() << "\n"; outs().flush();
}
/// CopyEnv - This function takes an array of environment variables and makes a
@@ -219,14 +226,14 @@ static void RemoveEnv(const char * name, char ** const envp) {
void GenerateBitcode(Module* M, const std::string& FileName) {
if (Verbose)
- cout << "Generating Bitcode To " << FileName << '\n';
+ outs() << "Generating Bitcode To " << FileName << '\n';
// Create the output file.
- std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
- std::ios::binary;
- std::ofstream Out(FileName.c_str(), io_mode);
- if (!Out.good())
- PrintAndExit("error opening '" + FileName + "' for writing!");
+ std::string ErrorInfo;
+ raw_fd_ostream Out(FileName.c_str(), ErrorInfo,
+ raw_fd_ostream::F_Binary);
+ if (!ErrorInfo.empty())
+ PrintAndExit(ErrorInfo);
// Ensure that the bitcode file gets removed from the disk if we get a
// terminating signal.
@@ -267,7 +274,7 @@ static int GenerateAssembly(const std::string &OutputFilename,
args.push_back(0);
if (Verbose) {
- cout << "Generating Assembly With: \n";
+ outs() << "Generating Assembly With: \n";
PrintCommand(args);
}
@@ -290,7 +297,7 @@ static int GenerateCFile(const std::string &OutputFile,
args.push_back(0);
if (Verbose) {
- cout << "Generating C Source With: \n";
+ outs() << "Generating C Source With: \n";
PrintCommand(args);
}
@@ -387,7 +394,7 @@ static int GenerateNative(const std::string &OutputFilename,
Args.push_back(0);
if (Verbose) {
- cout << "Generating Native Executable With:\n";
+ outs() << "Generating Native Executable With:\n";
PrintCommand(Args);
}
@@ -402,13 +409,14 @@ static int GenerateNative(const std::string &OutputFilename,
/// bitcode file for the program.
static void EmitShellScript(char **argv) {
if (Verbose)
- cout << "Emitting Shell Script\n";
+ outs() << "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
// build tree to the destination file.
std::string ErrMsg;
- sys::Path llvmstub = FindExecutable("llvm-stub.exe", argv[0]);
+ sys::Path llvmstub = FindExecutable("llvm-stub.exe", argv[0],
+ (void *)(intptr_t)&Optimize);
if (llvmstub.isEmpty())
PrintAndExit("Could not find llvm-stub.exe executable!");
@@ -419,9 +427,10 @@ static void EmitShellScript(char **argv) {
#endif
// Output the script to start the program...
- std::ofstream Out2(OutputFilename.c_str());
- if (!Out2.good())
- PrintAndExit("error opening '" + OutputFilename + "' for writing!");
+ std::string ErrorInfo;
+ raw_fd_ostream Out2(OutputFilename.c_str(), ErrorInfo);
+ if (!ErrorInfo.empty())
+ PrintAndExit(ErrorInfo);
Out2 << "#!/bin/sh\n";
// Allow user to setenv LLVMINTERP if lli is not in their PATH.
@@ -457,9 +466,9 @@ static void EmitShellScript(char **argv) {
if (FullLibraryPath.isEmpty())
FullLibraryPath = sys::Path::FindLibrary(*i);
if (!FullLibraryPath.isEmpty())
- Out2 << " -load=" << FullLibraryPath.toString() << " \\\n";
+ Out2 << " -load=" << FullLibraryPath.str() << " \\\n";
}
- Out2 << " $0.bc ${1+\"$@\"}\n";
+ Out2 << " " << BitcodeOutputFilename << " ${1+\"$@\"}\n";
Out2.close();
}
@@ -497,17 +506,12 @@ static void BuildLinkItems(
}
}
-// Rightly this should go in a header file but it just seems such a waste.
-namespace llvm {
-extern void Optimize(Module*);
-}
-
int main(int argc, char **argv, char **envp) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
try {
// Initial global variable above for convenience printing of program name.
@@ -568,16 +572,20 @@ int main(int argc, char **argv, char **envp) {
sys::Path ExeFile( OutputFilename );
if (ExeFile.getSuffix() == "") {
ExeFile.appendSuffix("exe");
- OutputFilename = ExeFile.toString();
+ OutputFilename = ExeFile.str();
}
}
#endif
// Generate the bitcode for the optimized module.
- std::string RealBitcodeOutput = OutputFilename;
+ // If -b wasn't specified, use the name specified
+ // with -o to construct BitcodeOutputFilename.
+ if (BitcodeOutputFilename.empty()) {
+ BitcodeOutputFilename = OutputFilename;
+ if (!LinkAsLibrary) BitcodeOutputFilename += ".bc";
+ }
- if (!LinkAsLibrary) RealBitcodeOutput += ".bc";
- GenerateBitcode(Composite.get(), RealBitcodeOutput);
+ GenerateBitcode(Composite.get(), BitcodeOutputFilename);
// If we are not linking a library, generate either a native executable
// or a JIT shell script, depending upon what the user wants.
@@ -602,12 +610,12 @@ int main(int argc, char **argv, char **envp) {
const char* args[4];
args[0] = I->c_str();
- args[1] = RealBitcodeOutput.c_str();
+ args[1] = BitcodeOutputFilename.c_str();
args[2] = tmp_output.c_str();
args[3] = 0;
if (0 == sys::Program::ExecuteAndWait(prog, args, 0,0,0,0, &ErrMsg)) {
if (tmp_output.isBitcodeFile() || tmp_output.isBitcodeFile()) {
- sys::Path target(RealBitcodeOutput);
+ sys::Path target(BitcodeOutputFilename);
target.eraseFromDisk();
if (tmp_output.renamePathOnDisk(target, &ErrMsg))
PrintAndExit(ErrMsg, 2);
@@ -633,21 +641,22 @@ int main(int argc, char **argv, char **envp) {
sys::RemoveFileOnSignal(sys::Path(OutputFilename));
// Determine the locations of the llc and gcc programs.
- sys::Path llc = FindExecutable("llc", argv[0]);
+ sys::Path llc = FindExecutable("llc", argv[0],
+ (void *)(intptr_t)&Optimize);
if (llc.isEmpty())
PrintAndExit("Failed to find llc");
- sys::Path gcc = FindExecutable("gcc", argv[0]);
+ sys::Path gcc = sys::Program::FindProgramByName("gcc");
if (gcc.isEmpty())
PrintAndExit("Failed to find gcc");
// Generate an assembly language file for the bitcode.
std::string ErrMsg;
- if (0 != GenerateAssembly(AssemblyFile.toString(), RealBitcodeOutput,
+ if (0 != GenerateAssembly(AssemblyFile.str(), BitcodeOutputFilename,
llc, ErrMsg))
PrintAndExit(ErrMsg);
- if (0 != GenerateNative(OutputFilename, AssemblyFile.toString(),
+ if (0 != GenerateNative(OutputFilename, AssemblyFile.str(),
NativeLinkItems, gcc, envp, ErrMsg))
PrintAndExit(ErrMsg);
@@ -662,22 +671,22 @@ int main(int argc, char **argv, char **envp) {
sys::RemoveFileOnSignal(sys::Path(OutputFilename));
// Determine the locations of the llc and gcc programs.
- sys::Path llc = FindExecutable("llc", argv[0]);
+ sys::Path llc = FindExecutable("llc", argv[0],
+ (void *)(intptr_t)&Optimize);
if (llc.isEmpty())
PrintAndExit("Failed to find llc");
- sys::Path gcc = FindExecutable("gcc", argv[0]);
+ sys::Path gcc = sys::Program::FindProgramByName("gcc");
if (gcc.isEmpty())
PrintAndExit("Failed to find gcc");
// Generate an assembly language file for the bitcode.
std::string ErrMsg;
- if (0 != GenerateCFile(
- CFile.toString(), RealBitcodeOutput, llc, ErrMsg))
+ if (GenerateCFile(CFile.str(), BitcodeOutputFilename, llc, ErrMsg))
PrintAndExit(ErrMsg);
- if (0 != GenerateNative(OutputFilename, CFile.toString(),
- NativeLinkItems, gcc, envp, ErrMsg))
+ if (GenerateNative(OutputFilename, CFile.str(),
+ NativeLinkItems, gcc, envp, ErrMsg))
PrintAndExit(ErrMsg);
// Remove the assembly language file.
@@ -693,10 +702,10 @@ int main(int argc, char **argv, char **envp) {
PrintAndExit(ErrMsg);
// Make the bitcode file readable and directly executable in LLEE as well
- if (sys::Path(RealBitcodeOutput).makeExecutableOnDisk(&ErrMsg))
+ if (sys::Path(BitcodeOutputFilename).makeExecutableOnDisk(&ErrMsg))
PrintAndExit(ErrMsg);
- if (sys::Path(RealBitcodeOutput).makeReadableOnDisk(&ErrMsg))
+ if (sys::Path(BitcodeOutputFilename).makeReadableOnDisk(&ErrMsg))
PrintAndExit(ErrMsg);
}
} catch (const std::string& msg) {
diff --git a/tools/llvm-link/CMakeLists.txt b/tools/llvm-link/CMakeLists.txt
index 69a435e..11933f7 100644
--- a/tools/llvm-link/CMakeLists.txt
+++ b/tools/llvm-link/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_LINK_COMPONENTS linker bitreader bitwriter)
+set(LLVM_LINK_COMPONENTS linker bitreader bitwriter asmparser)
add_llvm_tool(llvm-link
llvm-link.cpp
diff --git a/tools/llvm-link/Makefile b/tools/llvm-link/Makefile
index ddc7a59..2637018 100644
--- a/tools/llvm-link/Makefile
+++ b/tools/llvm-link/Makefile
@@ -9,7 +9,7 @@
LEVEL = ../..
TOOLNAME = llvm-link
-LINK_COMPONENTS = linker bitreader bitwriter
+LINK_COMPONENTS = linker bitreader bitwriter asmparser
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp
index f65e602..fae4d10 100644
--- a/tools/llvm-link/llvm-link.cpp
+++ b/tools/llvm-link/llvm-link.cpp
@@ -21,11 +21,11 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Streams.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/IRReader.h"
#include "llvm/System/Signals.h"
#include "llvm/System/Path.h"
-#include <fstream>
-#include <iostream>
#include <memory>
using namespace llvm;
@@ -37,7 +37,12 @@ static cl::opt<std::string>
OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
cl::value_desc("filename"));
-static cl::opt<bool> Force("f", cl::desc("Overwrite output files"));
+static cl::opt<bool>
+Force("f", cl::desc("Enable binary output on terminals"));
+
+static cl::opt<bool>
+OutputAssembly("S",
+ cl::desc("Write output as LLVM assembly"), cl::Hidden);
static cl::opt<bool>
Verbose("v", cl::desc("Print information about actions taken"));
@@ -48,34 +53,28 @@ DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden);
// LoadFile - Read the specified bitcode file in and return it. This routine
// searches the link path for the specified file to try to find it...
//
-static inline std::auto_ptr<Module> LoadFile(const std::string &FN,
+static inline std::auto_ptr<Module> LoadFile(const char *argv0,
+ const std::string &FN,
LLVMContext& Context) {
sys::Path Filename;
if (!Filename.set(FN)) {
- cerr << "Invalid file name: '" << FN << "'\n";
+ errs() << "Invalid file name: '" << FN << "'\n";
return std::auto_ptr<Module>();
}
- std::string ErrorMessage;
+ SMDiagnostic Err;
if (Filename.exists()) {
- if (Verbose) cerr << "Loading '" << Filename.c_str() << "'\n";
+ if (Verbose) errs() << "Loading '" << Filename.c_str() << "'\n";
Module* Result = 0;
- const std::string &FNStr = Filename.toString();
- if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(FNStr,
- &ErrorMessage)) {
- Result = ParseBitcodeFile(Buffer, Context, &ErrorMessage);
- delete Buffer;
- }
+ const std::string &FNStr = Filename.str();
+ Result = ParseIRFile(FNStr, Err, Context);
if (Result) return std::auto_ptr<Module>(Result); // Load successful!
- if (Verbose) {
- cerr << "Error opening bitcode file: '" << Filename.c_str() << "'";
- if (ErrorMessage.size()) cerr << ": " << ErrorMessage;
- cerr << "\n";
- }
+ if (Verbose)
+ Err.Print(argv0, errs());
} else {
- cerr << "Bitcode file: '" << Filename.c_str() << "' does not exist.\n";
+ errs() << "Bitcode file: '" << Filename.c_str() << "' does not exist.\n";
}
return std::auto_ptr<Module>();
@@ -86,32 +85,34 @@ int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
unsigned BaseArg = 0;
std::string ErrorMessage;
- std::auto_ptr<Module> Composite(LoadFile(InputFilenames[BaseArg], Context));
+ std::auto_ptr<Module> Composite(LoadFile(argv[0],
+ InputFilenames[BaseArg], Context));
if (Composite.get() == 0) {
- cerr << argv[0] << ": error loading file '"
- << InputFilenames[BaseArg] << "'\n";
+ errs() << argv[0] << ": error loading file '"
+ << InputFilenames[BaseArg] << "'\n";
return 1;
}
for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) {
- std::auto_ptr<Module> M(LoadFile(InputFilenames[i], Context));
+ std::auto_ptr<Module> M(LoadFile(argv[0],
+ InputFilenames[i], Context));
if (M.get() == 0) {
- cerr << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n";
+ errs() << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n";
return 1;
}
- if (Verbose) cerr << "Linking in '" << InputFilenames[i] << "'\n";
+ if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n";
if (Linker::LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
- cerr << argv[0] << ": link error in '" << InputFilenames[i]
- << "': " << ErrorMessage << "\n";
+ errs() << argv[0] << ": link error in '" << InputFilenames[i]
+ << "': " << ErrorMessage << "\n";
return 1;
}
}
@@ -119,39 +120,32 @@ int main(int argc, char **argv) {
// TODO: Iterate over the -l list and link in any modules containing
// global symbols that have not been resolved so far.
- if (DumpAsm) cerr << "Here's the assembly:\n" << *Composite.get();
+ if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;
- // FIXME: cout is not binary!
- std::ostream *Out = &std::cout; // Default to printing to stdout...
- if (OutputFilename != "-") {
- if (!Force && std::ifstream(OutputFilename.c_str())) {
- // If force is not specified, make sure not to overwrite a file!
- cerr << argv[0] << ": error opening '" << OutputFilename
- << "': file exists!\n"
- << "Use -f command line argument to force output\n";
- return 1;
- }
- std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
- std::ios::binary;
- Out = new std::ofstream(OutputFilename.c_str(), io_mode);
- if (!Out->good()) {
- cerr << argv[0] << ": error opening '" << OutputFilename << "'!\n";
- return 1;
- }
+ std::string ErrorInfo;
+ std::auto_ptr<raw_ostream>
+ Out(new raw_fd_ostream(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.get())) {
- cerr << argv[0] << ": linked module is broken!\n";
+ if (verifyModule(*Composite)) {
+ errs() << argv[0] << ": linked module is broken!\n";
return 1;
}
- if (Verbose) cerr << "Writing bitcode...\n";
- WriteBitcodeToFile(Composite.get(), *Out);
+ if (Verbose) errs() << "Writing bitcode...\n";
+ if (OutputAssembly) {
+ *Out << *Composite;
+ } else if (Force || !CheckBitcodeOutputToConsole(*Out, true))
+ WriteBitcodeToFile(Composite.get(), *Out);
- if (Out != &std::cout) delete Out;
return 0;
}
diff --git a/tools/llvm-mc/AsmCond.h b/tools/llvm-mc/AsmCond.h
new file mode 100644
index 0000000..92a115e
--- /dev/null
+++ b/tools/llvm-mc/AsmCond.h
@@ -0,0 +1,40 @@
+//===- AsmCond.h - Assembly file conditional assembly ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ASMCOND_H
+#define ASMCOND_H
+
+namespace llvm {
+
+/// AsmCond - Class to support conditional assembly
+///
+/// The conditional assembly feature (.if, .else, .elseif and .endif) is
+/// implemented with AsmCond that tells us what we are in the middle of
+/// processing. Ignore can be either true or false. When true we are ignoring
+/// the block of code in the middle of a conditional.
+
+class AsmCond {
+public:
+ enum ConditionalAssemblyType {
+ NoCond, // no conditional is being processed
+ IfCond, // inside if conditional
+ ElseIfCond, // inside elseif conditional
+ ElseCond // inside else conditional
+ };
+
+ ConditionalAssemblyType TheCond;
+ bool CondMet;
+ bool Ignore;
+
+ AsmCond() : TheCond(NoCond), CondMet(false), Ignore(false) {}
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/tools/llvm-mc/AsmLexer.cpp b/tools/llvm-mc/AsmLexer.cpp
index 7b744fb..99055c6 100644
--- a/tools/llvm-mc/AsmLexer.cpp
+++ b/tools/llvm-mc/AsmLexer.cpp
@@ -12,30 +12,24 @@
//===----------------------------------------------------------------------===//
#include "AsmLexer.h"
-#include "llvm/ADT/StringSet.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Config/config.h" // for strtoull.
+#include "llvm/MC/MCAsmInfo.h"
#include <cerrno>
#include <cstdio>
#include <cstdlib>
using namespace llvm;
-static StringSet<> &getSS(void *TheSS) {
- return *(StringSet<>*)TheSS;
-}
-
-AsmLexer::AsmLexer(SourceMgr &SM) : SrcMgr(SM) {
+AsmLexer::AsmLexer(SourceMgr &SM, const MCAsmInfo &_MAI) : SrcMgr(SM),
+ MAI(_MAI) {
CurBuffer = 0;
CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
CurPtr = CurBuf->getBufferStart();
TokStart = 0;
-
- TheStringSet = new StringSet<>();
}
AsmLexer::~AsmLexer() {
- delete &getSS(TheStringSet);
}
SMLoc AsmLexer::getLoc() const {
@@ -48,12 +42,27 @@ void AsmLexer::PrintMessage(SMLoc Loc, const std::string &Msg,
}
/// ReturnError - Set the error to the specified string at the specified
-/// location. This is defined to always return asmtok::Error.
-asmtok::TokKind AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
+/// location. This is defined to always return AsmToken::Error.
+AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error");
- return asmtok::Error;
+ return AsmToken(AsmToken::Error, StringRef(Loc, 0));
+}
+
+/// EnterIncludeFile - Enter the specified file. This prints an error and
+/// returns true on failure.
+bool AsmLexer::EnterIncludeFile(const std::string &Filename) {
+ int NewBuf = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr));
+ if (NewBuf == -1)
+ return true;
+
+ // Save the line number and lex buffer of the includer.
+ CurBuffer = NewBuf;
+ CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
+ CurPtr = CurBuf->getBufferStart();
+ return false;
}
+
int AsmLexer::getNextChar() {
char CurChar = *CurPtr++;
switch (CurChar) {
@@ -72,6 +81,10 @@ int AsmLexer::getNextChar() {
CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
CurPtr = ParentIncludeLoc.getPointer();
+
+ // Reset the token start pointer to the start of the new file.
+ TokStart = CurPtr;
+
return getNextChar();
}
@@ -83,37 +96,20 @@ int AsmLexer::getNextChar() {
}
/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
-asmtok::TokKind AsmLexer::LexIdentifier() {
+AsmToken AsmLexer::LexIdentifier() {
while (isalnum(*CurPtr) || *CurPtr == '_' || *CurPtr == '$' ||
*CurPtr == '.' || *CurPtr == '@')
++CurPtr;
- // Unique string.
- CurStrVal =
- getSS(TheStringSet).GetOrCreateValue(TokStart, CurPtr, 0).getKeyData();
- return asmtok::Identifier;
-}
-
-/// LexPercent: Register: %[a-zA-Z0-9]+
-asmtok::TokKind AsmLexer::LexPercent() {
- if (!isalnum(*CurPtr))
- return asmtok::Percent; // Single %.
-
- while (isalnum(*CurPtr))
- ++CurPtr;
-
- // Unique string.
- CurStrVal =
- getSS(TheStringSet).GetOrCreateValue(TokStart, CurPtr, 0).getKeyData();
- return asmtok::Register;
+ return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart));
}
/// LexSlash: Slash: /
/// C-Style Comment: /* ... */
-asmtok::TokKind AsmLexer::LexSlash() {
+AsmToken AsmLexer::LexSlash() {
switch (*CurPtr) {
case '*': break; // C style comment.
case '/': return ++CurPtr, LexLineComment();
- default: return asmtok::Slash;
+ default: return AsmToken(AsmToken::Slash, StringRef(CurPtr, 1));
}
// C Style comment.
@@ -135,14 +131,16 @@ asmtok::TokKind AsmLexer::LexSlash() {
/// LexLineComment: Comment: #[^\n]*
/// : //[^\n]*
-asmtok::TokKind AsmLexer::LexLineComment() {
+AsmToken AsmLexer::LexLineComment() {
+ // FIXME: This is broken if we happen to a comment at the end of a file, which
+ // was .included, and which doesn't end with a newline.
int CurChar = getNextChar();
while (CurChar != '\n' && CurChar != '\n' && CurChar != EOF)
CurChar = getNextChar();
if (CurChar == EOF)
- return asmtok::Eof;
- return asmtok::EndOfStatement;
+ return AsmToken(AsmToken::Eof, StringRef(CurPtr, 0));
+ return AsmToken(AsmToken::EndOfStatement, StringRef(CurPtr, 0));
}
@@ -154,7 +152,7 @@ asmtok::TokKind AsmLexer::LexLineComment() {
/// Hex integer: 0x[0-9a-fA-F]+
/// Decimal integer: [1-9][0-9]*
/// TODO: FP literal.
-asmtok::TokKind AsmLexer::LexDigit() {
+AsmToken AsmLexer::LexDigit() {
if (*CurPtr == ':')
return ReturnError(TokStart, "FIXME: local label not implemented");
if (*CurPtr == 'f' || *CurPtr == 'b')
@@ -164,8 +162,8 @@ asmtok::TokKind AsmLexer::LexDigit() {
if (CurPtr[-1] != '0') {
while (isdigit(*CurPtr))
++CurPtr;
- CurIntVal = strtoll(TokStart, 0, 10);
- return asmtok::IntVal;
+ return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart),
+ strtoll(TokStart, 0, 10));
}
if (*CurPtr == 'b') {
@@ -177,8 +175,8 @@ asmtok::TokKind AsmLexer::LexDigit() {
// Requires at least one binary digit.
if (CurPtr == NumStart)
return ReturnError(CurPtr-2, "Invalid binary number");
- CurIntVal = strtoll(NumStart, 0, 2);
- return asmtok::IntVal;
+ return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart),
+ strtoll(NumStart, 0, 2));
}
if (*CurPtr == 'x') {
@@ -192,29 +190,28 @@ asmtok::TokKind AsmLexer::LexDigit() {
return ReturnError(CurPtr-2, "Invalid hexadecimal number");
errno = 0;
- CurIntVal = strtoll(NumStart, 0, 16);
if (errno == EINVAL)
return ReturnError(CurPtr-2, "Invalid hexadecimal number");
if (errno == ERANGE) {
errno = 0;
- CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
if (errno == EINVAL)
return ReturnError(CurPtr-2, "Invalid hexadecimal number");
if (errno == ERANGE)
return ReturnError(CurPtr-2, "Hexadecimal number out of range");
}
- return asmtok::IntVal;
+ return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart),
+ (int64_t) strtoull(NumStart, 0, 16));
}
// Must be an octal number, it starts with 0.
while (*CurPtr >= '0' && *CurPtr <= '7')
++CurPtr;
- CurIntVal = strtoll(TokStart, 0, 8);
- return asmtok::IntVal;
+ return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart),
+ strtoll(TokStart, 0, 8));
}
/// LexQuote: String: "..."
-asmtok::TokKind AsmLexer::LexQuote() {
+AsmToken AsmLexer::LexQuote() {
int CurChar = getNextChar();
// TODO: does gas allow multiline string constants?
while (CurChar != '"') {
@@ -229,18 +226,35 @@ asmtok::TokKind AsmLexer::LexQuote() {
CurChar = getNextChar();
}
- // Unique string, include quotes for now.
- CurStrVal =
- getSS(TheStringSet).GetOrCreateValue(TokStart, CurPtr, 0).getKeyData();
- return asmtok::String;
+ return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
+}
+
+StringRef AsmLexer::LexUntilEndOfStatement() {
+ TokStart = CurPtr;
+
+ while (!isAtStartOfComment(*CurPtr) && // Start of line comment.
+ *CurPtr != ';' && // End of statement marker.
+ *CurPtr != '\n' &&
+ *CurPtr != '\r' &&
+ (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) {
+ ++CurPtr;
+ }
+ return StringRef(TokStart, CurPtr-TokStart);
}
+bool AsmLexer::isAtStartOfComment(char Char) {
+ // FIXME: This won't work for multi-character comment indicators like "//".
+ return Char == *MAI.getCommentString();
+}
-asmtok::TokKind AsmLexer::LexToken() {
+AsmToken AsmLexer::LexToken() {
TokStart = CurPtr;
// This always consumes at least one character.
int CurChar = getNextChar();
+ if (isAtStartOfComment(CurChar))
+ return LexLineComment();
+
switch (CurChar) {
default:
// Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
@@ -249,7 +263,7 @@ asmtok::TokKind AsmLexer::LexToken() {
// Unknown character, emit an error.
return ReturnError(TokStart, "invalid character in input");
- case EOF: return asmtok::Eof;
+ case EOF: return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
case 0:
case ' ':
case '\t':
@@ -257,52 +271,61 @@ asmtok::TokKind AsmLexer::LexToken() {
return LexToken();
case '\n': // FALL THROUGH.
case '\r': // FALL THROUGH.
- case ';': return asmtok::EndOfStatement;
- case ':': return asmtok::Colon;
- case '+': return asmtok::Plus;
- case '-': return asmtok::Minus;
- case '~': return asmtok::Tilde;
- case '(': return asmtok::LParen;
- case ')': return asmtok::RParen;
- case '*': return asmtok::Star;
- case ',': return asmtok::Comma;
- case '$': return asmtok::Dollar;
+ case ';': return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
+ case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
+ case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
+ case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
+ case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
+ case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
+ case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
+ case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1));
+ case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1));
+ case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1));
+ case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1));
+ case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
+ case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
+ case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
case '=':
if (*CurPtr == '=')
- return ++CurPtr, asmtok::EqualEqual;
- return asmtok::Equal;
+ return ++CurPtr, AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
+ return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
case '|':
if (*CurPtr == '|')
- return ++CurPtr, asmtok::PipePipe;
- return asmtok::Pipe;
- case '^': return asmtok::Caret;
+ return ++CurPtr, AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2));
+ return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1));
+ case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1));
case '&':
if (*CurPtr == '&')
- return ++CurPtr, asmtok::AmpAmp;
- return asmtok::Amp;
+ return ++CurPtr, AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2));
+ return AsmToken(AsmToken::Amp, StringRef(TokStart, 1));
case '!':
if (*CurPtr == '=')
- return ++CurPtr, asmtok::ExclaimEqual;
- return asmtok::Exclaim;
- case '%': return LexPercent();
+ return ++CurPtr, AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
+ return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1));
+ case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
case '/': return LexSlash();
- case '#': return LexLineComment();
+ case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1));
case '"': return LexQuote();
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return LexDigit();
case '<':
switch (*CurPtr) {
- case '<': return ++CurPtr, asmtok::LessLess;
- case '=': return ++CurPtr, asmtok::LessEqual;
- case '>': return ++CurPtr, asmtok::LessGreater;
- default: return asmtok::Less;
+ case '<': return ++CurPtr, AsmToken(AsmToken::LessLess,
+ StringRef(TokStart, 2));
+ case '=': return ++CurPtr, AsmToken(AsmToken::LessEqual,
+ StringRef(TokStart, 2));
+ case '>': return ++CurPtr, AsmToken(AsmToken::LessGreater,
+ StringRef(TokStart, 2));
+ default: return AsmToken(AsmToken::Less, StringRef(TokStart, 1));
}
case '>':
switch (*CurPtr) {
- case '>': return ++CurPtr, asmtok::GreaterGreater;
- case '=': return ++CurPtr, asmtok::GreaterEqual;
- default: return asmtok::Greater;
+ case '>': return ++CurPtr, AsmToken(AsmToken::GreaterGreater,
+ StringRef(TokStart, 2));
+ case '=': return ++CurPtr, AsmToken(AsmToken::GreaterEqual,
+ StringRef(TokStart, 2));
+ default: return AsmToken(AsmToken::Greater, StringRef(TokStart, 1));
}
// TODO: Quoted identifiers (objc methods etc)
diff --git a/tools/llvm-mc/AsmLexer.h b/tools/llvm-mc/AsmLexer.h
index 6360b12..0696abc 100644
--- a/tools/llvm-mc/AsmLexer.h
+++ b/tools/llvm-mc/AsmLexer.h
@@ -14,6 +14,9 @@
#ifndef ASMLEXER_H
#define ASMLEXER_H
+#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCAsmLexer.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/DataTypes.h"
#include <string>
#include <cassert>
@@ -22,95 +25,53 @@ namespace llvm {
class MemoryBuffer;
class SourceMgr;
class SMLoc;
-
-namespace asmtok {
- enum TokKind {
- // Markers
- Eof, Error,
-
- // String values.
- Identifier,
- Register,
- String,
-
- // Integer values.
- IntVal,
-
- // No-value.
- EndOfStatement,
- Colon,
- Plus, Minus, Tilde,
- Slash, // '/'
- LParen, RParen,
- Star, Comma, Dollar, Equal, EqualEqual,
-
- Pipe, PipePipe, Caret,
- Amp, AmpAmp, Exclaim, ExclaimEqual, Percent,
- Less, LessEqual, LessLess, LessGreater,
- Greater, GreaterEqual, GreaterGreater
- };
-}
+class MCAsmInfo;
/// AsmLexer - Lexer class for assembly files.
-class AsmLexer {
+class AsmLexer : public MCAsmLexer {
SourceMgr &SrcMgr;
+ const MCAsmInfo &MAI;
const char *CurPtr;
const MemoryBuffer *CurBuf;
- // A llvm::StringSet<>, which provides uniqued and null-terminated strings.
- void *TheStringSet;
- // Information about the current token.
const char *TokStart;
- asmtok::TokKind CurKind;
- const char *CurStrVal; // This is valid for Identifier.
- int64_t CurIntVal;
-
- /// CurBuffer - This is the current buffer index we're lexing from as managed
- /// by the SourceMgr object.
+
+ /// This is the current buffer index we're lexing from as managed by the
+ /// SourceMgr object.
int CurBuffer;
void operator=(const AsmLexer&); // DO NOT IMPLEMENT
AsmLexer(const AsmLexer&); // DO NOT IMPLEMENT
+
+protected:
+ /// LexToken - Read the next token and return its code.
+ virtual AsmToken LexToken();
+
public:
- AsmLexer(SourceMgr &SrcMgr);
+ AsmLexer(SourceMgr &SrcMgr, const MCAsmInfo &MAI);
~AsmLexer();
- asmtok::TokKind Lex() {
- return CurKind = LexToken();
- }
-
- asmtok::TokKind getKind() const { return CurKind; }
- bool is(asmtok::TokKind K) const { return CurKind == K; }
- bool isNot(asmtok::TokKind K) const { return CurKind != K; }
-
- const char *getCurStrVal() const {
- assert((CurKind == asmtok::Identifier || CurKind == asmtok::Register ||
- CurKind == asmtok::String) &&
- "This token doesn't have a string value");
- return CurStrVal;
- }
- int64_t getCurIntVal() const {
- assert(CurKind == asmtok::IntVal && "This token isn't an integer");
- return CurIntVal;
- }
-
SMLoc getLoc() const;
+ StringRef LexUntilEndOfStatement();
+
+ bool isAtStartOfComment(char Char);
+
+ /// EnterIncludeFile - Enter the specified file. This returns true on failure.
+ bool EnterIncludeFile(const std::string &Filename);
+
void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type) const;
private:
int getNextChar();
- asmtok::TokKind ReturnError(const char *Loc, const std::string &Msg);
+ AsmToken ReturnError(const char *Loc, const std::string &Msg);
- /// LexToken - Read the next token and return its code.
- asmtok::TokKind LexToken();
- asmtok::TokKind LexIdentifier();
- asmtok::TokKind LexPercent();
- asmtok::TokKind LexSlash();
- asmtok::TokKind LexLineComment();
- asmtok::TokKind LexDigit();
- asmtok::TokKind LexQuote();
+ AsmToken LexIdentifier();
+ AsmToken LexSlash();
+ AsmToken LexLineComment();
+ AsmToken LexDigit();
+ AsmToken LexQuote();
};
} // end namespace llvm
diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp
index f5bf589..aae27f5d 100644
--- a/tools/llvm-mc/AsmParser.cpp
+++ b/tools/llvm-mc/AsmParser.cpp
@@ -13,21 +13,79 @@
#include "AsmParser.h"
-#include "AsmExpr.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetAsmParser.h"
using namespace llvm;
-void AsmParser::Warning(SMLoc L, const char *Msg) {
- Lexer.PrintMessage(L, Msg, "warning");
+// Mach-O section uniquing.
+//
+// FIXME: Figure out where this should live, it should be shared by
+// TargetLoweringObjectFile.
+typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy;
+
+AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out,
+ const MCAsmInfo &_MAI)
+ : Lexer(_SM, _MAI), Ctx(_Ctx), Out(_Out), TargetParser(0),
+ SectionUniquingMap(0) {
+ // Debugging directives.
+ AddDirectiveHandler(".file", &AsmParser::ParseDirectiveFile);
+ AddDirectiveHandler(".line", &AsmParser::ParseDirectiveLine);
+ AddDirectiveHandler(".loc", &AsmParser::ParseDirectiveLoc);
+}
+
+
+
+AsmParser::~AsmParser() {
+ // If we have the MachO uniquing map, free it.
+ delete (MachOUniqueMapTy*)SectionUniquingMap;
}
-bool AsmParser::Error(SMLoc L, const char *Msg) {
- Lexer.PrintMessage(L, Msg, "error");
+const MCSection *AsmParser::getMachOSection(const StringRef &Segment,
+ const StringRef &Section,
+ unsigned TypeAndAttributes,
+ unsigned Reserved2,
+ SectionKind Kind) const {
+ // We unique sections by their segment/section pair. The returned section
+ // may not have the same flags as the requested section, if so this should be
+ // diagnosed by the client as an error.
+
+ // Create the map if it doesn't already exist.
+ if (SectionUniquingMap == 0)
+ SectionUniquingMap = new MachOUniqueMapTy();
+ MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)SectionUniquingMap;
+
+ // Form the name to look up.
+ SmallString<64> Name;
+ Name += Segment;
+ Name.push_back(',');
+ Name += Section;
+
+ // Do the lookup, if we have a hit, return it.
+ const MCSectionMachO *&Entry = Map[Name.str()];
+
+ // FIXME: This should validate the type and attributes.
+ if (Entry) return Entry;
+
+ // Otherwise, return a new section.
+ return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes,
+ Reserved2, Kind, Ctx);
+}
+
+void AsmParser::Warning(SMLoc L, const Twine &Msg) {
+ Lexer.PrintMessage(L, Msg.str(), "warning");
+}
+
+bool AsmParser::Error(SMLoc L, const Twine &Msg) {
+ Lexer.PrintMessage(L, Msg.str(), "error");
return true;
}
@@ -37,31 +95,87 @@ bool AsmParser::TokError(const char *Msg) {
}
bool AsmParser::Run() {
+ // Create the initial section.
+ //
+ // FIXME: Support -n.
+ // FIXME: Target hook & command line option for initial section.
+ Out.SwitchSection(getMachOSection("__TEXT", "__text",
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ 0, SectionKind()));
+
+
// Prime the lexer.
Lexer.Lex();
bool HadError = false;
+ AsmCond StartingCondState = TheCondState;
+
// While we have input, parse each statement.
- while (Lexer.isNot(asmtok::Eof)) {
+ while (Lexer.isNot(AsmToken::Eof)) {
+ // Handle conditional assembly here before calling ParseStatement()
+ if (Lexer.getKind() == AsmToken::Identifier) {
+ // If we have an identifier, handle it as the key symbol.
+ AsmToken ID = Lexer.getTok();
+ SMLoc IDLoc = ID.getLoc();
+ StringRef IDVal = ID.getString();
+
+ if (IDVal == ".if" ||
+ IDVal == ".elseif" ||
+ IDVal == ".else" ||
+ IDVal == ".endif") {
+ if (!ParseConditionalAssemblyDirectives(IDVal, IDLoc))
+ continue;
+ HadError = true;
+ EatToEndOfStatement();
+ continue;
+ }
+ }
+ if (TheCondState.Ignore) {
+ EatToEndOfStatement();
+ continue;
+ }
+
if (!ParseStatement()) continue;
- // If we had an error, remember it and recover by skipping to the next line.
+ // We had an error, remember it and recover by skipping to the next line.
HadError = true;
EatToEndOfStatement();
}
+
+ if (TheCondState.TheCond != StartingCondState.TheCond ||
+ TheCondState.Ignore != StartingCondState.Ignore)
+ return TokError("unmatched .ifs or .elses");
+ if (!HadError)
+ Out.Finish();
+
return HadError;
}
+/// ParseConditionalAssemblyDirectives - parse the conditional assembly
+/// directives
+bool AsmParser::ParseConditionalAssemblyDirectives(StringRef Directive,
+ SMLoc DirectiveLoc) {
+ if (Directive == ".if")
+ return ParseDirectiveIf(DirectiveLoc);
+ if (Directive == ".elseif")
+ return ParseDirectiveElseIf(DirectiveLoc);
+ if (Directive == ".else")
+ return ParseDirectiveElse(DirectiveLoc);
+ if (Directive == ".endif")
+ return ParseDirectiveEndIf(DirectiveLoc);
+ return true;
+}
+
/// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
void AsmParser::EatToEndOfStatement() {
- while (Lexer.isNot(asmtok::EndOfStatement) &&
- Lexer.isNot(asmtok::Eof))
+ while (Lexer.isNot(AsmToken::EndOfStatement) &&
+ Lexer.isNot(AsmToken::Eof))
Lexer.Lex();
// Eat EOL.
- if (Lexer.is(asmtok::EndOfStatement))
+ if (Lexer.is(AsmToken::EndOfStatement))
Lexer.Lex();
}
@@ -71,66 +185,71 @@ void AsmParser::EatToEndOfStatement() {
///
/// parenexpr ::= expr)
///
-bool AsmParser::ParseParenExpr(AsmExpr *&Res) {
+bool AsmParser::ParseParenExpr(const MCExpr *&Res) {
if (ParseExpression(Res)) return true;
- if (Lexer.isNot(asmtok::RParen))
+ if (Lexer.isNot(AsmToken::RParen))
return TokError("expected ')' in parentheses expression");
Lexer.Lex();
return false;
}
+MCSymbol *AsmParser::CreateSymbol(StringRef Name) {
+ if (MCSymbol *S = Ctx.LookupSymbol(Name))
+ return S;
+
+ // If the label starts with L it is an assembler temporary label.
+ if (Name.startswith("L"))
+ return Ctx.CreateTemporarySymbol(Name);
+
+ return Ctx.CreateSymbol(Name);
+}
+
/// ParsePrimaryExpr - Parse a primary expression and return it.
/// primaryexpr ::= (parenexpr
/// primaryexpr ::= symbol
/// primaryexpr ::= number
/// primaryexpr ::= ~,+,- primaryexpr
-bool AsmParser::ParsePrimaryExpr(AsmExpr *&Res) {
+bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res) {
switch (Lexer.getKind()) {
default:
return TokError("unknown token in expression");
- case asmtok::Exclaim:
+ case AsmToken::Exclaim:
Lexer.Lex(); // Eat the operator.
if (ParsePrimaryExpr(Res))
return true;
- Res = new AsmUnaryExpr(AsmUnaryExpr::LNot, Res);
+ Res = MCUnaryExpr::CreateLNot(Res, getContext());
return false;
- case asmtok::Identifier: {
+ case AsmToken::String:
+ case AsmToken::Identifier:
// This is a label, this should be parsed as part of an expression, to
// handle things like LFOO+4.
- MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal());
-
- // If this is use of an undefined symbol then mark it external.
- if (!Sym->getSection() && !Ctx.GetSymbolValue(Sym))
- Sym->setExternal(true);
-
- Res = new AsmSymbolRefExpr(Sym);
+ Res = MCSymbolRefExpr::Create(Lexer.getTok().getIdentifier(), getContext());
Lexer.Lex(); // Eat identifier.
return false;
- }
- case asmtok::IntVal:
- Res = new AsmConstantExpr(Lexer.getCurIntVal());
- Lexer.Lex(); // Eat identifier.
+ case AsmToken::Integer:
+ Res = MCConstantExpr::Create(Lexer.getTok().getIntVal(), getContext());
+ Lexer.Lex(); // Eat token.
return false;
- case asmtok::LParen:
+ case AsmToken::LParen:
Lexer.Lex(); // Eat the '('.
return ParseParenExpr(Res);
- case asmtok::Minus:
+ case AsmToken::Minus:
Lexer.Lex(); // Eat the operator.
if (ParsePrimaryExpr(Res))
return true;
- Res = new AsmUnaryExpr(AsmUnaryExpr::Minus, Res);
+ Res = MCUnaryExpr::CreateMinus(Res, getContext());
return false;
- case asmtok::Plus:
+ case AsmToken::Plus:
Lexer.Lex(); // Eat the operator.
if (ParsePrimaryExpr(Res))
return true;
- Res = new AsmUnaryExpr(AsmUnaryExpr::Plus, Res);
+ Res = MCUnaryExpr::CreatePlus(Res, getContext());
return false;
- case asmtok::Tilde:
+ case AsmToken::Tilde:
Lexer.Lex(); // Eat the operator.
if (ParsePrimaryExpr(Res))
return true;
- Res = new AsmUnaryExpr(AsmUnaryExpr::Not, Res);
+ Res = MCUnaryExpr::CreateNot(Res, getContext());
return false;
}
}
@@ -142,119 +261,101 @@ bool AsmParser::ParsePrimaryExpr(AsmExpr *&Res) {
/// expr ::= expr *,/,%,<<,>> expr -> highest.
/// expr ::= primaryexpr
///
-bool AsmParser::ParseExpression(AsmExpr *&Res) {
+bool AsmParser::ParseExpression(const MCExpr *&Res) {
Res = 0;
return ParsePrimaryExpr(Res) ||
ParseBinOpRHS(1, Res);
}
-bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
- AsmExpr *Expr;
-
- SMLoc StartLoc = Lexer.getLoc();
- if (ParseExpression(Expr))
+bool AsmParser::ParseParenExpression(const MCExpr *&Res) {
+ if (ParseParenExpr(Res))
return true;
- if (!Expr->EvaluateAsAbsolute(Ctx, Res))
- return Error(StartLoc, "expected absolute expression");
-
return false;
}
-bool AsmParser::ParseRelocatableExpression(MCValue &Res) {
- AsmExpr *Expr;
+bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
+ const MCExpr *Expr;
SMLoc StartLoc = Lexer.getLoc();
if (ParseExpression(Expr))
return true;
- if (!Expr->EvaluateAsRelocatable(Ctx, Res))
- return Error(StartLoc, "expected relocatable expression");
-
- return false;
-}
-
-bool AsmParser::ParseParenRelocatableExpression(MCValue &Res) {
- AsmExpr *Expr;
-
- SMLoc StartLoc = Lexer.getLoc();
- if (ParseParenExpr(Expr))
- return true;
-
- if (!Expr->EvaluateAsRelocatable(Ctx, Res))
- return Error(StartLoc, "expected relocatable expression");
+ if (!Expr->EvaluateAsAbsolute(Ctx, Res))
+ return Error(StartLoc, "expected absolute expression");
return false;
}
-static unsigned getBinOpPrecedence(asmtok::TokKind K,
- AsmBinaryExpr::Opcode &Kind) {
+static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
+ MCBinaryExpr::Opcode &Kind) {
switch (K) {
- default: return 0; // not a binop.
+ default:
+ return 0; // not a binop.
// Lowest Precedence: &&, ||
- case asmtok::AmpAmp:
- Kind = AsmBinaryExpr::LAnd;
+ case AsmToken::AmpAmp:
+ Kind = MCBinaryExpr::LAnd;
return 1;
- case asmtok::PipePipe:
- Kind = AsmBinaryExpr::LOr;
+ case AsmToken::PipePipe:
+ Kind = MCBinaryExpr::LOr;
return 1;
// Low Precedence: +, -, ==, !=, <>, <, <=, >, >=
- case asmtok::Plus:
- Kind = AsmBinaryExpr::Add;
+ case AsmToken::Plus:
+ Kind = MCBinaryExpr::Add;
return 2;
- case asmtok::Minus:
- Kind = AsmBinaryExpr::Sub;
+ case AsmToken::Minus:
+ Kind = MCBinaryExpr::Sub;
return 2;
- case asmtok::EqualEqual:
- Kind = AsmBinaryExpr::EQ;
+ case AsmToken::EqualEqual:
+ Kind = MCBinaryExpr::EQ;
return 2;
- case asmtok::ExclaimEqual:
- case asmtok::LessGreater:
- Kind = AsmBinaryExpr::NE;
+ case AsmToken::ExclaimEqual:
+ case AsmToken::LessGreater:
+ Kind = MCBinaryExpr::NE;
return 2;
- case asmtok::Less:
- Kind = AsmBinaryExpr::LT;
+ case AsmToken::Less:
+ Kind = MCBinaryExpr::LT;
return 2;
- case asmtok::LessEqual:
- Kind = AsmBinaryExpr::LTE;
+ case AsmToken::LessEqual:
+ Kind = MCBinaryExpr::LTE;
return 2;
- case asmtok::Greater:
- Kind = AsmBinaryExpr::GT;
+ case AsmToken::Greater:
+ Kind = MCBinaryExpr::GT;
return 2;
- case asmtok::GreaterEqual:
- Kind = AsmBinaryExpr::GTE;
+ case AsmToken::GreaterEqual:
+ Kind = MCBinaryExpr::GTE;
return 2;
// Intermediate Precedence: |, &, ^
//
// FIXME: gas seems to support '!' as an infix operator?
- case asmtok::Pipe:
- Kind = AsmBinaryExpr::Or;
+ case AsmToken::Pipe:
+ Kind = MCBinaryExpr::Or;
return 3;
- case asmtok::Caret:
- Kind = AsmBinaryExpr::Xor;
+ case AsmToken::Caret:
+ Kind = MCBinaryExpr::Xor;
return 3;
- case asmtok::Amp:
- Kind = AsmBinaryExpr::And;
+ case AsmToken::Amp:
+ Kind = MCBinaryExpr::And;
return 3;
// Highest Precedence: *, /, %, <<, >>
- case asmtok::Star:
- Kind = AsmBinaryExpr::Mul;
+ case AsmToken::Star:
+ Kind = MCBinaryExpr::Mul;
return 4;
- case asmtok::Slash:
- Kind = AsmBinaryExpr::Div;
+ case AsmToken::Slash:
+ Kind = MCBinaryExpr::Div;
return 4;
- case asmtok::Percent:
- Kind = AsmBinaryExpr::Mod;
+ case AsmToken::Percent:
+ Kind = MCBinaryExpr::Mod;
return 4;
- case asmtok::LessLess:
- Kind = AsmBinaryExpr::Shl;
+ case AsmToken::LessLess:
+ Kind = MCBinaryExpr::Shl;
return 4;
- case asmtok::GreaterGreater:
- Kind = AsmBinaryExpr::Shr;
+ case AsmToken::GreaterGreater:
+ Kind = MCBinaryExpr::Shr;
return 4;
}
}
@@ -262,9 +363,9 @@ static unsigned getBinOpPrecedence(asmtok::TokKind K,
/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'.
/// Res contains the LHS of the expression on input.
-bool AsmParser::ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res) {
+bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res) {
while (1) {
- AsmBinaryExpr::Opcode Kind = AsmBinaryExpr::Add;
+ MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
// If the next token is lower precedence than we are allowed to eat, return
@@ -275,19 +376,19 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res) {
Lexer.Lex();
// Eat the next primary expression.
- AsmExpr *RHS;
+ const MCExpr *RHS;
if (ParsePrimaryExpr(RHS)) return true;
// If BinOp binds less tightly with RHS than the operator after RHS, let
// the pending operator take RHS as its LHS.
- AsmBinaryExpr::Opcode Dummy;
+ MCBinaryExpr::Opcode Dummy;
unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
if (TokPrec < NextTokPrec) {
if (ParseBinOpRHS(Precedence+1, RHS)) return true;
}
// Merge LHS and RHS according to operator.
- Res = new AsmBinaryExpr(Kind, Res, RHS);
+ Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext());
}
}
@@ -299,24 +400,23 @@ bool AsmParser::ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res) {
/// ::= Label* Directive ...Operands... EndOfStatement
/// ::= Label* Identifier OperandList* EndOfStatement
bool AsmParser::ParseStatement() {
- switch (Lexer.getKind()) {
- default:
- return TokError("unexpected token at start of statement");
- case asmtok::EndOfStatement:
+ if (Lexer.is(AsmToken::EndOfStatement)) {
Lexer.Lex();
return false;
- case asmtok::Identifier:
- break;
- // TODO: Recurse on local labels etc.
}
-
- // If we have an identifier, handle it as the key symbol.
- SMLoc IDLoc = Lexer.getLoc();
- const char *IDVal = Lexer.getCurStrVal();
-
- // Consume the identifier, see what is after it.
- switch (Lexer.Lex()) {
- case asmtok::Colon: {
+
+ // Statements always start with an identifier.
+ AsmToken ID = Lexer.getTok();
+ SMLoc IDLoc = ID.getLoc();
+ StringRef IDVal;
+ if (ParseIdentifier(IDVal))
+ return TokError("unexpected token at start of statement");
+
+ // FIXME: Recurse on local labels?
+
+ // See what kind of statement we have.
+ switch (Lexer.getKind()) {
+ case AsmToken::Colon: {
// identifier ':' -> Label.
Lexer.Lex();
@@ -325,25 +425,21 @@ bool AsmParser::ParseStatement() {
// FIXME: Diagnostics. Note the location of the definition as a label.
// FIXME: This doesn't diagnose assignment to a symbol which has been
// implicitly marked as external.
- MCSymbol *Sym = Ctx.GetOrCreateSymbol(IDVal);
- if (Sym->getSection())
+ MCSymbol *Sym = CreateSymbol(IDVal);
+ if (!Sym->isUndefined())
return Error(IDLoc, "invalid symbol redefinition");
- if (Ctx.GetSymbolValue(Sym))
- return Error(IDLoc, "symbol already used as assembler variable");
- // Since we saw a label, create a symbol and emit it.
- // FIXME: If the label starts with L it is an assembler temporary label.
- // Why does the client of this api need to know this?
+ // Emit the label.
Out.EmitLabel(Sym);
return ParseStatement();
}
- case asmtok::Equal:
+ case AsmToken::Equal:
// identifier '=' ... -> assignment statement
Lexer.Lex();
- return ParseAssignment(IDVal, false);
+ return ParseAssignment(IDVal);
default: // Normal instruction or directive.
break;
@@ -352,184 +448,261 @@ bool AsmParser::ParseStatement() {
// Otherwise, we have a normal instruction or directive.
if (IDVal[0] == '.') {
// FIXME: This should be driven based on a hash lookup and callback.
- if (!strcmp(IDVal, ".section"))
+ if (IDVal == ".section")
return ParseDirectiveDarwinSection();
- if (!strcmp(IDVal, ".text"))
+ if (IDVal == ".text")
// FIXME: This changes behavior based on the -static flag to the
// assembler.
- return ParseDirectiveSectionSwitch("__TEXT,__text",
- "regular,pure_instructions");
- if (!strcmp(IDVal, ".const"))
- return ParseDirectiveSectionSwitch("__TEXT,__const");
- if (!strcmp(IDVal, ".static_const"))
- return ParseDirectiveSectionSwitch("__TEXT,__static_const");
- if (!strcmp(IDVal, ".cstring"))
- return ParseDirectiveSectionSwitch("__TEXT,__cstring",
- "cstring_literals");
- if (!strcmp(IDVal, ".literal4"))
- return ParseDirectiveSectionSwitch("__TEXT,__literal4", "4byte_literals");
- if (!strcmp(IDVal, ".literal8"))
- return ParseDirectiveSectionSwitch("__TEXT,__literal8", "8byte_literals");
- if (!strcmp(IDVal, ".literal16"))
- return ParseDirectiveSectionSwitch("__TEXT,__literal16",
- "16byte_literals");
- if (!strcmp(IDVal, ".constructor"))
- return ParseDirectiveSectionSwitch("__TEXT,__constructor");
- if (!strcmp(IDVal, ".destructor"))
- return ParseDirectiveSectionSwitch("__TEXT,__destructor");
- if (!strcmp(IDVal, ".fvmlib_init0"))
- return ParseDirectiveSectionSwitch("__TEXT,__fvmlib_init0");
- if (!strcmp(IDVal, ".fvmlib_init1"))
- return ParseDirectiveSectionSwitch("__TEXT,__fvmlib_init1");
- if (!strcmp(IDVal, ".symbol_stub")) // FIXME: Different on PPC.
- return ParseDirectiveSectionSwitch("__IMPORT,__jump_table,symbol_stubs",
- "self_modifying_code+pure_instructions,5");
- // FIXME: .picsymbol_stub on PPC.
- if (!strcmp(IDVal, ".data"))
- return ParseDirectiveSectionSwitch("__DATA,__data");
- if (!strcmp(IDVal, ".static_data"))
- return ParseDirectiveSectionSwitch("__DATA,__static_data");
- if (!strcmp(IDVal, ".non_lazy_symbol_pointer"))
- return ParseDirectiveSectionSwitch("__DATA,__nl_symbol_pointer",
- "non_lazy_symbol_pointers");
- if (!strcmp(IDVal, ".lazy_symbol_pointer"))
- return ParseDirectiveSectionSwitch("__DATA,__la_symbol_pointer",
- "lazy_symbol_pointers");
- if (!strcmp(IDVal, ".dyld"))
- return ParseDirectiveSectionSwitch("__DATA,__dyld");
- if (!strcmp(IDVal, ".mod_init_func"))
- return ParseDirectiveSectionSwitch("__DATA,__mod_init_func",
- "mod_init_funcs");
- if (!strcmp(IDVal, ".mod_term_func"))
- return ParseDirectiveSectionSwitch("__DATA,__mod_term_func",
- "mod_term_funcs");
- if (!strcmp(IDVal, ".const_data"))
- return ParseDirectiveSectionSwitch("__DATA,__const", "regular");
+ return ParseDirectiveSectionSwitch("__TEXT", "__text",
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
+ if (IDVal == ".const")
+ return ParseDirectiveSectionSwitch("__TEXT", "__const");
+ if (IDVal == ".static_const")
+ return ParseDirectiveSectionSwitch("__TEXT", "__static_const");
+ if (IDVal == ".cstring")
+ return ParseDirectiveSectionSwitch("__TEXT","__cstring",
+ MCSectionMachO::S_CSTRING_LITERALS);
+ if (IDVal == ".literal4")
+ return ParseDirectiveSectionSwitch("__TEXT", "__literal4",
+ MCSectionMachO::S_4BYTE_LITERALS,
+ 4);
+ if (IDVal == ".literal8")
+ return ParseDirectiveSectionSwitch("__TEXT", "__literal8",
+ MCSectionMachO::S_8BYTE_LITERALS,
+ 8);
+ if (IDVal == ".literal16")
+ return ParseDirectiveSectionSwitch("__TEXT","__literal16",
+ MCSectionMachO::S_16BYTE_LITERALS,
+ 16);
+ if (IDVal == ".constructor")
+ return ParseDirectiveSectionSwitch("__TEXT","__constructor");
+ if (IDVal == ".destructor")
+ return ParseDirectiveSectionSwitch("__TEXT","__destructor");
+ if (IDVal == ".fvmlib_init0")
+ return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init0");
+ if (IDVal == ".fvmlib_init1")
+ return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init1");
+
+ // FIXME: The assembler manual claims that this has the self modify code
+ // flag, at least on x86-32, but that does not appear to be correct.
+ if (IDVal == ".symbol_stub")
+ return ParseDirectiveSectionSwitch("__TEXT","__symbol_stub",
+ MCSectionMachO::S_SYMBOL_STUBS |
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ // FIXME: Different on PPC and ARM.
+ 0, 16);
+ // FIXME: PowerPC only?
+ if (IDVal == ".picsymbol_stub")
+ return ParseDirectiveSectionSwitch("__TEXT","__picsymbol_stub",
+ MCSectionMachO::S_SYMBOL_STUBS |
+ MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
+ 0, 26);
+ if (IDVal == ".data")
+ return ParseDirectiveSectionSwitch("__DATA", "__data");
+ if (IDVal == ".static_data")
+ return ParseDirectiveSectionSwitch("__DATA", "__static_data");
+
+ // FIXME: The section names of these two are misspelled in the assembler
+ // manual.
+ if (IDVal == ".non_lazy_symbol_pointer")
+ return ParseDirectiveSectionSwitch("__DATA", "__nl_symbol_ptr",
+ MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS,
+ 4);
+ if (IDVal == ".lazy_symbol_pointer")
+ return ParseDirectiveSectionSwitch("__DATA", "__la_symbol_ptr",
+ MCSectionMachO::S_LAZY_SYMBOL_POINTERS,
+ 4);
+
+ if (IDVal == ".dyld")
+ return ParseDirectiveSectionSwitch("__DATA", "__dyld");
+ if (IDVal == ".mod_init_func")
+ return ParseDirectiveSectionSwitch("__DATA", "__mod_init_func",
+ MCSectionMachO::S_MOD_INIT_FUNC_POINTERS,
+ 4);
+ if (IDVal == ".mod_term_func")
+ return ParseDirectiveSectionSwitch("__DATA", "__mod_term_func",
+ MCSectionMachO::S_MOD_TERM_FUNC_POINTERS,
+ 4);
+ if (IDVal == ".const_data")
+ return ParseDirectiveSectionSwitch("__DATA", "__const");
- // FIXME: Verify attributes on sections.
- if (!strcmp(IDVal, ".objc_class"))
- return ParseDirectiveSectionSwitch("__OBJC,__class");
- if (!strcmp(IDVal, ".objc_meta_class"))
- return ParseDirectiveSectionSwitch("__OBJC,__meta_class");
- if (!strcmp(IDVal, ".objc_cat_cls_meth"))
- return ParseDirectiveSectionSwitch("__OBJC,__cat_cls_meth");
- if (!strcmp(IDVal, ".objc_cat_inst_meth"))
- return ParseDirectiveSectionSwitch("__OBJC,__cat_inst_meth");
- if (!strcmp(IDVal, ".objc_protocol"))
- return ParseDirectiveSectionSwitch("__OBJC,__protocol");
- if (!strcmp(IDVal, ".objc_string_object"))
- return ParseDirectiveSectionSwitch("__OBJC,__string_object");
- if (!strcmp(IDVal, ".objc_cls_meth"))
- return ParseDirectiveSectionSwitch("__OBJC,__cls_meth");
- if (!strcmp(IDVal, ".objc_inst_meth"))
- return ParseDirectiveSectionSwitch("__OBJC,__inst_meth");
- if (!strcmp(IDVal, ".objc_cls_refs"))
- return ParseDirectiveSectionSwitch("__OBJC,__cls_refs");
- if (!strcmp(IDVal, ".objc_message_refs"))
- return ParseDirectiveSectionSwitch("__OBJC,__message_refs");
- if (!strcmp(IDVal, ".objc_symbols"))
- return ParseDirectiveSectionSwitch("__OBJC,__symbols");
- if (!strcmp(IDVal, ".objc_category"))
- return ParseDirectiveSectionSwitch("__OBJC,__category");
- if (!strcmp(IDVal, ".objc_class_vars"))
- return ParseDirectiveSectionSwitch("__OBJC,__class_vars");
- if (!strcmp(IDVal, ".objc_instance_vars"))
- return ParseDirectiveSectionSwitch("__OBJC,__instance_vars");
- if (!strcmp(IDVal, ".objc_module_info"))
- return ParseDirectiveSectionSwitch("__OBJC,__module_info");
- if (!strcmp(IDVal, ".objc_class_names"))
- return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals");
- if (!strcmp(IDVal, ".objc_meth_var_types"))
- return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals");
- if (!strcmp(IDVal, ".objc_meth_var_names"))
- return ParseDirectiveSectionSwitch("__TEXT,__cstring","cstring_literals");
- if (!strcmp(IDVal, ".objc_selector_strs"))
- return ParseDirectiveSectionSwitch("__OBJC,__selector_strs");
+ if (IDVal == ".objc_class")
+ return ParseDirectiveSectionSwitch("__OBJC", "__class",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_meta_class")
+ return ParseDirectiveSectionSwitch("__OBJC", "__meta_class",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_cat_cls_meth")
+ return ParseDirectiveSectionSwitch("__OBJC", "__cat_cls_meth",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_cat_inst_meth")
+ return ParseDirectiveSectionSwitch("__OBJC", "__cat_inst_meth",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_protocol")
+ return ParseDirectiveSectionSwitch("__OBJC", "__protocol",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_string_object")
+ return ParseDirectiveSectionSwitch("__OBJC", "__string_object",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_cls_meth")
+ return ParseDirectiveSectionSwitch("__OBJC", "__cls_meth",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_inst_meth")
+ return ParseDirectiveSectionSwitch("__OBJC", "__inst_meth",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_cls_refs")
+ return ParseDirectiveSectionSwitch("__OBJC", "__cls_refs",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
+ MCSectionMachO::S_LITERAL_POINTERS,
+ 4);
+ if (IDVal == ".objc_message_refs")
+ return ParseDirectiveSectionSwitch("__OBJC", "__message_refs",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
+ MCSectionMachO::S_LITERAL_POINTERS,
+ 4);
+ if (IDVal == ".objc_symbols")
+ return ParseDirectiveSectionSwitch("__OBJC", "__symbols",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_category")
+ return ParseDirectiveSectionSwitch("__OBJC", "__category",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_class_vars")
+ return ParseDirectiveSectionSwitch("__OBJC", "__class_vars",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_instance_vars")
+ return ParseDirectiveSectionSwitch("__OBJC", "__instance_vars",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_module_info")
+ return ParseDirectiveSectionSwitch("__OBJC", "__module_info",
+ MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
+ if (IDVal == ".objc_class_names")
+ return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
+ MCSectionMachO::S_CSTRING_LITERALS);
+ if (IDVal == ".objc_meth_var_types")
+ return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
+ MCSectionMachO::S_CSTRING_LITERALS);
+ if (IDVal == ".objc_meth_var_names")
+ return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
+ MCSectionMachO::S_CSTRING_LITERALS);
+ if (IDVal == ".objc_selector_strs")
+ return ParseDirectiveSectionSwitch("__OBJC", "__selector_strs",
+ MCSectionMachO::S_CSTRING_LITERALS);
// Assembler features
- if (!strcmp(IDVal, ".set"))
+ if (IDVal == ".set")
return ParseDirectiveSet();
// Data directives
- if (!strcmp(IDVal, ".ascii"))
+ if (IDVal == ".ascii")
return ParseDirectiveAscii(false);
- if (!strcmp(IDVal, ".asciz"))
+ if (IDVal == ".asciz")
return ParseDirectiveAscii(true);
- // FIXME: Target hooks for size? Also for "word", "hword".
- if (!strcmp(IDVal, ".byte"))
+ if (IDVal == ".byte")
return ParseDirectiveValue(1);
- if (!strcmp(IDVal, ".short"))
+ if (IDVal == ".short")
return ParseDirectiveValue(2);
- if (!strcmp(IDVal, ".long"))
+ if (IDVal == ".long")
return ParseDirectiveValue(4);
- if (!strcmp(IDVal, ".quad"))
+ if (IDVal == ".quad")
return ParseDirectiveValue(8);
// FIXME: Target hooks for IsPow2.
- if (!strcmp(IDVal, ".align"))
+ if (IDVal == ".align")
return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
- if (!strcmp(IDVal, ".align32"))
+ if (IDVal == ".align32")
return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
- if (!strcmp(IDVal, ".balign"))
+ if (IDVal == ".balign")
return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
- if (!strcmp(IDVal, ".balignw"))
+ if (IDVal == ".balignw")
return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
- if (!strcmp(IDVal, ".balignl"))
+ if (IDVal == ".balignl")
return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
- if (!strcmp(IDVal, ".p2align"))
+ if (IDVal == ".p2align")
return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
- if (!strcmp(IDVal, ".p2alignw"))
+ if (IDVal == ".p2alignw")
return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
- if (!strcmp(IDVal, ".p2alignl"))
+ if (IDVal == ".p2alignl")
return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
- if (!strcmp(IDVal, ".org"))
+ if (IDVal == ".org")
return ParseDirectiveOrg();
- if (!strcmp(IDVal, ".fill"))
+ if (IDVal == ".fill")
return ParseDirectiveFill();
- if (!strcmp(IDVal, ".space"))
+ if (IDVal == ".space")
return ParseDirectiveSpace();
// Symbol attribute directives
- if (!strcmp(IDVal, ".globl") || !strcmp(IDVal, ".global"))
+
+ if (IDVal == ".globl" || IDVal == ".global")
return ParseDirectiveSymbolAttribute(MCStreamer::Global);
- if (!strcmp(IDVal, ".hidden"))
+ if (IDVal == ".hidden")
return ParseDirectiveSymbolAttribute(MCStreamer::Hidden);
- if (!strcmp(IDVal, ".indirect_symbol"))
+ if (IDVal == ".indirect_symbol")
return ParseDirectiveSymbolAttribute(MCStreamer::IndirectSymbol);
- if (!strcmp(IDVal, ".internal"))
+ if (IDVal == ".internal")
return ParseDirectiveSymbolAttribute(MCStreamer::Internal);
- if (!strcmp(IDVal, ".lazy_reference"))
+ if (IDVal == ".lazy_reference")
return ParseDirectiveSymbolAttribute(MCStreamer::LazyReference);
- if (!strcmp(IDVal, ".no_dead_strip"))
+ if (IDVal == ".no_dead_strip")
return ParseDirectiveSymbolAttribute(MCStreamer::NoDeadStrip);
- if (!strcmp(IDVal, ".private_extern"))
+ if (IDVal == ".private_extern")
return ParseDirectiveSymbolAttribute(MCStreamer::PrivateExtern);
- if (!strcmp(IDVal, ".protected"))
+ if (IDVal == ".protected")
return ParseDirectiveSymbolAttribute(MCStreamer::Protected);
- if (!strcmp(IDVal, ".reference"))
+ if (IDVal == ".reference")
return ParseDirectiveSymbolAttribute(MCStreamer::Reference);
- if (!strcmp(IDVal, ".weak"))
+ if (IDVal == ".weak")
return ParseDirectiveSymbolAttribute(MCStreamer::Weak);
- if (!strcmp(IDVal, ".weak_definition"))
+ if (IDVal == ".weak_definition")
return ParseDirectiveSymbolAttribute(MCStreamer::WeakDefinition);
- if (!strcmp(IDVal, ".weak_reference"))
+ if (IDVal == ".weak_reference")
return ParseDirectiveSymbolAttribute(MCStreamer::WeakReference);
+ if (IDVal == ".comm")
+ return ParseDirectiveComm(/*IsLocal=*/false);
+ if (IDVal == ".lcomm")
+ return ParseDirectiveComm(/*IsLocal=*/true);
+ if (IDVal == ".zerofill")
+ return ParseDirectiveDarwinZerofill();
+ if (IDVal == ".desc")
+ return ParseDirectiveDarwinSymbolDesc();
+ if (IDVal == ".lsym")
+ return ParseDirectiveDarwinLsym();
+
+ if (IDVal == ".subsections_via_symbols")
+ return ParseDirectiveDarwinSubsectionsViaSymbols();
+ if (IDVal == ".abort")
+ return ParseDirectiveAbort();
+ if (IDVal == ".include")
+ return ParseDirectiveInclude();
+ if (IDVal == ".dump")
+ return ParseDirectiveDarwinDumpOrLoad(IDLoc, /*IsDump=*/true);
+ if (IDVal == ".load")
+ return ParseDirectiveDarwinDumpOrLoad(IDLoc, /*IsLoad=*/false);
+
+ // Look up the handler in the handler table,
+ bool(AsmParser::*Handler)(StringRef, SMLoc) = DirectiveMap[IDVal];
+ if (Handler)
+ return (this->*Handler)(IDVal, IDLoc);
+
+ // Target hook for parsing target specific directives.
+ if (!getTargetParser().ParseDirective(ID))
+ return false;
+
Warning(IDLoc, "ignoring directive for now");
EatToEndOfStatement();
return false;
}
MCInst Inst;
- if (ParseX86InstOperands(IDVal, Inst))
+ if (getTargetParser().ParseInstruction(IDVal, Inst))
return true;
- if (Lexer.isNot(asmtok::EndOfStatement))
+ if (Lexer.isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in argument list");
// Eat the end of statement marker.
@@ -542,15 +715,16 @@ bool AsmParser::ParseStatement() {
return false;
}
-bool AsmParser::ParseAssignment(const char *Name, bool IsDotSet) {
+bool AsmParser::ParseAssignment(const StringRef &Name) {
// FIXME: Use better location, we should use proper tokens.
SMLoc EqualLoc = Lexer.getLoc();
- MCValue Value;
- if (ParseRelocatableExpression(Value))
+ const MCExpr *Value;
+ SMLoc StartLoc = Lexer.getLoc();
+ if (ParseExpression(Value))
return true;
- if (Lexer.isNot(asmtok::EndOfStatement))
+ if (Lexer.isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in assignment");
// Eat the end of statement marker.
@@ -559,18 +733,29 @@ bool AsmParser::ParseAssignment(const char *Name, bool IsDotSet) {
// Diagnose assignment to a label.
//
// FIXME: Diagnostics. Note the location of the definition as a label.
- // FIXME: This doesn't diagnose assignment to a symbol which has been
- // implicitly marked as external.
// FIXME: Handle '.'.
// FIXME: Diagnose assignment to protected identifier (e.g., register name).
- MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name);
- if (Sym->getSection())
- return Error(EqualLoc, "invalid assignment to symbol emitted as a label");
- if (Sym->isExternal())
- return Error(EqualLoc, "invalid assignment to external symbol");
+ MCSymbol *Sym = CreateSymbol(Name);
+ if (!Sym->isUndefined() && !Sym->isAbsolute())
+ return Error(EqualLoc, "symbol has already been defined");
// Do the assignment.
- Out.EmitAssignment(Sym, Value, IsDotSet);
+ Out.EmitAssignment(Sym, Value);
+
+ return false;
+}
+
+/// ParseIdentifier:
+/// ::= identifier
+/// ::= string
+bool AsmParser::ParseIdentifier(StringRef &Res) {
+ if (Lexer.isNot(AsmToken::Identifier) &&
+ Lexer.isNot(AsmToken::String))
+ return true;
+
+ Res = Lexer.getTok().getIdentifier();
+
+ Lexer.Lex(); // Consume the identifier token.
return false;
}
@@ -578,16 +763,16 @@ bool AsmParser::ParseAssignment(const char *Name, bool IsDotSet) {
/// ParseDirectiveSet:
/// ::= .set identifier ',' expression
bool AsmParser::ParseDirectiveSet() {
- if (Lexer.isNot(asmtok::Identifier))
- return TokError("expected identifier after '.set' directive");
+ StringRef Name;
- const char *Name = Lexer.getCurStrVal();
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier after '.set' directive");
- if (Lexer.Lex() != asmtok::Comma)
+ if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in '.set'");
Lexer.Lex();
- return ParseAssignment(Name, true);
+ return ParseAssignment(Name);
}
/// ParseDirectiveSection:
@@ -595,69 +780,152 @@ bool AsmParser::ParseDirectiveSet() {
/// FIXME: This should actually parse out the segment, section, attributes and
/// sizeof_stub fields.
bool AsmParser::ParseDirectiveDarwinSection() {
- if (Lexer.isNot(asmtok::Identifier))
- return TokError("expected identifier after '.section' directive");
-
- std::string Section = Lexer.getCurStrVal();
+ SMLoc Loc = Lexer.getLoc();
+
+ StringRef SectionName;
+ if (ParseIdentifier(SectionName))
+ return Error(Loc, "expected identifier after '.section' directive");
+
+ // Verify there is a following comma.
+ if (!Lexer.is(AsmToken::Comma))
+ return TokError("unexpected token in '.section' directive");
+
+ std::string SectionSpec = SectionName;
+ SectionSpec += ",";
+
+ // Add all the tokens until the end of the line, ParseSectionSpecifier will
+ // handle this.
+ StringRef EOL = Lexer.LexUntilEndOfStatement();
+ SectionSpec.append(EOL.begin(), EOL.end());
+
Lexer.Lex();
-
- // Accept a comma separated list of modifiers.
- while (Lexer.is(asmtok::Comma)) {
- Lexer.Lex();
-
- if (Lexer.isNot(asmtok::Identifier))
- return TokError("expected identifier in '.section' directive");
- Section += ',';
- Section += Lexer.getCurStrVal();
- Lexer.Lex();
- }
-
- if (Lexer.isNot(asmtok::EndOfStatement))
+ if (Lexer.isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.section' directive");
Lexer.Lex();
- Out.SwitchSection(Ctx.GetSection(Section.c_str()));
+
+ StringRef Segment, Section;
+ unsigned TAA, StubSize;
+ std::string ErrorStr =
+ MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
+ TAA, StubSize);
+
+ if (!ErrorStr.empty())
+ return Error(Loc, ErrorStr.c_str());
+
+ // FIXME: Arch specific.
+ Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize,
+ SectionKind()));
return false;
}
-bool AsmParser::ParseDirectiveSectionSwitch(const char *Section,
- const char *Directives) {
- if (Lexer.isNot(asmtok::EndOfStatement))
+/// ParseDirectiveSectionSwitch -
+bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment,
+ const char *Section,
+ unsigned TAA, unsigned Align,
+ unsigned StubSize) {
+ if (Lexer.isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in section switching directive");
Lexer.Lex();
- std::string SectionStr = Section;
- if (Directives && Directives[0]) {
- SectionStr += ",";
- SectionStr += Directives;
+ // FIXME: Arch specific.
+ Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize,
+ SectionKind()));
+
+ // Set the implicit alignment, if any.
+ //
+ // FIXME: This isn't really what 'as' does; I think it just uses the implicit
+ // alignment on the section (e.g., if one manually inserts bytes into the
+ // section, then just issueing the section switch directive will not realign
+ // the section. However, this is arguably more reasonable behavior, and there
+ // is no good reason for someone to intentionally emit incorrectly sized
+ // values into the implicitly aligned sections.
+ if (Align)
+ Out.EmitValueToAlignment(Align, 0, 1, 0);
+
+ return false;
+}
+
+bool AsmParser::ParseEscapedString(std::string &Data) {
+ assert(Lexer.is(AsmToken::String) && "Unexpected current token!");
+
+ Data = "";
+ StringRef Str = Lexer.getTok().getStringContents();
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (Str[i] != '\\') {
+ Data += Str[i];
+ continue;
+ }
+
+ // Recognize escaped characters. Note that this escape semantics currently
+ // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes.
+ ++i;
+ if (i == e)
+ return TokError("unexpected backslash at end of string");
+
+ // Recognize octal sequences.
+ if ((unsigned) (Str[i] - '0') <= 7) {
+ // Consume up to three octal characters.
+ unsigned Value = Str[i] - '0';
+
+ if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
+ ++i;
+ Value = Value * 8 + (Str[i] - '0');
+
+ if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
+ ++i;
+ Value = Value * 8 + (Str[i] - '0');
+ }
+ }
+
+ if (Value > 255)
+ return TokError("invalid octal escape sequence (out of range)");
+
+ Data += (unsigned char) Value;
+ continue;
+ }
+
+ // Otherwise recognize individual escapes.
+ switch (Str[i]) {
+ default:
+ // Just reject invalid escape sequences for now.
+ return TokError("invalid escape sequence (unrecognized character)");
+
+ case 'b': Data += '\b'; break;
+ case 'f': Data += '\f'; break;
+ case 'n': Data += '\n'; break;
+ case 'r': Data += '\r'; break;
+ case 't': Data += '\t'; break;
+ case '"': Data += '"'; break;
+ case '\\': Data += '\\'; break;
+ }
}
-
- Out.SwitchSection(Ctx.GetSection(Section));
+
return false;
}
/// ParseDirectiveAscii:
/// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ]
bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
- if (Lexer.isNot(asmtok::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
for (;;) {
- if (Lexer.isNot(asmtok::String))
+ if (Lexer.isNot(AsmToken::String))
return TokError("expected string in '.ascii' or '.asciz' directive");
- // FIXME: This shouldn't use a const char* + strlen, the string could have
- // embedded nulls.
- // FIXME: Should have accessor for getting string contents.
- const char *Str = Lexer.getCurStrVal();
- Out.EmitBytes(Str + 1, strlen(Str) - 2);
+ std::string Data;
+ if (ParseEscapedString(Data))
+ return true;
+
+ Out.EmitBytes(Data);
if (ZeroTerminated)
- Out.EmitBytes("\0", 1);
+ Out.EmitBytes(StringRef("\0", 1));
Lexer.Lex();
- if (Lexer.is(asmtok::EndOfStatement))
+ if (Lexer.is(AsmToken::EndOfStatement))
break;
- if (Lexer.isNot(asmtok::Comma))
+ if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in '.ascii' or '.asciz' directive");
Lexer.Lex();
}
@@ -670,19 +938,20 @@ bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
/// ParseDirectiveValue
/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
bool AsmParser::ParseDirectiveValue(unsigned Size) {
- if (Lexer.isNot(asmtok::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
for (;;) {
- MCValue Expr;
- if (ParseRelocatableExpression(Expr))
+ const MCExpr *Value;
+ SMLoc StartLoc = Lexer.getLoc();
+ if (ParseExpression(Value))
return true;
- Out.EmitValue(Expr, Size);
+ Out.EmitValue(Value, Size);
- if (Lexer.is(asmtok::EndOfStatement))
+ if (Lexer.is(AsmToken::EndOfStatement))
break;
// FIXME: Improve diagnostic.
- if (Lexer.isNot(asmtok::Comma))
+ if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in directive");
Lexer.Lex();
}
@@ -701,8 +970,8 @@ bool AsmParser::ParseDirectiveSpace() {
int64_t FillExpr = 0;
bool HasFillExpr = false;
- if (Lexer.isNot(asmtok::EndOfStatement)) {
- if (Lexer.isNot(asmtok::Comma))
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in '.space' directive");
Lexer.Lex();
@@ -711,7 +980,7 @@ bool AsmParser::ParseDirectiveSpace() {
HasFillExpr = true;
- if (Lexer.isNot(asmtok::EndOfStatement))
+ if (Lexer.isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.space' directive");
}
@@ -722,7 +991,7 @@ bool AsmParser::ParseDirectiveSpace() {
// FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
for (uint64_t i = 0, e = NumBytes; i != e; ++i)
- Out.EmitValue(MCValue::get(FillExpr), 1);
+ Out.EmitValue(MCConstantExpr::Create(FillExpr, getContext()), 1);
return false;
}
@@ -734,7 +1003,7 @@ bool AsmParser::ParseDirectiveFill() {
if (ParseAbsoluteExpression(NumValues))
return true;
- if (Lexer.isNot(asmtok::Comma))
+ if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in '.fill' directive");
Lexer.Lex();
@@ -742,7 +1011,7 @@ bool AsmParser::ParseDirectiveFill() {
if (ParseAbsoluteExpression(FillSize))
return true;
- if (Lexer.isNot(asmtok::Comma))
+ if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in '.fill' directive");
Lexer.Lex();
@@ -750,16 +1019,16 @@ bool AsmParser::ParseDirectiveFill() {
if (ParseAbsoluteExpression(FillExpr))
return true;
- if (Lexer.isNot(asmtok::EndOfStatement))
+ if (Lexer.isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.fill' directive");
Lexer.Lex();
- if (FillSize != 1 && FillSize != 2 && FillSize != 4)
- return TokError("invalid '.fill' size, expected 1, 2, or 4");
+ if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8)
+ return TokError("invalid '.fill' size, expected 1, 2, 4, or 8");
for (uint64_t i = 0, e = NumValues; i != e; ++i)
- Out.EmitValue(MCValue::get(FillExpr), FillSize);
+ Out.EmitValue(MCConstantExpr::Create(FillExpr, getContext()), FillSize);
return false;
}
@@ -767,21 +1036,22 @@ bool AsmParser::ParseDirectiveFill() {
/// ParseDirectiveOrg
/// ::= .org expression [ , expression ]
bool AsmParser::ParseDirectiveOrg() {
- MCValue Offset;
- if (ParseRelocatableExpression(Offset))
+ const MCExpr *Offset;
+ SMLoc StartLoc = Lexer.getLoc();
+ if (ParseExpression(Offset))
return true;
// Parse optional fill expression.
int64_t FillExpr = 0;
- if (Lexer.isNot(asmtok::EndOfStatement)) {
- if (Lexer.isNot(asmtok::Comma))
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in '.org' directive");
Lexer.Lex();
if (ParseAbsoluteExpression(FillExpr))
return true;
- if (Lexer.isNot(asmtok::EndOfStatement))
+ if (Lexer.isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in '.org' directive");
}
@@ -797,6 +1067,7 @@ bool AsmParser::ParseDirectiveOrg() {
/// ParseDirectiveAlign
/// ::= {.align, ...} expression [ , expression [ , expression ]]
bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
+ SMLoc AlignmentLoc = Lexer.getLoc();
int64_t Alignment;
if (ParseAbsoluteExpression(Alignment))
return true;
@@ -805,22 +1076,22 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
bool HasFillExpr = false;
int64_t FillExpr = 0;
int64_t MaxBytesToFill = 0;
- if (Lexer.isNot(asmtok::EndOfStatement)) {
- if (Lexer.isNot(asmtok::Comma))
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in directive");
Lexer.Lex();
// The fill expression can be omitted while specifying a maximum number of
// alignment bytes, e.g:
// .align 3,,4
- if (Lexer.isNot(asmtok::Comma)) {
+ if (Lexer.isNot(AsmToken::Comma)) {
HasFillExpr = true;
if (ParseAbsoluteExpression(FillExpr))
return true;
}
- if (Lexer.isNot(asmtok::EndOfStatement)) {
- if (Lexer.isNot(asmtok::Comma))
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in directive");
Lexer.Lex();
@@ -828,7 +1099,7 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
if (ParseAbsoluteExpression(MaxBytesToFill))
return true;
- if (Lexer.isNot(asmtok::EndOfStatement))
+ if (Lexer.isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
}
}
@@ -843,15 +1114,20 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
// Compute alignment in bytes.
if (IsPow2) {
// FIXME: Diagnose overflow.
- Alignment = 1 << Alignment;
+ if (Alignment >= 32) {
+ Error(AlignmentLoc, "invalid alignment value");
+ Alignment = 31;
+ }
+
+ Alignment = 1ULL << Alignment;
}
- // Diagnose non-sensical max bytes to fill.
+ // Diagnose non-sensical max bytes to align.
if (MaxBytesLoc.isValid()) {
if (MaxBytesToFill < 1) {
- Warning(MaxBytesLoc, "alignment directive can never be satisfied in this "
- "many bytes, ignoring");
- return false;
+ Error(MaxBytesLoc, "alignment directive can never be satisfied in this "
+ "many bytes, ignoring maximum bytes expression");
+ MaxBytesToFill = 0;
}
if (MaxBytesToFill >= Alignment) {
@@ -870,24 +1146,21 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
/// ParseDirectiveSymbolAttribute
/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
bool AsmParser::ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr) {
- if (Lexer.isNot(asmtok::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
for (;;) {
- if (Lexer.isNot(asmtok::Identifier))
+ StringRef Name;
+
+ if (ParseIdentifier(Name))
return TokError("expected identifier in directive");
- MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal());
- Lexer.Lex();
-
- // If this is use of an undefined symbol then mark it external.
- if (!Sym->getSection() && !Ctx.GetSymbolValue(Sym))
- Sym->setExternal(true);
+ MCSymbol *Sym = CreateSymbol(Name);
Out.EmitSymbolAttribute(Sym, Attr);
- if (Lexer.is(asmtok::EndOfStatement))
+ if (Lexer.is(AsmToken::EndOfStatement))
break;
- if (Lexer.isNot(asmtok::Comma))
+ if (Lexer.isNot(AsmToken::Comma))
return TokError("unexpected token in directive");
Lexer.Lex();
}
@@ -896,3 +1169,513 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr) {
Lexer.Lex();
return false;
}
+
+/// ParseDirectiveDarwinSymbolDesc
+/// ::= .desc identifier , expression
+bool AsmParser::ParseDirectiveDarwinSymbolDesc() {
+ StringRef Name;
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = CreateSymbol(Name);
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.desc' directive");
+ Lexer.Lex();
+
+ SMLoc DescLoc = Lexer.getLoc();
+ int64_t DescValue;
+ if (ParseAbsoluteExpression(DescValue))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.desc' directive");
+
+ Lexer.Lex();
+
+ // Set the n_desc field of this Symbol to this DescValue
+ Out.EmitSymbolDesc(Sym, DescValue);
+
+ return false;
+}
+
+/// ParseDirectiveComm
+/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
+bool AsmParser::ParseDirectiveComm(bool IsLocal) {
+ SMLoc IDLoc = Lexer.getLoc();
+ StringRef Name;
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = CreateSymbol(Name);
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lexer.Lex();
+
+ int64_t Size;
+ SMLoc SizeLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(Size))
+ return true;
+
+ int64_t Pow2Alignment = 0;
+ SMLoc Pow2AlignmentLoc;
+ if (Lexer.is(AsmToken::Comma)) {
+ Lexer.Lex();
+ Pow2AlignmentLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(Pow2Alignment))
+ return true;
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.comm' or '.lcomm' directive");
+
+ Lexer.Lex();
+
+ // NOTE: a size of zero for a .comm should create a undefined symbol
+ // but a size of .lcomm creates a bss symbol of size zero.
+ if (Size < 0)
+ return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
+ "be less than zero");
+
+ // NOTE: The alignment in the directive is a power of 2 value, the assember
+ // may internally end up wanting an alignment in bytes.
+ // FIXME: Diagnose overflow.
+ if (Pow2Alignment < 0)
+ return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
+ "alignment, can't be less than zero");
+
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ // '.lcomm' is equivalent to '.zerofill'.
+ // Create the Symbol as a common or local common with Size and Pow2Alignment
+ if (IsLocal) {
+ Out.EmitZerofill(getMachOSection("__DATA", "__bss",
+ MCSectionMachO::S_ZEROFILL, 0,
+ SectionKind()),
+ Sym, Size, 1 << Pow2Alignment);
+ return false;
+ }
+
+ Out.EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
+ return false;
+}
+
+/// ParseDirectiveDarwinZerofill
+/// ::= .zerofill segname , sectname [, identifier , size_expression [
+/// , align_expression ]]
+bool AsmParser::ParseDirectiveDarwinZerofill() {
+ // FIXME: Handle quoted names here.
+
+ if (Lexer.isNot(AsmToken::Identifier))
+ return TokError("expected segment name after '.zerofill' directive");
+ StringRef Segment = Lexer.getTok().getString();
+ Lexer.Lex();
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lexer.Lex();
+
+ if (Lexer.isNot(AsmToken::Identifier))
+ return TokError("expected section name after comma in '.zerofill' "
+ "directive");
+ StringRef Section = Lexer.getTok().getString();
+ Lexer.Lex();
+
+ // If this is the end of the line all that was wanted was to create the
+ // the section but with no symbol.
+ if (Lexer.is(AsmToken::EndOfStatement)) {
+ // Create the zerofill section but no symbol
+ Out.EmitZerofill(getMachOSection(Segment, Section,
+ MCSectionMachO::S_ZEROFILL, 0,
+ SectionKind()));
+ return false;
+ }
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lexer.Lex();
+
+ if (Lexer.isNot(AsmToken::Identifier))
+ return TokError("expected identifier in directive");
+
+ // handle the identifier as the key symbol.
+ SMLoc IDLoc = Lexer.getLoc();
+ MCSymbol *Sym = CreateSymbol(Lexer.getTok().getString());
+ Lexer.Lex();
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lexer.Lex();
+
+ int64_t Size;
+ SMLoc SizeLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(Size))
+ return true;
+
+ int64_t Pow2Alignment = 0;
+ SMLoc Pow2AlignmentLoc;
+ if (Lexer.is(AsmToken::Comma)) {
+ Lexer.Lex();
+ Pow2AlignmentLoc = Lexer.getLoc();
+ if (ParseAbsoluteExpression(Pow2Alignment))
+ return true;
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.zerofill' directive");
+
+ Lexer.Lex();
+
+ if (Size < 0)
+ return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
+ "than zero");
+
+ // NOTE: The alignment in the directive is a power of 2 value, the assember
+ // may internally end up wanting an alignment in bytes.
+ // FIXME: Diagnose overflow.
+ if (Pow2Alignment < 0)
+ return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
+ "can't be less than zero");
+
+ if (!Sym->isUndefined())
+ return Error(IDLoc, "invalid symbol redefinition");
+
+ // Create the zerofill Symbol with Size and Pow2Alignment
+ //
+ // FIXME: Arch specific.
+ Out.EmitZerofill(getMachOSection(Segment, Section,
+ MCSectionMachO::S_ZEROFILL, 0,
+ SectionKind()),
+ Sym, Size, 1 << Pow2Alignment);
+
+ return false;
+}
+
+/// ParseDirectiveDarwinSubsectionsViaSymbols
+/// ::= .subsections_via_symbols
+bool AsmParser::ParseDirectiveDarwinSubsectionsViaSymbols() {
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.subsections_via_symbols' directive");
+
+ Lexer.Lex();
+
+ Out.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols);
+
+ return false;
+}
+
+/// ParseDirectiveAbort
+/// ::= .abort [ "abort_string" ]
+bool AsmParser::ParseDirectiveAbort() {
+ // FIXME: Use loc from directive.
+ SMLoc Loc = Lexer.getLoc();
+
+ StringRef Str = "";
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::String))
+ return TokError("expected string in '.abort' directive");
+
+ Str = Lexer.getTok().getString();
+
+ Lexer.Lex();
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.abort' directive");
+
+ Lexer.Lex();
+
+ // FIXME: Handle here.
+ if (Str.empty())
+ Error(Loc, ".abort detected. Assembly stopping.");
+ else
+ Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
+
+ return false;
+}
+
+/// ParseDirectiveLsym
+/// ::= .lsym identifier , expression
+bool AsmParser::ParseDirectiveDarwinLsym() {
+ StringRef Name;
+ if (ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ // Handle the identifier as the key symbol.
+ MCSymbol *Sym = CreateSymbol(Name);
+
+ if (Lexer.isNot(AsmToken::Comma))
+ return TokError("unexpected token in '.lsym' directive");
+ Lexer.Lex();
+
+ const MCExpr *Value;
+ SMLoc StartLoc = Lexer.getLoc();
+ if (ParseExpression(Value))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.lsym' directive");
+
+ Lexer.Lex();
+
+ // We don't currently support this directive.
+ //
+ // FIXME: Diagnostic location!
+ (void) Sym;
+ return TokError("directive '.lsym' is unsupported");
+}
+
+/// ParseDirectiveInclude
+/// ::= .include "filename"
+bool AsmParser::ParseDirectiveInclude() {
+ if (Lexer.isNot(AsmToken::String))
+ return TokError("expected string in '.include' directive");
+
+ std::string Filename = Lexer.getTok().getString();
+ SMLoc IncludeLoc = Lexer.getLoc();
+ Lexer.Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.include' directive");
+
+ // Strip the quotes.
+ Filename = Filename.substr(1, Filename.size()-2);
+
+ // Attempt to switch the lexer to the included file before consuming the end
+ // of statement to avoid losing it when we switch.
+ if (Lexer.EnterIncludeFile(Filename)) {
+ Lexer.PrintMessage(IncludeLoc,
+ "Could not find include file '" + Filename + "'",
+ "error");
+ return true;
+ }
+
+ return false;
+}
+
+/// ParseDirectiveDarwinDumpOrLoad
+/// ::= ( .dump | .load ) "filename"
+bool AsmParser::ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump) {
+ if (Lexer.isNot(AsmToken::String))
+ return TokError("expected string in '.dump' or '.load' directive");
+
+ Lexer.Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.dump' or '.load' directive");
+
+ Lexer.Lex();
+
+ // FIXME: If/when .dump and .load are implemented they will be done in the
+ // the assembly parser and not have any need for an MCStreamer API.
+ if (IsDump)
+ Warning(IDLoc, "ignoring directive .dump for now");
+ else
+ Warning(IDLoc, "ignoring directive .load for now");
+
+ return false;
+}
+
+/// ParseDirectiveIf
+/// ::= .if expression
+bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
+ // Consume the identifier that was the .if directive
+ Lexer.Lex();
+
+ TheCondStack.push_back(TheCondState);
+ TheCondState.TheCond = AsmCond::IfCond;
+ if(TheCondState.Ignore) {
+ EatToEndOfStatement();
+ }
+ else {
+ int64_t ExprValue;
+ if (ParseAbsoluteExpression(ExprValue))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.if' directive");
+
+ Lexer.Lex();
+
+ TheCondState.CondMet = ExprValue;
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// ParseDirectiveElseIf
+/// ::= .elseif expression
+bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or "
+ " an .elseif");
+ TheCondState.TheCond = AsmCond::ElseIfCond;
+
+ // Consume the identifier that was the .elseif directive
+ Lexer.Lex();
+
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet) {
+ TheCondState.Ignore = true;
+ EatToEndOfStatement();
+ }
+ else {
+ int64_t ExprValue;
+ if (ParseAbsoluteExpression(ExprValue))
+ return true;
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.elseif' directive");
+
+ Lexer.Lex();
+ TheCondState.CondMet = ExprValue;
+ TheCondState.Ignore = !TheCondState.CondMet;
+ }
+
+ return false;
+}
+
+/// ParseDirectiveElse
+/// ::= .else
+bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
+ // Consume the identifier that was the .else directive
+ Lexer.Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.else' directive");
+
+ Lexer.Lex();
+
+ if (TheCondState.TheCond != AsmCond::IfCond &&
+ TheCondState.TheCond != AsmCond::ElseIfCond)
+ Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an "
+ ".elseif");
+ TheCondState.TheCond = AsmCond::ElseCond;
+ bool LastIgnoreState = false;
+ if (!TheCondStack.empty())
+ LastIgnoreState = TheCondStack.back().Ignore;
+ if (LastIgnoreState || TheCondState.CondMet)
+ TheCondState.Ignore = true;
+ else
+ TheCondState.Ignore = false;
+
+ return false;
+}
+
+/// ParseDirectiveEndIf
+/// ::= .endif
+bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) {
+ // Consume the identifier that was the .endif directive
+ Lexer.Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.endif' directive");
+
+ Lexer.Lex();
+
+ if ((TheCondState.TheCond == AsmCond::NoCond) ||
+ TheCondStack.empty())
+ Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or "
+ ".else");
+ if (!TheCondStack.empty()) {
+ TheCondState = TheCondStack.back();
+ TheCondStack.pop_back();
+ }
+
+ return false;
+}
+
+/// ParseDirectiveFile
+/// ::= .file [number] string
+bool AsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) {
+ // FIXME: I'm not sure what this is.
+ int64_t FileNumber = -1;
+ if (Lexer.is(AsmToken::Integer)) {
+ FileNumber = Lexer.getTok().getIntVal();
+ Lexer.Lex();
+
+ if (FileNumber < 1)
+ return TokError("file number less than one");
+ }
+
+ if (Lexer.isNot(AsmToken::String))
+ return TokError("unexpected token in '.file' directive");
+
+ StringRef FileName = Lexer.getTok().getString();
+ Lexer.Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.file' directive");
+
+ // FIXME: Do something with the .file.
+
+ return false;
+}
+
+/// ParseDirectiveLine
+/// ::= .line [number]
+bool AsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) {
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Integer))
+ return TokError("unexpected token in '.line' directive");
+
+ int64_t LineNumber = Lexer.getTok().getIntVal();
+ (void) LineNumber;
+ Lexer.Lex();
+
+ // FIXME: Do something with the .line.
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.file' directive");
+
+ return false;
+}
+
+
+/// ParseDirectiveLoc
+/// ::= .loc number [number [number]]
+bool AsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
+ if (Lexer.isNot(AsmToken::Integer))
+ return TokError("unexpected token in '.loc' directive");
+
+ // FIXME: What are these fields?
+ int64_t FileNumber = Lexer.getTok().getIntVal();
+ (void) FileNumber;
+ // FIXME: Validate file.
+
+ Lexer.Lex();
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Integer))
+ return TokError("unexpected token in '.loc' directive");
+
+ int64_t Param2 = Lexer.getTok().getIntVal();
+ (void) Param2;
+ Lexer.Lex();
+
+ if (Lexer.isNot(AsmToken::EndOfStatement)) {
+ if (Lexer.isNot(AsmToken::Integer))
+ return TokError("unexpected token in '.loc' directive");
+
+ int64_t Param3 = Lexer.getTok().getIntVal();
+ (void) Param3;
+ Lexer.Lex();
+
+ // FIXME: Do something with the .loc.
+ }
+ }
+
+ if (Lexer.isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in '.file' directive");
+
+ return false;
+}
+
diff --git a/tools/llvm-mc/AsmParser.h b/tools/llvm-mc/AsmParser.h
index 333b284..171dfcd 100644
--- a/tools/llvm-mc/AsmParser.h
+++ b/tools/llvm-mc/AsmParser.h
@@ -14,89 +14,110 @@
#ifndef ASMPARSER_H
#define ASMPARSER_H
+#include <vector>
#include "AsmLexer.h"
+#include "AsmCond.h"
+#include "llvm/MC/MCAsmParser.h"
+#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/ADT/StringMap.h"
namespace llvm {
-class AsmExpr;
+class AsmCond;
class MCContext;
+class MCExpr;
class MCInst;
class MCStreamer;
+class MCAsmInfo;
class MCValue;
+class TargetAsmParser;
+class Twine;
-class AsmParser {
-public:
- struct X86Operand;
-
+class AsmParser : public MCAsmParser {
private:
AsmLexer Lexer;
MCContext &Ctx;
MCStreamer &Out;
-
+ TargetAsmParser *TargetParser;
+
+ AsmCond TheCondState;
+ std::vector<AsmCond> TheCondStack;
+
+ // FIXME: Figure out where this should leave, the code is a copy of that which
+ // is also used by TargetLoweringObjectFile.
+ mutable void *SectionUniquingMap;
+
+ /// DirectiveMap - This is a table handlers for directives. Each handler is
+ /// invoked after the directive identifier is read and is responsible for
+ /// parsing and validating the rest of the directive. The handler is passed
+ /// in the directive name and the location of the directive keyword.
+ StringMap<bool(AsmParser::*)(StringRef, SMLoc)> DirectiveMap;
public:
- AsmParser(SourceMgr &SM, MCContext &ctx, MCStreamer &OutStr)
- : Lexer(SM), Ctx(ctx), Out(OutStr) {}
- ~AsmParser() {}
-
+ AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out,
+ const MCAsmInfo &_MAI);
+ ~AsmParser();
+
bool Run();
+
+ void AddDirectiveHandler(StringRef Directive,
+ bool (AsmParser::*Handler)(StringRef, SMLoc)) {
+ DirectiveMap[Directive] = Handler;
+ }
+public:
+ TargetAsmParser &getTargetParser() const { return *TargetParser; }
+ void setTargetParser(TargetAsmParser &P) { TargetParser = &P; }
+
+ /// @name MCAsmParser Interface
+ /// {
+
+ virtual MCAsmLexer &getLexer() { return Lexer; }
+ virtual MCContext &getContext() { return Ctx; }
+ virtual MCStreamer &getStreamer() { return Out; }
+
+ virtual void Warning(SMLoc L, const Twine &Meg);
+ virtual bool Error(SMLoc L, const Twine &Msg);
+
+ virtual bool ParseExpression(const MCExpr *&Res);
+ virtual bool ParseParenExpression(const MCExpr *&Res);
+ virtual bool ParseAbsoluteExpression(int64_t &Res);
+
+ /// }
+
private:
+ MCSymbol *CreateSymbol(StringRef Name);
+
+ // FIXME: See comment on SectionUniquingMap.
+ const MCSection *getMachOSection(const StringRef &Segment,
+ const StringRef &Section,
+ unsigned TypeAndAttributes,
+ unsigned Reserved2,
+ SectionKind Kind) const;
+
bool ParseStatement();
- void Warning(SMLoc L, const char *Msg);
- bool Error(SMLoc L, const char *Msg);
bool TokError(const char *Msg);
+ bool ParseConditionalAssemblyDirectives(StringRef Directive,
+ SMLoc DirectiveLoc);
void EatToEndOfStatement();
- bool ParseAssignment(const char *Name, bool IsDotSet);
-
- /// ParseExpression - Parse a general assembly expression.
- ///
- /// @param Res - The resulting expression. The pointer value is null on error.
- /// @result - False on success.
- bool ParseExpression(AsmExpr *&Res);
-
- /// ParseAbsoluteExpression - Parse an expression which must evaluate to an
- /// absolute value.
- ///
- /// @param Res - The value of the absolute expression. The result is undefined
- /// on error.
- /// @result - False on success.
- bool ParseAbsoluteExpression(int64_t &Res);
-
- /// ParseRelocatableExpression - Parse an expression which must be
- /// relocatable.
- ///
- /// @param Res - The relocatable expression value. The result is undefined on
- /// error.
- /// @result - False on success.
- bool ParseRelocatableExpression(MCValue &Res);
-
- /// ParseParenRelocatableExpression - Parse an expression which must be
- /// relocatable, assuming that an initial '(' has already been consumed.
- ///
- /// @param Res - The relocatable expression value. The result is undefined on
- /// error.
- /// @result - False on success.
- ///
- /// @see ParseRelocatableExpression, ParseParenExpr.
- bool ParseParenRelocatableExpression(MCValue &Res);
-
- bool ParsePrimaryExpr(AsmExpr *&Res);
- bool ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res);
- bool ParseParenExpr(AsmExpr *&Res);
-
- // X86 specific.
- bool ParseX86InstOperands(const char *InstName, MCInst &Inst);
- bool ParseX86Operand(X86Operand &Op);
- bool ParseX86MemOperand(X86Operand &Op);
- bool ParseX86Register(X86Operand &Op);
+ bool ParseAssignment(const StringRef &Name);
+
+ bool ParsePrimaryExpr(const MCExpr *&Res);
+ bool ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res);
+ bool ParseParenExpr(const MCExpr *&Res);
+
+ /// ParseIdentifier - Parse an identifier or string (as a quoted identifier)
+ /// and set \arg Res to the identifier contents.
+ bool ParseIdentifier(StringRef &Res);
// Directive Parsing.
bool ParseDirectiveDarwinSection(); // Darwin specific ".section".
- bool ParseDirectiveSectionSwitch(const char *Section,
- const char *Directives = 0);
+ bool ParseDirectiveSectionSwitch(const char *Segment, const char *Section,
+ unsigned TAA = 0, unsigned ImplicitAlign = 0,
+ unsigned StubSize = 0);
bool ParseDirectiveAscii(bool ZeroTerminated); // ".ascii", ".asciiz"
bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ...
bool ParseDirectiveFill(); // ".fill"
@@ -109,7 +130,32 @@ private:
/// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which
/// accepts a single symbol (which should be a label or an external).
bool ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr);
-
+ bool ParseDirectiveDarwinSymbolDesc(); // Darwin specific ".desc"
+ bool ParseDirectiveDarwinLsym(); // Darwin specific ".lsym"
+
+ bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
+ bool ParseDirectiveDarwinZerofill(); // Darwin specific ".zerofill"
+
+ // Darwin specific ".subsections_via_symbols"
+ bool ParseDirectiveDarwinSubsectionsViaSymbols();
+ // Darwin specific .dump and .load
+ bool ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump);
+
+ bool ParseDirectiveAbort(); // ".abort"
+ bool ParseDirectiveInclude(); // ".include"
+
+ bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if"
+ bool ParseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
+ bool ParseDirectiveElse(SMLoc DirectiveLoc); // ".else"
+ bool ParseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
+
+ bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc); // ".file"
+ bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc); // ".line"
+ bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc); // ".loc"
+
+ /// ParseEscapedString - Parse the current token as a string which may include
+ /// escaped characters and return the string contents.
+ bool ParseEscapedString(std::string &Data);
};
} // end namespace llvm
diff --git a/tools/llvm-mc/CMakeLists.txt b/tools/llvm-mc/CMakeLists.txt
index b21a4b1..ce9d63b 100644
--- a/tools/llvm-mc/CMakeLists.txt
+++ b/tools/llvm-mc/CMakeLists.txt
@@ -1,9 +1,7 @@
-set(LLVM_LINK_COMPONENTS support MC)
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC)
add_llvm_tool(llvm-mc
llvm-mc.cpp
- AsmExpr.cpp
AsmLexer.cpp
AsmParser.cpp
- MC-X86Specific.cpp
)
diff --git a/tools/llvm-mc/Makefile b/tools/llvm-mc/Makefile
index 3c327da..9bfb773 100644
--- a/tools/llvm-mc/Makefile
+++ b/tools/llvm-mc/Makefile
@@ -9,9 +9,16 @@
LEVEL = ../..
TOOLNAME = llvm-mc
-LINK_COMPONENTS := support MC
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
+NO_INSTALL = 1
-include $(LEVEL)/Makefile.common
+# Include this here so we can get the configuration of the targets
+# that have been configured for construction. We have to do this
+# early so we can set up LINK_COMPONENTS before including Makefile.rules
+include $(LEVEL)/Makefile.config
+
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) MC support
+
+include $(LLVM_SRC_ROOT)/Makefile.rules
diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index b52edd1..329efe9 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/tools/llvm-mc/llvm-mc.cpp
@@ -12,16 +12,25 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/MC/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/ADT/OwningPtr.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/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
+#include "llvm/Target/TargetAsmParser.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetMachine.h" // FIXME.
+#include "llvm/Target/TargetSelect.h"
#include "AsmParser.h"
using namespace llvm;
@@ -32,10 +41,39 @@ static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"),
cl::value_desc("filename"));
+static cl::opt<bool>
+ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
+
+static cl::opt<unsigned>
+OutputAsmVariant("output-asm-variant",
+ cl::desc("Syntax variant to use for output printing"));
+
+enum OutputFileType {
+ OFT_AssemblyFile,
+ OFT_ObjectFile
+};
+static cl::opt<OutputFileType>
+FileType("filetype", cl::init(OFT_AssemblyFile),
+ cl::desc("Choose an output file type:"),
+ cl::values(
+ clEnumValN(OFT_AssemblyFile, "asm",
+ "Emit an assembly ('.s') file"),
+ clEnumValN(OFT_ObjectFile, "obj",
+ "Emit a native object ('.o') file"),
+ clEnumValEnd));
+
+static cl::opt<bool>
+Force("f", cl::desc("Enable binary output on terminals"));
+
static cl::list<std::string>
IncludeDirs("I", cl::desc("Directory of include files"),
cl::value_desc("directory"), cl::Prefix);
+static cl::opt<std::string>
+TripleName("triple", cl::desc("Target triple to assemble for,"
+ "see -version for available targets"),
+ cl::init(LLVM_HOSTTRIPLE));
+
enum ActionType {
AC_AsLex,
AC_Assemble
@@ -50,6 +88,18 @@ Action(cl::desc("Action to perform:"),
"Assemble a .s file (default)"),
clEnumValEnd));
+static const Target *GetTarget(const char *ProgName) {
+ // Get the target specific parser.
+ std::string Error;
+ const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
+ if (TheTarget)
+ return TheTarget;
+
+ errs() << ProgName << ": error: unable to get target for '" << TripleName
+ << "', see --version and --triple.\n";
+ return 0;
+}
+
static int AsLexInput(const char *ProgName) {
std::string ErrorMessage;
MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename,
@@ -72,78 +122,103 @@ static int AsLexInput(const char *ProgName) {
// it later.
SrcMgr.setIncludeDirs(IncludeDirs);
- AsmLexer Lexer(SrcMgr);
+ const Target *TheTarget = GetTarget(ProgName);
+ if (!TheTarget)
+ return 1;
+
+ const MCAsmInfo *MAI = TheTarget->createAsmInfo(TripleName);
+ assert(MAI && "Unable to create target asm info!");
+
+ AsmLexer Lexer(SrcMgr, *MAI);
bool Error = false;
- asmtok::TokKind Tok = Lexer.Lex();
- while (Tok != asmtok::Eof) {
- switch (Tok) {
+ while (Lexer.Lex().isNot(AsmToken::Eof)) {
+ switch (Lexer.getKind()) {
default:
Lexer.PrintMessage(Lexer.getLoc(), "unknown token", "warning");
Error = true;
break;
- case asmtok::Error:
+ case AsmToken::Error:
Error = true; // error already printed.
break;
- case asmtok::Identifier:
- outs() << "identifier: " << Lexer.getCurStrVal() << '\n';
- break;
- case asmtok::Register:
- outs() << "register: " << Lexer.getCurStrVal() << '\n';
+ case AsmToken::Identifier:
+ outs() << "identifier: " << Lexer.getTok().getString() << '\n';
break;
- case asmtok::String:
- outs() << "string: " << Lexer.getCurStrVal() << '\n';
+ case AsmToken::String:
+ outs() << "string: " << Lexer.getTok().getString() << '\n';
break;
- case asmtok::IntVal:
- outs() << "int: " << Lexer.getCurIntVal() << '\n';
+ case AsmToken::Integer:
+ outs() << "int: " << Lexer.getTok().getString() << '\n';
break;
- case asmtok::Amp: outs() << "Amp\n"; break;
- case asmtok::AmpAmp: outs() << "AmpAmp\n"; break;
- case asmtok::Caret: outs() << "Caret\n"; break;
- case asmtok::Colon: outs() << "Colon\n"; break;
- case asmtok::Comma: outs() << "Comma\n"; break;
- case asmtok::Dollar: outs() << "Dollar\n"; break;
- case asmtok::EndOfStatement: outs() << "EndOfStatement\n"; break;
- case asmtok::Eof: outs() << "Eof\n"; break;
- case asmtok::Equal: outs() << "Equal\n"; break;
- case asmtok::EqualEqual: outs() << "EqualEqual\n"; break;
- case asmtok::Exclaim: outs() << "Exclaim\n"; break;
- case asmtok::ExclaimEqual: outs() << "ExclaimEqual\n"; break;
- case asmtok::Greater: outs() << "Greater\n"; break;
- case asmtok::GreaterEqual: outs() << "GreaterEqual\n"; break;
- case asmtok::GreaterGreater: outs() << "GreaterGreater\n"; break;
- case asmtok::LParen: outs() << "LParen\n"; break;
- case asmtok::Less: outs() << "Less\n"; break;
- case asmtok::LessEqual: outs() << "LessEqual\n"; break;
- case asmtok::LessGreater: outs() << "LessGreater\n"; break;
- case asmtok::LessLess: outs() << "LessLess\n"; break;
- case asmtok::Minus: outs() << "Minus\n"; break;
- case asmtok::Percent: outs() << "Percent\n"; break;
- case asmtok::Pipe: outs() << "Pipe\n"; break;
- case asmtok::PipePipe: outs() << "PipePipe\n"; break;
- case asmtok::Plus: outs() << "Plus\n"; break;
- case asmtok::RParen: outs() << "RParen\n"; break;
- case asmtok::Slash: outs() << "Slash\n"; break;
- case asmtok::Star: outs() << "Star\n"; break;
- case asmtok::Tilde: outs() << "Tilde\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;
}
-
- Tok = Lexer.Lex();
}
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);
+}
+
static int AssembleInput(const char *ProgName) {
- std::string ErrorMessage;
- MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename,
- &ErrorMessage);
+ const Target *TheTarget = GetTarget(ProgName);
+ if (!TheTarget)
+ return 1;
+
+ std::string Error;
+ MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &Error);
if (Buffer == 0) {
errs() << ProgName << ": ";
- if (ErrorMessage.size())
- errs() << ErrorMessage << "\n";
+ if (Error.size())
+ errs() << Error << "\n";
else
errs() << "input file didn't read correctly.\n";
return 1;
@@ -151,7 +226,7 @@ static int AssembleInput(const char *ProgName) {
SourceMgr SrcMgr;
- // Tell SrcMgr about this buffer, which is what TGParser will pick up.
+ // Tell SrcMgr about this buffer, which is what the parser will pick up.
SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
// Record the location of the include directories so that the lexer can find
@@ -159,13 +234,53 @@ static int AssembleInput(const char *ProgName) {
SrcMgr.setIncludeDirs(IncludeDirs);
MCContext Ctx;
- OwningPtr<MCStreamer> Str(createAsmStreamer(Ctx, outs()));
+ 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, ""));
+
+ if (!TM) {
+ errs() << ProgName << ": error: could not create target for triple '"
+ << TripleName << "'.\n";
+ return 1;
+ }
+
+ OwningPtr<MCInstPrinter> IP;
+ OwningPtr<MCCodeEmitter> CE;
+ OwningPtr<MCStreamer> Str;
+
+ const MCAsmInfo *MAI = TheTarget->createAsmInfo(TripleName);
+ assert(MAI && "Unable to create target asm info!");
- // FIXME: Target hook & command line option for initial section.
- Str.get()->SwitchSection(Ctx.GetSection("__TEXT,__text,regular,pure_instructions"));
+ if (FileType == OFT_AssemblyFile) {
+ IP.reset(TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *Out));
+ if (ShowEncoding)
+ CE.reset(TheTarget->createCodeEmitter(*TM));
+ Str.reset(createAsmStreamer(Ctx, *Out, *MAI, IP.get(), CE.get()));
+ } else {
+ assert(FileType == OFT_ObjectFile && "Invalid file type!");
+ CE.reset(TheTarget->createCodeEmitter(*TM));
+ Str.reset(createMachOStreamer(Ctx, *Out, CE.get()));
+ }
- AsmParser Parser(SrcMgr, Ctx, *Str.get());
- return Parser.Run();
+ AsmParser Parser(SrcMgr, Ctx, *Str.get(), *MAI);
+ OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(Parser));
+ if (!TAP) {
+ errs() << ProgName
+ << ": error: this target does not support assembly parsing.\n";
+ return 1;
+ }
+
+ Parser.setTargetParser(*TAP.get());
+
+ int Res = Parser.Run();
+ if (Out != &fouts())
+ delete Out;
+
+ return Res;
}
@@ -174,6 +289,14 @@ int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ // Initialize targets and assembly printers/parsers.
+ llvm::InitializeAllTargetInfos();
+ // FIXME: We shouldn't need to initialize the Target(Machine)s.
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllAsmParsers();
+
cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
switch (Action) {
diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp
index 4e01180..2baf532 100644
--- a/tools/llvm-nm/llvm-nm.cpp
+++ b/tools/llvm-nm/llvm-nm.cpp
@@ -24,12 +24,12 @@
#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 <algorithm>
#include <cctype>
#include <cerrno>
#include <cstring>
-#include <iostream>
using namespace llvm;
namespace {
@@ -88,7 +88,8 @@ 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.hasAvailableExternallyLinkage()) return;
+ if (GV.hasPrivateLinkage() || GV.hasLinkerPrivateLinkage() ||
+ GV.hasAvailableExternallyLinkage()) return;
const std::string SymbolAddrStr = " "; // Not used yet...
char TypeChar = TypeCharForSymbol(GV);
@@ -99,31 +100,31 @@ static void DumpSymbolNameForGlobalValue(GlobalValue &GV) {
if (GV.hasLocalLinkage () && ExternalOnly)
return;
if (OutputFormat == posix) {
- std::cout << GV.getName () << " " << TypeCharForSymbol(GV) << " "
- << SymbolAddrStr << "\n";
+ outs() << GV.getName () << " " << TypeCharForSymbol(GV) << " "
+ << SymbolAddrStr << "\n";
} else if (OutputFormat == bsd) {
- std::cout << SymbolAddrStr << " " << TypeCharForSymbol(GV) << " "
- << GV.getName () << "\n";
+ outs() << SymbolAddrStr << " " << TypeCharForSymbol(GV) << " "
+ << GV.getName () << "\n";
} else if (OutputFormat == sysv) {
std::string PaddedName (GV.getName ());
while (PaddedName.length () < 20)
PaddedName += " ";
- std::cout << PaddedName << "|" << SymbolAddrStr << "| "
- << TypeCharForSymbol(GV)
- << " | | | |\n";
+ outs() << PaddedName << "|" << SymbolAddrStr << "| "
+ << TypeCharForSymbol(GV)
+ << " | | | |\n";
}
}
static void DumpSymbolNamesFromModule(Module *M) {
const std::string &Filename = M->getModuleIdentifier ();
if (OutputFormat == posix && MultipleFiles) {
- std::cout << Filename << ":\n";
+ outs() << Filename << ":\n";
} else if (OutputFormat == bsd && MultipleFiles) {
- std::cout << "\n" << Filename << ":\n";
+ outs() << "\n" << Filename << ":\n";
} else if (OutputFormat == sysv) {
- std::cout << "\n\nSymbols from " << Filename << ":\n\n"
- << "Name Value Class Type"
- << " Size Line Section\n";
+ outs() << "\n\nSymbols from " << Filename << ":\n\n"
+ << "Name Value Class Type"
+ << " Size Line Section\n";
}
std::for_each (M->begin(), M->end(), DumpSymbolNameForGlobalValue);
std::for_each (M->global_begin(), M->global_end(),
@@ -133,7 +134,7 @@ static void DumpSymbolNamesFromModule(Module *M) {
}
static void DumpSymbolNamesFromFile(std::string &Filename) {
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
std::string ErrorMessage;
sys::Path aPath(Filename);
// Note: Currently we do not support reading an archive from stdin.
@@ -144,29 +145,28 @@ static void DumpSymbolNamesFromFile(std::string &Filename) {
if (Buffer.get())
Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage);
- if (Result)
+ if (Result) {
DumpSymbolNamesFromModule(Result);
- else {
- std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
- return;
- }
+ delete Result;
+ } else
+ errs() << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
} else if (aPath.isArchive()) {
std::string ErrMsg;
Archive* archive = Archive::OpenAndLoad(sys::Path(Filename), Context,
&ErrorMessage);
if (!archive)
- std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
+ errs() << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
std::vector<Module *> Modules;
if (archive->getAllModules(Modules, &ErrorMessage)) {
- std::cerr << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
+ errs() << ToolName << ": " << Filename << ": " << ErrorMessage << "\n";
return;
}
MultipleFiles = true;
std::for_each (Modules.begin(), Modules.end(), DumpSymbolNamesFromModule);
} else {
- std::cerr << ToolName << ": " << Filename << ": "
- << "unrecognizable file type\n";
+ errs() << ToolName << ": " << Filename << ": "
+ << "unrecognizable file type\n";
return;
}
}
diff --git a/tools/llvm-prof/llvm-prof.cpp b/tools/llvm-prof/llvm-prof.cpp
index 2cff296..cff139e 100644
--- a/tools/llvm-prof/llvm-prof.cpp
+++ b/tools/llvm-prof/llvm-prof.cpp
@@ -16,17 +16,20 @@
#include "llvm/InstrTypes.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
+#include "llvm/PassManager.h"
#include "llvm/Assembly/AsmAnnotationWriter.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/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Format.h"
#include "llvm/System/Signals.h"
#include <algorithm>
-#include <iostream>
#include <iomanip>
#include <map>
#include <set>
@@ -55,71 +58,202 @@ namespace {
// PairSecondSort - A sorting predicate to sort by the second element of a pair.
template<class T>
struct PairSecondSortReverse
- : public std::binary_function<std::pair<T, unsigned>,
- std::pair<T, unsigned>, bool> {
- bool operator()(const std::pair<T, unsigned> &LHS,
- const std::pair<T, unsigned> &RHS) const {
+ : public std::binary_function<std::pair<T, double>,
+ std::pair<T, double>, bool> {
+ bool operator()(const std::pair<T, double> &LHS,
+ const std::pair<T, double> &RHS) const {
return LHS.second > RHS.second;
}
};
+static double ignoreMissing(double w) {
+ if (w == ProfileInfo::MissingValue) return 0;
+ return w;
+}
+
namespace {
class ProfileAnnotator : public AssemblyAnnotationWriter {
- std::map<const Function *, unsigned> &FuncFreqs;
- std::map<const BasicBlock*, unsigned> &BlockFreqs;
- std::map<ProfileInfoLoader::Edge, unsigned> &EdgeFreqs;
+ ProfileInfo &PI;
public:
- ProfileAnnotator(std::map<const Function *, unsigned> &FF,
- std::map<const BasicBlock*, unsigned> &BF,
- std::map<ProfileInfoLoader::Edge, unsigned> &EF)
- : FuncFreqs(FF), BlockFreqs(BF), EdgeFreqs(EF) {}
+ ProfileAnnotator(ProfileInfo& pi) : PI(pi) {}
virtual void emitFunctionAnnot(const Function *F, raw_ostream &OS) {
- OS << ";;; %" << F->getName() << " called " << FuncFreqs[F]
- << " times.\n;;;\n";
+ double w = PI.getExecutionCount(F);
+ if (w != ProfileInfo::MissingValue) {
+ OS << ";;; %" << F->getName() << " called "<<(unsigned)w
+ <<" times.\n;;;\n";
+ }
}
virtual void emitBasicBlockStartAnnot(const BasicBlock *BB,
raw_ostream &OS) {
- if (BlockFreqs.empty()) return;
- std::map<const BasicBlock *, unsigned>::const_iterator I =
- BlockFreqs.find(BB);
- if (I != BlockFreqs.end())
- OS << "\t;;; Basic block executed " << I->second << " times.\n";
- else
- OS << "\t;;; Never executed!\n";
+ double w = PI.getExecutionCount(BB);
+ if (w != ProfileInfo::MissingValue) {
+ if (w != 0) {
+ OS << "\t;;; Basic block executed " << (unsigned)w << " times.\n";
+ } else {
+ OS << "\t;;; Never executed!\n";
+ }
+ }
}
virtual void emitBasicBlockEndAnnot(const BasicBlock *BB, raw_ostream &OS) {
- if (EdgeFreqs.empty()) return;
-
// Figure out how many times each successor executed.
- std::vector<std::pair<const BasicBlock*, unsigned> > SuccCounts;
- const TerminatorInst *TI = BB->getTerminator();
+ std::vector<std::pair<ProfileInfo::Edge, double> > SuccCounts;
- std::map<ProfileInfoLoader::Edge, unsigned>::iterator I =
- EdgeFreqs.lower_bound(std::make_pair(const_cast<BasicBlock*>(BB), 0U));
- for (; I != EdgeFreqs.end() && I->first.first == BB; ++I)
- if (I->second)
- SuccCounts.push_back(std::make_pair(TI->getSuccessor(I->first.second),
- I->second));
+ const TerminatorInst *TI = BB->getTerminator();
+ for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
+ BasicBlock* Succ = TI->getSuccessor(s);
+ double w = ignoreMissing(PI.getEdgeWeight(std::make_pair(BB, Succ)));
+ if (w != 0)
+ SuccCounts.push_back(std::make_pair(std::make_pair(BB, Succ), w));
+ }
if (!SuccCounts.empty()) {
OS << "\t;;; Out-edge counts:";
for (unsigned i = 0, e = SuccCounts.size(); i != e; ++i)
- OS << " [" << SuccCounts[i].second << " -> "
- << SuccCounts[i].first->getName() << "]";
+ OS << " [" << (SuccCounts[i]).second << " -> "
+ << (SuccCounts[i]).first.second->getName() << "]";
OS << "\n";
}
}
};
}
+namespace {
+ /// ProfileInfoPrinterPass - Helper pass to dump the profile information for
+ /// a module.
+ //
+ // FIXME: This should move elsewhere.
+ class ProfileInfoPrinterPass : public ModulePass {
+ ProfileInfoLoader &PIL;
+ public:
+ static char ID; // Class identification, replacement for typeinfo.
+ explicit ProfileInfoPrinterPass(ProfileInfoLoader &_PIL)
+ : ModulePass(&ID), PIL(_PIL) {}
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequired<ProfileInfo>();
+ }
+
+ bool runOnModule(Module &M);
+ };
+}
+
+char ProfileInfoPrinterPass::ID = 0;
+
+bool ProfileInfoPrinterPass::runOnModule(Module &M) {
+ ProfileInfo &PI = getAnalysis<ProfileInfo>();
+ std::map<const Function *, unsigned> FuncFreqs;
+ std::map<const BasicBlock*, unsigned> BlockFreqs;
+ std::map<ProfileInfo::Edge, unsigned> EdgeFreqs;
+
+ // Output a report. Eventually, there will be multiple reports selectable on
+ // the command line, for now, just keep things simple.
+
+ // Emit the most frequent function table...
+ std::vector<std::pair<Function*, double> > FunctionCounts;
+ std::vector<std::pair<BasicBlock*, double> > Counts;
+ for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) {
+ if (FI->isDeclaration()) continue;
+ double w = ignoreMissing(PI.getExecutionCount(FI));
+ FunctionCounts.push_back(std::make_pair(FI, w));
+ for (Function::iterator BB = FI->begin(), BBE = FI->end();
+ BB != BBE; ++BB) {
+ double w = ignoreMissing(PI.getExecutionCount(BB));
+ Counts.push_back(std::make_pair(BB, w));
+ }
+ }
+
+ // Sort by the frequency, backwards.
+ sort(FunctionCounts.begin(), FunctionCounts.end(),
+ PairSecondSortReverse<Function*>());
+
+ double TotalExecutions = 0;
+ for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i)
+ TotalExecutions += FunctionCounts[i].second;
+
+ outs() << "===" << std::string(73, '-') << "===\n"
+ << "LLVM profiling output for execution";
+ if (PIL.getNumExecutions() != 1) outs() << "s";
+ outs() << ":\n";
+
+ for (unsigned i = 0, e = PIL.getNumExecutions(); i != e; ++i) {
+ outs() << " ";
+ if (e != 1) outs() << i+1 << ". ";
+ outs() << PIL.getExecution(i) << "\n";
+ }
+
+ outs() << "\n===" << std::string(73, '-') << "===\n";
+ outs() << "Function execution frequencies:\n\n";
+
+ // Print out the function frequencies...
+ outs() << " ## Frequency\n";
+ for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) {
+ if (FunctionCounts[i].second == 0) {
+ outs() << "\n NOTE: " << e-i << " function"
+ << (e-i-1 ? "s were" : " was") << " never executed!\n";
+ break;
+ }
+
+ outs() << format("%3d", i+1) << ". "
+ << format("%5.2g", FunctionCounts[i].second) << "/"
+ << format("%g", TotalExecutions) << " "
+ << FunctionCounts[i].first->getNameStr() << "\n";
+ }
+
+ std::set<Function*> FunctionsToPrint;
+
+ TotalExecutions = 0;
+ for (unsigned i = 0, e = Counts.size(); i != e; ++i)
+ TotalExecutions += Counts[i].second;
+
+ // Sort by the frequency, backwards.
+ sort(Counts.begin(), Counts.end(),
+ PairSecondSortReverse<BasicBlock*>());
+
+ outs() << "\n===" << std::string(73, '-') << "===\n";
+ outs() << "Top 20 most frequently executed basic blocks:\n\n";
+
+ // Print out the function frequencies...
+ outs() <<" ## %% \tFrequency\n";
+ unsigned BlocksToPrint = Counts.size();
+ if (BlocksToPrint > 20) BlocksToPrint = 20;
+ for (unsigned i = 0; i != BlocksToPrint; ++i) {
+ if (Counts[i].second == 0) break;
+ Function *F = Counts[i].first->getParent();
+ outs() << format("%3d", i+1) << ". "
+ << format("%5g", Counts[i].second/(double)TotalExecutions*100) << "% "
+ << format("%5.0f", Counts[i].second) << "/"
+ << format("%g", TotalExecutions) << "\t"
+ << F->getNameStr() << "() - "
+ << Counts[i].first->getNameStr() << "\n";
+ FunctionsToPrint.insert(F);
+ }
+
+ if (PrintAnnotatedLLVM || PrintAllCode) {
+ outs() << "\n===" << std::string(73, '-') << "===\n";
+ outs() << "Annotated LLVM code for the module:\n\n";
+
+ ProfileAnnotator PA(PI);
+
+ if (FunctionsToPrint.empty() || PrintAllCode)
+ M.print(outs(), &PA);
+ else
+ // Print just a subset of the functions.
+ for (std::set<Function*>::iterator I = FunctionsToPrint.begin(),
+ E = FunctionsToPrint.end(); I != E; ++I)
+ (*I)->print(outs(), &PA);
+ }
+
+ return false;
+}
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
try {
cl::ParseCommandLineOptions(argc, argv, "llvm profile dump decoder\n");
@@ -133,128 +267,29 @@ int main(int argc, char **argv) {
delete Buffer;
}
if (M == 0) {
- std::cerr << argv[0] << ": " << BitcodeFile << ": "
+ errs() << argv[0] << ": " << BitcodeFile << ": "
<< ErrorMessage << "\n";
return 1;
}
- // Read the profiling information
- ProfileInfoLoader PI(argv[0], ProfileDataFile, *M);
-
- std::map<const Function *, unsigned> FuncFreqs;
- std::map<const BasicBlock*, unsigned> BlockFreqs;
- std::map<ProfileInfoLoader::Edge, unsigned> EdgeFreqs;
-
- // Output a report. Eventually, there will be multiple reports selectable on
- // the command line, for now, just keep things simple.
-
- // Emit the most frequent function table...
- std::vector<std::pair<Function*, unsigned> > FunctionCounts;
- PI.getFunctionCounts(FunctionCounts);
- FuncFreqs.insert(FunctionCounts.begin(), FunctionCounts.end());
-
- // Sort by the frequency, backwards.
- sort(FunctionCounts.begin(), FunctionCounts.end(),
- PairSecondSortReverse<Function*>());
-
- uint64_t TotalExecutions = 0;
- for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i)
- TotalExecutions += FunctionCounts[i].second;
-
- std::cout << "===" << std::string(73, '-') << "===\n"
- << "LLVM profiling output for execution";
- if (PI.getNumExecutions() != 1) std::cout << "s";
- std::cout << ":\n";
-
- for (unsigned i = 0, e = PI.getNumExecutions(); i != e; ++i) {
- std::cout << " ";
- if (e != 1) std::cout << i+1 << ". ";
- std::cout << PI.getExecution(i) << "\n";
- }
-
- std::cout << "\n===" << std::string(73, '-') << "===\n";
- std::cout << "Function execution frequencies:\n\n";
-
- // Print out the function frequencies...
- std::cout << " ## Frequency\n";
- for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) {
- if (FunctionCounts[i].second == 0) {
- std::cout << "\n NOTE: " << e-i << " function" <<
- (e-i-1 ? "s were" : " was") << " never executed!\n";
- break;
- }
-
- std::cout << std::setw(3) << i+1 << ". "
- << std::setw(5) << FunctionCounts[i].second << "/"
- << TotalExecutions << " "
- << FunctionCounts[i].first->getName().c_str() << "\n";
- }
-
- std::set<Function*> FunctionsToPrint;
-
- // If we have block count information, print out the LLVM module with
- // frequency annotations.
- if (PI.hasAccurateBlockCounts()) {
- std::vector<std::pair<BasicBlock*, unsigned> > Counts;
- PI.getBlockCounts(Counts);
-
- TotalExecutions = 0;
- for (unsigned i = 0, e = Counts.size(); i != e; ++i)
- TotalExecutions += Counts[i].second;
-
- // Sort by the frequency, backwards.
- sort(Counts.begin(), Counts.end(),
- PairSecondSortReverse<BasicBlock*>());
-
- std::cout << "\n===" << std::string(73, '-') << "===\n";
- std::cout << "Top 20 most frequently executed basic blocks:\n\n";
-
- // Print out the function frequencies...
- std::cout <<" ## %% \tFrequency\n";
- unsigned BlocksToPrint = Counts.size();
- if (BlocksToPrint > 20) BlocksToPrint = 20;
- for (unsigned i = 0; i != BlocksToPrint; ++i) {
- if (Counts[i].second == 0) break;
- Function *F = Counts[i].first->getParent();
- std::cout << std::setw(3) << i+1 << ". "
- << std::setw(5) << std::setprecision(2)
- << Counts[i].second/(double)TotalExecutions*100 << "% "
- << std::setw(5) << Counts[i].second << "/"
- << TotalExecutions << "\t"
- << F->getName().c_str() << "() - "
- << Counts[i].first->getName().c_str() << "\n";
- FunctionsToPrint.insert(F);
- }
-
- BlockFreqs.insert(Counts.begin(), Counts.end());
- }
-
- if (PI.hasAccurateEdgeCounts()) {
- std::vector<std::pair<ProfileInfoLoader::Edge, unsigned> > Counts;
- PI.getEdgeCounts(Counts);
- EdgeFreqs.insert(Counts.begin(), Counts.end());
- }
+ // Read the profiling information. This is redundant since we load it again
+ // using the standard profile info provider pass, but for now this gives us
+ // access to additional information not exposed via the ProfileInfo
+ // interface.
+ ProfileInfoLoader PIL(argv[0], ProfileDataFile, *M);
- if (PrintAnnotatedLLVM || PrintAllCode) {
- std::cout << "\n===" << std::string(73, '-') << "===\n";
- std::cout << "Annotated LLVM code for the module:\n\n";
-
- ProfileAnnotator PA(FuncFreqs, BlockFreqs, EdgeFreqs);
-
- if (FunctionsToPrint.empty() || PrintAllCode)
- M->print(std::cout, &PA);
- else
- // Print just a subset of the functions.
- for (std::set<Function*>::iterator I = FunctionsToPrint.begin(),
- E = FunctionsToPrint.end(); I != E; ++I)
- (*I)->print(std::cout, &PA);
- }
+ // Run the printer pass.
+ PassManager PassMgr;
+ PassMgr.add(createProfileLoaderPass(ProfileDataFile));
+ PassMgr.add(new ProfileInfoPrinterPass(PIL));
+ PassMgr.run(*M);
return 0;
} catch (const std::string& msg) {
- std::cerr << argv[0] << ": " << msg << "\n";
+ errs() << argv[0] << ": " << msg << "\n";
} catch (...) {
- std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
+ errs() << argv[0] << ": Unexpected unknown exception occurred.\n";
}
+
return 1;
}
diff --git a/tools/llvm-ranlib/llvm-ranlib.cpp b/tools/llvm-ranlib/llvm-ranlib.cpp
index d9bcc48..dffe3ad 100644
--- a/tools/llvm-ranlib/llvm-ranlib.cpp
+++ b/tools/llvm-ranlib/llvm-ranlib.cpp
@@ -17,6 +17,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
#include <iostream>
#include <iomanip>
@@ -48,7 +49,7 @@ int main(int argc, char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal();
llvm::PrettyStackTraceProgram X(argc, argv);
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Have the command line options parsed and handle things
@@ -87,13 +88,13 @@ int main(int argc, char **argv) {
printSymbolTable(TheArchive);
} catch (const char* msg) {
- std::cerr << argv[0] << ": " << msg << "\n\n";
+ errs() << argv[0] << ": " << msg << "\n\n";
exitCode = 1;
} catch (const std::string& msg) {
- std::cerr << argv[0] << ": " << msg << "\n";
+ errs() << argv[0] << ": " << msg << "\n";
exitCode = 2;
} catch (...) {
- std::cerr << argv[0] << ": An unexpected unknown exception occurred.\n";
+ errs() << argv[0] << ": An unexpected unknown exception occurred.\n";
exitCode = 3;
}
return exitCode;
diff --git a/tools/llvm-stub/llvm-stub.c b/tools/llvm-stub/llvm-stub.c
index e5624a9..f2e478e 100644
--- a/tools/llvm-stub/llvm-stub.c
+++ b/tools/llvm-stub/llvm-stub.c
@@ -61,11 +61,10 @@ int main(int argc, char** argv) {
Args[1] = strcat(strcpy((char*)malloc(strlen(argv[0])+4), argv[0]), ".bc");
/* The rest of the args are as before. */
- memcpy(Args+2, argv+1, sizeof(char*)*argc);
+ memcpy((char **)Args+2, argv+1, sizeof(char*)*argc);
/* Run the JIT. */
- execvp(Interp, (char *const*)Args);
-
+ execvp(Interp, (char **)Args);
/* if _execv returns, the JIT could not be started. */
fprintf(stderr, "Could not execute the LLVM JIT. Either add 'lli' to your"
" path, or set the\ninterpreter you want to use in the LLVMINTERP "
diff --git a/tools/llvmc/doc/LLVMC-Reference.rst b/tools/llvmc/doc/LLVMC-Reference.rst
index b43c3e3..fad2ccc 100644
--- a/tools/llvmc/doc/LLVMC-Reference.rst
+++ b/tools/llvmc/doc/LLVMC-Reference.rst
@@ -97,6 +97,11 @@ configuration libraries:
the ``-o`` option. The ``--save-temps=cwd`` and ``--save-temps`` switches are
both synonyms for the default behaviour.
+* ``--temp-dir DIRECTORY`` - Store temporary files in the given directory. This
+ directory is deleted on exit unless ``--save-temps`` is specified. If
+ ``--save-temps=obj`` is also specified, ``--temp-dir`` is given the
+ precedence.
+
* ``--check-graph`` - Check the compilation for common errors like mismatched
output/input language names, multiple default edges and cycles. Because of
plugins, these checks can't be performed at compile-time. Exit with code zero
@@ -347,6 +352,12 @@ separate option groups syntactically.
3))``. Only list options can have this attribute; you can, however, use
the ``one_or_more`` and ``zero_or_one`` properties.
+ - ``init`` - this option has a default value, either a string (if it is a
+ parameter), or a boolean (if it is a switch; boolean constants are called
+ ``true`` and ``false``). List options can't have this attribute. Usage
+ examples: ``(switch_option "foo", (init true))``; ``(prefix_option "bar",
+ (init "baz"))``.
+
- ``extern`` - this option is defined in some other plugin, see below.
External options
@@ -362,7 +373,8 @@ for. Example::
(switch_option "E", (extern))
...
-See also the section on plugin `priorities`__.
+If an external option has additional attributes besides 'extern', they are
+ignored. See also the section on plugin `priorities`__.
__ priorities_
@@ -446,17 +458,27 @@ use TableGen inheritance instead.
- ``empty`` - The opposite of ``not_empty``. Equivalent to ``(not (not_empty
X))``. Provided for convenience.
+ - ``single_input_file`` - Returns true if there was only one input file
+ provided on the command-line. Used without arguments:
+ ``(single_input_file)``.
+
+ - ``multiple_input_files`` - Equivalent to ``(not (single_input_file))`` (the
+ case of zero input files is considered an error).
+
- ``default`` - Always evaluates to true. Should always be the last
test in the ``case`` expression.
- - ``and`` - A standard logical combinator that returns true iff all
- of its arguments return true. Used like this: ``(and (test1),
- (test2), ... (testN))``. Nesting of ``and`` and ``or`` is allowed,
- but not encouraged.
+ - ``and`` - A standard binary logical combinator that returns true iff all of
+ its arguments return true. Used like this: ``(and (test1), (test2),
+ ... (testN))``. Nesting of ``and`` and ``or`` is allowed, but not
+ encouraged.
+
+ - ``or`` - A binary logical combinator that returns true iff any of its
+ arguments returns true. Example: ``(or (test1), (test2), ... (testN))``.
+
+ - ``not`` - Standard unary logical combinator that negates its
+ argument. Example: ``(not (or (test1), (test2), ... (testN)))``.
- - ``or`` - Another logical combinator that returns true only if any
- one of its arguments returns true. Example: ``(or (test1),
- (test2), ... (testN))``.
Writing a tool description
@@ -487,8 +509,8 @@ The complete list of all currently implemented tool properties follows.
- ``in_language`` - input language name. Can be either a string or a
list, in case the tool supports multiple input languages.
- - ``out_language`` - output language name. Tools are not allowed to
- have multiple output languages.
+ - ``out_language`` - output language name. Multiple output languages are not
+ allowed.
- ``output_suffix`` - output file suffix. Can also be changed
dynamically, see documentation on actions.
diff --git a/tools/llvmc/example/Hello/Hello.cpp b/tools/llvmc/example/Hello/Hello.cpp
index 23a13a5..9c96bd0 100644
--- a/tools/llvmc/example/Hello/Hello.cpp
+++ b/tools/llvmc/example/Hello/Hello.cpp
@@ -13,13 +13,12 @@
#include "llvm/CompilerDriver/CompilationGraph.h"
#include "llvm/CompilerDriver/Plugin.h"
-
-#include <iostream>
+#include "llvm/Support/raw_ostream.h"
namespace {
struct MyPlugin : public llvmc::BasePlugin {
void PopulateLanguageMap(llvmc::LanguageMap&) const
- { std::cout << "Hello!\n"; }
+ { outs() << "Hello!\n"; }
void PopulateCompilationGraph(llvmc::CompilationGraph&) const
{}
diff --git a/tools/llvmc/example/mcc16/driver/Main.cpp b/tools/llvmc/example/mcc16/driver/Main.cpp
index b1f5b67..f42e17f 100644
--- a/tools/llvmc/example/mcc16/driver/Main.cpp
+++ b/tools/llvmc/example/mcc16/driver/Main.cpp
@@ -7,8 +7,31 @@
//
//===----------------------------------------------------------------------===//
//
-// Just include CompilerDriver/Main.inc.
+// Usually this file just includes CompilerDriver/Main.inc, but here we apply
+// some trickery to make the built-in '-save-temps' option hidden and enable
+// '--temp-dir' by default.
//
//===----------------------------------------------------------------------===//
-#include "llvm/CompilerDriver/Main.inc"
+#include "llvm/CompilerDriver/BuiltinOptions.h"
+#include "llvm/CompilerDriver/ForceLinkage.h"
+#include "llvm/System/Path.h"
+
+namespace llvmc {
+ int Main(int argc, char** argv);
+}
+
+int main(int argc, char** argv) {
+
+ // HACK
+ SaveTemps.setHiddenFlag(llvm::cl::Hidden);
+ TempDirname = "tmp-objs";
+
+ // Remove the temp dir if already exists.
+ llvm::sys::Path tempDir;
+ tempDir = TempDirname;
+ tempDir.eraseFromDisk(true);
+
+ llvmc::ForceLinkage();
+ return llvmc::Main(argc, argv);
+}
diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td b/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td
index de85fa9..3d25ab6 100644
--- a/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td
+++ b/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td
@@ -55,7 +55,7 @@ def llvm_ld_lto : Tool<[
(in_language "llvm-bitcode"),
(out_language "llvm-bitcode"),
(output_suffix "bc"),
- (cmd_line "$CALL(GetBinDir)llvm-ld -link-as-library $INFILE -o $OUTFILE"),
+ (cmd_line "$CALL(GetBinDir)llvm-ld -L $CALL(GetStdLibsDir) -l std $INFILE -b $OUTFILE"),
(actions (case
(switch_on "g"), (append_cmd "-disable-opt"),
(not_empty "Wo,"), (unpack_values "Wo,"))),
@@ -66,7 +66,7 @@ def llc : Tool<[
(in_language "llvm-bitcode"),
(out_language "assembler"),
(output_suffix "s"),
- (cmd_line "$CALL(GetBinDir)llc -march=pic16 -f $INFILE -o $OUTFILE"),
+ (cmd_line "$CALL(GetBinDir)llc -march=pic16 -disable-jump-tables -f $INFILE -o $OUTFILE"),
(actions (case
(switch_on "S"), (stop_compilation),
(not_empty "Wllc,"), (unpack_values "Wllc,"),
@@ -87,7 +87,7 @@ def mplink : Tool<[
(in_language "object-code"),
(out_language "executable"),
(output_suffix "out"),
- (cmd_line "$CALL(GetBinDir)mplink.exe /k $CALL(GetStdLinkerScriptsDir) /l $CALL(GetStdLibsDir) 16f1937.lkr intrinsics.lib std.lib $INFILE -o $OUTFILE"),
+ (cmd_line "$CALL(GetBinDir)mplink.exe -k $CALL(GetStdLinkerScriptsDir) -l $CALL(GetStdLibsDir) 16f1937_g.lkr intrinsics.lib devices.lib $INFILE -o $OUTFILE"),
(actions (case
(not_empty "Wl,"), (unpack_values "Wl,"))),
(join)
diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp b/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp
index 21a25b3..f8492ed 100644
--- a/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp
+++ b/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp
@@ -10,13 +10,17 @@ namespace llvmc {
}
// Returns the platform specific directory separator via #ifdefs.
-static std::string GetDirSeparator(void) {
+static std::string GetDirSeparator() {
+#ifdef _WIN32
+ return "\\";
+#else
return "/";
+#endif
}
namespace hooks {
// Get the dir where c16 executables reside.
-std::string GetBinDir (void) {
+std::string GetBinDir() {
// Construct a Path object from the program name.
void *P = (void*) (intptr_t) GetBinDir;
sys::Path ProgramFullPath
@@ -30,7 +34,7 @@ std::string GetBinDir (void) {
}
// Get the Top-level Installation dir for c16.
-std::string GetInstallDir (void) {
+std::string GetInstallDir() {
sys::Path BinDirPath = sys::Path(GetBinDir());
// Go one more level up to get the install dir.
@@ -40,22 +44,22 @@ std::string GetInstallDir (void) {
}
// Get the dir where the c16 header files reside.
-std::string GetStdHeadersDir (void) {
+std::string GetStdHeadersDir() {
return GetInstallDir() + "include";
}
// Get the dir where the assembler header files reside.
-std::string GetStdAsmHeadersDir (void) {
+std::string GetStdAsmHeadersDir() {
return GetInstallDir() + "inc";
}
// Get the dir where the linker scripts reside.
-std::string GetStdLinkerScriptsDir (void) {
+std::string GetStdLinkerScriptsDir() {
return GetInstallDir() + "lkr";
}
// Get the dir where startup code, intrinsics and lib reside.
-std::string GetStdLibsDir (void) {
+std::string GetStdLibsDir() {
return GetInstallDir() + "lib";
}
}
diff --git a/tools/llvmc/plugins/Base/Base.td.in b/tools/llvmc/plugins/Base/Base.td.in
index 757078a..be325a0 100644
--- a/tools/llvmc/plugins/Base/Base.td.in
+++ b/tools/llvmc/plugins/Base/Base.td.in
@@ -1,4 +1,4 @@
-//===- Base.td - LLVMC2 toolchain descriptions -------------*- tablegen -*-===//
+//===- Base.td - LLVMC toolchain descriptions --------------*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file contains compilation graph description used by llvmc2.
+// This file contains compilation graph description used by llvmc.
//
//===----------------------------------------------------------------------===//
@@ -32,10 +32,17 @@ def OptList : OptionList<[
(help "Enable threads")),
(parameter_option "linker",
(help "Choose linker (possible values: gcc, g++)")),
+ (parameter_option "MF",
+ (help "Specify a file to write dependencies to"), (hidden)),
+ (parameter_option "MT",
+ (help "Change the name of the rule emitted by dependency generation"),
+ (hidden)),
(parameter_list_option "include",
(help "Include the named file prior to preprocessing")),
(prefix_list_option "I",
(help "Add a directory to include path")),
+ (prefix_list_option "D",
+ (help "Define a macro")),
(prefix_list_option "Wa,",
(help "Pass options to assembler")),
(prefix_list_option "Wllc,",
@@ -70,19 +77,25 @@ class llvm_gcc_based <string cmd_prefix, string in_lang, string E_ext> : Tool<
!strconcat(cmd_prefix, " -c $INFILE -o $OUTFILE -emit-llvm"))),
(actions
(case
+ (and (multiple_input_files), (or (switch_on "S"), (switch_on "c"))),
+ (error "cannot specify -o with -c or -S with multiple files"),
(switch_on "E"), [(stop_compilation), (output_suffix E_ext)],
(and (switch_on "emit-llvm"), (switch_on "S")),
[(output_suffix "ll"), (stop_compilation)],
(and (switch_on "emit-llvm"), (switch_on "c")), (stop_compilation),
(switch_on "fsyntax-only"), (stop_compilation),
(not_empty "include"), (forward "include"),
- (not_empty "I"), (forward "I"))),
+ (not_empty "I"), (forward "I"),
+ (not_empty "D"), (forward "D"),
+ (not_empty "MF"), (forward "MF"),
+ (not_empty "MT"), (forward "MT"))),
(sink)
]>;
def llvm_gcc_c : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x c", "c", "i">;
def llvm_gcc_cpp : llvm_gcc_based<"@LLVMGXXCOMMAND@ -x c++", "c++", "i">;
-def llvm_gcc_m : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c", "objective-c", "mi">;
+def llvm_gcc_m : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c",
+ "objective-c", "mi">;
def llvm_gcc_mxx : llvm_gcc_based<"@LLVMGCCCOMMAND@ -x objective-c++",
"objective-c++", "mi">;
@@ -98,7 +111,8 @@ def llvm_as : Tool<
[(in_language "llvm-assembler"),
(out_language "llvm-bitcode"),
(output_suffix "bc"),
- (cmd_line "llvm-as $INFILE -o $OUTFILE")
+ (cmd_line "llvm-as $INFILE -o $OUTFILE"),
+ (actions (case (switch_on "emit-llvm"), (stop_compilation)))
]>;
def llvm_gcc_assembler : Tool<
@@ -112,7 +126,7 @@ def llvm_gcc_assembler : Tool<
]>;
def llc : Tool<
-[(in_language "llvm-bitcode"),
+[(in_language ["llvm-bitcode", "llvm-assembler"]),
(out_language "assembler"),
(output_suffix "s"),
(cmd_line "llc -f $INFILE -o $OUTFILE"),
@@ -132,7 +146,7 @@ class llvm_gcc_based_linker <string cmd_prefix> : Tool<
(switch_on "pthread"), (append_cmd "-lpthread"),
(not_empty "L"), (forward "L"),
(not_empty "l"), (forward "l"),
- (not_empty "Wl,"), (unpack_values "Wl,")))
+ (not_empty "Wl,"), (forward "Wl,")))
]>;
// Default linker
@@ -165,7 +179,7 @@ def CompilationGraph : CompilationGraph<[
Edge<"root", "llvm_gcc_cpp">,
Edge<"root", "llvm_gcc_m">,
Edge<"root", "llvm_gcc_mxx">,
- Edge<"root", "llvm_as">,
+ Edge<"root", "llc">,
Edge<"llvm_gcc_c", "llc">,
Edge<"llvm_gcc_cpp", "llc">,
@@ -173,6 +187,8 @@ def CompilationGraph : CompilationGraph<[
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))>,
diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp
index 1a21132..c621721 100644
--- a/tools/lto/LTOCodeGenerator.cpp
+++ b/tools/lto/LTOCodeGenerator.cpp
@@ -30,26 +30,25 @@
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/FileWriters.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/StandardPasses.h"
#include "llvm/Support/SystemUtils.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Host.h"
+#include "llvm/System/Program.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Target/TargetRegistry.h"
#include "llvm/Target/TargetSelect.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Config/config.h"
-
-
#include <cstdlib>
-#include <fstream>
#include <unistd.h>
#include <fcntl.h>
@@ -75,11 +74,10 @@ LTOCodeGenerator::LTOCodeGenerator()
_linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL),
_emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
_codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
- _nativeObjectFile(NULL), _gccPath(NULL), _assemblerPath(NULL)
+ _nativeObjectFile(NULL), _assemblerPath(NULL)
{
- InitializeAllTargets();
- InitializeAllAsmPrinters();
-
+ InitializeAllTargets();
+ InitializeAllAsmPrinters();
}
LTOCodeGenerator::~LTOCodeGenerator()
@@ -126,13 +124,6 @@ bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model,
return true;
}
-void LTOCodeGenerator::setGccPath(const char* path)
-{
- if ( _gccPath )
- delete _gccPath;
- _gccPath = new sys::Path(path);
-}
-
void LTOCodeGenerator::setAssemblerPath(const char* path)
{
if ( _assemblerPath )
@@ -146,31 +137,34 @@ void LTOCodeGenerator::addMustPreserveSymbol(const char* sym)
}
-bool LTOCodeGenerator::writeMergedModules(const char* path, std::string& errMsg)
-{
- if ( this->determineTarget(errMsg) )
- return true;
+bool LTOCodeGenerator::writeMergedModules(const char *path,
+ std::string &errMsg) {
+ if (determineTarget(errMsg))
+ return true;
- // mark which symbols can not be internalized
- this->applyScopeRestrictions();
+ // mark which symbols can not be internalized
+ applyScopeRestrictions();
- // create output file
- std::ofstream out(path, std::ios_base::out|std::ios::trunc|std::ios::binary);
- if ( out.fail() ) {
- errMsg = "could not open bitcode file for writing: ";
- errMsg += path;
- return true;
- }
-
- // write bitcode to it
- WriteBitcodeToFile(_linker.getModule(), out);
- if ( out.fail() ) {
- errMsg = "could not write bitcode file: ";
- errMsg += path;
- return true;
- }
+ // create output file
+ std::string ErrInfo;
+ raw_fd_ostream Out(path, ErrInfo,
+ raw_fd_ostream::F_Binary);
+ if (!ErrInfo.empty()) {
+ errMsg = "could not open bitcode file for writing: ";
+ errMsg += path;
+ return true;
+ }
- return false;
+ // write bitcode to it
+ WriteBitcodeToFile(_linker.getModule(), Out);
+
+ if (Out.has_error()) {
+ errMsg = "could not write bitcode file: ";
+ errMsg += path;
+ return true;
+ }
+
+ return false;
}
@@ -185,7 +179,8 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg)
// generate assembly code
bool genResult = false;
{
- raw_fd_ostream asmFile(uniqueAsmPath.c_str(), false, errMsg);
+ raw_fd_ostream asmFD(uniqueAsmPath.c_str(), errMsg);
+ formatted_raw_ostream asmFile(asmFD);
if (!errMsg.empty())
return NULL;
genResult = this->generateAssemblyCode(asmFile, errMsg);
@@ -206,9 +201,8 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg)
sys::RemoveFileOnSignal(uniqueObjPath);
// assemble the assembly code
- const std::string& uniqueObjStr = uniqueObjPath.toString();
- bool asmResult = this->assemble(uniqueAsmPath.toString(),
- uniqueObjStr, errMsg);
+ const std::string& uniqueObjStr = uniqueObjPath.str();
+ bool asmResult = this->assemble(uniqueAsmPath.str(), uniqueObjStr, errMsg);
if ( !asmResult ) {
// remove old buffer if compile() called twice
delete _nativeObjectFile;
@@ -237,9 +231,6 @@ bool LTOCodeGenerator::assemble(const std::string& asmPath,
if ( _assemblerPath ) {
tool = *_assemblerPath;
needsCompilerOptions = false;
- }
- else if ( _gccPath ) {
- tool = *_gccPath;
} else {
// find compiler driver
tool = sys::Program::FindProgramByName("gcc");
@@ -324,11 +315,12 @@ bool LTOCodeGenerator::assemble(const std::string& asmPath,
bool LTOCodeGenerator::determineTarget(std::string& errMsg)
{
if ( _target == NULL ) {
+ std::string Triple = _linker.getModule()->getTargetTriple();
+ if (Triple.empty())
+ Triple = sys::getHostTriple();
+
// create target machine from info for merged modules
- Module* mergedModule = _linker.getModule();
- const TargetMachineRegistry::entry* march =
- TargetMachineRegistry::getClosestStaticTargetForModule(
- *mergedModule, errMsg);
+ const Target *march = TargetRegistry::lookupTarget(Triple, errMsg);
if ( march == NULL )
return true;
@@ -347,9 +339,8 @@ bool LTOCodeGenerator::determineTarget(std::string& errMsg)
}
// construct LTModule, hand over ownership of module and target
- std::string FeatureStr =
- getFeatureString(_linker.getModule()->getTargetTriple().c_str());
- _target = march->CtorFn(*mergedModule, FeatureStr.c_str());
+ std::string FeatureStr = getFeatureString(Triple.c_str());
+ _target = march->createTargetMachine(Triple, FeatureStr);
}
return false;
}
@@ -366,19 +357,19 @@ void LTOCodeGenerator::applyScopeRestrictions()
// mark which symbols can not be internalized
if ( !_mustPreserveSymbols.empty() ) {
Mangler mangler(*mergedModule,
- _target->getTargetAsmInfo()->getGlobalPrefix());
+ _target->getMCAsmInfo()->getGlobalPrefix());
std::vector<const char*> mustPreserveList;
for (Module::iterator f = mergedModule->begin(),
e = mergedModule->end(); f != e; ++f) {
if ( !f->isDeclaration()
- && _mustPreserveSymbols.count(mangler.getValueName(f)) )
- mustPreserveList.push_back(::strdup(f->getName().c_str()));
+ && _mustPreserveSymbols.count(mangler.getMangledName(f)) )
+ mustPreserveList.push_back(::strdup(f->getNameStr().c_str()));
}
for (Module::global_iterator v = mergedModule->global_begin(),
e = mergedModule->global_end(); v != e; ++v) {
if ( !v->isDeclaration()
- && _mustPreserveSymbols.count(mangler.getValueName(v)) )
- mustPreserveList.push_back(::strdup(v->getName().c_str()));
+ && _mustPreserveSymbols.count(mangler.getMangledName(v)) )
+ mustPreserveList.push_back(::strdup(v->getNameStr().c_str()));
}
passes.add(createInternalizePass(mustPreserveList));
}
@@ -390,10 +381,10 @@ void LTOCodeGenerator::applyScopeRestrictions()
}
/// Optimize merged modules using various IPO passes
-bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
+bool LTOCodeGenerator::generateAssemblyCode(formatted_raw_ostream& out,
std::string& errMsg)
{
- if ( this->determineTarget(errMsg) )
+ if ( this->determineTarget(errMsg) )
return true;
// mark which symbols can not be internalized
@@ -401,9 +392,19 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
Module* mergedModule = _linker.getModule();
- // If target supports exception handling then enable it now.
- if ( _target->getTargetAsmInfo()->doesSupportExceptionHandling() )
- llvm::ExceptionHandling = true;
+ // If target supports exception handling then enable it now.
+ switch (_target->getMCAsmInfo()->getExceptionHandlingType()) {
+ case ExceptionHandling::Dwarf:
+ llvm::DwarfExceptionHandling = true;
+ break;
+ case ExceptionHandling::SjLj:
+ llvm::SjLjExceptionHandling = true;
+ break;
+ case ExceptionHandling::None:
+ break;
+ default:
+ assert (0 && "Unknown exception handling model!");
+ }
// if options were requested, set them
if ( !_codegenOptions.empty() )
@@ -430,16 +431,16 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
codeGenPasses->add(new TargetData(*_target->getTargetData()));
- MachineCodeEmitter* mce = NULL;
+ ObjectCodeEmitter* oce = NULL;
switch (_target->addPassesToEmitFile(*codeGenPasses, out,
TargetMachine::AssemblyFile,
CodeGenOpt::Aggressive)) {
case FileModel::MachOFile:
- mce = AddMachOWriter(*codeGenPasses, out, *_target);
+ oce = AddMachOWriter(*codeGenPasses, out, *_target);
break;
case FileModel::ElfFile:
- mce = AddELFWriter(*codeGenPasses, out, *_target);
+ oce = AddELFWriter(*codeGenPasses, out, *_target);
break;
case FileModel::AsmFile:
break;
@@ -449,7 +450,7 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
return true;
}
- if (_target->addPassesToEmitFileFinish(*codeGenPasses, mce,
+ if (_target->addPassesToEmitFileFinish(*codeGenPasses, oce,
CodeGenOpt::Aggressive)) {
errMsg = "target does not support generation of this file type";
return true;
@@ -467,6 +468,7 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
codeGenPasses->run(*it);
codeGenPasses->doFinalization();
+
return false; // success
}
diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h
index 5548050..0ebec2c 100644
--- a/tools/lto/LTOCodeGenerator.h
+++ b/tools/lto/LTOCodeGenerator.h
@@ -37,7 +37,6 @@ public:
bool addModule(class LTOModule*, std::string& errMsg);
bool setDebugInfo(lto_debug_model, std::string& errMsg);
bool setCodePICModel(lto_codegen_model, std::string& errMsg);
- void setGccPath(const char* path);
void setAssemblerPath(const char* path);
void addMustPreserveSymbol(const char* sym);
bool writeMergedModules(const char* path,
@@ -45,7 +44,7 @@ public:
const void* compile(size_t* length, std::string& errMsg);
void setCodeGenDebugOptions(const char *opts);
private:
- bool generateAssemblyCode(llvm::raw_ostream& out,
+ bool generateAssemblyCode(llvm::formatted_raw_ostream& out,
std::string& errMsg);
bool assemble(const std::string& asmPath,
const std::string& objPath, std::string& errMsg);
@@ -63,7 +62,6 @@ private:
StringSet _mustPreserveSymbols;
llvm::MemoryBuffer* _nativeObjectFile;
std::vector<const char*> _codegenOptions;
- llvm::sys::Path* _gccPath;
llvm::sys::Path* _assemblerPath;
};
diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp
index 9c8baef..e1cf48d 100644
--- a/tools/lto/LTOModule.cpp
+++ b/tools/lto/LTOModule.cpp
@@ -24,21 +24,21 @@
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
#include "llvm/System/Process.h"
#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetMachineRegistry.h"
-#include "llvm/Target/TargetAsmInfo.h"
-
-#include <fstream>
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetSelect.h"
using namespace llvm;
bool LTOModule::isBitcodeFile(const void* mem, size_t length)
{
- return ( llvm::sys::IdentifyFileType((char*)mem, length)
- == llvm::sys::Bitcode_FileType );
+ return llvm::sys::IdentifyFileType((char*)mem, length)
+ == llvm::sys::Bitcode_FileType;
}
bool LTOModule::isBitcodeFile(const char* path)
@@ -50,7 +50,7 @@ bool LTOModule::isBitcodeFileForTarget(const void* mem, size_t length,
const char* triplePrefix)
{
MemoryBuffer* buffer = makeBuffer(mem, length);
- if ( buffer == NULL )
+ if (!buffer)
return false;
return isTargetMatch(buffer, triplePrefix);
}
@@ -71,12 +71,12 @@ bool LTOModule::isTargetMatch(MemoryBuffer* buffer, const char* triplePrefix)
OwningPtr<ModuleProvider> mp(getBitcodeModuleProvider(buffer,
getGlobalContext()));
// on success, mp owns buffer and both are deleted at end of this method
- if ( !mp ) {
+ if (!mp) {
delete buffer;
return false;
}
std::string actualTarget = mp->getModule()->getTargetTriple();
- return ( strncmp(actualTarget.c_str(), triplePrefix,
+ return (strncmp(actualTarget.c_str(), triplePrefix,
strlen(triplePrefix)) == 0);
}
@@ -90,7 +90,7 @@ LTOModule* LTOModule::makeLTOModule(const char* path,
std::string& errMsg)
{
OwningPtr<MemoryBuffer> buffer(MemoryBuffer::getFile(path, &errMsg));
- if ( !buffer )
+ if (!buffer)
return NULL;
return makeLTOModule(buffer.get(), errMsg);
}
@@ -103,8 +103,8 @@ 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) )
+ if ((((uintptr_t)endPtr & (sys::Process::GetPageSize()-1)) == 0)
+ || (*endPtr != 0))
return MemoryBuffer::getMemBufferCopy(startPtr, endPtr);
else
return MemoryBuffer::getMemBuffer(startPtr, endPtr);
@@ -115,7 +115,7 @@ LTOModule* LTOModule::makeLTOModule(const void* mem, size_t length,
std::string& errMsg)
{
OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length));
- if ( !buffer )
+ if (!buffer)
return NULL;
return makeLTOModule(buffer.get(), errMsg);
}
@@ -127,6 +127,8 @@ LTOModule* LTOModule::makeLTOModule(const void* mem, size_t length,
/// subtarget. It would be better if we could encode this information into the
/// IR. See <rdar://5972456>.
std::string getFeatureString(const char *TargetTriple) {
+ InitializeAllTargets();
+
SubtargetFeatures Features;
if (strncmp(TargetTriple, "powerpc-apple-", 14) == 0) {
@@ -142,20 +144,25 @@ std::string getFeatureString(const char *TargetTriple) {
LTOModule* LTOModule::makeLTOModule(MemoryBuffer* buffer,
std::string& errMsg)
{
+ InitializeAllTargets();
+
// parse bitcode buffer
OwningPtr<Module> m(ParseBitcodeFile(buffer, getGlobalContext(), &errMsg));
- if ( !m )
+ if (!m)
return NULL;
- // find machine architecture for this module
- const TargetMachineRegistry::entry* march =
- TargetMachineRegistry::getClosestStaticTargetForModule(*m, errMsg);
- if ( march == 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
- std::string FeatureStr = getFeatureString(m->getTargetTriple().c_str());
- TargetMachine* target = march->CtorFn(*m, FeatureStr);
+ std::string FeatureStr = getFeatureString(Triple.c_str());
+ TargetMachine* target = march->createTargetMachine(Triple, FeatureStr);
return new LTOModule(m.take(), target);
}
@@ -189,7 +196,7 @@ bool LTOModule::objcClassNameFromExpression(Constant* c, std::string& name)
if (GlobalVariable* gvn = dyn_cast<GlobalVariable>(op)) {
Constant* cn = gvn->getInitializer();
if (ConstantArray* ca = dyn_cast<ConstantArray>(cn)) {
- if ( ca->isCString() ) {
+ if (ca->isCString()) {
name = ".objc_class_name_" + ca->getAsString();
return true;
}
@@ -205,9 +212,9 @@ 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) ) {
+ if (objcClassNameFromExpression(c->getOperand(1), superclassName)) {
NameAndAttributes info;
- if ( _undefines.find(superclassName.c_str()) == _undefines.end() ) {
+ 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;
@@ -217,7 +224,7 @@ void LTOModule::addObjCClass(GlobalVariable* clgv)
}
// third slot in __OBJC,__class is pointer to class name
std::string className;
- if ( objcClassNameFromExpression(c->getOperand(2), className) ) {
+ if (objcClassNameFromExpression(c->getOperand(2), className)) {
const char* symbolName = ::strdup(className.c_str());
NameAndAttributes info;
info.name = symbolName;
@@ -238,9 +245,9 @@ 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) ) {
+ if (objcClassNameFromExpression(c->getOperand(1), targetclassName)) {
NameAndAttributes info;
- if ( _undefines.find(targetclassName.c_str()) == _undefines.end() ){
+ 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;
@@ -256,9 +263,9 @@ void LTOModule::addObjCCategory(GlobalVariable* clgv)
void LTOModule::addObjCClassRef(GlobalVariable* clgv)
{
std::string targetclassName;
- if ( objcClassNameFromExpression(clgv->getInitializer(), targetclassName) ){
+ if (objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) {
NameAndAttributes info;
- if ( _undefines.find(targetclassName.c_str()) == _undefines.end() ) {
+ 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;
@@ -293,23 +300,23 @@ void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler& mangler)
// 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 */ ) {
+ 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 (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 ) {
+ 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 ) {
+ else if (v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) {
if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
addObjCClassRef(gv);
}
@@ -325,35 +332,35 @@ void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler& mangler)
void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
- bool isFunction)
+ bool isFunction)
{
// ignore all llvm.* symbols
- if ( strncmp(def->getNameStart(), "llvm.", 5) == 0 )
+ if (def->getName().startswith("llvm."))
return;
// string is owned by _defines
- const char* symbolName = ::strdup(mangler.getValueName(def).c_str());
+ const char* symbolName = ::strdup(mangler.getMangledName(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 )
+ if (isFunction)
attr |= LTO_SYMBOL_PERMISSIONS_CODE;
else {
GlobalVariable* gv = dyn_cast<GlobalVariable>(def);
- if ( (gv != NULL) && gv->isConstant() )
+ if (gv && gv->isConstant())
attr |= LTO_SYMBOL_PERMISSIONS_RODATA;
else
attr |= LTO_SYMBOL_PERMISSIONS_DATA;
}
// set definition part
- if ( def->hasWeakLinkage() || def->hasLinkOnceLinkage() ) {
+ if (def->hasWeakLinkage() || def->hasLinkOnceLinkage()) {
attr |= LTO_SYMBOL_DEFINITION_WEAK;
}
- else if ( def->hasCommonLinkage()) {
+ else if (def->hasCommonLinkage()) {
attr |= LTO_SYMBOL_DEFINITION_TENTATIVE;
}
else {
@@ -361,12 +368,12 @@ void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
}
// set scope part
- if ( def->hasHiddenVisibility() )
+ if (def->hasHiddenVisibility())
attr |= LTO_SYMBOL_SCOPE_HIDDEN;
- else if ( def->hasProtectedVisibility() )
+ else if (def->hasProtectedVisibility())
attr |= LTO_SYMBOL_SCOPE_PROTECTED;
- else if ( def->hasExternalLinkage() || def->hasWeakLinkage()
- || def->hasLinkOnceLinkage() || def->hasCommonLinkage() )
+ else if (def->hasExternalLinkage() || def->hasWeakLinkage()
+ || def->hasLinkOnceLinkage() || def->hasCommonLinkage())
attr |= LTO_SYMBOL_SCOPE_DEFAULT;
else
attr |= LTO_SYMBOL_SCOPE_INTERNAL;
@@ -381,7 +388,7 @@ void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
void LTOModule::addAsmGlobalSymbol(const char *name) {
// only add new define if not already defined
- if ( _defines.count(name, &name[strlen(name)+1]) == 0 )
+ if (_defines.count(name) == 0)
return;
// string is owned by _defines
@@ -398,10 +405,14 @@ void LTOModule::addAsmGlobalSymbol(const char *name) {
void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler)
{
// ignore all llvm.* symbols
- if ( strncmp(decl->getNameStart(), "llvm.", 5) == 0 )
+ if (decl->getName().startswith("llvm."))
return;
- const char* name = mangler.getValueName(decl).c_str();
+ // ignore all aliases
+ if (isa<GlobalAlias>(decl))
+ return;
+
+ std::string name = mangler.getMangledName(decl);
// we already have the symbol
if (_undefines.find(name) != _undefines.end())
@@ -409,7 +420,7 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler)
NameAndAttributes info;
// string is owned by _undefines
- info.name = ::strdup(name);
+ info.name = ::strdup(name.c_str());
if (decl->hasExternalWeakLinkage())
info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF;
else
@@ -419,11 +430,11 @@ void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler)
-// Find exeternal symbols referenced by VALUE. This is a recursive function.
+// 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() )
+ 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
@@ -431,11 +442,11 @@ void LTOModule::findExternalRefs(Value* value, Mangler &mangler) {
// 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..
+ // Handle ConstantExpr, ConstantStruct, ConstantArry etc.
for (unsigned i = 0, e = c->getNumOperands(); i != e; ++i)
findExternalRefs(c->getOperand(i), mangler);
}
@@ -443,11 +454,11 @@ void LTOModule::findExternalRefs(Value* value, Mangler &mangler) {
void LTOModule::lazyParseSymbols()
{
- if ( !_symbolsParsed ) {
+ if (!_symbolsParsed) {
_symbolsParsed = true;
// Use mangler to add GlobalPrefix to names to match linker names.
- Mangler mangler(*_module, _target->getTargetAsmInfo()->getGlobalPrefix());
+ Mangler mangler(*_module, _target->getMCAsmInfo()->getGlobalPrefix());
// add chars used in ObjC method names so method names aren't mangled
mangler.markCharAcceptable('[');
mangler.markCharAcceptable(']');
@@ -459,7 +470,7 @@ void LTOModule::lazyParseSymbols()
// add functions
for (Module::iterator f = _module->begin(); f != _module->end(); ++f) {
- if ( f->isDeclaration() )
+ if (f->isDeclaration())
addPotentialUndefinedSymbol(f, mangler);
else
addDefinedFunctionSymbol(f, mangler);
@@ -468,7 +479,7 @@ void LTOModule::lazyParseSymbols()
// add data
for (Module::global_iterator v = _module->global_begin(),
e = _module->global_end(); v != e; ++v) {
- if ( v->isDeclaration() )
+ if (v->isDeclaration())
addPotentialUndefinedSymbol(v, mangler);
else
addDefinedDataSymbol(v, mangler);
@@ -505,8 +516,7 @@ void LTOModule::lazyParseSymbols()
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->getKeyData(), it->getKeyData()+
- it->getKeyLength()) == 0 ) {
+ if (_defines.count(it->getKey()) == 0) {
NameAndAttributes info = it->getValue();
_symbols.push_back(info);
}
@@ -525,7 +535,7 @@ uint32_t LTOModule::getSymbolCount()
lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index)
{
lazyParseSymbols();
- if ( index < _symbols.size() )
+ if (index < _symbols.size())
return _symbols[index].attributes;
else
return lto_symbol_attributes(0);
@@ -534,9 +544,8 @@ lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index)
const char* LTOModule::getSymbolName(uint32_t index)
{
lazyParseSymbols();
- if ( index < _symbols.size() )
+ if (index < _symbols.size())
return _symbols[index].name;
else
return NULL;
}
-
diff --git a/tools/lto/Makefile b/tools/lto/Makefile
index c8ad9fe..3120aa5 100644
--- a/tools/lto/Makefile
+++ b/tools/lto/Makefile
@@ -22,7 +22,7 @@ LINK_COMPONENTS := $(TARGETS_TO_BUILD) ipo scalaropts linker bitreader bitwriter
include $(LEVEL)/Makefile.common
-ifeq ($(OS),Darwin)
+ifeq ($(HOST_OS),Darwin)
# set dylib internal version number to llvmCore submission number
ifdef LLVM_SUBMIT_VERSION
LLVMLibsOptions := $(LLVMLibsOptions) -Wl,-current_version \
diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp
index 936aeae..cc841bd 100644
--- a/tools/lto/lto.cpp
+++ b/tools/lto/lto.cpp
@@ -203,14 +203,6 @@ bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model)
}
//
-// sets the path to gcc
-//
-void lto_codegen_set_gcc_path(lto_code_gen_t cg, const char* path)
-{
- cg->setGccPath(path);
-}
-
-//
// sets the path to the assembler tool
//
void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path)
diff --git a/tools/opt/AnalysisWrappers.cpp b/tools/opt/AnalysisWrappers.cpp
index 631a0dd..18360f8 100644
--- a/tools/opt/AnalysisWrappers.cpp
+++ b/tools/opt/AnalysisWrappers.cpp
@@ -21,6 +21,7 @@
#include "llvm/Pass.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Support/raw_ostream.h"
#include <iostream>
using namespace llvm;
@@ -33,27 +34,31 @@ namespace {
static char ID; // Pass ID, replacement for typeid
ExternalFunctionsPassedConstants() : ModulePass(&ID) {}
virtual bool runOnModule(Module &M) {
- for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
- if (I->isDeclaration()) {
- bool PrintedFn = false;
- for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
- UI != E; ++UI)
- if (Instruction *User = dyn_cast<Instruction>(*UI)) {
- CallSite CS = CallSite::get(User);
- if (CS.getInstruction()) {
- for (CallSite::arg_iterator AI = CS.arg_begin(),
- E = CS.arg_end(); AI != E; ++AI)
- if (isa<Constant>(*AI)) {
- if (!PrintedFn) {
- std::cerr << "Function '" << I->getName() << "':\n";
- PrintedFn = true;
- }
- std::cerr << *User;
- break;
- }
- }
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ if (!I->isDeclaration()) continue;
+
+ bool PrintedFn = false;
+ for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
+ UI != E; ++UI) {
+ Instruction *User = dyn_cast<Instruction>(*UI);
+ if (!User) continue;
+
+ CallSite CS = CallSite::get(User);
+ if (!CS.getInstruction()) continue;
+
+ for (CallSite::arg_iterator AI = CS.arg_begin(),
+ E = CS.arg_end(); AI != E; ++AI) {
+ if (!isa<Constant>(*AI)) continue;
+
+ if (!PrintedFn) {
+ errs() << "Function '" << I->getName() << "':\n";
+ PrintedFn = true;
}
+ errs() << *User;
+ break;
+ }
}
+ }
return false;
}
@@ -77,7 +82,7 @@ namespace {
AU.addRequiredTransitive<CallGraph>();
}
virtual bool runOnModule(Module &M) {
- getAnalysis<CallGraph>().print(std::cerr, &M);
+ getAnalysis<CallGraph>().print(errs(), &M);
return false;
}
};
diff --git a/tools/opt/CMakeLists.txt b/tools/opt/CMakeLists.txt
index efcca80..b75cda0 100644
--- a/tools/opt/CMakeLists.txt
+++ b/tools/opt/CMakeLists.txt
@@ -1,5 +1,5 @@
set(LLVM_REQUIRES_EH 1)
-set(LLVM_LINK_COMPONENTS bitreader bitwriter instrumentation scalaropts ipo)
+set(LLVM_LINK_COMPONENTS bitreader asmparser bitwriter instrumentation scalaropts ipo)
add_llvm_tool(opt
AnalysisWrappers.cpp
diff --git a/tools/opt/GraphPrinters.cpp b/tools/opt/GraphPrinters.cpp
index 5d581e4..1ae6be2 100644
--- a/tools/opt/GraphPrinters.cpp
+++ b/tools/opt/GraphPrinters.cpp
@@ -28,9 +28,10 @@ static void WriteGraphToFile(std::ostream &O, const std::string &GraphName,
const GraphType &GT) {
std::string Filename = GraphName + ".dot";
O << "Writing '" << Filename << "'...";
- std::ofstream F(Filename.c_str());
+ std::string ErrInfo;
+ raw_fd_ostream F(Filename.c_str(), ErrInfo);
- if (F.good())
+ if (ErrInfo.empty())
WriteGraph(F, GT);
else
O << " error opening file for writing!";
@@ -70,8 +71,7 @@ namespace {
return false;
}
- void print(std::ostream &OS) const {}
- void print(std::ostream &OS, const llvm::Module*) const {}
+ void print(raw_ostream &OS, const llvm::Module*) const {}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<CallGraph>();
diff --git a/tools/opt/Makefile b/tools/opt/Makefile
index 0afb002..b17be34 100644
--- a/tools/opt/Makefile
+++ b/tools/opt/Makefile
@@ -10,6 +10,6 @@ LEVEL = ../..
TOOLNAME = opt
REQUIRES_EH := 1
-LINK_COMPONENTS := bitreader bitwriter instrumentation scalaropts ipo
+LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo
include $(LEVEL)/Makefile.common
diff --git a/tools/opt/PrintSCC.cpp b/tools/opt/PrintSCC.cpp
index be65264..66709ff 100644
--- a/tools/opt/PrintSCC.cpp
+++ b/tools/opt/PrintSCC.cpp
@@ -29,8 +29,8 @@
#include "llvm/Module.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Support/CFG.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SCCIterator.h"
-#include <iostream>
using namespace llvm;
namespace {
@@ -39,7 +39,7 @@ namespace {
CFGSCC() : FunctionPass(&ID) {}
bool runOnFunction(Function& func);
- void print(std::ostream &O, const Module* = 0) const { }
+ void print(raw_ostream &O, const Module* = 0) const { }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
@@ -53,7 +53,7 @@ namespace {
// run - Print out SCCs in the call graph for the specified module.
bool runOnModule(Module &M);
- void print(std::ostream &O, const Module* = 0) const { }
+ void print(raw_ostream &O, const Module* = 0) const { }
// getAnalysisUsage - This pass requires the CallGraph.
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
@@ -73,18 +73,18 @@ namespace {
bool CFGSCC::runOnFunction(Function &F) {
unsigned sccNum = 0;
- std::cout << "SCCs for Function " << F.getName() << " in PostOrder:";
+ outs() << "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;
- std::cout << "\nSCC #" << ++sccNum << " : ";
+ outs() << "\nSCC #" << ++sccNum << " : ";
for (std::vector<BasicBlock*>::const_iterator I = nextSCC.begin(),
E = nextSCC.end(); I != E; ++I)
- std::cout << (*I)->getName() << ", ";
+ outs() << (*I)->getName() << ", ";
if (nextSCC.size() == 1 && SCCI.hasLoop())
- std::cout << " (Has self-loop).";
+ outs() << " (Has self-loop).";
}
- std::cout << "\n";
+ outs() << "\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;
- std::cout << "SCCs for the program in PostOrder:";
+ outs() << "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;
- std::cout << "\nSCC #" << ++sccNum << " : ";
+ outs() << "\nSCC #" << ++sccNum << " : ";
for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(),
E = nextSCC.end(); I != E; ++I)
- std::cout << ((*I)->getFunction() ? (*I)->getFunction()->getName()
- : std::string("Indirect CallGraph node")) << ", ";
+ outs() << ((*I)->getFunction() ? (*I)->getFunction()->getNameStr()
+ : std::string("Indirect CallGraph node")) << ", ";
if (nextSCC.size() == 1 && SCCI.hasLoop())
- std::cout << " (Has self-loop).";
+ outs() << " (Has self-loop).";
}
- std::cout << "\n";
+ outs() << "\n";
return true;
}
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 6891619..fe0e036 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -26,17 +26,15 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/System/Signals.h"
+#include "llvm/Support/IRReader.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/StandardPasses.h"
-#include "llvm/Support/Streams.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/LinkAllVMCore.h"
-#include <iostream>
-#include <fstream>
#include <memory>
#include <algorithm>
using namespace llvm;
@@ -50,7 +48,7 @@ PassList(cl::desc("Optimizations available:"));
// Other command line options...
//
static cl::opt<std::string>
-InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
+InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
cl::init("-"), cl::value_desc("filename"));
static cl::opt<std::string>
@@ -58,7 +56,7 @@ OutputFilename("o", cl::desc("Override output filename"),
cl::value_desc("filename"), cl::init("-"));
static cl::opt<bool>
-Force("f", cl::desc("Overwrite output files"));
+Force("f", cl::desc("Enable binary output on terminals"));
static cl::opt<bool>
PrintEachXForm("p", cl::desc("Print module after each transformation"));
@@ -68,6 +66,10 @@ NoOutput("disable-output",
cl::desc("Do not write result bitcode file"), cl::Hidden);
static cl::opt<bool>
+OutputAssembly("S",
+ cl::desc("Write output as LLVM assembly"), cl::Hidden);
+
+static cl::opt<bool>
NoVerify("disable-verify", cl::desc("Do not verify result module"), cl::Hidden);
static cl::opt<bool>
@@ -80,15 +82,23 @@ StripDebug("strip-debug",
static cl::opt<bool>
DisableInline("disable-inlining", cl::desc("Do not run the inliner pass"));
-static cl::opt<bool>
-DisableOptimizations("disable-opt",
+static cl::opt<bool>
+DisableOptimizations("disable-opt",
cl::desc("Do not run any optimization passes"));
static cl::opt<bool>
-StandardCompileOpts("std-compile-opts",
+DisableInternalize("disable-internalize",
+ cl::desc("Do not mark all symbols as internal"));
+
+static cl::opt<bool>
+StandardCompileOpts("std-compile-opts",
cl::desc("Include the standard compile time optimizations"));
static cl::opt<bool>
+StandardLinkOpts("std-link-opts",
+ cl::desc("Include the standard link time optimizations"));
+
+static cl::opt<bool>
OptLevelO1("O1",
cl::desc("Optimization level 1. Similar to llvm-gcc -O1"));
@@ -102,7 +112,8 @@ OptLevelO3("O3",
static cl::opt<bool>
UnitAtATime("funit-at-a-time",
- cl::desc("Enable IPO. This is same as llvm-gcc's -funit-at-a-time"));
+ cl::desc("Enable IPO. This is same as llvm-gcc's -funit-at-a-time"),
+ cl::init(true));
static cl::opt<bool>
DisableSimplifyLibCalls("disable-simplify-libcalls",
@@ -123,23 +134,24 @@ namespace {
struct CallGraphSCCPassPrinter : public CallGraphSCCPass {
static char ID;
const PassInfo *PassToPrint;
- CallGraphSCCPassPrinter(const PassInfo *PI) :
+ CallGraphSCCPassPrinter(const PassInfo *PI) :
CallGraphSCCPass(&ID), PassToPrint(PI) {}
- virtual bool runOnSCC(const std::vector<CallGraphNode *>&SCC) {
+ virtual bool runOnSCC(std::vector<CallGraphNode *>&SCC) {
if (!Quiet) {
- cout << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+ outs() << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
Function *F = SCC[i]->getFunction();
- if (F)
- getAnalysisID<Pass>(PassToPrint).print(cout, F->getParent());
+ if (F) {
+ getAnalysisID<Pass>(PassToPrint).print(outs(), F->getParent());
+ }
}
}
// Get and print pass...
return false;
}
-
+
virtual const char *getPassName() const { return "'Pass' Printer"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
@@ -158,8 +170,8 @@ struct ModulePassPrinter : public ModulePass {
virtual bool runOnModule(Module &M) {
if (!Quiet) {
- cout << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
- getAnalysisID<Pass>(PassToPrint).print(cout, &M);
+ outs() << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+ getAnalysisID<Pass>(PassToPrint).print(outs(), &M);
}
// Get and print pass...
@@ -182,12 +194,12 @@ struct FunctionPassPrinter : public FunctionPass {
PassToPrint(PI) {}
virtual bool runOnFunction(Function &F) {
- if (!Quiet) {
- cout << "Printing analysis '" << PassToPrint->getPassName()
- << "' for function '" << F.getName() << "':\n";
+ if (!Quiet) {
+ outs() << "Printing analysis '" << PassToPrint->getPassName()
+ << "' for function '" << F.getName() << "':\n";
}
// Get and print pass...
- getAnalysisID<Pass>(PassToPrint).print(cout, F.getParent());
+ getAnalysisID<Pass>(PassToPrint).print(outs(), F.getParent());
return false;
}
@@ -204,19 +216,19 @@ char FunctionPassPrinter::ID = 0;
struct LoopPassPrinter : public LoopPass {
static char ID;
const PassInfo *PassToPrint;
- LoopPassPrinter(const PassInfo *PI) :
+ LoopPassPrinter(const PassInfo *PI) :
LoopPass(&ID), PassToPrint(PI) {}
virtual bool runOnLoop(Loop *L, LPPassManager &LPM) {
if (!Quiet) {
- cout << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
- getAnalysisID<Pass>(PassToPrint).print(cout,
+ outs() << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
+ getAnalysisID<Pass>(PassToPrint).print(outs(),
L->getHeader()->getParent()->getParent());
}
// Get and print pass...
return false;
}
-
+
virtual const char *getPassName() const { return "'Pass' Printer"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
@@ -230,17 +242,17 @@ char LoopPassPrinter::ID = 0;
struct BasicBlockPassPrinter : public BasicBlockPass {
const PassInfo *PassToPrint;
static char ID;
- BasicBlockPassPrinter(const PassInfo *PI)
+ BasicBlockPassPrinter(const PassInfo *PI)
: BasicBlockPass(&ID), PassToPrint(PI) {}
virtual bool runOnBasicBlock(BasicBlock &BB) {
if (!Quiet) {
- cout << "Printing Analysis info for BasicBlock '" << BB.getName()
- << "': Pass " << PassToPrint->getPassName() << ":\n";
+ outs() << "Printing Analysis info for BasicBlock '" << BB.getName()
+ << "': Pass " << PassToPrint->getPassName() << ":\n";
}
// Get and print pass...
- getAnalysisID<Pass>(PassToPrint).print(cout, BB.getParent()->getParent());
+ getAnalysisID<Pass>(PassToPrint).print(outs(), BB.getParent()->getParent());
return false;
}
@@ -261,8 +273,8 @@ inline void addPass(PassManager &PM, Pass *P) {
if (VerifyEach) PM.add(createVerifierPass());
}
-/// AddOptimizationPasses - This routine adds optimization passes
-/// based on selected optimization level, OptLevel. This routine
+/// AddOptimizationPasses - This routine adds optimization passes
+/// based on selected optimization level, OptLevel. This routine
/// duplicates llvm-gcc behaviour.
///
/// OptLevel - Optimization Level
@@ -294,7 +306,7 @@ void AddStandardCompilePasses(PassManager &PM) {
llvm::Pass *InliningPass = !DisableInline ? createFunctionInliningPass() : 0;
// -std-compile-opts adds the same module passes as -O3.
- createStandardModulePasses(&PM, 3,
+ createStandardModulePasses(&PM, 3,
/*OptimizeSize=*/ false,
/*UnitAtATime=*/ true,
/*UnrollLoops=*/ true,
@@ -303,6 +315,20 @@ void AddStandardCompilePasses(PassManager &PM) {
InliningPass);
}
+void AddStandardLinkPasses(PassManager &PM) {
+ PM.add(createVerifierPass()); // Verify that input is correct
+
+ // If the -strip-debug command line option was specified, do it.
+ if (StripDebug)
+ addPass(PM, createStripSymbolsPass(true));
+
+ if (DisableOptimizations) return;
+
+ createStandardLTOPasses(&PM, /*Internalize=*/ !DisableInternalize,
+ /*RunInliner=*/ !DisableInline,
+ /*VerifyEach=*/ VerifyEach);
+}
+
} // anonymous namespace
@@ -311,7 +337,7 @@ void AddStandardCompilePasses(PassManager &PM) {
//
int main(int argc, char **argv) {
llvm_shutdown_obj X; // Call llvm_shutdown() on exit.
- LLVMContext Context;
+ LLVMContext &Context = getGlobalContext();
try {
cl::ParseCommandLineOptions(argc, argv,
"llvm .bc -> .bc modular optimizer and analysis printer\n");
@@ -321,56 +347,41 @@ int main(int argc, char **argv) {
// FIXME: The choice of target should be controllable on the command line.
std::auto_ptr<TargetMachine> target;
- std::string ErrorMessage;
+ SMDiagnostic Err;
// Load the input module...
std::auto_ptr<Module> M;
- if (MemoryBuffer *Buffer
- = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)) {
- M.reset(ParseBitcodeFile(Buffer, Context, &ErrorMessage));
- delete Buffer;
- }
-
+ M.reset(ParseIRFile(InputFilename, Err, Context));
+
if (M.get() == 0) {
- cerr << argv[0] << ": ";
- if (ErrorMessage.size())
- cerr << ErrorMessage << "\n";
- else
- cerr << "bitcode didn't read correctly.\n";
+ Err.Print(argv[0], errs());
return 1;
}
// Figure out what stream we are supposed to write to...
- // FIXME: cout is not binary!
- std::ostream *Out = &std::cout; // Default to printing to stdout...
+ // FIXME: outs() is not binary!
+ raw_ostream *Out = &outs(); // Default to printing to stdout...
if (OutputFilename != "-") {
- if (!Force && std::ifstream(OutputFilename.c_str())) {
- // If force is not specified, make sure not to overwrite a file!
- cerr << argv[0] << ": error opening '" << OutputFilename
- << "': file exists!\n"
- << "Use -f command line argument to force output\n";
- return 1;
- }
- std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
- std::ios::binary;
- Out = new std::ofstream(OutputFilename.c_str(), io_mode);
-
- if (!Out->good()) {
- cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
- return 1;
- }
-
// 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;
+ }
}
// If the output is set to be emitted to standard out, and standard out is a
// 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 && CheckBitcodeOutputToConsole(Out,!Quiet)) {
- NoOutput = true;
- }
+ if (!Force && !NoOutput && !OutputAssembly)
+ if (CheckBitcodeOutputToConsole(*Out, !Quiet))
+ NoOutput = true;
// Create a PassManager to hold and optimize the collection of passes we are
// about to build...
@@ -385,7 +396,7 @@ int main(int argc, char **argv) {
FPasses = new FunctionPassManager(new ExistingModuleProvider(M.get()));
FPasses->add(new TargetData(M.get()));
}
-
+
// If the -strip-debug command line option was specified, add it. If
// -std-compile-opts was also specified, it will handle StripDebug.
if (StripDebug && !StandardCompileOpts)
@@ -395,12 +406,18 @@ int main(int argc, char **argv) {
for (unsigned i = 0; i < PassList.size(); ++i) {
// Check to see if -std-compile-opts was specified before this option. If
// so, handle it.
- if (StandardCompileOpts &&
+ if (StandardCompileOpts &&
StandardCompileOpts.getPosition() < PassList.getPosition(i)) {
AddStandardCompilePasses(Passes);
StandardCompileOpts = false;
}
-
+
+ if (StandardLinkOpts &&
+ StandardLinkOpts.getPosition() < PassList.getPosition(i)) {
+ AddStandardLinkPasses(Passes);
+ StandardLinkOpts = false;
+ }
+
if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) {
AddOptimizationPasses(Passes, *FPasses, 1);
OptLevelO1 = false;
@@ -421,8 +438,8 @@ int main(int argc, char **argv) {
if (PassInf->getNormalCtor())
P = PassInf->getNormalCtor()();
else
- cerr << argv[0] << ": cannot create pass: "
- << PassInf->getPassName() << "\n";
+ errs() << argv[0] << ": cannot create pass: "
+ << PassInf->getPassName() << "\n";
if (P) {
bool isBBPass = dynamic_cast<BasicBlockPass*>(P) != 0;
bool isLPass = !isBBPass && dynamic_cast<LoopPass*>(P) != 0;
@@ -444,30 +461,36 @@ int main(int argc, char **argv) {
Passes.add(new ModulePassPrinter(PassInf));
}
}
-
+
if (PrintEachXForm)
Passes.add(createPrintModulePass(&errs()));
}
-
+
// If -std-compile-opts was specified at the end of the pass list, add them.
if (StandardCompileOpts) {
AddStandardCompilePasses(Passes);
StandardCompileOpts = false;
- }
+ }
+
+ if (StandardLinkOpts) {
+ AddStandardLinkPasses(Passes);
+ StandardLinkOpts = false;
+ }
if (OptLevelO1) {
- AddOptimizationPasses(Passes, *FPasses, 1);
- }
+ AddOptimizationPasses(Passes, *FPasses, 1);
+ }
if (OptLevelO2) {
- AddOptimizationPasses(Passes, *FPasses, 2);
- }
+ AddOptimizationPasses(Passes, *FPasses, 2);
+ }
if (OptLevelO3) {
- AddOptimizationPasses(Passes, *FPasses, 3);
- }
+ AddOptimizationPasses(Passes, *FPasses, 3);
+ }
if (OptLevelO1 || OptLevelO2 || OptLevelO3) {
+ FPasses->doInitialization();
for (Module::iterator I = M.get()->begin(), E = M.get()->end();
I != E; ++I)
FPasses->run(*I);
@@ -477,22 +500,26 @@ int main(int argc, char **argv) {
if (!NoVerify && !VerifyEach)
Passes.add(createVerifierPass());
- // Write bitcode out to disk or cout as the last step...
- if (!NoOutput && !AnalyzeOnly)
- Passes.add(CreateBitcodeWriterPass(*Out));
+ // Write bitcode or assembly out to disk or outs() as the last step...
+ if (!NoOutput && !AnalyzeOnly) {
+ if (OutputAssembly)
+ Passes.add(createPrintModulePass(Out));
+ else
+ Passes.add(createBitcodeWriterPass(*Out));
+ }
// Now that we have all of the passes ready, run them.
Passes.run(*M.get());
- // Delete the ofstream.
- if (Out != &std::cout)
+ // Delete the raw_fd_ostream.
+ if (Out != &outs())
delete Out;
return 0;
} catch (const std::string& msg) {
- cerr << argv[0] << ": " << msg << "\n";
+ errs() << argv[0] << ": " << msg << "\n";
} catch (...) {
- cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
+ errs() << argv[0] << ": Unexpected unknown exception occurred.\n";
}
llvm_shutdown();
return 1;
OpenPOWER on IntegriCloud