head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.11
	netbsd-11-0-RC3:1.1.1.11
	netbsd-11-0-RC2:1.1.1.11
	netbsd-11-0-RC1:1.1.1.11
	perseant-exfatfs-base-20250801:1.1.1.11
	netbsd-11:1.1.1.11.0.10
	netbsd-11-base:1.1.1.11
	netbsd-10-1-RELEASE:1.1.1.11
	perseant-exfatfs-base-20240630:1.1.1.11
	perseant-exfatfs:1.1.1.11.0.8
	perseant-exfatfs-base:1.1.1.11
	netbsd-8-3-RELEASE:1.1.1.8
	netbsd-9-4-RELEASE:1.1.1.10
	netbsd-10-0-RELEASE:1.1.1.11
	netbsd-10-0-RC6:1.1.1.11
	netbsd-10-0-RC5:1.1.1.11
	netbsd-10-0-RC4:1.1.1.11
	netbsd-10-0-RC3:1.1.1.11
	netbsd-10-0-RC2:1.1.1.11
	netbsd-10-0-RC1:1.1.1.11
	netbsd-10:1.1.1.11.0.6
	netbsd-10-base:1.1.1.11
	netbsd-9-3-RELEASE:1.1.1.10
	cjep_sun2x:1.1.1.11.0.4
	cjep_sun2x-base:1.1.1.11
	cjep_staticlib_x-base1:1.1.1.11
	netbsd-9-2-RELEASE:1.1.1.10
	cjep_staticlib_x:1.1.1.11.0.2
	cjep_staticlib_x-base:1.1.1.11
	netbsd-9-1-RELEASE:1.1.1.10
	phil-wifi-20200421:1.1.1.11
	phil-wifi-20200411:1.1.1.11
	phil-wifi-20200406:1.1.1.11
	netbsd-8-2-RELEASE:1.1.1.8
	netbsd-9-0-RELEASE:1.1.1.10
	netbsd-9-0-RC2:1.1.1.10
	netbsd-9-0-RC1:1.1.1.10
	netbsd-9:1.1.1.10.0.2
	netbsd-9-base:1.1.1.10
	phil-wifi-20190609:1.1.1.10
	netbsd-8-1-RELEASE:1.1.1.8
	netbsd-8-1-RC1:1.1.1.8
	pgoyette-compat-merge-20190127:1.1.1.9.2.1
	pgoyette-compat-20190127:1.1.1.10
	pgoyette-compat-20190118:1.1.1.10
	pgoyette-compat-1226:1.1.1.10
	pgoyette-compat-1126:1.1.1.10
	pgoyette-compat-1020:1.1.1.10
	pgoyette-compat-0930:1.1.1.10
	pgoyette-compat-0906:1.1.1.10
	netbsd-7-2-RELEASE:1.1.1.5.2.1
	pgoyette-compat-0728:1.1.1.10
	clang-337282:1.1.1.10
	netbsd-8-0-RELEASE:1.1.1.8
	phil-wifi:1.1.1.9.0.4
	phil-wifi-base:1.1.1.9
	pgoyette-compat-0625:1.1.1.9
	netbsd-8-0-RC2:1.1.1.8
	pgoyette-compat-0521:1.1.1.9
	pgoyette-compat-0502:1.1.1.9
	pgoyette-compat-0422:1.1.1.9
	netbsd-8-0-RC1:1.1.1.8
	pgoyette-compat-0415:1.1.1.9
	pgoyette-compat-0407:1.1.1.9
	pgoyette-compat-0330:1.1.1.9
	pgoyette-compat-0322:1.1.1.9
	pgoyette-compat-0315:1.1.1.9
	netbsd-7-1-2-RELEASE:1.1.1.5.2.1
	pgoyette-compat:1.1.1.9.0.2
	pgoyette-compat-base:1.1.1.9
	netbsd-7-1-1-RELEASE:1.1.1.5.2.1
	clang-319952:1.1.1.9
	matt-nb8-mediatek:1.1.1.8.0.10
	matt-nb8-mediatek-base:1.1.1.8
	clang-309604:1.1.1.9
	perseant-stdc-iso10646:1.1.1.8.0.8
	perseant-stdc-iso10646-base:1.1.1.8
	netbsd-8:1.1.1.8.0.6
	netbsd-8-base:1.1.1.8
	prg-localcount2-base3:1.1.1.8
	prg-localcount2-base2:1.1.1.8
	prg-localcount2-base1:1.1.1.8
	prg-localcount2:1.1.1.8.0.4
	prg-localcount2-base:1.1.1.8
	pgoyette-localcount-20170426:1.1.1.8
	bouyer-socketcan-base1:1.1.1.8
	pgoyette-localcount-20170320:1.1.1.8
	netbsd-7-1:1.1.1.5.2.1.0.6
	netbsd-7-1-RELEASE:1.1.1.5.2.1
	netbsd-7-1-RC2:1.1.1.5.2.1
	clang-294123:1.1.1.8
	netbsd-7-nhusb-base-20170116:1.1.1.5.2.1
	bouyer-socketcan:1.1.1.8.0.2
	bouyer-socketcan-base:1.1.1.8
	clang-291444:1.1.1.8
	pgoyette-localcount-20170107:1.1.1.7
	netbsd-7-1-RC1:1.1.1.5.2.1
	pgoyette-localcount-20161104:1.1.1.7
	netbsd-7-0-2-RELEASE:1.1.1.5.2.1
	localcount-20160914:1.1.1.7
	netbsd-7-nhusb:1.1.1.5.2.1.0.4
	netbsd-7-nhusb-base:1.1.1.5.2.1
	clang-280599:1.1.1.7
	pgoyette-localcount-20160806:1.1.1.7
	pgoyette-localcount-20160726:1.1.1.7
	pgoyette-localcount:1.1.1.7.0.2
	pgoyette-localcount-base:1.1.1.7
	netbsd-7-0-1-RELEASE:1.1.1.5.2.1
	clang-261930:1.1.1.7
	netbsd-7-0:1.1.1.5.2.1.0.2
	netbsd-7-0-RELEASE:1.1.1.5.2.1
	netbsd-7-0-RC3:1.1.1.5.2.1
	netbsd-7-0-RC2:1.1.1.5.2.1
	netbsd-7-0-RC1:1.1.1.5.2.1
	clang-237755:1.1.1.6
	clang-232565:1.1.1.6
	clang-227398:1.1.1.6
	tls-maxphys-base:1.1.1.5
	tls-maxphys:1.1.1.5.0.4
	netbsd-7:1.1.1.5.0.2
	netbsd-7-base:1.1.1.5
	clang-215315:1.1.1.5
	clang-209886:1.1.1.4
	yamt-pagecache:1.1.1.3.0.4
	yamt-pagecache-base9:1.1.1.3
	tls-earlyentropy:1.1.1.3.0.2
	tls-earlyentropy-base:1.1.1.4
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.3
	riastradh-drm2-base3:1.1.1.3
	clang-202566:1.1.1.3
	clang-201163:1.1.1.2
	clang-199312:1.1.1.1
	clang-198450:1.1.1.1
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.48;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.48;	author joerg;	state Exp;
branches;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.02.14.20.07.01;	author joerg;	state Exp;
branches;
next	1.1.1.3;
commitid	annVkZ1sc17rF6px;

1.1.1.3
date	2014.03.04.19.53.18;	author joerg;	state Exp;
branches
	1.1.1.3.2.1
	1.1.1.3.4.1;
next	1.1.1.4;
commitid	29z1hJonZISIXprx;

1.1.1.4
date	2014.05.30.18.14.49;	author joerg;	state Exp;
branches;
next	1.1.1.5;
commitid	8q0kdlBlCn09GACx;

1.1.1.5
date	2014.08.10.17.08.24;	author joerg;	state Exp;
branches
	1.1.1.5.2.1
	1.1.1.5.4.1;
next	1.1.1.6;
commitid	N85tXAN6Ex9VZPLx;

1.1.1.6
date	2015.01.29.19.57.27;	author joerg;	state Exp;
branches;
next	1.1.1.7;
commitid	mlISSizlPKvepX7y;

1.1.1.7
date	2016.02.27.22.10.57;	author joerg;	state Exp;
branches
	1.1.1.7.2.1;
next	1.1.1.8;
commitid	tIimz3oDlh1NpBWy;

1.1.1.8
date	2017.01.11.10.32.22;	author joerg;	state Exp;
branches;
next	1.1.1.9;
commitid	CNnUNfII1jgNmxBz;

1.1.1.9
date	2017.08.01.19.37.51;	author joerg;	state Exp;
branches
	1.1.1.9.2.1
	1.1.1.9.4.1;
next	1.1.1.10;
commitid	pMuDy65V0VicSx1A;

1.1.1.10
date	2018.07.17.18.32.07;	author joerg;	state Exp;
branches;
next	1.1.1.11;
commitid	wDzL46ALjrCZgwKA;

1.1.1.11
date	2019.11.13.22.23.05;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.3.2.1
date	2014.08.10.07.08.25;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.3.4.1
date	2014.03.04.19.53.18;	author yamt;	state dead;
branches;
next	1.1.1.3.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.3.4.2
date	2014.05.22.16.19.47;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.5.2.1
date	2015.06.04.20.04.46;	author snj;	state Exp;
branches;
next	;
commitid	yRnjq9fueSo6n9oy;

1.1.1.5.4.1
date	2014.08.10.17.08.24;	author tls;	state dead;
branches;
next	1.1.1.5.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.5.4.2
date	2014.08.19.23.49.27;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.7.2.1
date	2017.03.20.06.53.37;	author pgoyette;	state Exp;
branches;
next	;
commitid	jjw7cAwgyKq7RfKz;

