2010-05-21 01:49:16 +08:00
|
|
|
//===-- cc1as_main.cpp - Clang Assembler ---------------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2010-05-21 01:49:16 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// 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"
|
2012-12-04 17:25:21 +08:00
|
|
|
#include "clang/Basic/DiagnosticOptions.h"
|
|
|
|
#include "clang/Driver/DriverDiagnostic.h"
|
2010-05-21 01:49:16 +08:00
|
|
|
#include "clang/Driver/Options.h"
|
|
|
|
#include "clang/Frontend/FrontendDiagnostic.h"
|
|
|
|
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
2013-06-15 01:17:23 +08:00
|
|
|
#include "clang/Frontend/Utils.h"
|
2015-04-10 05:06:11 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2010-05-21 01:49:16 +08:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2010-08-30 17:42:39 +08:00
|
|
|
#include "llvm/ADT/Triple.h"
|
2013-01-02 19:45:17 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
2012-12-04 17:25:21 +08:00
|
|
|
#include "llvm/MC/MCAsmBackend.h"
|
2010-07-17 10:26:21 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2010-05-21 01:49:16 +08:00
|
|
|
#include "llvm/MC/MCCodeEmitter.h"
|
|
|
|
#include "llvm/MC/MCContext.h"
|
2011-07-11 12:24:19 +08:00
|
|
|
#include "llvm/MC/MCInstrInfo.h"
|
2011-07-20 14:22:27 +08:00
|
|
|
#include "llvm/MC/MCObjectFileInfo.h"
|
2018-05-19 02:26:45 +08:00
|
|
|
#include "llvm/MC/MCObjectWriter.h"
|
2012-12-04 17:25:21 +08:00
|
|
|
#include "llvm/MC/MCParser/MCAsmParser.h"
|
2016-01-27 18:01:30 +08:00
|
|
|
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
|
2011-07-19 04:57:51 +08:00
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
2018-12-13 01:30:16 +08:00
|
|
|
#include "llvm/MC/MCSectionMachO.h"
|
2010-05-21 01:49:16 +08:00
|
|
|
#include "llvm/MC/MCStreamer.h"
|
2011-07-09 14:04:17 +08:00
|
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
2014-04-23 19:15:49 +08:00
|
|
|
#include "llvm/MC/MCTargetOptions.h"
|
2013-06-15 01:17:23 +08:00
|
|
|
#include "llvm/Option/Arg.h"
|
|
|
|
#include "llvm/Option/ArgList.h"
|
|
|
|
#include "llvm/Option/OptTable.h"
|
2010-05-21 02:15:20 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2010-05-21 01:49:16 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2013-06-26 20:48:34 +08:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2012-12-04 17:25:21 +08:00
|
|
|
#include "llvm/Support/FormattedStream.h"
|
|
|
|
#include "llvm/Support/Host.h"
|
2010-05-21 01:49:16 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2010-11-30 02:12:39 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
|
|
|
#include "llvm/Support/Signals.h"
|
2012-12-04 17:25:21 +08:00
|
|
|
#include "llvm/Support/SourceMgr.h"
|
2011-08-25 02:09:14 +08:00
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
|
|
#include "llvm/Support/TargetSelect.h"
|
|
|
|
#include "llvm/Support/Timer.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2014-03-09 19:36:40 +08:00
|
|
|
#include <memory>
|
2014-06-13 01:19:42 +08:00
|
|
|
#include <system_error>
|
2010-05-21 01:49:16 +08:00
|
|
|
using namespace clang;
|
|
|
|
using namespace clang::driver;
|
2014-07-09 22:05:11 +08:00
|
|
|
using namespace clang::driver::options;
|
2010-05-21 01:49:16 +08:00
|
|
|
using namespace llvm;
|
2013-06-15 01:17:23 +08:00
|
|
|
using namespace llvm::opt;
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Helper class for representing a single invocation of the assembler.
|
2010-05-21 01:49:16 +08:00
|
|
|
struct AssemblerInvocation {
|
|
|
|
/// @name Target Options
|
|
|
|
/// @{
|
|
|
|
|
2012-02-11 04:37:10 +08:00
|
|
|
/// The name of the target triple to assemble for.
|
2010-05-21 01:49:16 +08:00
|
|
|
std::string Triple;
|
|
|
|
|
2012-02-11 04:37:10 +08:00
|
|
|
/// 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;
|
|
|
|
|
2016-12-02 02:42:16 +08:00
|
|
|
/// The list of symbol definitions.
|
|
|
|
std::vector<std::string> SymbolDefs;
|
|
|
|
|
2010-05-21 01:49:16 +08:00
|
|
|
/// @}
|
|
|
|
/// @name Language Options
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
std::vector<std::string> IncludePaths;
|
|
|
|
unsigned NoInitialTextSection : 1;
|
2011-03-29 06:49:24 +08:00
|
|
|
unsigned SaveTemporaryLabels : 1;
|
2011-12-23 03:31:58 +08:00
|
|
|
unsigned GenDwarfForAssembly : 1;
|
2016-05-29 10:01:14 +08:00
|
|
|
unsigned RelaxELFRelocations : 1;
|
2014-05-19 21:39:13 +08:00
|
|
|
unsigned DwarfVersion;
|
2011-12-23 03:31:58 +08:00
|
|
|
std::string DwarfDebugFlags;
|
2013-01-18 05:38:06 +08:00
|
|
|
std::string DwarfDebugProducer;
|
2012-12-18 05:40:04 +08:00
|
|
|
std::string DebugCompilationDir;
|
2018-07-10 23:15:24 +08:00
|
|
|
std::map<const std::string, const std::string> DebugPrefixMap;
|
2017-06-09 08:40:30 +08:00
|
|
|
llvm::DebugCompressionType CompressDebugSections =
|
|
|
|
llvm::DebugCompressionType::None;
|
2012-12-18 08:31:10 +08:00
|
|
|
std::string MainFileName;
|
2018-05-23 02:52:37 +08:00
|
|
|
std::string SplitDwarfFile;
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
/// @}
|
|
|
|
/// @name Frontend Options
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
std::string InputFile;
|
2010-05-21 02:15:20 +08:00
|
|
|
std::vector<std::string> LLVMArgs;
|
2010-05-21 01:49:16 +08:00
|
|
|
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;
|
2010-05-21 02:15:20 +08:00
|
|
|
unsigned ShowHelp : 1;
|
|
|
|
unsigned ShowVersion : 1;
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
/// @}
|
|
|
|
/// @name Transliterate Options
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
unsigned OutputAsmVariant;
|
|
|
|
unsigned ShowEncoding : 1;
|
|
|
|
unsigned ShowInst : 1;
|
|
|
|
|
|
|
|
/// @}
|
|
|
|
/// @name Assembler Options
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
unsigned RelaxAll : 1;
|
2011-01-24 01:58:26 +08:00
|
|
|
unsigned NoExecStack : 1;
|
2014-08-27 02:40:25 +08:00
|
|
|
unsigned FatalWarnings : 1;
|
2015-12-22 06:09:34 +08:00
|
|
|
unsigned IncrementalLinkerCompatible : 1;
|
2018-12-13 01:30:16 +08:00
|
|
|
unsigned EmbedBitcode : 1;
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2015-09-18 19:13:43 +08:00
|
|
|
/// The name of the relocation model to use.
|
|
|
|
std::string RelocationModel;
|
|
|
|
|
2019-03-26 16:01:18 +08:00
|
|
|
/// The ABI targeted by the backend. Specified using -target-abi. Empty
|
|
|
|
/// otherwise.
|
|
|
|
std::string TargetABI;
|
|
|
|
|
2010-05-21 01:49:16 +08:00
|
|
|
/// @}
|
|
|
|
|
|
|
|
public:
|
|
|
|
AssemblerInvocation() {
|
|
|
|
Triple = "";
|
|
|
|
NoInitialTextSection = 0;
|
|
|
|
InputFile = "-";
|
2010-05-21 02:15:20 +08:00
|
|
|
OutputPath = "-";
|
2010-05-21 01:49:16 +08:00
|
|
|
OutputType = FT_Asm;
|
|
|
|
OutputAsmVariant = 0;
|
|
|
|
ShowInst = 0;
|
|
|
|
ShowEncoding = 0;
|
|
|
|
RelaxAll = 0;
|
2011-01-24 01:58:26 +08:00
|
|
|
NoExecStack = 0;
|
2014-08-27 02:40:25 +08:00
|
|
|
FatalWarnings = 0;
|
2015-12-22 06:09:34 +08:00
|
|
|
IncrementalLinkerCompatible = 0;
|
2015-10-14 00:22:51 +08:00
|
|
|
DwarfVersion = 0;
|
2018-12-13 01:30:16 +08:00
|
|
|
EmbedBitcode = 0;
|
2010-05-21 01:49:16 +08:00
|
|
|
}
|
|
|
|
|
2014-08-16 05:38:36 +08:00
|
|
|
static bool CreateFromArgs(AssemblerInvocation &Res,
|
|
|
|
ArrayRef<const char *> Argv,
|
|
|
|
DiagnosticsEngine &Diags);
|
2010-05-21 01:49:16 +08:00
|
|
|
};
|
|
|
|
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2011-12-23 11:05:38 +08:00
|
|
|
bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
|
2014-08-16 05:38:36 +08:00
|
|
|
ArrayRef<const char *> Argv,
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &Diags) {
|
2011-12-23 11:05:38 +08:00
|
|
|
bool Success = true;
|
|
|
|
|
2010-05-21 01:49:16 +08:00
|
|
|
// Parse the arguments.
|
2014-07-09 22:05:11 +08:00
|
|
|
std::unique_ptr<OptTable> OptTbl(createDriverOptTable());
|
|
|
|
|
|
|
|
const unsigned IncludedFlagsBitmask = options::CC1AsOption;
|
2010-05-21 01:49:16 +08:00
|
|
|
unsigned MissingArgIndex, MissingArgCount;
|
2015-06-23 06:07:27 +08:00
|
|
|
InputArgList Args = OptTbl->ParseArgs(Argv, MissingArgIndex, MissingArgCount,
|
|
|
|
IncludedFlagsBitmask);
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
// Check for missing argument error.
|
2011-12-23 11:05:38 +08:00
|
|
|
if (MissingArgCount) {
|
2010-05-21 01:49:16 +08:00
|
|
|
Diags.Report(diag::err_drv_missing_argument)
|
2015-06-23 06:07:27 +08:00
|
|
|
<< Args.getArgString(MissingArgIndex) << MissingArgCount;
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
}
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
// Issue errors on unknown arguments.
|
2015-06-23 06:07:27 +08:00
|
|
|
for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
|
2018-01-14 01:09:11 +08:00
|
|
|
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;
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
}
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
// Construct the invocation.
|
|
|
|
|
|
|
|
// Target Options
|
2015-06-23 06:07:27 +08:00
|
|
|
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
|
|
|
|
Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
|
|
|
|
Opts.Features = Args.getAllArgValues(OPT_target_feature);
|
2012-02-11 04:37:10 +08:00
|
|
|
|
|
|
|
// Use the default target triple if unspecified.
|
|
|
|
if (Opts.Triple.empty())
|
|
|
|
Opts.Triple = llvm::sys::getDefaultTargetTriple();
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
// Language Options
|
2015-06-23 06:07:27 +08:00
|
|
|
Opts.IncludePaths = Args.getAllArgValues(OPT_I);
|
|
|
|
Opts.NoInitialTextSection = Args.hasArg(OPT_n);
|
|
|
|
Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels);
|
2015-10-08 12:24:12 +08:00
|
|
|
// Any DebugInfoKind implies GenDwarfForAssembly.
|
|
|
|
Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ);
|
2017-06-23 23:34:16 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-29 10:01:14 +08:00
|
|
|
Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
|
2016-04-20 04:31:19 +08:00
|
|
|
Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);
|
2015-06-23 06:07:27 +08:00
|
|
|
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);
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2018-07-10 23:15:24 +08:00
|
|
|
for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
|
|
|
|
Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
|
|
|
|
|
2010-05-21 01:49:16 +08:00
|
|
|
// Frontend Options
|
2015-06-23 06:07:27 +08:00
|
|
|
if (Args.hasArg(OPT_INPUT)) {
|
2010-05-21 01:49:16 +08:00
|
|
|
bool First = true;
|
2017-02-18 09:14:43 +08:00
|
|
|
for (const Arg *A : Args.filtered(OPT_INPUT)) {
|
|
|
|
if (First) {
|
2012-11-01 12:30:05 +08:00
|
|
|
Opts.InputFile = A->getValue();
|
2017-02-18 09:14:43 +08:00
|
|
|
First = false;
|
|
|
|
} else {
|
2015-06-23 06:07:27 +08:00
|
|
|
Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
}
|
2010-05-21 01:49:16 +08:00
|
|
|
}
|
|
|
|
}
|
2015-06-23 06:07:27 +08:00
|
|
|
Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
|
|
|
|
Opts.OutputPath = Args.getLastArgValue(OPT_o);
|
2018-05-23 02:52:37 +08:00
|
|
|
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
|
2015-06-23 06:07:27 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_filetype)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Name = A->getValue();
|
2010-05-21 01:49:16 +08:00
|
|
|
unsigned OutputType = StringSwitch<unsigned>(Name)
|
|
|
|
.Case("asm", FT_Asm)
|
|
|
|
.Case("null", FT_Null)
|
|
|
|
.Case("obj", FT_Obj)
|
|
|
|
.Default(~0U);
|
2011-12-23 11:05:38 +08:00
|
|
|
if (OutputType == ~0U) {
|
2015-06-23 06:07:27 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
} else
|
2010-05-21 01:49:16 +08:00
|
|
|
Opts.OutputType = FileType(OutputType);
|
|
|
|
}
|
2015-06-23 06:07:27 +08:00
|
|
|
Opts.ShowHelp = Args.hasArg(OPT_help);
|
|
|
|
Opts.ShowVersion = Args.hasArg(OPT_version);
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
// Transliterate Options
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.OutputAsmVariant =
|
2015-06-23 06:07:27 +08:00
|
|
|
getLastArgIntValue(Args, OPT_output_asm_variant, 0, Diags);
|
|
|
|
Opts.ShowEncoding = Args.hasArg(OPT_show_encoding);
|
|
|
|
Opts.ShowInst = Args.hasArg(OPT_show_inst);
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
// Assemble Options
|
2015-06-23 06:07:27 +08:00
|
|
|
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
|
|
|
|
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
|
|
|
|
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
|
2015-09-18 19:13:43 +08:00
|
|
|
Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
|
2019-03-26 16:01:18 +08:00
|
|
|
Opts.TargetABI = Args.getLastArgValue(OPT_target_abi);
|
2015-12-22 06:09:34 +08:00
|
|
|
Opts.IncrementalLinkerCompatible =
|
|
|
|
Args.hasArg(OPT_mincremental_linker_compatible);
|
2016-12-02 02:42:16 +08:00
|
|
|
Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);
|
2011-12-23 11:05:38 +08:00
|
|
|
|
2018-12-13 01:30:16 +08:00
|
|
|
// EmbedBitcode Option. If -fembed-bitcode is enabled, set the flag.
|
|
|
|
// EmbedBitcode behaves the same for all embed options for assembly files.
|
|
|
|
if (auto *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) {
|
|
|
|
Opts.EmbedBitcode = llvm::StringSwitch<unsigned>(A->getValue())
|
|
|
|
.Case("all", 1)
|
|
|
|
.Case("bitcode", 1)
|
|
|
|
.Case("marker", 1)
|
|
|
|
.Default(0);
|
|
|
|
}
|
|
|
|
|
2011-12-27 03:29:47 +08:00
|
|
|
return Success;
|
2010-05-21 01:49:16 +08:00
|
|
|
}
|
|
|
|
|
2015-04-10 05:50:11 +08:00
|
|
|
static std::unique_ptr<raw_fd_ostream>
|
2018-05-23 02:52:37 +08:00
|
|
|
getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
|
2010-05-21 01:49:16 +08:00
|
|
|
// Make sure that the Out file gets unlinked from the disk if we get a
|
|
|
|
// SIGINT.
|
2018-05-23 02:52:37 +08:00
|
|
|
if (Path != "-")
|
|
|
|
sys::RemoveFileOnSignal(Path);
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2014-08-26 02:17:04 +08:00
|
|
|
std::error_code EC;
|
2015-04-10 05:50:11 +08:00
|
|
|
auto Out = llvm::make_unique<raw_fd_ostream>(
|
2018-05-23 02:52:37 +08:00
|
|
|
Path, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
|
2014-08-26 02:17:04 +08:00
|
|
|
if (EC) {
|
2018-05-23 02:52:37 +08:00
|
|
|
Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
|
2014-06-08 16:38:04 +08:00
|
|
|
return nullptr;
|
2010-05-21 01:49:16 +08:00
|
|
|
}
|
|
|
|
|
2015-04-10 05:06:11 +08:00
|
|
|
return Out;
|
2010-05-21 01:49:16 +08:00
|
|
|
}
|
|
|
|
|
2011-09-26 07:23:43 +08:00
|
|
|
static bool ExecuteAssembler(AssemblerInvocation &Opts,
|
|
|
|
DiagnosticsEngine &Diags) {
|
2010-05-21 01:49:16 +08:00
|
|
|
// Get the target specific parser.
|
|
|
|
std::string Error;
|
2014-05-31 08:02:21 +08:00
|
|
|
const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);
|
2014-05-31 08:02:27 +08:00
|
|
|
if (!TheTarget)
|
|
|
|
return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2014-07-07 01:43:24 +08:00
|
|
|
ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
|
|
|
|
MemoryBuffer::getFileOrSTDIN(Opts.InputFile);
|
|
|
|
|
|
|
|
if (std::error_code EC = Buffer.getError()) {
|
|
|
|
Error = EC.message();
|
2014-05-31 08:02:27 +08:00
|
|
|
return Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
|
2010-05-21 01:49:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SourceMgr SrcMgr;
|
|
|
|
|
|
|
|
// Tell SrcMgr about this buffer, which is what the parser will pick up.
|
2019-03-02 04:58:04 +08:00
|
|
|
unsigned BufferIndex = SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
// Record the location of the include directories so that the lexer can find
|
|
|
|
// it later.
|
|
|
|
SrcMgr.setIncludeDirs(Opts.IncludePaths);
|
|
|
|
|
2014-03-08 04:03:18 +08:00
|
|
|
std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
|
2011-07-19 04:57:51 +08:00
|
|
|
assert(MRI && "Unable to create target register info!");
|
|
|
|
|
2014-03-08 04:03:18 +08:00
|
|
|
std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple));
|
2013-05-13 09:24:18 +08:00
|
|
|
assert(MAI && "Unable to create target asm info!");
|
|
|
|
|
2014-04-01 07:47:13 +08:00
|
|
|
// Ensure MCAsmInfo initialization occurs before any use, otherwise sections
|
|
|
|
// may be created with a combination of default and explicit settings.
|
2017-06-09 08:40:30 +08:00
|
|
|
MAI->setCompressDebugSections(Opts.CompressDebugSections);
|
2014-04-01 07:47:13 +08:00
|
|
|
|
2016-05-29 10:01:14 +08:00
|
|
|
MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations);
|
|
|
|
|
2010-05-21 01:49:16 +08:00
|
|
|
bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
|
2018-05-23 02:52:37 +08:00
|
|
|
if (Opts.OutputPath.empty())
|
|
|
|
Opts.OutputPath = "-";
|
|
|
|
std::unique_ptr<raw_fd_ostream> FDOS =
|
|
|
|
getOutputStream(Opts.OutputPath, Diags, IsBinary);
|
2015-04-14 23:15:49 +08:00
|
|
|
if (!FDOS)
|
2014-05-31 08:02:27 +08:00
|
|
|
return true;
|
2018-05-23 02:52:37 +08:00
|
|
|
std::unique_ptr<raw_fd_ostream> DwoOS;
|
|
|
|
if (!Opts.SplitDwarfFile.empty())
|
|
|
|
DwoOS = getOutputStream(Opts.SplitDwarfFile, Diags, IsBinary);
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2011-07-20 14:22:27 +08:00
|
|
|
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
|
|
|
|
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
|
2014-03-08 04:03:18 +08:00
|
|
|
std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
|
2014-04-01 07:13:30 +08:00
|
|
|
|
2013-06-18 15:22:05 +08:00
|
|
|
MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
|
2015-09-18 19:13:43 +08:00
|
|
|
|
2016-05-18 19:58:56 +08:00
|
|
|
bool PIC = false;
|
2015-09-18 19:13:43 +08:00
|
|
|
if (Opts.RelocationModel == "static") {
|
2016-05-18 19:58:56 +08:00
|
|
|
PIC = false;
|
2015-09-18 19:13:43 +08:00
|
|
|
} else if (Opts.RelocationModel == "pic") {
|
2016-05-18 19:58:56 +08:00
|
|
|
PIC = true;
|
2015-09-18 19:13:43 +08:00
|
|
|
} else {
|
|
|
|
assert(Opts.RelocationModel == "dynamic-no-pic" &&
|
|
|
|
"Invalid PIC model!");
|
2016-05-18 19:58:56 +08:00
|
|
|
PIC = false;
|
2015-09-18 19:13:43 +08:00
|
|
|
}
|
|
|
|
|
2017-08-03 04:32:35 +08:00
|
|
|
MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, Ctx);
|
2011-03-29 06:49:24 +08:00
|
|
|
if (Opts.SaveTemporaryLabels)
|
|
|
|
Ctx.setAllowTemporaryLabels(false);
|
2011-12-23 03:31:58 +08:00
|
|
|
if (Opts.GenDwarfForAssembly)
|
|
|
|
Ctx.setGenDwarfForAssembly(true);
|
|
|
|
if (!Opts.DwarfDebugFlags.empty())
|
|
|
|
Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags));
|
2013-01-18 05:38:06 +08:00
|
|
|
if (!Opts.DwarfDebugProducer.empty())
|
|
|
|
Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));
|
2012-12-18 05:40:04 +08:00
|
|
|
if (!Opts.DebugCompilationDir.empty())
|
|
|
|
Ctx.setCompilationDir(Opts.DebugCompilationDir);
|
2019-03-02 04:58:04 +08:00
|
|
|
else {
|
|
|
|
// If no compilation dir is set, try to use the current directory.
|
|
|
|
SmallString<128> CWD;
|
|
|
|
if (!sys::fs::current_path(CWD))
|
|
|
|
Ctx.setCompilationDir(CWD);
|
|
|
|
}
|
2018-07-10 23:15:24 +08:00
|
|
|
if (!Opts.DebugPrefixMap.empty())
|
|
|
|
for (const auto &KV : Opts.DebugPrefixMap)
|
|
|
|
Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
|
2012-12-18 08:31:10 +08:00
|
|
|
if (!Opts.MainFileName.empty())
|
|
|
|
Ctx.setMainFileName(StringRef(Opts.MainFileName));
|
2014-05-19 21:39:13 +08:00
|
|
|
Ctx.setDwarfVersion(Opts.DwarfVersion);
|
2019-03-02 04:58:04 +08:00
|
|
|
if (Opts.GenDwarfForAssembly)
|
|
|
|
Ctx.setGenDwarfRootFile(Opts.InputFile,
|
|
|
|
SrcMgr.getMemoryBuffer(BufferIndex)->getBuffer());
|
2010-12-10 15:40:14 +08:00
|
|
|
|
2012-02-11 04:37:10 +08:00
|
|
|
// 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];
|
|
|
|
}
|
|
|
|
|
2014-03-08 04:03:18 +08:00
|
|
|
std::unique_ptr<MCStreamer> Str;
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2014-03-08 04:03:18 +08:00
|
|
|
std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
|
|
|
|
std::unique_ptr<MCSubtargetInfo> STI(
|
|
|
|
TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));
|
2011-07-11 12:24:19 +08:00
|
|
|
|
2015-04-14 23:15:49 +08:00
|
|
|
raw_pwrite_stream *Out = FDOS.get();
|
|
|
|
std::unique_ptr<buffer_ostream> BOS;
|
|
|
|
|
2019-03-26 16:01:18 +08:00
|
|
|
MCTargetOptions MCOptions;
|
|
|
|
MCOptions.ABIName = Opts.TargetABI;
|
|
|
|
|
2011-01-24 01:58:26 +08:00
|
|
|
// FIXME: There is a bit of code duplication with addPassesToEmitFile.
|
2010-05-21 01:49:16 +08:00
|
|
|
if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
|
2015-03-31 08:10:23 +08:00
|
|
|
MCInstPrinter *IP = TheTarget->createMCInstPrinter(
|
2015-09-16 00:17:27 +08:00
|
|
|
llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI);
|
2018-04-27 23:45:54 +08:00
|
|
|
|
|
|
|
std::unique_ptr<MCCodeEmitter> CE;
|
|
|
|
if (Opts.ShowEncoding)
|
|
|
|
CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
|
|
|
|
std::unique_ptr<MCAsmBackend> MAB(
|
|
|
|
TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
|
|
|
|
|
2015-04-10 05:06:11 +08:00
|
|
|
auto FOut = llvm::make_unique<formatted_raw_ostream>(*Out);
|
|
|
|
Str.reset(TheTarget->createAsmStreamer(
|
|
|
|
Ctx, std::move(FOut), /*asmverbose*/ true,
|
2018-04-27 23:45:54 +08:00
|
|
|
/*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB),
|
|
|
|
Opts.ShowInst));
|
2010-05-21 01:49:16 +08:00
|
|
|
} else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
|
|
|
|
Str.reset(createNullStreamer(Ctx));
|
|
|
|
} else {
|
|
|
|
assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
|
|
|
|
"Invalid file type!");
|
2015-04-14 23:15:49 +08:00
|
|
|
if (!FDOS->supportsSeeking()) {
|
|
|
|
BOS = make_unique<buffer_ostream>(*FDOS);
|
|
|
|
Out = BOS.get();
|
|
|
|
}
|
|
|
|
|
2018-04-27 23:45:54 +08:00
|
|
|
std::unique_ptr<MCCodeEmitter> CE(
|
|
|
|
TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
|
|
|
|
std::unique_ptr<MCAsmBackend> MAB(
|
|
|
|
TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
|
2018-05-23 02:52:37 +08:00
|
|
|
std::unique_ptr<MCObjectWriter> OW =
|
|
|
|
DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)
|
|
|
|
: MAB->createObjectWriter(*Out);
|
2018-04-27 23:45:54 +08:00
|
|
|
|
2015-09-16 00:17:27 +08:00
|
|
|
Triple T(Opts.Triple);
|
2015-12-22 06:09:34 +08:00
|
|
|
Str.reset(TheTarget->createMCObjectStreamer(
|
2018-05-19 02:26:45 +08:00
|
|
|
T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
|
|
|
|
Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
|
2015-12-22 06:09:34 +08:00
|
|
|
/*DWARFMustBeAtTheEnd*/ true));
|
2014-10-16 00:12:57 +08:00
|
|
|
Str.get()->InitSections(Opts.NoExecStack);
|
2010-05-21 01:49:16 +08:00
|
|
|
}
|
|
|
|
|
2018-12-13 01:30:16 +08:00
|
|
|
// When -fembed-bitcode is passed to clang_as, a 1-byte marker
|
|
|
|
// is emitted in __LLVM,__asm section if the object file is MachO format.
|
|
|
|
if (Opts.EmbedBitcode && Ctx.getObjectFileInfo()->getObjectFileType() ==
|
|
|
|
MCObjectFileInfo::IsMachO) {
|
|
|
|
MCSection *AsmLabel = Ctx.getMachOSection(
|
|
|
|
"__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());
|
|
|
|
Str.get()->SwitchSection(AsmLabel);
|
|
|
|
Str.get()->EmitZeros(1);
|
|
|
|
}
|
|
|
|
|
[MC] Change AsmParser to leverage Assembler during evaluation
Teach AsmParser to check with Assembler for when evaluating constant
expressions. This improves the handing of preprocessor expressions
that must be resolved at parse time. This idiom can be found as
assembling-time assertion checks in source-level assemblers. Note that
this relies on the MCStreamer to keep sufficient tabs on Section /
Fragment information which the MCAsmStreamer does not. As a result the
textual output may fail where the equivalent object generation would
pass. This can most easily be resolved by folding the MCAsmStreamer
and MCObjectStreamer together which is planned for in a separate
patch.
Currently, this feature is only enabled for assembly input, keeping IR
compilation consistent between assembly and object generation.
Reviewers: echristo, rnk, probinson, espindola, peter.smith
Reviewed By: peter.smith
Subscribers: eraman, peter.smith, arichardson, jyknight, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D45164
llvm-svn: 331218
2018-05-01 03:22:40 +08:00
|
|
|
// Assembly to object compilation should leverage assembly info.
|
|
|
|
Str->setUseAssemblerInfoForParsing(true);
|
|
|
|
|
2014-05-31 08:02:27 +08:00
|
|
|
bool Failed = false;
|
2014-05-31 08:02:21 +08:00
|
|
|
|
2014-03-08 04:03:18 +08:00
|
|
|
std::unique_ptr<MCAsmParser> Parser(
|
|
|
|
createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
|
2014-04-23 19:15:49 +08:00
|
|
|
|
|
|
|
// FIXME: init MCTargetOptions from sanitizer flags here.
|
2014-03-08 04:03:18 +08:00
|
|
|
std::unique_ptr<MCTargetAsmParser> TAP(
|
2019-03-26 16:01:18 +08:00
|
|
|
TheTarget->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
|
2014-05-31 08:02:27 +08:00
|
|
|
if (!TAP)
|
|
|
|
Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2016-12-02 02:42:16 +08:00
|
|
|
// Set values for symbols, if any.
|
|
|
|
for (auto &S : Opts.SymbolDefs) {
|
2016-12-06 10:49:16 +08:00
|
|
|
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);
|
2016-12-02 02:42:16 +08:00
|
|
|
}
|
|
|
|
|
2014-05-31 08:02:27 +08:00
|
|
|
if (!Failed) {
|
2014-05-31 08:02:21 +08:00
|
|
|
Parser->setTargetParser(*TAP.get());
|
2014-05-31 08:02:27 +08:00
|
|
|
Failed = Parser->Run(Opts.NoInitialTextSection);
|
2014-05-31 08:02:21 +08:00
|
|
|
}
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2015-07-24 10:12:43 +08:00
|
|
|
// Close Streamer first.
|
|
|
|
// It might have a reference to the output stream.
|
|
|
|
Str.reset();
|
2014-05-31 08:02:21 +08:00
|
|
|
// Close the output stream early.
|
2015-04-14 23:15:49 +08:00
|
|
|
BOS.reset();
|
|
|
|
FDOS.reset();
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2014-05-31 08:02:21 +08:00
|
|
|
// Delete output file if there were errors.
|
2018-05-23 02:52:37 +08:00
|
|
|
if (Failed) {
|
|
|
|
if (Opts.OutputPath != "-")
|
|
|
|
sys::fs::remove(Opts.OutputPath);
|
|
|
|
if (!Opts.SplitDwarfFile.empty() && Opts.SplitDwarfFile != "-")
|
|
|
|
sys::fs::remove(Opts.SplitDwarfFile);
|
|
|
|
}
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2014-05-31 08:02:27 +08:00
|
|
|
return Failed;
|
2010-05-21 01:49:16 +08:00
|
|
|
}
|
|
|
|
|
2013-03-28 02:28:23 +08:00
|
|
|
static void LLVMErrorHandler(void *UserData, const std::string &Message,
|
|
|
|
bool GenCrashDiag) {
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
Diags.Report(diag::err_fe_error_backend) << Message;
|
|
|
|
|
|
|
|
// We cannot recover from llvm errors.
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2014-08-16 05:38:36 +08:00
|
|
|
int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
|
2010-05-21 01:49:16 +08:00
|
|
|
// Initialize targets and assembly printers/parsers.
|
|
|
|
InitializeAllTargetInfos();
|
2011-07-23 05:59:11 +08:00
|
|
|
InitializeAllTargetMCs();
|
2010-05-21 01:49:16 +08:00
|
|
|
InitializeAllAsmParsers();
|
|
|
|
|
|
|
|
// Construct our diagnostic client.
|
2012-10-24 06:26:28 +08:00
|
|
|
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
|
2010-08-19 06:29:43 +08:00
|
|
|
TextDiagnosticPrinter *DiagClient
|
2012-10-24 06:26:28 +08:00
|
|
|
= new TextDiagnosticPrinter(errs(), &*DiagOpts);
|
2010-08-19 06:29:43 +08:00
|
|
|
DiagClient->setPrefix("clang -cc1as");
|
2012-02-20 22:00:23 +08:00
|
|
|
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
|
2012-10-24 06:26:28 +08:00
|
|
|
DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
// Set an error handler, so that any LLVM backend diagnostics go through our
|
|
|
|
// error handler.
|
2010-08-19 05:23:17 +08:00
|
|
|
ScopedFatalErrorHandler FatalErrorHandler
|
|
|
|
(LLVMErrorHandler, static_cast<void*>(&Diags));
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
// Parse the arguments.
|
|
|
|
AssemblerInvocation Asm;
|
2014-08-16 05:38:36 +08:00
|
|
|
if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))
|
2011-12-23 11:05:38 +08:00
|
|
|
return 1;
|
2010-05-21 01:49:16 +08:00
|
|
|
|
2010-05-21 02:15:20 +08:00
|
|
|
if (Asm.ShowHelp) {
|
2014-07-09 22:05:11 +08:00
|
|
|
std::unique_ptr<OptTable> Opts(driver::createDriverOptTable());
|
2018-10-10 08:15:33 +08:00
|
|
|
Opts->PrintHelp(llvm::outs(), "clang -cc1as [options] file...",
|
|
|
|
"Clang Integrated Assembler",
|
2017-07-26 17:10:17 +08:00
|
|
|
/*Include=*/driver::options::CC1AsOption, /*Exclude=*/0,
|
|
|
|
/*ShowAllAliases=*/false);
|
2010-05-21 02:15:20 +08:00
|
|
|
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();
|
2017-04-20 04:57:13 +08:00
|
|
|
auto Args = llvm::make_unique<const char*[]>(NumArgs + 2);
|
2010-05-21 02:15:20 +08:00
|
|
|
Args[0] = "clang (LLVM option parsing)";
|
|
|
|
for (unsigned i = 0; i != NumArgs; ++i)
|
|
|
|
Args[i + 1] = Asm.LLVMArgs[i].c_str();
|
2014-06-08 16:38:04 +08:00
|
|
|
Args[NumArgs + 1] = nullptr;
|
2017-04-20 04:57:13 +08:00
|
|
|
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
|
2010-05-21 02:15:20 +08:00
|
|
|
}
|
|
|
|
|
2010-05-21 01:49:16 +08:00
|
|
|
// Execute the invocation, unless there were parsing errors.
|
2014-05-31 08:02:27 +08:00
|
|
|
bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);
|
2010-05-21 01:49:16 +08:00
|
|
|
|
|
|
|
// If any timers were active but haven't been destroyed yet, print their
|
|
|
|
// results now.
|
|
|
|
TimerGroup::printAll(errs());
|
|
|
|
|
2014-05-31 08:02:27 +08:00
|
|
|
return !!Failed;
|
2010-05-21 01:49:16 +08:00
|
|
|
}
|