[llvm-commits] [gcc-plugin] r80004 - in /gcc-plugin/trunk: Makefile llvm-backend.cpp
Duncan Sands
baldrick at free.fr
Tue Aug 25 10:24:02 PDT 2009
Author: baldrick
Date: Tue Aug 25 12:24:01 2009
New Revision: 80004
URL: http://llvm.org/viewvc/llvm-project?rev=80004&view=rev
Log:
Teach the plugin how to write .s files. Since it's
hard to stop gcc outputting stuff the following trick
is used: very early on, the plugin discovers the name
of the .s file, and replaces it with /dev/null or the
host equivalent. This is done early enough that gcc
hasn't had time to output anything yet. The result
is that all gcc generated output is discarded, and
the plugin can freely write to the original file. For
efficiency it would be nice to reduce to a minimum the
amount of stuff gcc calculates and outputs (eg: global
variables), but than can wait till later. Currently
the plugin is capable of generating correct code for
the empty function!
Various notes:
Output is done using raw_ostream and formatted_raw_ostream,
like in clang.
The .ident string is implemented as a module level ASM.
This means it will end up in bitcode too. Might be worth
doing in llvm-gcc as well.
Some flags (emit_llvm etc) are not wired up yet. The
flag_inline_trees flag does not exist anymore - will take
care of this properly later.
Modified:
gcc-plugin/trunk/Makefile
gcc-plugin/trunk/llvm-backend.cpp
Modified: gcc-plugin/trunk/Makefile
URL: http://llvm.org/viewvc/llvm-project/gcc-plugin/trunk/Makefile?rev=80004&r1=80003&r2=80004&view=diff
==============================================================================
--- gcc-plugin/trunk/Makefile (original)
+++ gcc-plugin/trunk/Makefile Tue Aug 25 12:24:01 2009
@@ -21,7 +21,7 @@
-I${GCCOBJECT_DIR}/libdecnumber -I.
CXXFLAGS+=$(CFLAGS) $(shell llvm-config --cppflags)
-LDFLAGS+=$(shell llvm-config --ldflags) $(shell llvm-config --libs analysis core target x86)
+LDFLAGS+=$(shell llvm-config --ldflags) $(shell llvm-config --libs analysis core ipo scalaropts target x86)
llvm.so: $(PLUGIN_OBJECT_FILES)
$(CXX) -shared $^ -o $@ ${LDFLAGS}
Modified: gcc-plugin/trunk/llvm-backend.cpp
URL: http://llvm.org/viewvc/llvm-project/gcc-plugin/trunk/llvm-backend.cpp?rev=80004&r1=80003&r2=80004&view=diff
==============================================================================
--- gcc-plugin/trunk/llvm-backend.cpp (original)
+++ gcc-plugin/trunk/llvm-backend.cpp Tue Aug 25 12:24:01 2009
@@ -79,6 +79,7 @@
#include "tree-inline.h"
#include "tree-flow.h"
#include "tree-pass.h"
+#include "version.h"
}
// Plugin headers
@@ -99,17 +100,22 @@
// Non-zero if implicit floating point instructions are disabled.
static int flag_no_implicit_float = 0;
+/// llvm_asm_file_name - Name of file to use for assembly code output.
+static const char *llvm_asm_file_name;
+
// Global state for the LLVM backend.
Module *TheModule = 0;
DebugInfo *TheDebugInfo = 0;
TargetMachine *TheTarget = 0;
TargetFolder *TheFolder = 0;
TypeConverter *TheTypeConverter = 0;
+llvm::raw_ostream *OutStream = 0; // Stream to write assembly code to.
+llvm::formatted_raw_ostream FormattedOutStream;
-/// DisableLLVMOptimizations - Allow the user to specify:
-/// "-mllvm -disable-llvm-optzns" on the llvm-gcc command line to force llvm
-/// optimizations off.
-static cl::opt<bool> DisableLLVMOptimizations("disable-llvm-optzns");
+static bool DisableLLVMOptimizations = false;//TODO
+static bool emit_llvm = false;//TODO
+static bool emit_llvm_bc = false;//TODO
+static int flag_inline_trees = 2;//TODO
std::vector<std::pair<Constant*, int> > StaticCtors, StaticDtors;
SmallSetVector<Constant*, 32> AttributeUsedGlobals;
@@ -125,7 +131,7 @@
static void createPerFunctionOptimizationPasses();
static void createPerModuleOptimizationPasses();
-static void destroyOptimizationPasses();
+//TODOstatic void destroyOptimizationPasses();
//TODO//===----------------------------------------------------------------------===//
//TODO// Matching LLVM Values with GCC DECL trees
@@ -489,6 +495,30 @@
TheModule = new Module("", getGlobalContext());
+ if (main_input_filename)
+ TheModule->setModuleIdentifier(main_input_filename);
+
+ // Insert a special .ident directive to identify the version of the plugin
+ // which compiled this code. The format of the .ident string is patterned
+ // after the ones produced by GCC.
+#ifdef IDENT_ASM_OP
+ if (!flag_no_ident) {
+ const char *pkg_version = "(GNU) ";
+
+ if (strcmp ("(GCC) ", pkgversion_string))
+ pkg_version = pkgversion_string;
+
+ std::string IdentString = IDENT_ASM_OP;
+ IdentString += "\"GCC: ";
+ IdentString += pkg_version;
+ IdentString += version_string;
+ IdentString += "; LLVM: ";
+ IdentString += REVISION;
+ IdentString += '"';
+ TheModule->setModuleInlineAsm(IdentString);
+ }
+#endif
+
// If the target wants to override the architecture, e.g. turning
// powerpc-darwin-... into powerpc64-darwin-... when -m64 is enabled, do so
// now.
@@ -548,6 +578,8 @@
//TODO if (!flag_pch_file &&
//TODO debug_info_level > DINFO_LEVEL_NONE)
//TODO TheDebugInfo = new DebugInfo(TheModule);
+//TODO if (TheDebugInfo)
+//TODO TheDebugInfo->Initialize();
//TODO}
//TODO
//TODO/// performLateBackendInitialization - Set backend options that may only be
@@ -567,25 +599,27 @@
//TODO I->addFnAttr(Attribute::NoImplicitFloat);
//TODO }
//TODO}
-//TODO
-//TODOvoid llvm_lang_dependent_init(const char *Name) {
-//TODO if (TheDebugInfo)
-//TODO TheDebugInfo->Initialize();
-//TODO if (Name)
-//TODO TheModule->setModuleIdentifier(Name);
-//TODO}
Initialized = true;
}
-void llvm_lang_dependent_init(const char *Name) {
- if (TheDebugInfo)
- TheDebugInfo->Initialize();
- if (Name)
- TheModule->setModuleIdentifier(Name);
+/// InitializeOutputStreams - Initialize the assembly code output streams.
+static void InitializeOutputStreams(bool Binary) {
+ assert(!OutStream && "Output stream already initialized!");
+ std::string Error;
+ unsigned Flags = raw_fd_ostream::F_Force;
+
+ if (Binary)
+ Flags |= raw_fd_ostream::F_Binary;
+
+ OutStream = new raw_fd_ostream(llvm_asm_file_name, Error, Flags);
+
+ if (!Error.empty())
+ llvm_report_error(Error);
+
+ FormattedOutStream.setStream(*OutStream,
+ formatted_raw_ostream::PRESERVE_STREAM);
}
-//TODOoFILEstream *AsmOutStream = 0;
-//TODOstatic formatted_raw_ostream *AsmOutRawStream = 0;
//TODOoFILEstream *AsmIntermediateOutStream = 0;
//TODO
//TODO/// llvm_pch_read - Read bytecode from PCH file. Initialize TheModule and setup
@@ -650,7 +684,7 @@
//TODO
//TODO // Emit an LLVM .bc file to the output. This is used when passed
//TODO // -emit-llvm -c to the GCC driver.
-//TODO PerModulePasses->add(CreateBitcodeWriterPass(*AsmOutStream));
+//TODO PerModulePasses->add(createBitcodeWriterPass(*AsmOutStream));
//TODO
//TODO // Disable emission of .ident into the output file... which is completely
//TODO // wrong for llvm/.bc emission cases.
@@ -670,174 +704,178 @@
//TODO PerModulePasses = 0;
//TODO CodeGenPasses = 0;
//TODO}
-//TODO
-//TODOstatic void createPerFunctionOptimizationPasses() {
-//TODO if (PerFunctionPasses)
-//TODO return;
-//TODO
-//TODO // Create and set up the per-function pass manager.
-//TODO // FIXME: Move the code generator to be function-at-a-time.
-//TODO PerFunctionPasses =
-//TODO new FunctionPassManager(new ExistingModuleProvider(TheModule));
-//TODO PerFunctionPasses->add(new TargetData(*TheTarget->getTargetData()));
-//TODO
-//TODO // In -O0 if checking is disabled, we don't even have per-function passes.
-//TODO bool HasPerFunctionPasses = false;
-//TODO#ifdef ENABLE_CHECKING
-//TODO PerFunctionPasses->add(createVerifierPass());
-//TODO HasPerFunctionPasses = true;
-//TODO#endif
-//TODO
-//TODO if (optimize > 0 && !DisableLLVMOptimizations) {
-//TODO HasPerFunctionPasses = true;
-//TODO PerFunctionPasses->add(createCFGSimplificationPass());
-//TODO if (optimize == 1)
-//TODO PerFunctionPasses->add(createPromoteMemoryToRegisterPass());
-//TODO else
-//TODO PerFunctionPasses->add(createScalarReplAggregatesPass());
-//TODO PerFunctionPasses->add(createInstructionCombiningPass());
-//TODO }
-//TODO
-//TODO // If there are no module-level passes that have to be run, we codegen as
-//TODO // each function is parsed.
-//TODO // FIXME: We can't figure this out until we know there are no always-inline
-//TODO // functions.
-//TODO // FIXME: This is disabled right now until bugs can be worked out. Reenable
-//TODO // this for fast -O0 compiles!
-//TODO if (!emit_llvm_bc && !emit_llvm && 0) {
-//TODO FunctionPassManager *PM = PerFunctionPasses;
-//TODO HasPerFunctionPasses = true;
-//TODO
-//TODO CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
-//TODO
-//TODO switch (optimize) {
-//TODO default: break;
-//TODO case 0: OptLevel = CodeGenOpt::None; break;
-//TODO case 3: OptLevel = CodeGenOpt::Aggressive; break;
-//TODO }
-//TODO
-//TODO // Normal mode, emit a .s file by running the code generator.
-//TODO // Note, this also adds codegenerator level optimization passes.
-//TODO switch (TheTarget->addPassesToEmitFile(*PM, *AsmOutRawStream,
-//TODO TargetMachine::AssemblyFile,
-//TODO OptLevel)) {
-//TODO default:
-//TODO case FileModel::Error:
-//TODO errs() << "Error interfacing to target machine!\n";
-//TODO exit(1);
-//TODO case FileModel::AsmFile:
-//TODO break;
-//TODO }
-//TODO
-//TODO if (TheTarget->addPassesToEmitFileFinish(*PM, (MachineCodeEmitter *)0,
-//TODO OptLevel)) {
-//TODO errs() << "Error interfacing to target machine!\n";
-//TODO exit(1);
-//TODO }
-//TODO }
-//TODO
-//TODO if (HasPerFunctionPasses) {
-//TODO PerFunctionPasses->doInitialization();
-//TODO } else {
-//TODO delete PerFunctionPasses;
-//TODO PerFunctionPasses = 0;
-//TODO }
-//TODO}
-//TODO
-//TODOstatic void createPerModuleOptimizationPasses() {
-//TODO if (PerModulePasses)
-//TODO // llvm_pch_write_init has already created the per module passes.
-//TODO return;
-//TODO
-//TODO // FIXME: AT -O0/O1, we should stream out functions at a time.
-//TODO PerModulePasses = new PassManager();
-//TODO PerModulePasses->add(new TargetData(*TheTarget->getTargetData()));
-//TODO bool HasPerModulePasses = false;
-//TODO
-//TODO if (!DisableLLVMOptimizations) {
-//TODO bool NeedAlwaysInliner = false;
-//TODO llvm::Pass *InliningPass = 0;
-//TODO if (flag_inline_trees > 1) { // respect -fno-inline-functions
-//TODO InliningPass = createFunctionInliningPass(); // Inline small functions
-//TODO } else {
-//TODO // If full inliner is not run, check if always-inline is needed to handle
-//TODO // functions that are marked as always_inline.
-//TODO for (Module::iterator I = TheModule->begin(), E = TheModule->end();
-//TODO I != E; ++I)
-//TODO if (I->hasFnAttr(Attribute::AlwaysInline)) {
-//TODO NeedAlwaysInliner = true;
-//TODO break;
-//TODO }
-//TODO
-//TODO if (NeedAlwaysInliner)
-//TODO InliningPass = createAlwaysInlinerPass(); // Inline always_inline funcs
-//TODO }
-//TODO
-//TODO HasPerModulePasses = true;
-//TODO createStandardModulePasses(PerModulePasses, optimize,
-//TODO optimize_size || optimize < 3,
-//TODO flag_unit_at_a_time, flag_unroll_loops,
-//TODO !flag_no_simplify_libcalls, flag_exceptions,
-//TODO InliningPass);
-//TODO }
-//TODO
-//TODO if (emit_llvm_bc) {
-//TODO // Emit an LLVM .bc file to the output. This is used when passed
-//TODO // -emit-llvm -c to the GCC driver.
-//TODO PerModulePasses->add(CreateBitcodeWriterPass(*AsmOutStream));
-//TODO HasPerModulePasses = true;
-//TODO } else if (emit_llvm) {
-//TODO // Emit an LLVM .ll file to the output. This is used when passed
-//TODO // -emit-llvm -S to the GCC driver.
-//TODO PerModulePasses->add(createPrintModulePass(AsmOutRawStream));
-//TODO HasPerModulePasses = true;
-//TODO } else {
-//TODO // If there are passes we have to run on the entire module, we do codegen
-//TODO // as a separate "pass" after that happens.
-//TODO // However if there are no module-level passes that have to be run, we
-//TODO // codegen as each function is parsed.
-//TODO // FIXME: This is disabled right now until bugs can be worked out. Reenable
-//TODO // this for fast -O0 compiles!
-//TODO if (PerModulePasses || 1) {
-//TODO FunctionPassManager *PM = CodeGenPasses =
-//TODO new FunctionPassManager(new ExistingModuleProvider(TheModule));
-//TODO PM->add(new TargetData(*TheTarget->getTargetData()));
-//TODO
-//TODO CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
-//TODO
-//TODO switch (optimize) {
-//TODO default: break;
-//TODO case 0: OptLevel = CodeGenOpt::None; break;
-//TODO case 3: OptLevel = CodeGenOpt::Aggressive; break;
-//TODO }
-//TODO
-//TODO // Normal mode, emit a .s file by running the code generator.
-//TODO // Note, this also adds codegenerator level optimization passes.
-//TODO switch (TheTarget->addPassesToEmitFile(*PM, *AsmOutRawStream,
-//TODO TargetMachine::AssemblyFile,
-//TODO OptLevel)) {
-//TODO default:
-//TODO case FileModel::Error:
-//TODO errs() << "Error interfacing to target machine!\n";
-//TODO exit(1);
-//TODO case FileModel::AsmFile:
-//TODO break;
-//TODO }
-//TODO
-//TODO if (TheTarget->addPassesToEmitFileFinish(*PM, (MachineCodeEmitter *)0,
-//TODO OptLevel)) {
-//TODO errs() << "Error interfacing to target machine!\n";
-//TODO exit(1);
-//TODO }
-//TODO }
-//TODO }
-//TODO
-//TODO if (!HasPerModulePasses) {
-//TODO delete PerModulePasses;
-//TODO PerModulePasses = 0;
-//TODO }
-//TODO}
-//TODO
+
+static void createPerFunctionOptimizationPasses() {
+ if (PerFunctionPasses)
+ return;
+
+ // Create and set up the per-function pass manager.
+ // FIXME: Move the code generator to be function-at-a-time.
+ PerFunctionPasses =
+ new FunctionPassManager(new ExistingModuleProvider(TheModule));
+ PerFunctionPasses->add(new TargetData(*TheTarget->getTargetData()));
+
+ // In -O0 if checking is disabled, we don't even have per-function passes.
+ bool HasPerFunctionPasses = false;
+#ifdef ENABLE_CHECKING
+ PerFunctionPasses->add(createVerifierPass());
+ HasPerFunctionPasses = true;
+#endif
+
+ if (optimize > 0 && !DisableLLVMOptimizations) {
+ HasPerFunctionPasses = true;
+ PerFunctionPasses->add(createCFGSimplificationPass());
+ if (optimize == 1)
+ PerFunctionPasses->add(createPromoteMemoryToRegisterPass());
+ else
+ PerFunctionPasses->add(createScalarReplAggregatesPass());
+ PerFunctionPasses->add(createInstructionCombiningPass());
+ }
+
+ // If there are no module-level passes that have to be run, we codegen as
+ // each function is parsed.
+ // FIXME: We can't figure this out until we know there are no always-inline
+ // functions.
+ // FIXME: This is disabled right now until bugs can be worked out. Reenable
+ // this for fast -O0 compiles!
+ if (!emit_llvm_bc && !emit_llvm && 0) {
+ FunctionPassManager *PM = PerFunctionPasses;
+ HasPerFunctionPasses = true;
+
+ CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
+
+ switch (optimize) {
+ default: break;
+ case 0: OptLevel = CodeGenOpt::None; break;
+ case 3: OptLevel = CodeGenOpt::Aggressive; break;
+ }
+
+ // Normal mode, emit a .s file by running the code generator.
+ // Note, this also adds codegenerator level optimization passes.
+ InitializeOutputStreams(false);
+ switch (TheTarget->addPassesToEmitFile(*PM, FormattedOutStream,
+ TargetMachine::AssemblyFile,
+ OptLevel)) {
+ default:
+ case FileModel::Error:
+ errs() << "Error interfacing to target machine!\n";
+ exit(1);
+ case FileModel::AsmFile:
+ break;
+ }
+
+ if (TheTarget->addPassesToEmitFileFinish(*PM, (MachineCodeEmitter *)0,
+ OptLevel)) {
+ errs() << "Error interfacing to target machine!\n";
+ exit(1);
+ }
+ }
+
+ if (HasPerFunctionPasses) {
+ PerFunctionPasses->doInitialization();
+ } else {
+ delete PerFunctionPasses;
+ PerFunctionPasses = 0;
+ }
+}
+
+static void createPerModuleOptimizationPasses() {
+ if (PerModulePasses)
+ // llvm_pch_write_init has already created the per module passes.
+ return;
+
+ // FIXME: AT -O0/O1, we should stream out functions at a time.
+ PerModulePasses = new PassManager();
+ PerModulePasses->add(new TargetData(*TheTarget->getTargetData()));
+ bool HasPerModulePasses = false;
+
+ if (!DisableLLVMOptimizations) {
+ bool NeedAlwaysInliner = false;
+ llvm::Pass *InliningPass = 0;
+ if (flag_inline_trees > 1) { // respect -fno-inline-functions
+ InliningPass = createFunctionInliningPass(); // Inline small functions
+ } else {
+ // If full inliner is not run, check if always-inline is needed to handle
+ // functions that are marked as always_inline.
+ for (Module::iterator I = TheModule->begin(), E = TheModule->end();
+ I != E; ++I)
+ if (I->hasFnAttr(Attribute::AlwaysInline)) {
+ NeedAlwaysInliner = true;
+ break;
+ }
+
+ if (NeedAlwaysInliner)
+ InliningPass = createAlwaysInlinerPass(); // Inline always_inline funcs
+ }
+
+ HasPerModulePasses = true;
+ createStandardModulePasses(PerModulePasses, optimize,
+ optimize_size || optimize < 3,
+ flag_unit_at_a_time, flag_unroll_loops,
+ !flag_no_simplify_libcalls, flag_exceptions,
+ InliningPass);
+ }
+
+ if (emit_llvm_bc) {
+ // Emit an LLVM .bc file to the output. This is used when passed
+ // -emit-llvm -c to the GCC driver.
+ InitializeOutputStreams(true);
+ PerModulePasses->add(createBitcodeWriterPass(*OutStream));
+ HasPerModulePasses = true;
+ } else if (emit_llvm) {
+ // Emit an LLVM .ll file to the output. This is used when passed
+ // -emit-llvm -S to the GCC driver.
+ InitializeOutputStreams(false);
+ PerModulePasses->add(createPrintModulePass(OutStream));
+ HasPerModulePasses = true;
+ } else {
+ // If there are passes we have to run on the entire module, we do codegen
+ // as a separate "pass" after that happens.
+ // However if there are no module-level passes that have to be run, we
+ // codegen as each function is parsed.
+ // FIXME: This is disabled right now until bugs can be worked out. Reenable
+ // this for fast -O0 compiles!
+ if (PerModulePasses || 1) {
+ FunctionPassManager *PM = CodeGenPasses =
+ new FunctionPassManager(new ExistingModuleProvider(TheModule));
+ PM->add(new TargetData(*TheTarget->getTargetData()));
+
+ CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
+
+ switch (optimize) {
+ default: break;
+ case 0: OptLevel = CodeGenOpt::None; break;
+ case 3: OptLevel = CodeGenOpt::Aggressive; break;
+ }
+
+ // Normal mode, emit a .s file by running the code generator.
+ // Note, this also adds codegenerator level optimization passes.
+ InitializeOutputStreams(false);
+ switch (TheTarget->addPassesToEmitFile(*PM, FormattedOutStream,
+ TargetMachine::AssemblyFile,
+ OptLevel)) {
+ default:
+ case FileModel::Error:
+ errs() << "Error interfacing to target machine!\n";
+ exit(1);
+ case FileModel::AsmFile:
+ break;
+ }
+
+ if (TheTarget->addPassesToEmitFileFinish(*PM, (MachineCodeEmitter *)0,
+ OptLevel)) {
+ errs() << "Error interfacing to target machine!\n";
+ exit(1);
+ }
+ }
+ }
+
+ if (!HasPerModulePasses) {
+ delete PerModulePasses;
+ PerModulePasses = 0;
+ }
+}
+
//TODO/// llvm_asm_file_start - Start the .s file.
//TODOvoid llvm_asm_file_start(void) {
//TODO timevar_push(TV_LLVM_INIT);
@@ -893,81 +931,83 @@
Array, Name);
}
-//TODO/// llvm_asm_file_end - Finish the .s file.
-//TODOvoid llvm_asm_file_end(void) {
+/// llvm_finish_unit - Finish the .s file.
+static void llvm_finish_unit(void *gcc_data, void *user_data) {
+ LazilyInitializeModule();
+
//TODO timevar_push(TV_LLVM_PERFILE);
-//TODO LLVMContext &Context = getGlobalContext();
-//TODO
+ LLVMContext &Context = getGlobalContext();
+
//TODO performLateBackendInitialization();
-//TODO createPerFunctionOptimizationPasses();
+ createPerFunctionOptimizationPasses();
//TODO
//TODO if (flag_pch_file) {
//TODO writeLLVMTypesStringTable();
//TODO writeLLVMValues();
//TODO }
-//TODO
-//TODO // Add an llvm.global_ctors global if needed.
-//TODO if (!StaticCtors.empty())
-//TODO CreateStructorsList(StaticCtors, "llvm.global_ctors");
-//TODO // Add an llvm.global_dtors global if needed.
-//TODO if (!StaticDtors.empty())
-//TODO CreateStructorsList(StaticDtors, "llvm.global_dtors");
-//TODO
-//TODO if (!AttributeUsedGlobals.empty()) {
-//TODO std::vector<Constant *> AUGs;
-//TODO const Type *SBP= PointerType::getUnqual(Type::getInt8Ty(Context));
-//TODO for (SmallSetVector<Constant *,32>::iterator
-//TODO AI = AttributeUsedGlobals.begin(),
-//TODO AE = AttributeUsedGlobals.end(); AI != AE; ++AI) {
-//TODO Constant *C = *AI;
-//TODO AUGs.push_back(TheFolder->CreateBitCast(C, SBP));
-//TODO }
-//TODO
-//TODO ArrayType *AT = ArrayType::get(SBP, AUGs.size());
-//TODO Constant *Init = ConstantArray::get(AT, AUGs);
-//TODO GlobalValue *gv = new GlobalVariable(*TheModule, AT, false,
-//TODO GlobalValue::AppendingLinkage, Init,
-//TODO "llvm.used");
-//TODO gv->setSection("llvm.metadata");
-//TODO AttributeUsedGlobals.clear();
-//TODO }
-//TODO
-//TODO if (!AttributeCompilerUsedGlobals.empty()) {
-//TODO std::vector<Constant *> ACUGs;
-//TODO const Type *SBP= PointerType::getUnqual(Type::getInt8Ty(Context));
-//TODO for (SmallSetVector<Constant *,32>::iterator
-//TODO AI = AttributeCompilerUsedGlobals.begin(),
-//TODO AE = AttributeCompilerUsedGlobals.end(); AI != AE; ++AI) {
-//TODO Constant *C = *AI;
-//TODO ACUGs.push_back(TheFolder->CreateBitCast(C, SBP));
-//TODO }
-//TODO
-//TODO ArrayType *AT = ArrayType::get(SBP, ACUGs.size());
-//TODO Constant *Init = ConstantArray::get(AT, ACUGs);
-//TODO GlobalValue *gv = new GlobalVariable(*TheModule, AT, false,
-//TODO GlobalValue::AppendingLinkage, Init,
-//TODO "llvm.compiler.used");
-//TODO gv->setSection("llvm.metadata");
-//TODO AttributeCompilerUsedGlobals.clear();
-//TODO }
-//TODO
-//TODO // Add llvm.global.annotations
-//TODO if (!AttributeAnnotateGlobals.empty()) {
-//TODO Constant *Array = ConstantArray::get(
-//TODO ArrayType::get(AttributeAnnotateGlobals[0]->getType(),
-//TODO AttributeAnnotateGlobals.size()),
-//TODO AttributeAnnotateGlobals);
-//TODO GlobalValue *gv = new GlobalVariable(*TheModule, Array->getType(), false,
-//TODO GlobalValue::AppendingLinkage, Array,
-//TODO "llvm.global.annotations");
-//TODO gv->setSection("llvm.metadata");
-//TODO AttributeAnnotateGlobals.clear();
-//TODO }
-//TODO
-//TODO // Finish off the per-function pass.
-//TODO if (PerFunctionPasses)
-//TODO PerFunctionPasses->doFinalization();
-//TODO
+
+ // Add an llvm.global_ctors global if needed.
+ if (!StaticCtors.empty())
+ CreateStructorsList(StaticCtors, "llvm.global_ctors");
+ // Add an llvm.global_dtors global if needed.
+ if (!StaticDtors.empty())
+ CreateStructorsList(StaticDtors, "llvm.global_dtors");
+
+ if (!AttributeUsedGlobals.empty()) {
+ std::vector<Constant *> AUGs;
+ const Type *SBP= PointerType::getUnqual(Type::getInt8Ty(Context));
+ for (SmallSetVector<Constant *,32>::iterator
+ AI = AttributeUsedGlobals.begin(),
+ AE = AttributeUsedGlobals.end(); AI != AE; ++AI) {
+ Constant *C = *AI;
+ AUGs.push_back(TheFolder->CreateBitCast(C, SBP));
+ }
+
+ ArrayType *AT = ArrayType::get(SBP, AUGs.size());
+ Constant *Init = ConstantArray::get(AT, AUGs);
+ GlobalValue *gv = new GlobalVariable(*TheModule, AT, false,
+ GlobalValue::AppendingLinkage, Init,
+ "llvm.used");
+ gv->setSection("llvm.metadata");
+ AttributeUsedGlobals.clear();
+ }
+
+ if (!AttributeCompilerUsedGlobals.empty()) {
+ std::vector<Constant *> ACUGs;
+ const Type *SBP= PointerType::getUnqual(Type::getInt8Ty(Context));
+ for (SmallSetVector<Constant *,32>::iterator
+ AI = AttributeCompilerUsedGlobals.begin(),
+ AE = AttributeCompilerUsedGlobals.end(); AI != AE; ++AI) {
+ Constant *C = *AI;
+ ACUGs.push_back(TheFolder->CreateBitCast(C, SBP));
+ }
+
+ ArrayType *AT = ArrayType::get(SBP, ACUGs.size());
+ Constant *Init = ConstantArray::get(AT, ACUGs);
+ GlobalValue *gv = new GlobalVariable(*TheModule, AT, false,
+ GlobalValue::AppendingLinkage, Init,
+ "llvm.compiler.used");
+ gv->setSection("llvm.metadata");
+ AttributeCompilerUsedGlobals.clear();
+ }
+
+ // Add llvm.global.annotations
+ if (!AttributeAnnotateGlobals.empty()) {
+ Constant *Array = ConstantArray::get(
+ ArrayType::get(AttributeAnnotateGlobals[0]->getType(),
+ AttributeAnnotateGlobals.size()),
+ AttributeAnnotateGlobals);
+ GlobalValue *gv = new GlobalVariable(*TheModule, Array->getType(), false,
+ GlobalValue::AppendingLinkage, Array,
+ "llvm.global.annotations");
+ gv->setSection("llvm.metadata");
+ AttributeAnnotateGlobals.clear();
+ }
+
+ // Finish off the per-function pass.
+ if (PerFunctionPasses)
+ PerFunctionPasses->doFinalization();
+
//TODO // Emit intermediate file before module level optimization passes are run.
//TODO if (flag_debug_llvm_module_opt) {
//TODO
@@ -975,14 +1015,14 @@
//TODO IntermediatePM->add(new TargetData(*TheTarget->getTargetData()));
//TODO
//TODO char asm_intermediate_out_filename[MAXPATHLEN];
-//TODO strcpy(&asm_intermediate_out_filename[0], asm_file_name);
+//TODO strcpy(&asm_intermediate_out_filename[0], llvm_asm_file_name);
//TODO strcat(&asm_intermediate_out_filename[0],".0");
//TODO FILE *asm_intermediate_out_file = fopen(asm_intermediate_out_filename, "w+b");
//TODO AsmIntermediateOutStream = new oFILEstream(asm_intermediate_out_file);
//TODO raw_ostream *AsmIntermediateRawOutStream =
//TODO new raw_os_ostream(*AsmIntermediateOutStream);
//TODO if (emit_llvm_bc)
-//TODO IntermediatePM->add(CreateBitcodeWriterPass(*AsmIntermediateOutStream));
+//TODO IntermediatePM->add(createBitcodeWriterPass(*AsmIntermediateOutStream));
//TODO if (emit_llvm)
//TODO IntermediatePM->add(createPrintModulePass(AsmIntermediateRawOutStream));
//TODO IntermediatePM->run(*TheModule);
@@ -994,32 +1034,31 @@
//TODO delete AsmIntermediateOutStream;
//TODO AsmIntermediateOutStream = 0;
//TODO }
-//TODO
-//TODO // Run module-level optimizers, if any are present.
-//TODO createPerModuleOptimizationPasses();
-//TODO if (PerModulePasses)
-//TODO PerModulePasses->run(*TheModule);
-//TODO
-//TODO // Run the code generator, if present.
-//TODO if (CodeGenPasses) {
-//TODO CodeGenPasses->doInitialization();
-//TODO for (Module::iterator I = TheModule->begin(), E = TheModule->end();
-//TODO I != E; ++I)
-//TODO if (!I->isDeclaration())
-//TODO CodeGenPasses->run(*I);
-//TODO CodeGenPasses->doFinalization();
-//TODO }
-//TODO
-//TODO AsmOutRawStream->flush();
-//TODO AsmOutStream->flush();
-//TODO fflush(asm_out_file);
+
+ // Run module-level optimizers, if any are present.
+ createPerModuleOptimizationPasses();
+ if (PerModulePasses)
+ PerModulePasses->run(*TheModule);
+
+ // Run the code generator, if present.
+ if (CodeGenPasses) {
+ CodeGenPasses->doInitialization();
+ for (Module::iterator I = TheModule->begin(), E = TheModule->end();
+ I != E; ++I)
+ if (!I->isDeclaration())
+ CodeGenPasses->run(*I);
+ CodeGenPasses->doFinalization();
+ }
+
+ FormattedOutStream.flush();
+ OutStream->flush();
//TODO delete AsmOutRawStream;
//TODO AsmOutRawStream = 0;
//TODO delete AsmOutStream;
//TODO AsmOutStream = 0;
//TODO timevar_pop(TV_LLVM_PERFILE);
-//TODO}
-//TODO
+}
+
//TODO// llvm_call_llvm_shutdown - Release LLVM global state.
//TODOvoid llvm_call_llvm_shutdown(void) {
//TODO llvm_shutdown();
@@ -1897,13 +1936,13 @@
Function *Fn = Emitter.EmitFunction();
//TODO performLateBackendInitialization();
-//TODO createPerFunctionOptimizationPasses();
-//TODO
-//TODO if (PerFunctionPasses)
-//TODO PerFunctionPasses->run(*Fn);
-//TODO
-//TODO // TODO: Nuke the .ll code for the function at -O[01] if we don't want to
-//TODO // inline it or something else.
+ createPerFunctionOptimizationPasses();
+
+ if (PerFunctionPasses)
+ PerFunctionPasses->run(*Fn);
+
+ // TODO: Nuke the .ll code for the function at -O[01] if we don't want to
+ // inline it or something else.
// Finally, we have written out this function!
TREE_ASM_WRITTEN(current_function_decl) = 1;
@@ -1919,6 +1958,31 @@
return 0;
}
+/// TakeoverAsmOutput - Obtain exclusive use of the assembly code output file.
+/// Any GCC output will be thrown away.
+static void TakeoverAsmOutput(void) {
+ // Calculate the output file name as in init_asm_output (toplev.c).
+ if (!dump_base_name && main_input_filename)
+ dump_base_name = main_input_filename[0] ? main_input_filename : "gccdump";
+
+ if (!main_input_filename && !asm_file_name) {
+ llvm_asm_file_name = "-";
+ } else if (!asm_file_name) {
+ int len = strlen (dump_base_name);
+ char *dumpname = XNEWVEC (char, len + 6);
+
+ memcpy (dumpname, dump_base_name, len + 1);
+ strip_off_ending (dumpname, len);
+ strcat (dumpname, ".s");
+ llvm_asm_file_name = dumpname;
+ } else {
+ llvm_asm_file_name = asm_file_name;
+ }
+
+ // Redirect any GCC output to /dev/null.
+ asm_file_name = HOST_BIT_BUCKET;
+}
+
/// pass_emit_llvm - RTL pass that turns gimple functions into LLVM IR.
static struct rtl_opt_pass pass_emit_llvm =
{
@@ -2037,6 +2101,9 @@
// Provide our version and help information.
register_callback (plugin_name, PLUGIN_INFO, NULL, &llvm_plugin_info);
+ // Obtain exclusive use of the assembly code output file.
+ TakeoverAsmOutput();
+
// Replace rtl expansion with gimple to LLVM conversion.
pass_info.pass = &pass_emit_llvm.pass;
pass_info.reference_pass_name = "expand";
@@ -2067,5 +2134,8 @@
register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
}
+ // Finish the .s file.
+ register_callback (plugin_name, PLUGIN_FINISH_UNIT, llvm_finish_unit, NULL);
+
return 0;
}
More information about the llvm-commits
mailing list