1.1.1.9.2.1
date	2018.07.28.04.34.16;	author pgoyette;	state Exp;
branches;
next	;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.9.4.1
date	2019.06.10.21.46.43;	author christos;	state Exp;
branches;
next	1.1.1.9.4.2;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.9.4.2
date	2020.04.13.07.50.33;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@//===-- cc1as_main.cpp - Clang Assembler  ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the entry point to the clang -cc1as functionality, which implements
// the direct interface to the LLVM MC based assembler.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/CC1AsOptions.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
using namespace clang;
using namespace clang::driver;
using namespace llvm;
using namespace llvm::opt;

namespace {

/// \brief Helper class for representing a single invocation of the assembler.
struct AssemblerInvocation {
  /// @@name Target Options
  /// @@{

  /// The name of the target triple to assemble for.
  std::string Triple;

  /// If given, the name of the target CPU to determine which instructions
  /// are legal.
  std::string CPU;

  /// The list of target specific features to enable or disable -- this should
  /// be a list of strings starting with '+' or '-'.
  std::vector<std::string> Features;

  /// @@}
  /// @@name Language Options
  /// @@{

  std::vector<std::string> IncludePaths;
  unsigned NoInitialTextSection : 1;
  unsigned SaveTemporaryLabels : 1;
  unsigned GenDwarfForAssembly : 1;
  std::string DwarfDebugFlags;
  std::string DwarfDebugProducer;
  std::string DebugCompilationDir;
  std::string MainFileName;

  /// @@}
  /// @@name Frontend Options
  /// @@{

  std::string InputFile;
  std::vector<std::string> LLVMArgs;
  std::string OutputPath;
  enum FileType {
    FT_Asm,  ///< Assembly (.s) output, transliterate mode.
    FT_Null, ///< No output, for timing purposes.
    FT_Obj   ///< Object file output.
  };
  FileType OutputType;
  unsigned ShowHelp : 1;
  unsigned ShowVersion : 1;

  /// @@}
  /// @@name Transliterate Options
  /// @@{

  unsigned OutputAsmVariant;
  unsigned ShowEncoding : 1;
  unsigned ShowInst : 1;

  /// @@}
  /// @@name Assembler Options
  /// @@{

  unsigned RelaxAll : 1;
  unsigned NoExecStack : 1;

  /// @@}

public:
  AssemblerInvocation() {
    Triple = "";
    NoInitialTextSection = 0;
    InputFile = "-";
    OutputPath = "-";
    OutputType = FT_Asm;
    OutputAsmVariant = 0;
    ShowInst = 0;
    ShowEncoding = 0;
    RelaxAll = 0;
    NoExecStack = 0;
  }

  static bool CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin,
                             const char **ArgEnd, DiagnosticsEngine &Diags);
};

}

bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
                                         const char **ArgBegin,
                                         const char **ArgEnd,
                                         DiagnosticsEngine &Diags) {
  using namespace clang::driver::cc1asoptions;
  bool Success = true;

  // Parse the arguments.
  OwningPtr<OptTable> OptTbl(createCC1AsOptTable());
  unsigned MissingArgIndex, MissingArgCount;
  OwningPtr<InputArgList> Args(
    OptTbl->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));

  // Check for missing argument error.
  if (MissingArgCount) {
    Diags.Report(diag::err_drv_missing_argument)
      << Args->getArgString(MissingArgIndex) << MissingArgCount;
    Success = false;
  }

  // Issue errors on unknown arguments.
  for (arg_iterator it = Args->filtered_begin(cc1asoptions::OPT_UNKNOWN),
         ie = Args->filtered_end(); it != ie; ++it) {
    Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args);
    Success = false;
  }

  // Construct the invocation.

  // Target Options
  Opts.Triple = llvm::Triple::normalize(Args->getLastArgValue(OPT_triple));
  Opts.CPU = Args->getLastArgValue(OPT_target_cpu);
  Opts.Features = Args->getAllArgValues(OPT_target_feature);

  // Use the default target triple if unspecified.
  if (Opts.Triple.empty())
    Opts.Triple = llvm::sys::getDefaultTargetTriple();

  // Language Options
  Opts.IncludePaths = Args->getAllArgValues(OPT_I);
  Opts.NoInitialTextSection = Args->hasArg(OPT_n);
  Opts.SaveTemporaryLabels = Args->hasArg(OPT_msave_temp_labels);
  Opts.GenDwarfForAssembly = Args->hasArg(OPT_g);
  Opts.DwarfDebugFlags = Args->getLastArgValue(OPT_dwarf_debug_flags);
  Opts.DwarfDebugProducer = Args->getLastArgValue(OPT_dwarf_debug_producer);
  Opts.DebugCompilationDir = Args->getLastArgValue(OPT_fdebug_compilation_dir);
  Opts.MainFileName = Args->getLastArgValue(OPT_main_file_name);

  // Frontend Options
  if (Args->hasArg(OPT_INPUT)) {
    bool First = true;
    for (arg_iterator it = Args->filtered_begin(OPT_INPUT),
           ie = Args->filtered_end(); it != ie; ++it, First=false) {
      const Arg *A = it;
      if (First)
        Opts.InputFile = A->getValue();
      else {
        Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(*Args);
        Success = false;
      }
    }
  }
  Opts.LLVMArgs = Args->getAllArgValues(OPT_mllvm);
  Opts.OutputPath = Args->getLastArgValue(OPT_o);
  if (Arg *A = Args->getLastArg(OPT_filetype)) {
    StringRef Name = A->getValue();
    unsigned OutputType = StringSwitch<unsigned>(Name)
      .Case("asm", FT_Asm)
      .Case("null", FT_Null)
      .Case("obj", FT_Obj)
      .Default(~0U);
    if (OutputType == ~0U) {
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(*Args) << Name;
      Success = false;
    } else
      Opts.OutputType = FileType(OutputType);
  }
  Opts.ShowHelp = Args->hasArg(OPT_help);
  Opts.ShowVersion = Args->hasArg(OPT_version);

  // Transliterate Options
  Opts.OutputAsmVariant =
      getLastArgIntValue(*Args.get(), OPT_output_asm_variant, 0, Diags);
  Opts.ShowEncoding = Args->hasArg(OPT_show_encoding);
  Opts.ShowInst = Args->hasArg(OPT_show_inst);

  // Assemble Options
  Opts.RelaxAll = Args->hasArg(OPT_mrelax_all);
  Opts.NoExecStack =  Args->hasArg(OPT_mno_exec_stack);

  return Success;
}

static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts,
                                              DiagnosticsEngine &Diags,
                                              bool Binary) {
  if (Opts.OutputPath.empty())
    Opts.OutputPath = "-";

  // Make sure that the Out file gets unlinked from the disk if we get a
  // SIGINT.
  if (Opts.OutputPath != "-")
    sys::RemoveFileOnSignal(Opts.OutputPath);

  std::string Error;
  raw_fd_ostream *Out =
      new raw_fd_ostream(Opts.OutputPath.c_str(), Error,
                         (Binary ? sys::fs::F_Binary : sys::fs::F_None));
  if (!Error.empty()) {
    Diags.Report(diag::err_fe_unable_to_open_output)
      << Opts.OutputPath << Error;
    return 0;
  }

  return new formatted_raw_ostream(*Out, formatted_raw_ostream::DELETE_STREAM);
}

static bool ExecuteAssembler(AssemblerInvocation &Opts,
                             DiagnosticsEngine &Diags) {
  // Get the target specific parser.
  std::string Error;
  const Target *TheTarget(TargetRegistry::lookupTarget(Opts.Triple, Error));
  if (!TheTarget) {
    Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
    return false;
  }

  OwningPtr<MemoryBuffer> BufferPtr;
  if (error_code ec = MemoryBuffer::getFileOrSTDIN(Opts.InputFile, BufferPtr)) {
    Error = ec.message();
    Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
    return false;
  }
  MemoryBuffer *Buffer = BufferPtr.take();

  SourceMgr SrcMgr;

  // 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
  // it later.
  SrcMgr.setIncludeDirs(Opts.IncludePaths);

  OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
  assert(MRI && "Unable to create target register info!");

  OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple));
  assert(MAI && "Unable to create target asm info!");

  bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
  formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary);
  if (!Out)
    return false;

  // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
  // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
  OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
  MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
  // FIXME: Assembler behavior can change with -static.
  MOFI->InitMCObjectFileInfo(Opts.Triple,
                             Reloc::Default, CodeModel::Default, Ctx);
  if (Opts.SaveTemporaryLabels)
    Ctx.setAllowTemporaryLabels(false);
  if (Opts.GenDwarfForAssembly)
    Ctx.setGenDwarfForAssembly(true);
  if (!Opts.DwarfDebugFlags.empty())
    Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags));
  if (!Opts.DwarfDebugProducer.empty())
    Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));
  if (!Opts.DebugCompilationDir.empty())
    Ctx.setCompilationDir(Opts.DebugCompilationDir);
  if (!Opts.MainFileName.empty())
    Ctx.setMainFileName(StringRef(Opts.MainFileName));

  // Build up the feature string from the target feature list.
  std::string FS;
  if (!Opts.Features.empty()) {
    FS = Opts.Features[0];
    for (unsigned i = 1, e = Opts.Features.size(); i != e; ++i)
      FS += "," + Opts.Features[i];
  }

  OwningPtr<MCStreamer> Str;

  OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
  OwningPtr<MCSubtargetInfo>
    STI(TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));

  // FIXME: There is a bit of code duplication with addPassesToEmitFile.
  if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
    MCInstPrinter *IP =
      TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI, *MCII, *MRI,
                                     *STI);
    MCCodeEmitter *CE = 0;
    MCAsmBackend *MAB = 0;
    if (Opts.ShowEncoding) {
      CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
      MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU);
    }
    Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true,
                                           /*useLoc*/ true,
                                           /*useCFI*/ true,
                                           /*useDwarfDirectory*/ true,
                                           IP, CE, MAB,
                                           Opts.ShowInst));
  } else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
    Str.reset(createNullStreamer(Ctx));
  } else {
    assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
           "Invalid file type!");
    MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
    MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,
                                                      Opts.CPU);
    Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out,
                                                CE, Opts.RelaxAll,
                                                Opts.NoExecStack));
    Str.get()->InitSections();
  }

  OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx,
                                                  *Str.get(), *MAI));
  OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser, *MCII));
  if (!TAP) {
    Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
    return false;
  }

  Parser->setTargetParser(*TAP.get());

  bool Success = !Parser->Run(Opts.NoInitialTextSection);

  // Close the output.
  delete Out;

  // Delete output on errors.
  if (!Success && Opts.OutputPath != "-")
    sys::fs::remove(Opts.OutputPath);

  return Success;
}

