llvm-mirror/include/llvm/CodeGen/CommandFlags.h
Oliver Stannard ffdf511cf4 [ARM] Add support for embedded position-independent code
This patch adds support for some new relocation models to the ARM
backend:

* Read-only position independence (ROPI): Code and read-only data is accessed
  PC-relative. The offsets between all code and RO data sections are known at
  static link time. This does not affect read-write data.
* Read-write position independence (RWPI): Read-write data is accessed relative
  to the static base register (r9). The offsets between all writeable data
  sections are known at static link time. This does not affect read-only data.

These two modes are independent (they specify how different objects
should be addressed), so they can be used individually or together. They
are otherwise the same as the "static" relocation model, and are not
compatible with SysV-style PIC using a global offset table.

These modes are normally used by bare-metal systems or systems with
small real-time operating systems. They are designed to avoid the need
for a dynamic linker, the only initialisation required is setting r9 to
an appropriate value for RWPI code.

I have only added support to SelectionDAG, not FastISel, because
FastISel is currently disabled for bare-metal targets where these modes
would be used.

Differential Revision: https://reviews.llvm.org/D23195

llvm-svn: 278015
2016-08-08 15:28:31 +00:00

394 lines
15 KiB
C++

//===-- CommandFlags.h - Command Line Flags Interface -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains codegen-specific flags that are shared between different
// command line tools. The tools "llc" and "opt" both use this file to prevent
// flag duplication.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_COMMANDFLAGS_H
#define LLVM_CODEGEN_COMMANDFLAGS_H
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Host.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRecip.h"
#include <string>
using namespace llvm;
cl::opt<std::string>
MArch("march", cl::desc("Architecture to generate code for (see --version)"));
cl::opt<std::string>
MCPU("mcpu",
cl::desc("Target a specific cpu type (-mcpu=help for details)"),
cl::value_desc("cpu-name"),
cl::init(""));
cl::list<std::string>
MAttrs("mattr",
cl::CommaSeparated,
cl::desc("Target specific attributes (-mattr=help for details)"),
cl::value_desc("a1,+a2,-a3,..."));
cl::opt<Reloc::Model> RelocModel(
"relocation-model", cl::desc("Choose relocation model"),
cl::values(
clEnumValN(Reloc::Static, "static", "Non-relocatable code"),
clEnumValN(Reloc::PIC_, "pic",
"Fully relocatable, position independent code"),
clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
"Relocatable external references, non-relocatable code"),
clEnumValN(Reloc::ROPI, "ropi",
"Code and read-only data relocatable, accessed PC-relative"),
clEnumValN(Reloc::RWPI, "rwpi",
"Read-write data relocatable, accessed relative to static base"),
clEnumValN(Reloc::ROPI_RWPI, "ropi-rwpi",
"Combination of ropi and rwpi"),
clEnumValEnd));
static inline Optional<Reloc::Model> getRelocModel() {
if (RelocModel.getNumOccurrences()) {
Reloc::Model R = RelocModel;
return R;
}
return None;
}
cl::opt<ThreadModel::Model>
TMModel("thread-model",
cl::desc("Choose threading model"),
cl::init(ThreadModel::POSIX),
cl::values(clEnumValN(ThreadModel::POSIX, "posix",
"POSIX thread model"),
clEnumValN(ThreadModel::Single, "single",
"Single thread model"),
clEnumValEnd));
cl::opt<llvm::CodeModel::Model>
CMModel("code-model",
cl::desc("Choose code model"),
cl::init(CodeModel::Default),
cl::values(clEnumValN(CodeModel::Default, "default",
"Target default code model"),
clEnumValN(CodeModel::Small, "small",
"Small code model"),
clEnumValN(CodeModel::Kernel, "kernel",
"Kernel code model"),
clEnumValN(CodeModel::Medium, "medium",
"Medium code model"),
clEnumValN(CodeModel::Large, "large",
"Large code model"),
clEnumValEnd));
cl::opt<llvm::ExceptionHandling>
ExceptionModel("exception-model",
cl::desc("exception model"),
cl::init(ExceptionHandling::None),
cl::values(clEnumValN(ExceptionHandling::None, "default",
"default exception handling model"),
clEnumValN(ExceptionHandling::DwarfCFI, "dwarf",
"DWARF-like CFI based exception handling"),
clEnumValN(ExceptionHandling::SjLj, "sjlj",
"SjLj exception handling"),
clEnumValN(ExceptionHandling::ARM, "arm",
"ARM EHABI exceptions"),
clEnumValN(ExceptionHandling::WinEH, "wineh",
"Windows exception model"),
clEnumValEnd));
cl::opt<TargetMachine::CodeGenFileType>
FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
cl::desc("Choose a file type (not all types are supported by all targets):"),
cl::values(
clEnumValN(TargetMachine::CGFT_AssemblyFile, "asm",
"Emit an assembly ('.s') file"),
clEnumValN(TargetMachine::CGFT_ObjectFile, "obj",
"Emit a native object ('.o') file"),
clEnumValN(TargetMachine::CGFT_Null, "null",
"Emit nothing, for performance testing"),
clEnumValEnd));
cl::opt<bool>
EnableFPMAD("enable-fp-mad",
cl::desc("Enable less precise MAD instructions to be generated"),
cl::init(false));
cl::opt<bool>
DisableFPElim("disable-fp-elim",
cl::desc("Disable frame pointer elimination optimization"),
cl::init(false));
cl::opt<bool>
EnableUnsafeFPMath("enable-unsafe-fp-math",
cl::desc("Enable optimizations that may decrease FP precision"),
cl::init(false));
cl::opt<bool>
EnableNoInfsFPMath("enable-no-infs-fp-math",
cl::desc("Enable FP math optimizations that assume no +-Infs"),
cl::init(false));
cl::opt<bool>
EnableNoNaNsFPMath("enable-no-nans-fp-math",
cl::desc("Enable FP math optimizations that assume no NaNs"),
cl::init(false));
cl::opt<bool>
EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math",
cl::Hidden,
cl::desc("Force codegen to assume rounding mode can change dynamically"),
cl::init(false));
cl::opt<llvm::FloatABI::ABIType>
FloatABIForCalls("float-abi",
cl::desc("Choose float ABI type"),
cl::init(FloatABI::Default),
cl::values(
clEnumValN(FloatABI::Default, "default",
"Target default float ABI type"),
clEnumValN(FloatABI::Soft, "soft",
"Soft float ABI (implied by -soft-float)"),
clEnumValN(FloatABI::Hard, "hard",
"Hard float ABI (uses FP registers)"),
clEnumValEnd));
cl::opt<llvm::FPOpFusion::FPOpFusionMode>
FuseFPOps("fp-contract",
cl::desc("Enable aggressive formation of fused FP ops"),
cl::init(FPOpFusion::Standard),
cl::values(
clEnumValN(FPOpFusion::Fast, "fast",
"Fuse FP ops whenever profitable"),
clEnumValN(FPOpFusion::Standard, "on",
"Only fuse 'blessed' FP ops."),
clEnumValN(FPOpFusion::Strict, "off",
"Only fuse FP ops when the result won't be affected."),
clEnumValEnd));
cl::list<std::string>
ReciprocalOps("recip",
cl::CommaSeparated,
cl::desc("Choose reciprocal operation types and parameters."),
cl::value_desc("all,none,default,divf,!vec-sqrtd,vec-divd:0,sqrt:9..."));
cl::opt<bool>
DontPlaceZerosInBSS("nozero-initialized-in-bss",
cl::desc("Don't place zero-initialized symbols into bss section"),
cl::init(false));
cl::opt<bool>
EnableGuaranteedTailCallOpt("tailcallopt",
cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."),
cl::init(false));
cl::opt<bool>
DisableTailCalls("disable-tail-calls",
cl::desc("Never emit tail calls"),
cl::init(false));
cl::opt<bool>
StackSymbolOrdering("stack-symbol-ordering",
cl::desc("Order local stack symbols."),
cl::init(true));
cl::opt<unsigned>
OverrideStackAlignment("stack-alignment",
cl::desc("Override default stack alignment"),
cl::init(0));
cl::opt<bool>
StackRealign("stackrealign",
cl::desc("Force align the stack to the minimum alignment"),
cl::init(false));
cl::opt<std::string>
TrapFuncName("trap-func", cl::Hidden,
cl::desc("Emit a call to trap function rather than a trap instruction"),
cl::init(""));
cl::opt<bool>
UseCtors("use-ctors",
cl::desc("Use .ctors instead of .init_array."),
cl::init(false));
cl::opt<bool> DataSections("data-sections",
cl::desc("Emit data into separate sections"),
cl::init(false));
cl::opt<bool>
FunctionSections("function-sections",
cl::desc("Emit functions into separate sections"),
cl::init(false));
cl::opt<bool> EmulatedTLS("emulated-tls",
cl::desc("Use emulated TLS model"),
cl::init(false));
cl::opt<bool> UniqueSectionNames("unique-section-names",
cl::desc("Give unique names to every section"),
cl::init(true));
cl::opt<llvm::JumpTable::JumpTableType>
JTableType("jump-table-type",
cl::desc("Choose the type of Jump-Instruction Table for jumptable."),
cl::init(JumpTable::Single),
cl::values(
clEnumValN(JumpTable::Single, "single",
"Create a single table for all jumptable functions"),
clEnumValN(JumpTable::Arity, "arity",
"Create one table per number of parameters."),
clEnumValN(JumpTable::Simplified, "simplified",
"Create one table per simplified function type."),
clEnumValN(JumpTable::Full, "full",
"Create one table per unique function type."),
clEnumValEnd));
cl::opt<llvm::EABI> EABIVersion(
"meabi", cl::desc("Set EABI type (default depends on triple):"),
cl::init(EABI::Default),
cl::values(clEnumValN(EABI::Default, "default",
"Triple default EABI version"),
clEnumValN(EABI::EABI4, "4", "EABI version 4"),
clEnumValN(EABI::EABI5, "5", "EABI version 5"),
clEnumValN(EABI::GNU, "gnu", "EABI GNU"), clEnumValEnd));
cl::opt<DebuggerKind>
DebuggerTuningOpt("debugger-tune",
cl::desc("Tune debug info for a particular debugger"),
cl::init(DebuggerKind::Default),
cl::values(
clEnumValN(DebuggerKind::GDB, "gdb", "gdb"),
clEnumValN(DebuggerKind::LLDB, "lldb", "lldb"),
clEnumValN(DebuggerKind::SCE, "sce",
"SCE targets (e.g. PS4)"),
clEnumValEnd));
// Common utility function tightly tied to the options listed here. Initializes
// a TargetOptions object with CodeGen flags and returns it.
static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
TargetOptions Options;
Options.LessPreciseFPMADOption = EnableFPMAD;
Options.AllowFPOpFusion = FuseFPOps;
Options.Reciprocals = TargetRecip(ReciprocalOps);
Options.UnsafeFPMath = EnableUnsafeFPMath;
Options.NoInfsFPMath = EnableNoInfsFPMath;
Options.NoNaNsFPMath = EnableNoNaNsFPMath;
Options.HonorSignDependentRoundingFPMathOption =
EnableHonorSignDependentRoundingFPMath;
if (FloatABIForCalls != FloatABI::Default)
Options.FloatABIType = FloatABIForCalls;
Options.NoZerosInBSS = DontPlaceZerosInBSS;
Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
Options.StackAlignmentOverride = OverrideStackAlignment;
Options.StackSymbolOrdering = StackSymbolOrdering;
Options.UseInitArray = !UseCtors;
Options.DataSections = DataSections;
Options.FunctionSections = FunctionSections;
Options.UniqueSectionNames = UniqueSectionNames;
Options.EmulatedTLS = EmulatedTLS;
Options.ExceptionModel = ExceptionModel;
Options.MCOptions = InitMCTargetOptionsFromFlags();
Options.JTType = JTableType;
Options.ThreadModel = TMModel;
Options.EABIVersion = EABIVersion;
Options.DebuggerTuning = DebuggerTuningOpt;
return Options;
}
static inline std::string getCPUStr() {
// If user asked for the 'native' CPU, autodetect here. If autodection fails,
// this will set the CPU to an empty string which tells the target to
// pick a basic default.
if (MCPU == "native")
return sys::getHostCPUName();
return MCPU;
}
static inline std::string getFeaturesStr() {
SubtargetFeatures Features;
// If user asked for the 'native' CPU, we need to autodetect features.
// This is necessary for x86 where the CPU might not support all the
// features the autodetected CPU name lists in the target. For example,
// not all Sandybridge processors support AVX.
if (MCPU == "native") {
StringMap<bool> HostFeatures;
if (sys::getHostCPUFeatures(HostFeatures))
for (auto &F : HostFeatures)
Features.AddFeature(F.first(), F.second);
}
for (unsigned i = 0; i != MAttrs.size(); ++i)
Features.AddFeature(MAttrs[i]);
return Features.getString();
}
/// \brief Set function attributes of functions in Module M based on CPU,
/// Features, and command line flags.
static inline void setFunctionAttributes(StringRef CPU, StringRef Features,
Module &M) {
for (auto &F : M) {
auto &Ctx = F.getContext();
AttributeSet Attrs = F.getAttributes(), NewAttrs;
if (!CPU.empty())
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
"target-cpu", CPU);
if (!Features.empty())
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
"target-features", Features);
if (DisableFPElim.getNumOccurrences() > 0)
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
"no-frame-pointer-elim",
DisableFPElim ? "true" : "false");
if (DisableTailCalls.getNumOccurrences() > 0)
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
"disable-tail-calls",
toStringRef(DisableTailCalls));
if (StackRealign)
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
"stackrealign");
if (TrapFuncName.getNumOccurrences() > 0)
for (auto &B : F)
for (auto &I : B)
if (auto *Call = dyn_cast<CallInst>(&I))
if (const auto *F = Call->getCalledFunction())
if (F->getIntrinsicID() == Intrinsic::debugtrap ||
F->getIntrinsicID() == Intrinsic::trap)
Call->addAttribute(llvm::AttributeSet::FunctionIndex,
"trap-func-name", TrapFuncName);
// Let NewAttrs override Attrs.
NewAttrs = Attrs.addAttributes(Ctx, AttributeSet::FunctionIndex, NewAttrs);
F.setAttributes(NewAttrs);
}
}
#endif