diff --git a/llvm/tools/llc/Makefile b/llvm/tools/llc/Makefile index 692a50349ffc..48a20d3ebc4c 100644 --- a/llvm/tools/llc/Makefile +++ b/llvm/tools/llc/Makefile @@ -1,6 +1,6 @@ LEVEL = ../.. TOOLNAME = llc -USEDLIBS = sparc regalloc sched select sparc regalloc sched select target opt livevar bcreader vmcore asmwriter analysis support +USEDLIBS = sparc regalloc sched select sparc regalloc sched select target opt instrument livevar bcreader vmcore asmwriter analysis support include $(LEVEL)/Makefile.common diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp index c8dc8ab08da6..b769cb5cfd48 100644 --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -8,16 +8,24 @@ #include "llvm/Optimizations/Normalize.h" #include "llvm/Target/Sparc.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/Instrumentation/TraceValues.h" #include "llvm/Support/CommandLine.h" #include "llvm/Module.h" #include "llvm/Method.h" #include +#include #include cl::String InputFilename ("", "Input filename", cl::NoFlags, "-"); cl::String OutputFilename("o", "Output filename", cl::NoFlags, ""); cl::Flag Force ("f", "Overwrite output files", cl::NoFlags, false); -cl::Flag DumpAsm ("d", "Print assembly as compiled", cl::Hidden, false); +cl::Flag DumpAsm ("d", "Print bytecode before native code generation", cl::Hidden,false); +cl::Flag DoNotEmitAssembly("noasm", "Do not emit assembly code", cl::Hidden, false); +cl::Flag TraceBBValues ("trace", + "Trace values at basic block and method exits", + cl::NoFlags, false); +cl::Flag TraceMethodValues("tracem", "Trace values only at method exits", + cl::NoFlags, false); #include "llvm/Assembly/Writer.h" // For DumpAsm @@ -139,46 +147,134 @@ static void NormalizeMethod(Method *M) { NormalizePhiConstantArgs(M); } +inline string +GetFileNameRoot(const string& InputFilename) +{ + string IFN = InputFilename; + string outputFilename; + int Len = IFN.length(); + if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') { + outputFilename = string(IFN.begin(), IFN.end()-3); // s/.bc/.s/ + } else { + outputFilename = IFN; // Append a .s to it + } + return outputFilename; +} + +inline string +GetTraceAssemblyFileName(const string& inFilename) +{ + assert(inFilename != "-" && "files on stdin not supported with tracing"); + string traceFileName = GetFileNameRoot(inFilename); + traceFileName += ".trace.ll"; + return traceFileName; +} //===---------------------------------------------------------------------===// -// Function main() +// Function PreprocessModule() // -// Entry point for the llc compiler. +// Normalization to simplify later passes. //===---------------------------------------------------------------------===// -int main(int argc, char **argv) { - // Parse command line options... - cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n"); - - // Allocate a target... in the future this will be controllable on the - // command line. - auto_ptr Target(allocateSparcTargetMachine()); - - // Load the module to be compiled... - auto_ptr M(ParseBytecodeFile(InputFilename)); - if (M.get() == 0) { - cerr << "bytecode didn't read correctly.\n"; - return 1; - } - - InsertMallocFreeDecls(M.get()); - - // Loop over all of the methods in the module, compiling them. - for (Module::const_iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) { - Method *Meth = *MI; - - NormalizeMethod(Meth); - ReplaceMallocFree(Meth, Target->DataLayout); - - if (DumpAsm) - cerr << "Method after xformations: \n" << Meth; - - if (Target->compileMethod(Meth)) { - cerr << "Error compiling " << InputFilename << "!\n"; - return 1; - } - } +int +PreprocessModule(Module* module) +{ + InsertMallocFreeDecls(module); + for (Module::const_iterator MI=module->begin(); MI != module->end(); ++MI) + if (! (*MI)->isExternal()) + NormalizeMethod(*MI); + + return 0; +} + + +//===---------------------------------------------------------------------===// +// Function OptimizeModule() +// +// Module optimization. +//===---------------------------------------------------------------------===// + +int +OptimizeModule(Module* module) +{ + return 0; +} + + +//===---------------------------------------------------------------------===// +// Function GenerateCodeForModule() +// +// Native code generation for a specified target. +//===---------------------------------------------------------------------===// + +int +GenerateCodeForModule(Module* module, TargetMachine* target) +{ + // Since any transformation pass may introduce external function decls + // into the method list, find current methods first and then walk only those. + // + vector initialMethods(module->begin(), module->end()); + + + // Replace malloc and free instructions with library calls + // + for (unsigned i=0, N = initialMethods.size(); i < N; i++) + if (! initialMethods[i]->isExternal()) + ReplaceMallocFree(initialMethods[i], target->DataLayout); + + + // Insert trace code to assist debugging + // + if (TraceBBValues || TraceMethodValues) + { + // Insert trace code in all methods in the module + for (unsigned i=0, N = initialMethods.size(); i < N; i++) + if (! initialMethods[i]->isExternal()) + InsertCodeToTraceValues(initialMethods[i], TraceBBValues, + TraceBBValues || TraceMethodValues); + + // Then write the module with tracing code out in assembly form + string traceFileName = GetTraceAssemblyFileName(InputFilename); + ofstream* ofs = new ofstream(traceFileName.c_str(), + (Force ? 0 : ios::noreplace)|ios::out); + if (!ofs->good()) { + cerr << "Error opening " << traceFileName << "!\n"; + delete ofs; + return 1; + } + WriteToAssembly(module, *ofs); + delete ofs; + } + + + // Generate native target code for all methods + // + for (unsigned i=0, N = initialMethods.size(); i < N; i++) + if (! initialMethods[i]->isExternal()) + { + if (DumpAsm) + cerr << "Method after xformations: \n" << initialMethods[i]; + + if (target->compileMethod(initialMethods[i])) { + cerr << "Error compiling " << InputFilename << "!\n"; + return 1; + } + } + + return 0; +} + + +//===---------------------------------------------------------------------===// +// Function EmitAssemblyForModule() +// +// Write assembly code to specified output file; .s by default. +//===---------------------------------------------------------------------===// + +int +EmitAssemblyForModule(Module* module, TargetMachine* target) +{ // Figure out where we are going to send the output... ostream *Out = 0; if (OutputFilename != "") { // Specified an output filename? @@ -189,13 +285,7 @@ int main(int argc, char **argv) { OutputFilename = "-"; Out = &cout; } else { - string IFN = InputFilename; - int Len = IFN.length(); - if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') { - OutputFilename = string(IFN.begin(), IFN.end()-3); // s/.bc/.s/ - } else { - OutputFilename = IFN; // Append a .s to it - } + string OutputFilename = GetFileNameRoot(InputFilename); OutputFilename += ".s"; Out = new ofstream(OutputFilename.c_str(), (Force ? 0 : ios::noreplace)|ios::out); @@ -208,10 +298,48 @@ int main(int argc, char **argv) { } // Emit the output... - Target->emitAssembly(M.get(), *Out); + target->emitAssembly(module, *Out); if (Out != &cout) delete Out; + return 0; } +//===---------------------------------------------------------------------===// +// Function main() +// +// Entry point for the llc compiler. +//===---------------------------------------------------------------------===// + +int +main(int argc, char **argv) +{ + // Parse command line options... + cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n"); + + // Allocate a target... in the future this will be controllable on the + // command line. + auto_ptr target(allocateSparcTargetMachine()); + + // Load the module to be compiled... + auto_ptr M(ParseBytecodeFile(InputFilename)); + if (M.get() == 0) { + cerr << "bytecode didn't read correctly.\n"; + return 1; + } + + int failed = PreprocessModule(M.get()); + + if (!failed) + failed = OptimizeModule(M.get()); + + if (!failed) + failed = GenerateCodeForModule(M.get(), target.get()); + + if (!failed && ! DoNotEmitAssembly) + failed = EmitAssemblyForModule(M.get(), target.get()); + + return failed; +} +