static void LLVMErrorHandler(void *UserData, const std::string &Message,
                             bool GenCrashDiag) {
  DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);

  Diags.Report(diag::err_fe_error_backend) << Message;

  // We cannot recover from llvm errors.
  exit(1);
}

int cc1as_main(const char **ArgBegin, const char **ArgEnd,
               const char *Argv0, void *MainAddr) {
  // Print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(ArgEnd - ArgBegin, ArgBegin);
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.

  // Initialize targets and assembly printers/parsers.
  InitializeAllTargetInfos();
  InitializeAllTargetMCs();
  InitializeAllAsmParsers();

  // Construct our diagnostic client.
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  TextDiagnosticPrinter *DiagClient
    = new TextDiagnosticPrinter(errs(), &*DiagOpts);
  DiagClient->setPrefix("clang -cc1as");
  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);

  // Set an error handler, so that any LLVM backend diagnostics go through our
  // error handler.
  ScopedFatalErrorHandler FatalErrorHandler
    (LLVMErrorHandler, static_cast<void*>(&Diags));

  // Parse the arguments.
  AssemblerInvocation Asm;
  if (!AssemblerInvocation::CreateFromArgs(Asm, ArgBegin, ArgEnd, Diags))
    return 1;

  // Honor -help.
  if (Asm.ShowHelp) {
    OwningPtr<OptTable> Opts(driver::createCC1AsOptTable());
    Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler");
    return 0;
  }

  // Honor -version.
  //
  // FIXME: Use a better -version message?
  if (Asm.ShowVersion) {
    llvm::cl::PrintVersionMessage();
    return 0;
  }

  // Honor -mllvm.
  //
  // FIXME: Remove this, one day.
  if (!Asm.LLVMArgs.empty()) {
    unsigned NumArgs = Asm.LLVMArgs.size();
    const char **Args = new const char*[NumArgs + 2];
    Args[0] = "clang (LLVM option parsing)";
    for (unsigned i = 0; i != NumArgs; ++i)
      Args[i + 1] = Asm.LLVMArgs[i].c_str();
    Args[NumArgs + 1] = 0;
    llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args);
  }

  // Execute the invocation, unless there were parsing errors.
  bool Success = false;
  if (!Diags.hasErrorOccurred())
    Success = ExecuteAssembler(Asm, Diags);

  // If any timers were active but haven't been destroyed yet, print their
  // results now.
  TimerGroup::printAll(errs());

  return !Success;
}
@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.2
log
@Import Clang 3.5svn r201163.
@
text
@d348 1
d362 1
a362 1
                                                CE, *STI, Opts.RelaxAll,
@


1.1.1.3
log
@Import Clang 3.5svn r202566.
@
text
@d254 1
a254 1
                         (Binary ? sys::fs::F_None : sys::fs::F_Text));
@


1.1.1.3.2.1
log
@Rebase.
@
text
@d23 1
a37 1
#include "llvm/MC/MCTargetOptions.h"
a56 1
#include <memory>
a87 2
  unsigned CompressDebugSections : 1;
  unsigned DwarfVersion;
a137 1
    DwarfVersion = 3;
d154 1
a154 1
  std::unique_ptr<OptTable> OptTbl(createCC1AsOptTable());
d156 2
a157 2
  std::unique_ptr<InputArgList> Args(
      OptTbl->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount));
a188 7
  Opts.CompressDebugSections = Args->hasArg(OPT_compress_debug_sections);
  if (Args->hasArg(OPT_gdwarf_2))
    Opts.DwarfVersion = 2;
  if (Args->hasArg(OPT_gdwarf_3))
    Opts.DwarfVersion = 3;
  if (Args->hasArg(OPT_gdwarf_4))
    Opts.DwarfVersion = 4;
d274 1
a274 1
  std::unique_ptr<MemoryBuffer> BufferPtr;
d280 1
a280 1
  MemoryBuffer *Buffer = BufferPtr.release();
d291 1
a291 1
  std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
d294 1
a294 1
  std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple));
a296 5
  // Ensure MCAsmInfo initialization occurs before any use, otherwise sections
  // may be created with a combination of default and explicit settings.
  if (Opts.CompressDebugSections)
    MAI->setCompressDebugSections(true);

d304 1
a304 2
  std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());

a320 1
  Ctx.setDwarfVersion(Opts.DwarfVersion);
d330 1
a330 1
  std::unique_ptr<MCStreamer> Str;
d332 3
a334 3
  std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
  std::unique_ptr<MCSubtargetInfo> STI(
      TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));
d348 1
d366 3
a368 7
  std::unique_ptr<MCAsmParser> Parser(
      createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));

  // FIXME: init MCTargetOptions from sanitizer flags here.
  MCTargetOptions Options;
  std::unique_ptr<MCTargetAsmParser> TAP(
      TheTarget->createMCAsmParser(*STI, *Parser, *MCII, Options));
d430 1
a430 1
    std::unique_ptr<OptTable> Opts(driver::createCC1AsOptTable());
@


1.1.1.4
log
@Import Clang 3.5svn r209886.
@
text
@d23 1
a37 1
#include "llvm/MC/MCTargetOptions.h"
a56 1
#include <memory>
a87 2
  unsigned CompressDebugSections : 1;
  unsigned DwarfVersion;
a137 1
    DwarfVersion = 3;
d154 1
a154 1
  std::unique_ptr<OptTable> OptTbl(createCC1AsOptTable());
d156 2
a157 2
  std::unique_ptr<InputArgList> Args(
      OptTbl->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount));
a188 7
  Opts.CompressDebugSections = Args->hasArg(OPT_compress_debug_sections);
  if (Args->hasArg(OPT_gdwarf_2))
    Opts.DwarfVersion = 2;
  if (Args->hasArg(OPT_gdwarf_3))
    Opts.DwarfVersion = 3;
  if (Args->hasArg(OPT_gdwarf_4))
    Opts.DwarfVersion = 4;
d274 1
a274 1
  std::unique_ptr<MemoryBuffer> BufferPtr;
d280 1
a280 1
  MemoryBuffer *Buffer = BufferPtr.release();
d291 1
a291 1
  std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
d294 1
a294 1
  std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple));
a296 5
  // Ensure MCAsmInfo initialization occurs before any use, otherwise sections
  // may be created with a combination of default and explicit settings.
  if (Opts.CompressDebugSections)
    MAI->setCompressDebugSections(true);

d304 1
a304 2
  std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());

a320 1
  Ctx.setDwarfVersion(Opts.DwarfVersion);
d330 1
a330 1
  std::unique_ptr<MCStreamer> Str;
d332 3
a334 3
  std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
  std::unique_ptr<MCSubtargetInfo> STI(
      TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));
d348 1
d366 3
a368 7
  std::unique_ptr<MCAsmParser> Parser(
      createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));

  // FIXME: init MCTargetOptions from sanitizer flags here.
  MCTargetOptions Options;
  std::unique_ptr<MCTargetAsmParser> TAP(
      TheTarget->createMCAsmParser(*STI, *Parser, *MCII, Options));
d430 1
a430 1
    std::unique_ptr<OptTable> Opts(driver::createCC1AsOptTable());
@


1.1.1.5
log
@Import clang 3.6svn r215315.
@
text
@d17 1
d56 1
a57 1
#include <system_error>
a59 1
using namespace clang::driver::options;
d154 1
d158 1
a158 3
  std::unique_ptr<OptTable> OptTbl(createDriverOptTable());

  const unsigned IncludedFlagsBitmask = options::CC1AsOption;
d161 1
a161 2
      OptTbl->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount,
                        IncludedFlagsBitmask));
d166 1
a166 1
        << Args->getArgString(MissingArgIndex) << MissingArgCount;
