C++程序  |  161行  |  4.48 KB

//===- main.cpp -----------------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/PreferenceOptions.h>
#include <mcld/TripleOptions.h>
#include <mcld/DynamicSectionOptions.h>
#include <mcld/OutputFormatOptions.h>
#include <mcld/SearchPathOptions.h>
#include <mcld/OptimizationOptions.h>
#include <mcld/SymbolOptions.h>
#include <mcld/TargetControlOptions.h>
#include <mcld/ScriptOptions.h>
#include <mcld/PositionalOptions.h>

#include <mcld/Module.h>
#include <mcld/Environment.h>
#include <mcld/LinkerConfig.h>
#include <mcld/LinkerScript.h>
#include <mcld/Linker.h>
#include <mcld/IRBuilder.h>
#include <mcld/MC/InputAction.h>
#include <mcld/Support/raw_ostream.h>
#include <mcld/Support/MsgHandling.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/Signals.h>
#include <string>
#include <cassert>

/// configure linker
static inline bool ConfigLinker(int pArgc,
                                char* pArgv[],
                                const char* pName,
                                mcld::Module& pModule,
                                mcld::LinkerScript& pScript,
                                mcld::LinkerConfig& pConfig,
                                mcld::IRBuilder& pBuilder,
                                std::vector<mcld::InputAction*>& pInputActions)
{
  mcld::PreferenceOptions     preference;
  mcld::TripleOptions         triple;
  mcld::DynamicSectionOptions dynamic_section;
  mcld::OutputFormatOptions   output_format;
  mcld::SearchPathOptions     search_path;
  mcld::OptimizationOptions   optimization;
  mcld::SymbolOptions         symbol;
  mcld::TargetControlOptions  target_control;
  mcld::ScriptOptions         script;
  mcld::PositionalOptions     positional;

  llvm::cl::ParseCommandLineOptions(pArgc, pArgv, pName);

  if (!preference.parse(pConfig))
    return false;

  if (!triple.parse(pArgc, pArgv, pConfig))
    return false;

  if (!dynamic_section.parse(pConfig, pScript))
    return false;

  if (!output_format.parse(pModule, pConfig))
    return false;

  if (!search_path.parse(pConfig, pScript))
    return false;

  if (!optimization.parse(pConfig))
    return false;

  if (!symbol.parse(pConfig))
    return false;

  if (!target_control.parse(pConfig))
    return false;

  if (!script.parse(pScript))
    return false;

  if (!positional.parse(pInputActions, pConfig, pScript))
    return false;

  if (pConfig.options().soname().empty())
    pConfig.options().setSOName(pModule.name());

  return true;
}

static
inline bool InitializeInputs(mcld::IRBuilder& pBuilder,
                             std::vector<mcld::InputAction*>& pInputActions)
{
  for (std::vector<mcld::InputAction*>::iterator action = pInputActions.begin(),
    actionEnd = pInputActions.end(); action != actionEnd; ++action) {
    assert(*action != NULL);
    (*action)->activate(pBuilder.getInputBuilder());
    delete *action;
  }

  if (pBuilder.getInputBuilder().isInGroup()) {
    mcld::fatal(mcld::diag::fatal_forbid_nest_group);
    return false;
  }

  return true;
}

int main(int argc, char* argv[])
{
  llvm::sys::PrintStackTraceOnErrorSignal();
  llvm::llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
  mcld::Initialize();

  mcld::LinkerScript script;
  mcld::LinkerConfig config;
  mcld::Module module(script);
  mcld::IRBuilder builder(module, config);
  std::vector<mcld::InputAction*> input_actions;

  if (!ConfigLinker(argc, argv, "MCLinker\n", module, script, config, builder,
                    input_actions)) {
    mcld::errs() << argv[0]
                 << ": failed to process linker options from command line!\n";
    return 1;
  }

  mcld::Linker linker;
  if (!linker.emulate(script, config)) {
    mcld::errs() << argv[0]
                 << ": failed to emulate target!\n";
    return 1;
  }

  // FIXME: is it possible to have a lightweight MCLinker pass?
  if (!InitializeInputs(builder, input_actions)) {
    mcld::errs() << argv[0]
                 << ": failed to initialize input tree!\n";
    return 1;
  }

  if (!linker.link(module, builder)) {
    mcld::errs() << argv[0]
                 << ": failed to link objects!\n";
    return 1;
  }

  if (!linker.emit(module, module.name())) {
    mcld::errs() << argv[0]
                 << ": failed to emit output!\n";
    return 1;
  }

  mcld::Finalize();

  return 0;
}