d171 3
a173 4
  for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
                    ie = Args->filtered_end();
       it != ie; ++it) {
    Diags.Report(diag::err_drv_unknown_argument) << (*it)->getAsString(*Args);
d192 1
a192 1
  Opts.GenDwarfForAssembly = Args->hasArg(OPT_g_Flag);
d269 1
a269 2
    delete Out;
    return nullptr;
d279 4
a282 10
  const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);
  if (!TheTarget)
    return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;

  ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
      MemoryBuffer::getFileOrSTDIN(Opts.InputFile);

  if (std::error_code EC = Buffer.getError()) {
    Error = EC.message();
    return Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
d285 8
d296 1
a296 1
  SrcMgr.AddNewSourceBuffer(Buffer->release(), SMLoc());
d314 1
a314 2
  std::unique_ptr<formatted_raw_ostream> Out(
      GetOutputStream(Opts, Diags, IsBinary));
d316 1
a316 1
    return true;
d359 2
a360 2
    MCCodeEmitter *CE = nullptr;
    MCAsmBackend *MAB = nullptr;
a382 2
  bool Failed = false;

d390 6
a395 2
  if (!TAP)
    Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
d397 1
a397 4
  if (!Failed) {
    Parser->setTargetParser(*TAP.get());
    Failed = Parser->Run(Opts.NoInitialTextSection);
  }
d399 2
a400 2
  // Close the output stream early.
  Out.reset();
d402 2
a403 2
  // Delete output file if there were errors.
  if (Failed && Opts.OutputPath != "-")
d406 1
a406 1
  return Failed;
d449 1
d451 2
a452 3
    std::unique_ptr<OptTable> Opts(driver::createDriverOptTable());
    Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler",
                    /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0);
d473 1
a473 1
    Args[NumArgs + 1] = nullptr;
d478 3
a480 1
  bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);
d486 1
a486 1
  return !!Failed;
a487 1

@


1.1.1.5.2.1
log
@Update LLVM to 3.6.1, requested by joerg in ticket 824.
@
text
@a125 1
  unsigned FatalWarnings : 1;
a140 1
    FatalWarnings = 0;
d144 2
a145 3
  static bool CreateFromArgs(AssemblerInvocation &Res,
                             ArrayRef<const char *> Argv,
                             DiagnosticsEngine &Diags);
d151 2
a152 1
                                         ArrayRef<const char *> Argv,
d162 1
a162 1
      OptTbl->ParseArgs(Argv.begin(), Argv.end(), MissingArgIndex, MissingArgCount,
d249 1
a249 2
  Opts.NoExecStack = Args->hasArg(OPT_mno_exec_stack);
  Opts.FatalWarnings =  Args->hasArg(OPT_massembler_fatal_warnings);
d265 7
a271 6
  std::error_code EC;
  raw_fd_ostream *Out = new raw_fd_ostream(
      Opts.OutputPath, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
  if (EC) {
    Diags.Report(diag::err_fe_unable_to_open_output) << Opts.OutputPath
                                                     << EC.message();
d298 1
a298 1
  SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());
d381 3
a383 2
                                                CE, *STI, Opts.RelaxAll));
    Str.get()->InitSections(Opts.NoExecStack);
d423 2
a424 1
int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
d427 1
a427 1
  PrettyStackTraceProgram X(Argv.size(), Argv.data());
d450 1
a450 1
  if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))
@


1.1.1.6
log
@Import Clang 3.6RC1 r227398.
@
text
@a125 1
  unsigned FatalWarnings : 1;
a140 1
    FatalWarnings = 0;
d144 2
a145 3
  static bool CreateFromArgs(AssemblerInvocation &Res,
                             ArrayRef<const char *> Argv,
                             DiagnosticsEngine &Diags);
d151 2
a152 1
                                         ArrayRef<const char *> Argv,
d162 1
a162 1
      OptTbl->ParseArgs(Argv.begin(), Argv.end(), MissingArgIndex, MissingArgCount,
d249 1
a249 2
  Opts.NoExecStack = Args->hasArg(OPT_mno_exec_stack);
  Opts.FatalWarnings =  Args->hasArg(OPT_massembler_fatal_warnings);
d265 7
a271 6
  std::error_code EC;
  raw_fd_ostream *Out = new raw_fd_ostream(
      Opts.OutputPath, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
  if (EC) {
    Diags.Report(diag::err_fe_unable_to_open_output) << Opts.OutputPath
                                                     << EC.message();
d298 1
a298 1
  SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());
d381 3
a383 2
                                                CE, *STI, Opts.RelaxAll));
    Str.get()->InitSections(Opts.NoExecStack);
d423 2
a424 1
int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
d427 1
a427 1
  PrettyStackTraceProgram X(Argv.size(), Argv.data());
d450 1
a450 1
  if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))
@


1.1.1.7
log
@Import Clang 3.8.0rc3 r261930.
@
text
@a21 1
#include "llvm/ADT/STLExtras.h"
a126 4
  unsigned IncrementalLinkerCompatible : 1;

  /// The name of the relocation model to use.
  std::string RelocationModel;
d143 1
a143 2
    IncrementalLinkerCompatible = 0;
    DwarfVersion = 0;
d163 3
a165 2
  InputArgList Args = OptTbl->ParseArgs(Argv, MissingArgIndex, MissingArgCount,
                                        IncludedFlagsBitmask);
d170 1
a170 1
        << Args.getArgString(MissingArgIndex) << MissingArgCount;
d175 4
a178 2
  for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
    Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
d185 3
a187 3
  Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
  Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
  Opts.Features = Args.getAllArgValues(OPT_target_feature);
d194 15
a208 11
  Opts.IncludePaths = Args.getAllArgValues(OPT_I);
  Opts.NoInitialTextSection = Args.hasArg(OPT_n);
  Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels);
  // Any DebugInfoKind implies GenDwarfForAssembly.
  Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ);
  Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections);
  Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags);
  Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
  Opts.DwarfDebugProducer = Args.getLastArgValue(OPT_dwarf_debug_producer);
  Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
  Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
d211 1
a211 1
  if (Args.hasArg(OPT_INPUT)) {
d213 2
a214 3
    for (arg_iterator it = Args.filtered_begin(OPT_INPUT),
                      ie = Args.filtered_end();
         it != ie; ++it, First = false) {
d219 1
a219 1
        Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
d224 3
a226 3
  Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
  Opts.OutputPath = Args.getLastArgValue(OPT_o);
  if (Arg *A = Args.getLastArg(OPT_filetype)) {
d234 2
a235 1
      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
d240 2
a241 2
  Opts.ShowHelp = Args.hasArg(OPT_help);
  Opts.ShowVersion = Args.hasArg(OPT_version);
d245 3
a247 3
      getLastArgIntValue(Args, OPT_output_asm_variant, 0, Diags);
  Opts.ShowEncoding = Args.hasArg(OPT_show_encoding);
  Opts.ShowInst = Args.hasArg(OPT_show_inst);
d250 3
a252 6
  Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
  Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
  Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
  Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
  Opts.IncrementalLinkerCompatible =
      Args.hasArg(OPT_mincremental_linker_compatible);
d257 3
a259 3
static std::unique_ptr<raw_fd_ostream>
getOutputStream(AssemblerInvocation &Opts, DiagnosticsEngine &Diags,
                bool Binary) {
d269 1
a269 1
  auto Out = llvm::make_unique<raw_fd_ostream>(
d274 1
d278 1
a278 1
  return Out;
d318 3
a320 2
  std::unique_ptr<raw_fd_ostream> FDOS = getOutputStream(Opts, Diags, IsBinary);
  if (!FDOS)
d328 3
a330 14

  llvm::Reloc::Model RM = llvm::Reloc::Default;
  if (Opts.RelocationModel == "static") {
    RM = llvm::Reloc::Static;
  } else if (Opts.RelocationModel == "pic") {
    RM = llvm::Reloc::PIC_;
  } else {
    assert(Opts.RelocationModel == "dynamic-no-pic" &&
           "Invalid PIC model!");
    RM = llvm::Reloc::DynamicNoPIC;
  }

  MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), RM,
                             CodeModel::Default, Ctx);
a358 3
  raw_pwrite_stream *Out = FDOS.get();
  std::unique_ptr<buffer_ostream> BOS;

d361 3
a363 2
    MCInstPrinter *IP = TheTarget->createMCInstPrinter(
        llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI);
d367 1
a367 1
      CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
d370 4
a373 4
    auto FOut = llvm::make_unique<formatted_raw_ostream>(*Out);
    Str.reset(TheTarget->createAsmStreamer(
        Ctx, std::move(FOut), /*asmverbose*/ true,
        /*useDwarfDirectory*/ true, IP, CE, MAB, Opts.ShowInst));
d379 1
a379 6
    if (!FDOS->supportsSeeking()) {
      BOS = make_unique<buffer_ostream>(*FDOS);
      Out = BOS.get();
    }

    MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
d382 2
a383 5
    Triple T(Opts.Triple);
    Str.reset(TheTarget->createMCObjectStreamer(
        T, Ctx, *MAB, *Out, CE, *STI, Opts.RelaxAll,
        Opts.IncrementalLinkerCompatible,
        /*DWARFMustBeAtTheEnd*/ true));
a403 3
  // Close Streamer first.
  // It might have a reference to the output stream.
  Str.reset();
d405 1
a405 2
  BOS.reset();
  FDOS.reset();
d490 1
@


1.1.1.7.2.1
log
@Sync with HEAD
@
text
@a32 1
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
d36 1
d46 1
d49 1
a81 3
  /// The list of symbol definitions.
  std::vector<std::string> SymbolDefs;

a90 1
  unsigned RelaxELFRelocations : 1;
d203 1
a203 2
  Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
  Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);
a254 1
  Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);
d316 1
a316 3
    MAI->setCompressDebugSections(DebugCompressionType::DCT_ZlibGnu);

  MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations);
d329 1
a329 1
  bool PIC = false;
d331 1
a331 1
    PIC = false;
d333 1
a333 1
    PIC = true;
d337 1
a337 1
    PIC = false;
d340 2
a341 1
  MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, CodeModel::Default, Ctx);
d381 1
a381 2
      MCTargetOptions Options;
      MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU, Options);
a397 1
    MCTargetOptions Options;
d399 1
a399 1
                                                      Opts.CPU, Options);
a419 11
  // Set values for symbols, if any.
  for (auto &S : Opts.SymbolDefs) {
    auto Pair = StringRef(S).split('=');
    auto Sym = Pair.first;
    auto Val = Pair.second;
    int64_t Value;
    // We have already error checked this in the driver.
    Val.getAsInteger(0, Value);
    Ctx.setSymbolValue(Parser->getStreamer(), Sym, Value);
  }

d450 5
@


1.1.1.8
log
@Import Clang pre-4.0.0 r291444.
@
text
@a32 1
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
d36 1
d46 1
d49 1
a81 3
  /// The list of symbol definitions.
  std::vector<std::string> SymbolDefs;

a90 1
  unsigned RelaxELFRelocations : 1;
d203 1
a203 2
  Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
  Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);
a254 1
  Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);
d316 1
a316 3
    MAI->setCompressDebugSections(DebugCompressionType::DCT_ZlibGnu);

  MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations);
d329 1
a329 1
  bool PIC = false;
d331 1
a331 1
    PIC = false;
d333 1
a333 1
    PIC = true;
d337 1
a337 1
    PIC = false;
d340 2
a341 1
  MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, CodeModel::Default, Ctx);
d381 1
a381 2
      MCTargetOptions Options;
      MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU, Options);
a397 1
    MCTargetOptions Options;
d399 1
a399 1
                                                      Opts.CPU, Options);
a419 11
  // Set values for symbols, if any.
  for (auto &S : Opts.SymbolDefs) {
    auto Pair = StringRef(S).split('=');
    auto Sym = Pair.first;
    auto Val = Pair.second;
    int64_t Value;
    // We have already error checked this in the driver.
    Val.getAsInteger(0, Value);
    Ctx.setSymbolValue(Parser->getStreamer(), Sym, Value);
  }

d450 5
@


1.1.1.9
log
@Import clang r309604 from branches/release_50
@
text
@d91 1
a96 2
  llvm::DebugCompressionType CompressDebugSections =
      llvm::DebugCompressionType::None;
d204 1
a204 16

  if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections,
                                     OPT_compress_debug_sections_EQ)) {
    if (A->getOption().getID() == OPT_compress_debug_sections) {
      // TODO: be more clever about the compression type auto-detection
      Opts.CompressDebugSections = llvm::DebugCompressionType::GNU;
    } else {
      Opts.CompressDebugSections =
          llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
              .Case("none", llvm::DebugCompressionType::None)
              .Case("zlib", llvm::DebugCompressionType::Z)
              .Case("zlib-gnu", llvm::DebugCompressionType::GNU)
              .Default(llvm::DebugCompressionType::None);
    }
  }

d215 5
a219 2
    for (const Arg *A : Args.filtered(OPT_INPUT)) {
      if (First) {
d221 1
a221 2
        First = false;
      } else {
d319 2
a320 1
  MAI->setCompressDebugSections(Opts.CompressDebugSections);
d511 1
a511 1
    auto Args = llvm::make_unique<const char*[]>(NumArgs + 2);
d516 1
a516 1
    llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
@


1.1.1.9.4.1
log
@Sync with HEAD
@
text
@a31 1
#include "llvm/MC/MCObjectWriter.h"
d64 1
a64 1
/// Helper class for representing a single invocation of the assembler.
a95 1
  std::map<const std::string, const std::string> DebugPrefixMap;
a98 1
  std::string SplitDwarfFile;
d184 1
a184 7
    auto ArgString = A->getAsString(Args);
    std::string Nearest;
    if (OptTbl->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
      Diags.Report(diag::err_drv_unknown_argument) << ArgString;
    else
      Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
          << ArgString << Nearest;
a227 3
  for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
    Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));

a242 1
  Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
d278 5
a282 1
getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
d285 2
a286 2
  if (Path != "-")
    sys::RemoveFileOnSignal(Path);
d290 1
a290 1
      Path, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
d292 2
a293 1
    Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
d338 1
a338 4
  if (Opts.OutputPath.empty())
    Opts.OutputPath = "-";
  std::unique_ptr<raw_fd_ostream> FDOS =
      getOutputStream(Opts.OutputPath, Diags, IsBinary);
a340 3
  std::unique_ptr<raw_fd_ostream> DwoOS;
  if (!Opts.SplitDwarfFile.empty())
    DwoOS = getOutputStream(Opts.SplitDwarfFile, Diags, IsBinary);
d359 1
a359 1
  MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, Ctx);
a369 3
  if (!Opts.DebugPrefixMap.empty())
    for (const auto &KV : Opts.DebugPrefixMap)
      Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
d395 7
a401 8

    std::unique_ptr<MCCodeEmitter> CE;
    if (Opts.ShowEncoding)
      CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
    MCTargetOptions MCOptions;
    std::unique_ptr<MCAsmBackend> MAB(
        TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));

d405 1
a405 2
        /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB),
        Opts.ShowInst));
d416 4
a419 9
    std::unique_ptr<MCCodeEmitter> CE(
        TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
    MCTargetOptions MCOptions;
    std::unique_ptr<MCAsmBackend> MAB(
        TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
    std::unique_ptr<MCObjectWriter> OW =
        DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)
              : MAB->createObjectWriter(*Out);

d422 2
a423 2
        T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
        Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
a427 3
  // Assembly to object compilation should leverage assembly info.
  Str->setUseAssemblerInfoForParsing(true);

d464 2
a465 6
  if (Failed) {
    if (Opts.OutputPath != "-")
      sys::fs::remove(Opts.OutputPath);
    if (!Opts.SplitDwarfFile.empty() && Opts.SplitDwarfFile != "-")
      sys::fs::remove(Opts.SplitDwarfFile);
  }
d507 1
a507 2
                    /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0,
                    /*ShowAllAliases=*/false);
@


1.1.1.9.4.2
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.9.2.1
log
@Sync with HEAD
@
text
@a31 1
#include "llvm/MC/MCObjectWriter.h"
d64 1
a64 1
/// Helper class for representing a single invocation of the assembler.
a95 1
  std::map<const std::string, const std::string> DebugPrefixMap;
a98 1
  std::string SplitDwarfFile;
d184 1
a184 7
    auto ArgString = A->getAsString(Args);
    std::string Nearest;
    if (OptTbl->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
      Diags.Report(diag::err_drv_unknown_argument) << ArgString;
    else
      Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
          << ArgString << Nearest;
a227 3
  for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
    Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));

a242 1
  Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
d278 5
a282 1
getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
d285 2
a286 2
  if (Path != "-")
    sys::RemoveFileOnSignal(Path);
d290 1
a290 1
      Path, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
d292 2
a293 1
    Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
d338 1
a338 4
  if (Opts.OutputPath.empty())
    Opts.OutputPath = "-";
  std::unique_ptr<raw_fd_ostream> FDOS =
      getOutputStream(Opts.OutputPath, Diags, IsBinary);
a340 3
  std::unique_ptr<raw_fd_ostream> DwoOS;
  if (!Opts.SplitDwarfFile.empty())
    DwoOS = getOutputStream(Opts.SplitDwarfFile, Diags, IsBinary);
d359 1
a359 1
  MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, Ctx);
a369 3
  if (!Opts.DebugPrefixMap.empty())
    for (const auto &KV : Opts.DebugPrefixMap)
      Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
d395 7
a401 8

    std::unique_ptr<MCCodeEmitter> CE;
    if (Opts.ShowEncoding)
      CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
    MCTargetOptions MCOptions;
    std::unique_ptr<MCAsmBackend> MAB(
        TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));

d405 1
a405 2
        /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB),
        Opts.ShowInst));
d416 4
a419 9
    std::unique_ptr<MCCodeEmitter> CE(
        TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
    MCTargetOptions MCOptions;
    std::unique_ptr<MCAsmBackend> MAB(
        TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
    std::unique_ptr<MCObjectWriter> OW =
        DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)
              : MAB->createObjectWriter(*Out);

d422 2
a423 2
        T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
        Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
a427 3
  // Assembly to object compilation should leverage assembly info.
  Str->setUseAssemblerInfoForParsing(true);

d464 2
a465 6
  if (Failed) {
    if (Opts.OutputPath != "-")
      sys::fs::remove(Opts.OutputPath);
    if (!Opts.SplitDwarfFile.empty() && Opts.SplitDwarfFile != "-")
      sys::fs::remove(Opts.SplitDwarfFile);
  }
d507 1
a507 2
                    /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0,
                    /*ShowAllAliases=*/false);
@


1.1.1.10
log
@Import clang r337282 from trunk
@
text
@a31 1
#include "llvm/MC/MCObjectWriter.h"
d64 1
a64 1
/// Helper class for representing a single invocation of the assembler.
a95 1
  std::map<const std::string, const std::string> DebugPrefixMap;
a98 1
  std::string SplitDwarfFile;
d184 1
a184 7
    auto ArgString = A->getAsString(Args);
    std::string Nearest;
    if (OptTbl->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
      Diags.Report(diag::err_drv_unknown_argument) << ArgString;
    else
      Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
          << ArgString << Nearest;
a227 3
  for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
    Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));

a242 1
  Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
d278 5
a282 1
getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
d285 2
a286 2
  if (Path != "-")
    sys::RemoveFileOnSignal(Path);
d290 1
a290 1
      Path, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
d292 2
a293 1
    Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
d338 1
a338 4
  if (Opts.OutputPath.empty())
    Opts.OutputPath = "-";
  std::unique_ptr<raw_fd_ostream> FDOS =
      getOutputStream(Opts.OutputPath, Diags, IsBinary);
a340 3
  std::unique_ptr<raw_fd_ostream> DwoOS;
  if (!Opts.SplitDwarfFile.empty())
    DwoOS = getOutputStream(Opts.SplitDwarfFile, Diags, IsBinary);
d359 1
a359 1
  MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, Ctx);
a369 3
  if (!Opts.DebugPrefixMap.empty())
    for (const auto &KV : Opts.DebugPrefixMap)
      Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
d395 7
a401 8

    std::unique_ptr<MCCodeEmitter> CE;
    if (Opts.ShowEncoding)
      CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
    MCTargetOptions MCOptions;
    std::unique_ptr<MCAsmBackend> MAB(
        TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));

d405 1
a405 2
        /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB),
        Opts.ShowInst));
d416 4
a419 9
    std::unique_ptr<MCCodeEmitter> CE(
        TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
    MCTargetOptions MCOptions;
    std::unique_ptr<MCAsmBackend> MAB(
        TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
    std::unique_ptr<MCObjectWriter> OW =
        DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)
              : MAB->createObjectWriter(*Out);

d422 2
a423 2
        T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
        Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
a427 3
  // Assembly to object compilation should leverage assembly info.
  Str->setUseAssemblerInfoForParsing(true);

d464 2
a465 6
  if (Failed) {
    if (Opts.OutputPath != "-")
      sys::fs::remove(Opts.OutputPath);
    if (!Opts.SplitDwarfFile.empty() && Opts.SplitDwarfFile != "-")
      sys::fs::remove(Opts.SplitDwarfFile);
  }
d507 1
a507 2
                    /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0,
                    /*ShowAllAliases=*/false);
@


1.1.1.11
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.5.4.1
log
@file cc1as_main.cpp was added on branch tls-maxphys on 2014-08-19 23:49:27 +0000
@
text
@d1 490
@


1.1.1.5.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 490
//===-- cc1as_main.cpp - Clang Assembler  ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the entry point to the clang -cc1as functionality, which implements
// the direct interface to the LLVM MC based assembler.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
#include <system_error>
using namespace clang;
using namespace clang::driver;
using namespace clang::driver::options;
using namespace llvm;
using namespace llvm::opt;

namespace {

/// \brief Helper class for representing a single invocation of the assembler.
struct AssemblerInvocation {
  /// @@name Target Options
  /// @@{

  /// The name of the target triple to assemble for.
  std::string Triple;

  /// If given, the name of the target CPU to determine which instructions
  /// are legal.
  std::string CPU;

  /// The list of target specific features to enable or disable -- this should
  /// be a list of strings starting with '+' or '-'.
  std::vector<std::string> Features;

  /// @@}
  /// @@name Language Options
  /// @@{

  std::vector<std::string> IncludePaths;
  unsigned NoInitialTextSection : 1;
  unsigned SaveTemporaryLabels : 1;
  unsigned GenDwarfForAssembly : 1;
  unsigned CompressDebugSections : 1;
  unsigned DwarfVersion;
  std::string DwarfDebugFlags;
  std::string DwarfDebugProducer;
  std::string DebugCompilationDir;
  std::string MainFileName;

  /// @@}
  /// @@name Frontend Options
  /// @@{

  std::string InputFile;
  std::vector<std::string> LLVMArgs;
  std::string OutputPath;
  enum FileType {
    FT_Asm,  ///< Assembly (.s) output, transliterate mode.
    FT_Null, ///< No output, for timing purposes.
    FT_Obj   ///< Object file output.
  };
  FileType OutputType;
  unsigned ShowHelp : 1;
  unsigned ShowVersion : 1;

  /// @@}
  /// @@name Transliterate Options
  /// @@{

  unsigned OutputAsmVariant;
  unsigned ShowEncoding : 1;
  unsigned ShowInst : 1;

  /// @@}
  /// @@name Assembler Options
  /// @@{

  unsigned RelaxAll : 1;
  unsigned NoExecStack : 1;

  /// @@}

public:
  AssemblerInvocation() {
    Triple = "";
    NoInitialTextSection = 0;
    InputFile = "-";
    OutputPath = "-";
    OutputType = FT_Asm;
    OutputAsmVariant = 0;
    ShowInst = 0;
    ShowEncoding = 0;
    RelaxAll = 0;
    NoExecStack = 0;
    DwarfVersion = 3;
  }

  static bool CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin,
                             const char **ArgEnd, DiagnosticsEngine &Diags);
};

}

bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
                                         const char **ArgBegin,
                                         const char **ArgEnd,
                                         DiagnosticsEngine &Diags) {
  bool Success = true;

  // Parse the arguments.
  std::unique_ptr<OptTable> OptTbl(createDriverOptTable());

  const unsigned IncludedFlagsBitmask = options::CC1AsOption;
  unsigned MissingArgIndex, MissingArgCount;
  std::unique_ptr<InputArgList> Args(
      OptTbl->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount,
                        IncludedFlagsBitmask));

  // Check for missing argument error.
  if (MissingArgCount) {
    Diags.Report(diag::err_drv_missing_argument)
        << Args->getArgString(MissingArgIndex) << MissingArgCount;
    Success = false;
  }

  // Issue errors on unknown arguments.
  for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
                    ie = Args->filtered_end();
       it != ie; ++it) {
    Diags.Report(diag::err_drv_unknown_argument) << (*it)->getAsString(*Args);
    Success = false;
  }

  // Construct the invocation.

  // Target Options
  Opts.Triple = llvm::Triple::normalize(Args->getLastArgValue(OPT_triple));
  Opts.CPU = Args->getLastArgValue(OPT_target_cpu);
  Opts.Features = Args->getAllArgValues(OPT_target_feature);

  // Use the default target triple if unspecified.
  if (Opts.Triple.empty())
    Opts.Triple = llvm::sys::getDefaultTargetTriple();

  // Language Options
  Opts.IncludePaths = Args->getAllArgValues(OPT_I);
  Opts.NoInitialTextSection = Args->hasArg(OPT_n);
  Opts.SaveTemporaryLabels = Args->hasArg(OPT_msave_temp_labels);
  Opts.GenDwarfForAssembly = Args->hasArg(OPT_g_Flag);
  Opts.CompressDebugSections = Args->hasArg(OPT_compress_debug_sections);
  if (Args->hasArg(OPT_gdwarf_2))
    Opts.DwarfVersion = 2;
  if (Args->hasArg(OPT_gdwarf_3))
    Opts.DwarfVersion = 3;
  if (Args->hasArg(OPT_gdwarf_4))
    Opts.DwarfVersion = 4;
  Opts.DwarfDebugFlags = Args->getLastArgValue(OPT_dwarf_debug_flags);
  Opts.DwarfDebugProducer = Args->getLastArgValue(OPT_dwarf_debug_producer);
  Opts.DebugCompilationDir = Args->getLastArgValue(OPT_fdebug_compilation_dir);
  Opts.MainFileName = Args->getLastArgValue(OPT_main_file_name);

  // Frontend Options
  if (Args->hasArg(OPT_INPUT)) {
    bool First = true;
    for (arg_iterator it = Args->filtered_begin(OPT_INPUT),
           ie = Args->filtered_end(); it != ie; ++it, First=false) {
      const Arg *A = it;
      if (First)
        Opts.InputFile = A->getValue();
      else {
        Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(*Args);
        Success = false;
      }
    }
  }
  Opts.LLVMArgs = Args->getAllArgValues(OPT_mllvm);
  Opts.OutputPath = Args->getLastArgValue(OPT_o);
  if (Arg *A = Args->getLastArg(OPT_filetype)) {
    StringRef Name = A->getValue();
    unsigned OutputType = StringSwitch<unsigned>(Name)
      .Case("asm", FT_Asm)
      .Case("null", FT_Null)
      .Case("obj", FT_Obj)
      .Default(~0U);
    if (OutputType == ~0U) {
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(*Args) << Name;
      Success = false;
    } else
      Opts.OutputType = FileType(OutputType);
  }
  Opts.ShowHelp = Args->hasArg(OPT_help);
  Opts.ShowVersion = Args->hasArg(OPT_version);

  // Transliterate Options
  Opts.OutputAsmVariant =
      getLastArgIntValue(*Args.get(), OPT_output_asm_variant, 0, Diags);
  Opts.ShowEncoding = Args->hasArg(OPT_show_encoding);
  Opts.ShowInst = Args->hasArg(OPT_show_inst);

  // Assemble Options
  Opts.RelaxAll = Args->hasArg(OPT_mrelax_all);
  Opts.NoExecStack =  Args->hasArg(OPT_mno_exec_stack);

  return Success;
}

static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts,
                                              DiagnosticsEngine &Diags,
                                              bool Binary) {
  if (Opts.OutputPath.empty())
    Opts.OutputPath = "-";

  // Make sure that the Out file gets unlinked from the disk if we get a
  // SIGINT.
  if (Opts.OutputPath != "-")
    sys::RemoveFileOnSignal(Opts.OutputPath);

  std::string Error;
  raw_fd_ostream *Out =
      new raw_fd_ostream(Opts.OutputPath.c_str(), Error,
                         (Binary ? sys::fs::F_None : sys::fs::F_Text));
  if (!Error.empty()) {
    Diags.Report(diag::err_fe_unable_to_open_output)
      << Opts.OutputPath << Error;
    delete Out;
    return nullptr;
  }

  return new formatted_raw_ostream(*Out, formatted_raw_ostream::DELETE_STREAM);
}

static bool ExecuteAssembler(AssemblerInvocation &Opts,
                             DiagnosticsEngine &Diags) {
  // Get the target specific parser.
  std::string Error;
  const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);
  if (!TheTarget)
    return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;

  ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
      MemoryBuffer::getFileOrSTDIN(Opts.InputFile);

  if (std::error_code EC = Buffer.getError()) {
    Error = EC.message();
    return Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
  }

  SourceMgr SrcMgr;

  // Tell SrcMgr about this buffer, which is what the parser will pick up.
  SrcMgr.AddNewSourceBuffer(Buffer->release(), SMLoc());

  // Record the location of the include directories so that the lexer can find
  // it later.
  SrcMgr.setIncludeDirs(Opts.IncludePaths);

  std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
  assert(MRI && "Unable to create target register info!");

  std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple));
  assert(MAI && "Unable to create target asm info!");

  // Ensure MCAsmInfo initialization occurs before any use, otherwise sections
  // may be created with a combination of default and explicit settings.
  if (Opts.CompressDebugSections)
    MAI->setCompressDebugSections(true);

  bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
  std::unique_ptr<formatted_raw_ostream> Out(
      GetOutputStream(Opts, Diags, IsBinary));
  if (!Out)
    return true;

  // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
  // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
  std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());

  MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
  // FIXME: Assembler behavior can change with -static.
  MOFI->InitMCObjectFileInfo(Opts.Triple,
                             Reloc::Default, CodeModel::Default, Ctx);
  if (Opts.SaveTemporaryLabels)
    Ctx.setAllowTemporaryLabels(false);
  if (Opts.GenDwarfForAssembly)
    Ctx.setGenDwarfForAssembly(true);
  if (!Opts.DwarfDebugFlags.empty())
    Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags));
  if (!Opts.DwarfDebugProducer.empty())
    Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));
  if (!Opts.DebugCompilationDir.empty())
    Ctx.setCompilationDir(Opts.DebugCompilationDir);
  if (!Opts.MainFileName.empty())
    Ctx.setMainFileName(StringRef(Opts.MainFileName));
  Ctx.setDwarfVersion(Opts.DwarfVersion);

  // Build up the feature string from the target feature list.
  std::string FS;
  if (!Opts.Features.empty()) {
    FS = Opts.Features[0];
    for (unsigned i = 1, e = Opts.Features.size(); i != e; ++i)
      FS += "," + Opts.Features[i];
  }

  std::unique_ptr<MCStreamer> Str;

  std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
  std::unique_ptr<MCSubtargetInfo> STI(
      TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));

  // FIXME: There is a bit of code duplication with addPassesToEmitFile.
  if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
    MCInstPrinter *IP =
      TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI, *MCII, *MRI,
                                     *STI);
    MCCodeEmitter *CE = nullptr;
    MCAsmBackend *MAB = nullptr;
    if (Opts.ShowEncoding) {
      CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
      MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU);
    }
    Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true,
                                           /*useDwarfDirectory*/ true,
                                           IP, CE, MAB,
                                           Opts.ShowInst));
  } else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
    Str.reset(createNullStreamer(Ctx));
  } else {
    assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
           "Invalid file type!");
    MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
    MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,
                                                      Opts.CPU);
    Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out,
                                                CE, *STI, Opts.RelaxAll,
                                                Opts.NoExecStack));
    Str.get()->InitSections();
  }

  bool Failed = false;

  std::unique_ptr<MCAsmParser> Parser(
      createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));

  // FIXME: init MCTargetOptions from sanitizer flags here.
  MCTargetOptions Options;
  std::unique_ptr<MCTargetAsmParser> TAP(
      TheTarget->createMCAsmParser(*STI, *Parser, *MCII, Options));
  if (!TAP)
    Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;

  if (!Failed) {
    Parser->setTargetParser(*TAP.get());
    Failed = Parser->Run(Opts.NoInitialTextSection);
  }

  // Close the output stream early.
  Out.reset();

  // Delete output file if there were errors.
  if (Failed && Opts.OutputPath != "-")
    sys::fs::remove(Opts.OutputPath);

  return Failed;
}

static void LLVMErrorHandler(void *UserData, const std::string &Message,
                             bool GenCrashDiag) {
  DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);

  Diags.Report(diag::err_fe_error_backend) << Message;

  // We cannot recover from llvm errors.
  exit(1);
}

int cc1as_main(const char **ArgBegin, const char **ArgEnd,
               const char *Argv0, void *MainAddr) {
  // Print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(ArgEnd - ArgBegin, ArgBegin);
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.

  // Initialize targets and assembly printers/parsers.
  InitializeAllTargetInfos();
  InitializeAllTargetMCs();
  InitializeAllAsmParsers();

  // Construct our diagnostic client.
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  TextDiagnosticPrinter *DiagClient
    = new TextDiagnosticPrinter(errs(), &*DiagOpts);
  DiagClient->setPrefix("clang -cc1as");
  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);

  // Set an error handler, so that any LLVM backend diagnostics go through our
  // error handler.
  ScopedFatalErrorHandler FatalErrorHandler
    (LLVMErrorHandler, static_cast<void*>(&Diags));

  // Parse the arguments.
  AssemblerInvocation Asm;
  if (!AssemblerInvocation::CreateFromArgs(Asm, ArgBegin, ArgEnd, Diags))
    return 1;

  if (Asm.ShowHelp) {
    std::unique_ptr<OptTable> Opts(driver::createDriverOptTable());
    Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler",
                    /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0);
    return 0;
  }

  // Honor -version.
  //
  // FIXME: Use a better -version message?
  if (Asm.ShowVersion) {
    llvm::cl::PrintVersionMessage();
    return 0;
  }

  // Honor -mllvm.
  //
  // FIXME: Remove this, one day.
  if (!Asm.LLVMArgs.empty()) {
    unsigned NumArgs = Asm.LLVMArgs.size();
    const char **Args = new const char*[NumArgs + 2];
    Args[0] = "clang (LLVM option parsing)";
    for (unsigned i = 0; i != NumArgs; ++i)
      Args[i + 1] = Asm.LLVMArgs[i].c_str();
    Args[NumArgs + 1] = nullptr;
    llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args);
  }

  // Execute the invocation, unless there were parsing errors.
  bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);

  // If any timers were active but haven't been destroyed yet, print their
  // results now.
  TimerGroup::printAll(errs());

  return !!Failed;
}

@


1.1.1.3.4.1
log
@file cc1as_main.cpp was added on branch yamt-pagecache on 2014-05-22 16:19:47 +0000
@
text
@d1 466
@


1.1.1.3.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 466
//===-- cc1as_main.cpp - Clang Assembler  ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the entry point to the clang -cc1as functionality, which implements
// the direct interface to the LLVM MC based assembler.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/CC1AsOptions.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
using namespace clang;
using namespace clang::driver;
using namespace llvm;
using namespace llvm::opt;

namespace {

/// \brief Helper class for representing a single invocation of the assembler.
struct AssemblerInvocation {
  /// @@name Target Options
  /// @@{

  /// The name of the target triple to assemble for.
  std::string Triple;

  /// If given, the name of the target CPU to determine which instructions
  /// are legal.
  std::string CPU;

  /// The list of target specific features to enable or disable -- this should
  /// be a list of strings starting with '+' or '-'.
  std::vector<std::string> Features;

  /// @@}
  /// @@name Language Options
  /// @@{

  std::vector<std::string> IncludePaths;
  unsigned NoInitialTextSection : 1;
  unsigned SaveTemporaryLabels : 1;
  unsigned GenDwarfForAssembly : 1;
  std::string DwarfDebugFlags;
  std::string DwarfDebugProducer;
  std::string DebugCompilationDir;
  std::string MainFileName;

  /// @@}
  /// @@name Frontend Options
  /// @@{

  std::string InputFile;
  std::vector<std::string> LLVMArgs;
  std::string OutputPath;
  enum FileType {
    FT_Asm,  ///< Assembly (.s) output, transliterate mode.
    FT_Null, ///< No output, for timing purposes.
    FT_Obj   ///< Object file output.
  };
  FileType OutputType;
  unsigned ShowHelp : 1;
  unsigned ShowVersion : 1;

  /// @@}
  /// @@name Transliterate Options
  /// @@{

  unsigned OutputAsmVariant;
  unsigned ShowEncoding : 1;
  unsigned ShowInst : 1;

  /// @@}
  /// @@name Assembler Options
  /// @@{

  unsigned RelaxAll : 1;
  unsigned NoExecStack : 1;

  /// @@}

public:
  AssemblerInvocation() {
    Triple = "";
    NoInitialTextSection = 0;
    InputFile = "-";
    OutputPath = "-";
    OutputType = FT_Asm;
    OutputAsmVariant = 0;
    ShowInst = 0;
    ShowEncoding = 0;
    RelaxAll = 0;
    NoExecStack = 0;
  }

  static bool CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin,
                             const char **ArgEnd, DiagnosticsEngine &Diags);
};

}

bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
                                         const char **ArgBegin,
                                         const char **ArgEnd,
                                         DiagnosticsEngine &Diags) {
  using namespace clang::driver::cc1asoptions;
  bool Success = true;

  // Parse the arguments.
  OwningPtr<OptTable> OptTbl(createCC1AsOptTable());
  unsigned MissingArgIndex, MissingArgCount;
  OwningPtr<InputArgList> Args(
    OptTbl->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));

  // Check for missing argument error.
  if (MissingArgCount) {
    Diags.Report(diag::err_drv_missing_argument)
      << Args->getArgString(MissingArgIndex) << MissingArgCount;
    Success = false;
  }

  // Issue errors on unknown arguments.
  for (arg_iterator it = Args->filtered_begin(cc1asoptions::OPT_UNKNOWN),
         ie = Args->filtered_end(); it != ie; ++it) {
    Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args);
    Success = false;
  }

  // Construct the invocation.

  // Target Options
  Opts.Triple = llvm::Triple::normalize(Args->getLastArgValue(OPT_triple));
  Opts.CPU = Args->getLastArgValue(OPT_target_cpu);
  Opts.Features = Args->getAllArgValues(OPT_target_feature);

  // Use the default target triple if unspecified.
  if (Opts.Triple.empty())
    Opts.Triple = llvm::sys::getDefaultTargetTriple();

  // Language Options
  Opts.IncludePaths = Args->getAllArgValues(OPT_I);
  Opts.NoInitialTextSection = Args->hasArg(OPT_n);
  Opts.SaveTemporaryLabels = Args->hasArg(OPT_msave_temp_labels);
  Opts.GenDwarfForAssembly = Args->hasArg(OPT_g);
  Opts.DwarfDebugFlags = Args->getLastArgValue(OPT_dwarf_debug_flags);
  Opts.DwarfDebugProducer = Args->getLastArgValue(OPT_dwarf_debug_producer);
  Opts.DebugCompilationDir = Args->getLastArgValue(OPT_fdebug_compilation_dir);
  Opts.MainFileName = Args->getLastArgValue(OPT_main_file_name);

  // Frontend Options
  if (Args->hasArg(OPT_INPUT)) {
    bool First = true;
    for (arg_iterator it = Args->filtered_begin(OPT_INPUT),
           ie = Args->filtered_end(); it != ie; ++it, First=false) {
      const Arg *A = it;
      if (First)
        Opts.InputFile = A->getValue();
      else {
        Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(*Args);
        Success = false;
      }
    }
  }
  Opts.LLVMArgs = Args->getAllArgValues(OPT_mllvm);
  Opts.OutputPath = Args->getLastArgValue(OPT_o);
  if (Arg *A = Args->getLastArg(OPT_filetype)) {
    StringRef Name = A->getValue();
    unsigned OutputType = StringSwitch<unsigned>(Name)
      .Case("asm", FT_Asm)
      .Case("null", FT_Null)
      .Case("obj", FT_Obj)
      .Default(~0U);
    if (OutputType == ~0U) {
      Diags.Report(diag::err_drv_invalid_value)
        << A->getAsString(*Args) << Name;
      Success = false;
    } else
      Opts.OutputType = FileType(OutputType);
  }
  Opts.ShowHelp = Args->hasArg(OPT_help);
  Opts.ShowVersion = Args->hasArg(OPT_version);

  // Transliterate Options
  Opts.OutputAsmVariant =
      getLastArgIntValue(*Args.get(), OPT_output_asm_variant, 0, Diags);
  Opts.ShowEncoding = Args->hasArg(OPT_show_encoding);
  Opts.ShowInst = Args->hasArg(OPT_show_inst);

  // Assemble Options
  Opts.RelaxAll = Args->hasArg(OPT_mrelax_all);
  Opts.NoExecStack =  Args->hasArg(OPT_mno_exec_stack);

  return Success;
}

static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts,
                                              DiagnosticsEngine &Diags,
                                              bool Binary) {
  if (Opts.OutputPath.empty())
    Opts.OutputPath = "-";

  // Make sure that the Out file gets unlinked from the disk if we get a
  // SIGINT.
  if (Opts.OutputPath != "-")
    sys::RemoveFileOnSignal(Opts.OutputPath);

  std::string Error;
  raw_fd_ostream *Out =
      new raw_fd_ostream(Opts.OutputPath.c_str(), Error,
                         (Binary ? sys::fs::F_None : sys::fs::F_Text));
  if (!Error.empty()) {
    Diags.Report(diag::err_fe_unable_to_open_output)
      << Opts.OutputPath << Error;
    return 0;
  }

  return new formatted_raw_ostream(*Out, formatted_raw_ostream::DELETE_STREAM);
}

static bool ExecuteAssembler(AssemblerInvocation &Opts,
                             DiagnosticsEngine &Diags) {
  // Get the target specific parser.
  std::string Error;
  const Target *TheTarget(TargetRegistry::lookupTarget(Opts.Triple, Error));
  if (!TheTarget) {
    Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
    return false;
  }

  OwningPtr<MemoryBuffer> BufferPtr;
  if (error_code ec = MemoryBuffer::getFileOrSTDIN(Opts.InputFile, BufferPtr)) {
    Error = ec.message();
    Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
    return false;
  }
  MemoryBuffer *Buffer = BufferPtr.take();

  SourceMgr SrcMgr;

  // 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
  // it later.
  SrcMgr.setIncludeDirs(Opts.IncludePaths);

  OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
  assert(MRI && "Unable to create target register info!");

  OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple));
  assert(MAI && "Unable to create target asm info!");

  bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
  formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary);
  if (!Out)
    return false;

  // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
  // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
  OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
  MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
  // FIXME: Assembler behavior can change with -static.
  MOFI->InitMCObjectFileInfo(Opts.Triple,
                             Reloc::Default, CodeModel::Default, Ctx);
  if (Opts.SaveTemporaryLabels)
    Ctx.setAllowTemporaryLabels(false);
  if (Opts.GenDwarfForAssembly)
    Ctx.setGenDwarfForAssembly(true);
  if (!Opts.DwarfDebugFlags.empty())
    Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags));
  if (!Opts.DwarfDebugProducer.empty())
    Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));
  if (!Opts.DebugCompilationDir.empty())
    Ctx.setCompilationDir(Opts.DebugCompilationDir);
  if (!Opts.MainFileName.empty())
    Ctx.setMainFileName(StringRef(Opts.MainFileName));

  // Build up the feature string from the target feature list.
  std::string FS;
  if (!Opts.Features.empty()) {
    FS = Opts.Features[0];
    for (unsigned i = 1, e = Opts.Features.size(); i != e; ++i)
      FS += "," + Opts.Features[i];
  }

  OwningPtr<MCStreamer> Str;

  OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
  OwningPtr<MCSubtargetInfo>
    STI(TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));

  // FIXME: There is a bit of code duplication with addPassesToEmitFile.
  if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
    MCInstPrinter *IP =
      TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI, *MCII, *MRI,
                                     *STI);
    MCCodeEmitter *CE = 0;
    MCAsmBackend *MAB = 0;
    if (Opts.ShowEncoding) {
      CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
      MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU);
    }
    Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true,
                                           /*useCFI*/ true,
                                           /*useDwarfDirectory*/ true,
                                           IP, CE, MAB,
                                           Opts.ShowInst));
  } else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
    Str.reset(createNullStreamer(Ctx));
  } else {
    assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
           "Invalid file type!");
    MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
    MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,
                                                      Opts.CPU);
    Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out,
                                                CE, *STI, Opts.RelaxAll,
                                                Opts.NoExecStack));
    Str.get()->InitSections();
  }

  OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx,
                                                  *Str.get(), *MAI));
  OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser, *MCII));
  if (!TAP) {
    Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
    return false;
  }

  Parser->setTargetParser(*TAP.get());

  bool Success = !Parser->Run(Opts.NoInitialTextSection);

  // Close the output.
  delete Out;

  // Delete output on errors.
  if (!Success && Opts.OutputPath != "-")
    sys::fs::remove(Opts.OutputPath);

  return Success;
}

static void LLVMErrorHandler(void *UserData, const std::string &Message,
                             bool GenCrashDiag) {
  DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);

  Diags.Report(diag::err_fe_error_backend) << Message;

  // We cannot recover from llvm errors.
  exit(1);
}

int cc1as_main(const char **ArgBegin, const char **ArgEnd,
               const char *Argv0, void *MainAddr) {
  // Print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(ArgEnd - ArgBegin, ArgBegin);
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.

  // Initialize targets and assembly printers/parsers.
  InitializeAllTargetInfos();
  InitializeAllTargetMCs();
  InitializeAllAsmParsers();

  // Construct our diagnostic client.
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  TextDiagnosticPrinter *DiagClient
    = new TextDiagnosticPrinter(errs(), &*DiagOpts);
  DiagClient->setPrefix("clang -cc1as");
  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);

  // Set an error handler, so that any LLVM backend diagnostics go through our
  // error handler.
  ScopedFatalErrorHandler FatalErrorHandler
    (LLVMErrorHandler, static_cast<void*>(&Diags));

  // Parse the arguments.
  AssemblerInvocation Asm;
  if (!AssemblerInvocation::CreateFromArgs(Asm, ArgBegin, ArgEnd, Diags))
    return 1;

  // Honor -help.
  if (Asm.ShowHelp) {
    OwningPtr<OptTable> Opts(driver::createCC1AsOptTable());
    Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler");
    return 0;
  }

  // Honor -version.
  //
  // FIXME: Use a better -version message?
  if (Asm.ShowVersion) {
    llvm::cl::PrintVersionMessage();
    return 0;
  }

  // Honor -mllvm.
  //
  // FIXME: Remove this, one day.
  if (!Asm.LLVMArgs.empty()) {
    unsigned NumArgs = Asm.LLVMArgs.size();
    const char **Args = new const char*[NumArgs + 2];
    Args[0] = "clang (LLVM option parsing)";
    for (unsigned i = 0; i != NumArgs; ++i)
      Args[i + 1] = Asm.LLVMArgs[i].c_str();
    Args[NumArgs + 1] = 0;
    llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args);
  }

  // Execute the invocation, unless there were parsing errors.
  bool Success = false;
  if (!Diags.hasErrorOccurred())
    Success = ExecuteAssembler(Asm, Diags);

  // If any timers were active but haven't been destroyed yet, print their
  // results now.
  TimerGroup::printAll(errs());

  return !Success;
}
@


