You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,76 +0,0 @@
|
||||
//===-- ARMAsmBackend.h - ARM Assembler Backend -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARM_ARMASMBACKEND_H
|
||||
#define LLVM_LIB_TARGET_ARM_ARMASMBACKEND_H
|
||||
|
||||
#include "MCTargetDesc/ARMFixupKinds.h"
|
||||
#include "MCTargetDesc/ARMMCTargetDesc.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ARMAsmBackend : public MCAsmBackend {
|
||||
const MCSubtargetInfo &STI;
|
||||
bool isThumbMode; // Currently emitting Thumb code.
|
||||
bool IsLittleEndian; // Big or little endian.
|
||||
public:
|
||||
ARMAsmBackend(const Target &T, const MCSubtargetInfo &STI, bool IsLittle)
|
||||
: MCAsmBackend(), STI(STI),
|
||||
isThumbMode(STI.getTargetTriple().isThumb()),
|
||||
IsLittleEndian(IsLittle) {}
|
||||
|
||||
unsigned getNumFixupKinds() const override {
|
||||
return ARM::NumTargetFixupKinds;
|
||||
}
|
||||
|
||||
bool hasNOP() const { return STI.getFeatureBits()[ARM::HasV6T2Ops]; }
|
||||
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
|
||||
|
||||
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target) override;
|
||||
|
||||
unsigned adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target, uint64_t Value,
|
||||
bool IsResolved, MCContext &Ctx,
|
||||
bool IsLittleEndian) const;
|
||||
|
||||
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target, MutableArrayRef<char> Data,
|
||||
uint64_t Value, bool IsResolved) const override;
|
||||
|
||||
unsigned getRelaxedOpcode(unsigned Op) const;
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const override;
|
||||
|
||||
const char *reasonForFixupRelaxation(const MCFixup &Fixup,
|
||||
uint64_t Value) const;
|
||||
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override;
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override;
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
|
||||
void handleAssemblerFlag(MCAssemblerFlag Flag) override;
|
||||
|
||||
unsigned getPointerSize() const { return 4; }
|
||||
bool isThumb() const { return isThumbMode; }
|
||||
void setIsThumb(bool it) { isThumbMode = it; }
|
||||
bool isLittle() const { return IsLittleEndian; }
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -1,38 +0,0 @@
|
||||
//===-- ARMAsmBackendDarwin.h ARM Asm Backend Darwin ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARM_ARMASMBACKENDDARWIN_H
|
||||
#define LLVM_LIB_TARGET_ARM_ARMASMBACKENDDARWIN_H
|
||||
|
||||
#include "ARMAsmBackend.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
|
||||
namespace llvm {
|
||||
class ARMAsmBackendDarwin : public ARMAsmBackend {
|
||||
const MCRegisterInfo &MRI;
|
||||
public:
|
||||
const MachO::CPUSubTypeARM Subtype;
|
||||
ARMAsmBackendDarwin(const Target &T, const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI, MachO::CPUSubTypeARM st)
|
||||
: ARMAsmBackend(T, STI, /* IsLittleEndian */ true), MRI(MRI),
|
||||
Subtype(st) {}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createObjectWriter(raw_pwrite_stream &OS) const override {
|
||||
return createARMMachObjectWriter(OS, /*Is64Bit=*/false, MachO::CPU_TYPE_ARM,
|
||||
Subtype);
|
||||
}
|
||||
|
||||
uint32_t generateCompactUnwindEncoding(
|
||||
ArrayRef<MCCFIInstruction> Instrs) const override;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -1,34 +0,0 @@
|
||||
//===-- ARMAsmBackendELF.h ARM Asm Backend ELF -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARM_ELFARMASMBACKEND_H
|
||||
#define LLVM_LIB_TARGET_ARM_ELFARMASMBACKEND_H
|
||||
|
||||
#include "ARMAsmBackend.h"
|
||||
#include "MCTargetDesc/ARMMCTargetDesc.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class ARMAsmBackendELF : public ARMAsmBackend {
|
||||
public:
|
||||
uint8_t OSABI;
|
||||
ARMAsmBackendELF(const Target &T, const MCSubtargetInfo &STI, uint8_t OSABI,
|
||||
bool IsLittle)
|
||||
: ARMAsmBackend(T, STI, IsLittle), OSABI(OSABI) {}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createObjectWriter(raw_pwrite_stream &OS) const override {
|
||||
return createARMELFObjectWriter(OS, OSABI, isLittle());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,29 +0,0 @@
|
||||
//===-- ARMAsmBackendWinCOFF.h - ARM Asm Backend WinCOFF --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARM_ARMASMBACKENDWINCOFF_H
|
||||
#define LLVM_LIB_TARGET_ARM_ARMASMBACKENDWINCOFF_H
|
||||
|
||||
#include "ARMAsmBackend.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class ARMAsmBackendWinCOFF : public ARMAsmBackend {
|
||||
public:
|
||||
ARMAsmBackendWinCOFF(const Target &T, const MCSubtargetInfo &STI)
|
||||
: ARMAsmBackend(T, STI, true) {}
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createObjectWriter(raw_pwrite_stream &OS) const override {
|
||||
return createARMWinCOFFObjectWriter(OS, /*Is64Bit=*/false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,411 +0,0 @@
|
||||
//===-- ARMBaseInfo.h - Top level definitions for ARM -------- --*- 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 small standalone helper functions and enum definitions for
|
||||
// the ARM target useful for the compiler back-end and the MC libraries.
|
||||
// As such, it deliberately does not include references to LLVM core
|
||||
// code gen types, passes, etc..
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMBASEINFO_H
|
||||
#define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMBASEINFO_H
|
||||
|
||||
#include "ARMMCTargetDesc.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "Utils/ARMBaseInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace ARM_PROC {
|
||||
enum IMod {
|
||||
IE = 2,
|
||||
ID = 3
|
||||
};
|
||||
|
||||
enum IFlags {
|
||||
F = 1,
|
||||
I = 2,
|
||||
A = 4
|
||||
};
|
||||
|
||||
inline static const char *IFlagsToString(unsigned val) {
|
||||
switch (val) {
|
||||
default: llvm_unreachable("Unknown iflags operand");
|
||||
case F: return "f";
|
||||
case I: return "i";
|
||||
case A: return "a";
|
||||
}
|
||||
}
|
||||
|
||||
inline static const char *IModToString(unsigned val) {
|
||||
switch (val) {
|
||||
default: llvm_unreachable("Unknown imod operand");
|
||||
case IE: return "ie";
|
||||
case ID: return "id";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace ARM_MB {
|
||||
// The Memory Barrier Option constants map directly to the 4-bit encoding of
|
||||
// the option field for memory barrier operations.
|
||||
enum MemBOpt {
|
||||
RESERVED_0 = 0,
|
||||
OSHLD = 1,
|
||||
OSHST = 2,
|
||||
OSH = 3,
|
||||
RESERVED_4 = 4,
|
||||
NSHLD = 5,
|
||||
NSHST = 6,
|
||||
NSH = 7,
|
||||
RESERVED_8 = 8,
|
||||
ISHLD = 9,
|
||||
ISHST = 10,
|
||||
ISH = 11,
|
||||
RESERVED_12 = 12,
|
||||
LD = 13,
|
||||
ST = 14,
|
||||
SY = 15
|
||||
};
|
||||
|
||||
inline static const char *MemBOptToString(unsigned val, bool HasV8) {
|
||||
switch (val) {
|
||||
default: llvm_unreachable("Unknown memory operation");
|
||||
case SY: return "sy";
|
||||
case ST: return "st";
|
||||
case LD: return HasV8 ? "ld" : "#0xd";
|
||||
case RESERVED_12: return "#0xc";
|
||||
case ISH: return "ish";
|
||||
case ISHST: return "ishst";
|
||||
case ISHLD: return HasV8 ? "ishld" : "#0x9";
|
||||
case RESERVED_8: return "#0x8";
|
||||
case NSH: return "nsh";
|
||||
case NSHST: return "nshst";
|
||||
case NSHLD: return HasV8 ? "nshld" : "#0x5";
|
||||
case RESERVED_4: return "#0x4";
|
||||
case OSH: return "osh";
|
||||
case OSHST: return "oshst";
|
||||
case OSHLD: return HasV8 ? "oshld" : "#0x1";
|
||||
case RESERVED_0: return "#0x0";
|
||||
}
|
||||
}
|
||||
} // namespace ARM_MB
|
||||
|
||||
namespace ARM_ISB {
|
||||
enum InstSyncBOpt {
|
||||
RESERVED_0 = 0,
|
||||
RESERVED_1 = 1,
|
||||
RESERVED_2 = 2,
|
||||
RESERVED_3 = 3,
|
||||
RESERVED_4 = 4,
|
||||
RESERVED_5 = 5,
|
||||
RESERVED_6 = 6,
|
||||
RESERVED_7 = 7,
|
||||
RESERVED_8 = 8,
|
||||
RESERVED_9 = 9,
|
||||
RESERVED_10 = 10,
|
||||
RESERVED_11 = 11,
|
||||
RESERVED_12 = 12,
|
||||
RESERVED_13 = 13,
|
||||
RESERVED_14 = 14,
|
||||
SY = 15
|
||||
};
|
||||
|
||||
inline static const char *InstSyncBOptToString(unsigned val) {
|
||||
switch (val) {
|
||||
default:
|
||||
llvm_unreachable("Unknown memory operation");
|
||||
case RESERVED_0: return "#0x0";
|
||||
case RESERVED_1: return "#0x1";
|
||||
case RESERVED_2: return "#0x2";
|
||||
case RESERVED_3: return "#0x3";
|
||||
case RESERVED_4: return "#0x4";
|
||||
case RESERVED_5: return "#0x5";
|
||||
case RESERVED_6: return "#0x6";
|
||||
case RESERVED_7: return "#0x7";
|
||||
case RESERVED_8: return "#0x8";
|
||||
case RESERVED_9: return "#0x9";
|
||||
case RESERVED_10: return "#0xa";
|
||||
case RESERVED_11: return "#0xb";
|
||||
case RESERVED_12: return "#0xc";
|
||||
case RESERVED_13: return "#0xd";
|
||||
case RESERVED_14: return "#0xe";
|
||||
case SY: return "sy";
|
||||
}
|
||||
}
|
||||
} // namespace ARM_ISB
|
||||
|
||||
/// isARMLowRegister - Returns true if the register is a low register (r0-r7).
|
||||
///
|
||||
static inline bool isARMLowRegister(unsigned Reg) {
|
||||
using namespace ARM;
|
||||
switch (Reg) {
|
||||
case R0: case R1: case R2: case R3:
|
||||
case R4: case R5: case R6: case R7:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// ARMII - This namespace holds all of the target specific flags that
|
||||
/// instruction info tracks.
|
||||
///
|
||||
namespace ARMII {
|
||||
|
||||
/// ARM Index Modes
|
||||
enum IndexMode {
|
||||
IndexModeNone = 0,
|
||||
IndexModePre = 1,
|
||||
IndexModePost = 2,
|
||||
IndexModeUpd = 3
|
||||
};
|
||||
|
||||
/// ARM Addressing Modes
|
||||
enum AddrMode {
|
||||
AddrModeNone = 0,
|
||||
AddrMode1 = 1,
|
||||
AddrMode2 = 2,
|
||||
AddrMode3 = 3,
|
||||
AddrMode4 = 4,
|
||||
AddrMode5 = 5,
|
||||
AddrMode6 = 6,
|
||||
AddrModeT1_1 = 7,
|
||||
AddrModeT1_2 = 8,
|
||||
AddrModeT1_4 = 9,
|
||||
AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data
|
||||
AddrModeT2_i12 = 11,
|
||||
AddrModeT2_i8 = 12,
|
||||
AddrModeT2_so = 13,
|
||||
AddrModeT2_pc = 14, // +/- i12 for pc relative data
|
||||
AddrModeT2_i8s4 = 15, // i8 * 4
|
||||
AddrMode_i12 = 16
|
||||
};
|
||||
|
||||
inline static const char *AddrModeToString(AddrMode addrmode) {
|
||||
switch (addrmode) {
|
||||
case AddrModeNone: return "AddrModeNone";
|
||||
case AddrMode1: return "AddrMode1";
|
||||
case AddrMode2: return "AddrMode2";
|
||||
case AddrMode3: return "AddrMode3";
|
||||
case AddrMode4: return "AddrMode4";
|
||||
case AddrMode5: return "AddrMode5";
|
||||
case AddrMode6: return "AddrMode6";
|
||||
case AddrModeT1_1: return "AddrModeT1_1";
|
||||
case AddrModeT1_2: return "AddrModeT1_2";
|
||||
case AddrModeT1_4: return "AddrModeT1_4";
|
||||
case AddrModeT1_s: return "AddrModeT1_s";
|
||||
case AddrModeT2_i12: return "AddrModeT2_i12";
|
||||
case AddrModeT2_i8: return "AddrModeT2_i8";
|
||||
case AddrModeT2_so: return "AddrModeT2_so";
|
||||
case AddrModeT2_pc: return "AddrModeT2_pc";
|
||||
case AddrModeT2_i8s4: return "AddrModeT2_i8s4";
|
||||
case AddrMode_i12: return "AddrMode_i12";
|
||||
}
|
||||
}
|
||||
|
||||
/// Target Operand Flag enum.
|
||||
enum TOF {
|
||||
//===------------------------------------------------------------------===//
|
||||
// ARM Specific MachineOperand flags.
|
||||
|
||||
MO_NO_FLAG = 0,
|
||||
|
||||
/// MO_LO16 - On a symbol operand, this represents a relocation containing
|
||||
/// lower 16 bit of the address. Used only via movw instruction.
|
||||
MO_LO16 = 0x1,
|
||||
|
||||
/// MO_HI16 - On a symbol operand, this represents a relocation containing
|
||||
/// higher 16 bit of the address. Used only via movt instruction.
|
||||
MO_HI16 = 0x2,
|
||||
|
||||
/// MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects
|
||||
/// just that part of the flag set.
|
||||
MO_OPTION_MASK = 0x3,
|
||||
|
||||
/// MO_GOT - On a symbol operand, this represents a GOT relative relocation.
|
||||
MO_GOT = 0x8,
|
||||
|
||||
/// MO_SBREL - On a symbol operand, this represents a static base relative
|
||||
/// relocation. Used in movw and movt instructions.
|
||||
MO_SBREL = 0x10,
|
||||
|
||||
/// MO_DLLIMPORT - On a symbol operand, this represents that the reference
|
||||
/// to the symbol is for an import stub. This is used for DLL import
|
||||
/// storage class indication on Windows.
|
||||
MO_DLLIMPORT = 0x20,
|
||||
|
||||
/// MO_SECREL - On a symbol operand this indicates that the immediate is
|
||||
/// the offset from beginning of section.
|
||||
///
|
||||
/// This is the TLS offset for the COFF/Windows TLS mechanism.
|
||||
MO_SECREL = 0x40,
|
||||
|
||||
/// MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it
|
||||
/// represents a symbol which, if indirect, will get special Darwin mangling
|
||||
/// as a non-lazy-ptr indirect symbol (i.e. "L_FOO$non_lazy_ptr"). Can be
|
||||
/// combined with MO_LO16, MO_HI16 or MO_NO_FLAG (in a constant-pool, for
|
||||
/// example).
|
||||
MO_NONLAZY = 0x80,
|
||||
|
||||
// It's undefined behaviour if an enum overflows the range between its
|
||||
// smallest and largest values, but since these are |ed together, it can
|
||||
// happen. Put a sentinel in (values of this enum are stored as "unsigned
|
||||
// char").
|
||||
MO_UNUSED_MAXIMUM = 0xff
|
||||
};
|
||||
|
||||
enum {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Instruction Flags.
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// This four-bit field describes the addressing mode used.
|
||||
AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h
|
||||
|
||||
// IndexMode - Unindex, pre-indexed, or post-indexed are valid for load
|
||||
// and store ops only. Generic "updating" flag is used for ld/st multiple.
|
||||
// The index mode enums are declared in ARMBaseInfo.h
|
||||
IndexModeShift = 5,
|
||||
IndexModeMask = 3 << IndexModeShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Instruction encoding formats.
|
||||
//
|
||||
FormShift = 7,
|
||||
FormMask = 0x3f << FormShift,
|
||||
|
||||
// Pseudo instructions
|
||||
Pseudo = 0 << FormShift,
|
||||
|
||||
// Multiply instructions
|
||||
MulFrm = 1 << FormShift,
|
||||
|
||||
// Branch instructions
|
||||
BrFrm = 2 << FormShift,
|
||||
BrMiscFrm = 3 << FormShift,
|
||||
|
||||
// Data Processing instructions
|
||||
DPFrm = 4 << FormShift,
|
||||
DPSoRegFrm = 5 << FormShift,
|
||||
|
||||
// Load and Store
|
||||
LdFrm = 6 << FormShift,
|
||||
StFrm = 7 << FormShift,
|
||||
LdMiscFrm = 8 << FormShift,
|
||||
StMiscFrm = 9 << FormShift,
|
||||
LdStMulFrm = 10 << FormShift,
|
||||
|
||||
LdStExFrm = 11 << FormShift,
|
||||
|
||||
// Miscellaneous arithmetic instructions
|
||||
ArithMiscFrm = 12 << FormShift,
|
||||
SatFrm = 13 << FormShift,
|
||||
|
||||
// Extend instructions
|
||||
ExtFrm = 14 << FormShift,
|
||||
|
||||
// VFP formats
|
||||
VFPUnaryFrm = 15 << FormShift,
|
||||
VFPBinaryFrm = 16 << FormShift,
|
||||
VFPConv1Frm = 17 << FormShift,
|
||||
VFPConv2Frm = 18 << FormShift,
|
||||
VFPConv3Frm = 19 << FormShift,
|
||||
VFPConv4Frm = 20 << FormShift,
|
||||
VFPConv5Frm = 21 << FormShift,
|
||||
VFPLdStFrm = 22 << FormShift,
|
||||
VFPLdStMulFrm = 23 << FormShift,
|
||||
VFPMiscFrm = 24 << FormShift,
|
||||
|
||||
// Thumb format
|
||||
ThumbFrm = 25 << FormShift,
|
||||
|
||||
// Miscelleaneous format
|
||||
MiscFrm = 26 << FormShift,
|
||||
|
||||
// NEON formats
|
||||
NGetLnFrm = 27 << FormShift,
|
||||
NSetLnFrm = 28 << FormShift,
|
||||
NDupFrm = 29 << FormShift,
|
||||
NLdStFrm = 30 << FormShift,
|
||||
N1RegModImmFrm= 31 << FormShift,
|
||||
N2RegFrm = 32 << FormShift,
|
||||
NVCVTFrm = 33 << FormShift,
|
||||
NVDupLnFrm = 34 << FormShift,
|
||||
N2RegVShLFrm = 35 << FormShift,
|
||||
N2RegVShRFrm = 36 << FormShift,
|
||||
N3RegFrm = 37 << FormShift,
|
||||
N3RegVShFrm = 38 << FormShift,
|
||||
NVExtFrm = 39 << FormShift,
|
||||
NVMulSLFrm = 40 << FormShift,
|
||||
NVTBLFrm = 41 << FormShift,
|
||||
N3RegCplxFrm = 43 << FormShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Misc flags.
|
||||
|
||||
// UnaryDP - Indicates this is a unary data processing instruction, i.e.
|
||||
// it doesn't have a Rn operand.
|
||||
UnaryDP = 1 << 13,
|
||||
|
||||
// Xform16Bit - Indicates this Thumb2 instruction may be transformed into
|
||||
// a 16-bit Thumb instruction if certain conditions are met.
|
||||
Xform16Bit = 1 << 14,
|
||||
|
||||
// ThumbArithFlagSetting - The instruction is a 16-bit flag setting Thumb
|
||||
// instruction. Used by the parser to determine whether to require the 'S'
|
||||
// suffix on the mnemonic (when not in an IT block) or preclude it (when
|
||||
// in an IT block).
|
||||
ThumbArithFlagSetting = 1 << 18,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Code domain.
|
||||
DomainShift = 15,
|
||||
DomainMask = 7 << DomainShift,
|
||||
DomainGeneral = 0 << DomainShift,
|
||||
DomainVFP = 1 << DomainShift,
|
||||
DomainNEON = 2 << DomainShift,
|
||||
DomainNEONA8 = 4 << DomainShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Field shifts - such shifts are used to set field while generating
|
||||
// machine instructions.
|
||||
//
|
||||
// FIXME: This list will need adjusting/fixing as the MC code emitter
|
||||
// takes shape and the ARMCodeEmitter.cpp bits go away.
|
||||
ShiftTypeShift = 4,
|
||||
|
||||
M_BitShift = 5,
|
||||
ShiftImmShift = 5,
|
||||
ShiftShift = 7,
|
||||
N_BitShift = 7,
|
||||
ImmHiShift = 8,
|
||||
SoRotImmShift = 8,
|
||||
RegRsShift = 8,
|
||||
ExtRotImmShift = 10,
|
||||
RegRdLoShift = 12,
|
||||
RegRdShift = 12,
|
||||
RegRdHiShift = 16,
|
||||
RegRnShift = 16,
|
||||
S_BitShift = 20,
|
||||
W_BitShift = 21,
|
||||
AM3_I_BitShift = 22,
|
||||
D_BitShift = 22,
|
||||
U_BitShift = 23,
|
||||
P_BitShift = 24,
|
||||
I_BitShift = 25,
|
||||
CondShift = 28
|
||||
};
|
||||
|
||||
} // end namespace ARMII
|
||||
|
||||
} // end namespace llvm;
|
||||
|
||||
#endif
|
@ -1,244 +0,0 @@
|
||||
//===-- ARMELFObjectWriter.cpp - ARM ELF Writer ---------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/ARMFixupKinds.h"
|
||||
#include "MCTargetDesc/ARMMCTargetDesc.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstdint>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class ARMELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
enum { DefaultEABIVersion = 0x05000000U };
|
||||
|
||||
unsigned GetRelocTypeInner(const MCValue &Target, const MCFixup &Fixup,
|
||||
bool IsPCRel, MCContext &Ctx) const;
|
||||
|
||||
public:
|
||||
ARMELFObjectWriter(uint8_t OSABI);
|
||||
|
||||
~ARMELFObjectWriter() override = default;
|
||||
|
||||
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
|
||||
const MCFixup &Fixup, bool IsPCRel) const override;
|
||||
|
||||
bool needsRelocateWithSymbol(const MCSymbol &Sym,
|
||||
unsigned Type) const override;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
|
||||
: MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
|
||||
ELF::EM_ARM,
|
||||
/*HasRelocationAddend*/ false) {}
|
||||
|
||||
bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
|
||||
unsigned Type) const {
|
||||
// FIXME: This is extremely conservative. This really needs to use a
|
||||
// whitelist with a clear explanation for why each realocation needs to
|
||||
// point to the symbol, not to the section.
|
||||
switch (Type) {
|
||||
default:
|
||||
return true;
|
||||
|
||||
case ELF::R_ARM_PREL31:
|
||||
case ELF::R_ARM_ABS32:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Need to examine the Fixup when determining whether to
|
||||
// emit the relocation as an explicit symbol or as a section relative
|
||||
// offset
|
||||
unsigned ARMELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
return GetRelocTypeInner(Target, Fixup, IsPCRel, Ctx);
|
||||
}
|
||||
|
||||
unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel,
|
||||
MCContext &Ctx) const {
|
||||
MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
|
||||
|
||||
if (IsPCRel) {
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
default:
|
||||
Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
|
||||
return ELF::R_ARM_NONE;
|
||||
case FK_Data_4:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_ARM_REL32;
|
||||
case MCSymbolRefExpr::VK_GOTTPOFF:
|
||||
return ELF::R_ARM_TLS_IE32;
|
||||
case MCSymbolRefExpr::VK_ARM_GOT_PREL:
|
||||
return ELF::R_ARM_GOT_PREL;
|
||||
case MCSymbolRefExpr::VK_ARM_PREL31:
|
||||
return ELF::R_ARM_PREL31;
|
||||
}
|
||||
case ARM::fixup_arm_blx:
|
||||
case ARM::fixup_arm_uncondbl:
|
||||
switch (Modifier) {
|
||||
case MCSymbolRefExpr::VK_PLT:
|
||||
return ELF::R_ARM_CALL;
|
||||
case MCSymbolRefExpr::VK_TLSCALL:
|
||||
return ELF::R_ARM_TLS_CALL;
|
||||
default:
|
||||
return ELF::R_ARM_CALL;
|
||||
}
|
||||
case ARM::fixup_arm_condbl:
|
||||
case ARM::fixup_arm_condbranch:
|
||||
case ARM::fixup_arm_uncondbranch:
|
||||
return ELF::R_ARM_JUMP24;
|
||||
case ARM::fixup_t2_condbranch:
|
||||
return ELF::R_ARM_THM_JUMP19;
|
||||
case ARM::fixup_t2_uncondbranch:
|
||||
return ELF::R_ARM_THM_JUMP24;
|
||||
case ARM::fixup_arm_movt_hi16:
|
||||
return ELF::R_ARM_MOVT_PREL;
|
||||
case ARM::fixup_arm_movw_lo16:
|
||||
return ELF::R_ARM_MOVW_PREL_NC;
|
||||
case ARM::fixup_t2_movt_hi16:
|
||||
return ELF::R_ARM_THM_MOVT_PREL;
|
||||
case ARM::fixup_t2_movw_lo16:
|
||||
return ELF::R_ARM_THM_MOVW_PREL_NC;
|
||||
case ARM::fixup_arm_thumb_br:
|
||||
return ELF::R_ARM_THM_JUMP11;
|
||||
case ARM::fixup_arm_thumb_bcc:
|
||||
return ELF::R_ARM_THM_JUMP8;
|
||||
case ARM::fixup_arm_thumb_bl:
|
||||
case ARM::fixup_arm_thumb_blx:
|
||||
switch (Modifier) {
|
||||
case MCSymbolRefExpr::VK_TLSCALL:
|
||||
return ELF::R_ARM_THM_TLS_CALL;
|
||||
default:
|
||||
return ELF::R_ARM_THM_CALL;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
default:
|
||||
Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
|
||||
return ELF::R_ARM_NONE;
|
||||
case FK_Data_1:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_ARM_ABS8;
|
||||
}
|
||||
case FK_Data_2:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("unsupported modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_ARM_ABS16;
|
||||
}
|
||||
case FK_Data_4:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_ARM_NONE:
|
||||
return ELF::R_ARM_NONE;
|
||||
case MCSymbolRefExpr::VK_GOT:
|
||||
return ELF::R_ARM_GOT_BREL;
|
||||
case MCSymbolRefExpr::VK_TLSGD:
|
||||
return ELF::R_ARM_TLS_GD32;
|
||||
case MCSymbolRefExpr::VK_TPOFF:
|
||||
return ELF::R_ARM_TLS_LE32;
|
||||
case MCSymbolRefExpr::VK_GOTTPOFF:
|
||||
return ELF::R_ARM_TLS_IE32;
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_ARM_ABS32;
|
||||
case MCSymbolRefExpr::VK_GOTOFF:
|
||||
return ELF::R_ARM_GOTOFF32;
|
||||
case MCSymbolRefExpr::VK_ARM_GOT_PREL:
|
||||
return ELF::R_ARM_GOT_PREL;
|
||||
case MCSymbolRefExpr::VK_ARM_TARGET1:
|
||||
return ELF::R_ARM_TARGET1;
|
||||
case MCSymbolRefExpr::VK_ARM_TARGET2:
|
||||
return ELF::R_ARM_TARGET2;
|
||||
case MCSymbolRefExpr::VK_ARM_PREL31:
|
||||
return ELF::R_ARM_PREL31;
|
||||
case MCSymbolRefExpr::VK_ARM_SBREL:
|
||||
return ELF::R_ARM_SBREL32;
|
||||
case MCSymbolRefExpr::VK_ARM_TLSLDO:
|
||||
return ELF::R_ARM_TLS_LDO32;
|
||||
case MCSymbolRefExpr::VK_TLSCALL:
|
||||
return ELF::R_ARM_TLS_CALL;
|
||||
case MCSymbolRefExpr::VK_TLSDESC:
|
||||
return ELF::R_ARM_TLS_GOTDESC;
|
||||
case MCSymbolRefExpr::VK_TLSLDM:
|
||||
return ELF::R_ARM_TLS_LDM32;
|
||||
case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
|
||||
return ELF::R_ARM_TLS_DESCSEQ;
|
||||
}
|
||||
case ARM::fixup_arm_condbranch:
|
||||
case ARM::fixup_arm_uncondbranch:
|
||||
return ELF::R_ARM_JUMP24;
|
||||
case ARM::fixup_arm_movt_hi16:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_ARM_MOVT_ABS;
|
||||
case MCSymbolRefExpr::VK_ARM_SBREL:
|
||||
return ELF::R_ARM_MOVT_BREL;
|
||||
}
|
||||
case ARM::fixup_arm_movw_lo16:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_ARM_MOVW_ABS_NC;
|
||||
case MCSymbolRefExpr::VK_ARM_SBREL:
|
||||
return ELF::R_ARM_MOVW_BREL_NC;
|
||||
}
|
||||
case ARM::fixup_t2_movt_hi16:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_ARM_THM_MOVT_ABS;
|
||||
case MCSymbolRefExpr::VK_ARM_SBREL:
|
||||
return ELF::R_ARM_THM_MOVT_BREL;
|
||||
}
|
||||
case ARM::fixup_t2_movw_lo16:
|
||||
switch (Modifier) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
return ELF::R_ARM_THM_MOVW_ABS_NC;
|
||||
case MCSymbolRefExpr::VK_ARM_SBREL:
|
||||
return ELF::R_ARM_THM_MOVW_BREL_NC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
llvm::createARMELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI,
|
||||
bool IsLittleEndian) {
|
||||
return createELFObjectWriter(llvm::make_unique<ARMELFObjectWriter>(OSABI), OS,
|
||||
IsLittleEndian);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,114 +0,0 @@
|
||||
//===-- ARMFixupKinds.h - ARM Specific Fixup Entries ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMFIXUPKINDS_H
|
||||
#define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMFIXUPKINDS_H
|
||||
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace ARM {
|
||||
enum Fixups {
|
||||
// 12-bit PC relative relocation for symbol addresses
|
||||
fixup_arm_ldst_pcrel_12 = FirstTargetFixupKind,
|
||||
|
||||
// Equivalent to fixup_arm_ldst_pcrel_12, with the 16-bit halfwords reordered.
|
||||
fixup_t2_ldst_pcrel_12,
|
||||
|
||||
// 10-bit PC relative relocation for symbol addresses used in
|
||||
// LDRD/LDRH/LDRB/etc. instructions. All bits are encoded.
|
||||
fixup_arm_pcrel_10_unscaled,
|
||||
// 10-bit PC relative relocation for symbol addresses used in VFP instructions
|
||||
// where the lower 2 bits are not encoded (so it's encoded as an 8-bit
|
||||
// immediate).
|
||||
fixup_arm_pcrel_10,
|
||||
// Equivalent to fixup_arm_pcrel_10, accounting for the short-swapped encoding
|
||||
// of Thumb2 instructions.
|
||||
fixup_t2_pcrel_10,
|
||||
// 9-bit PC relative relocation for symbol addresses used in VFP instructions
|
||||
// where bit 0 not encoded (so it's encoded as an 8-bit immediate).
|
||||
fixup_arm_pcrel_9,
|
||||
// Equivalent to fixup_arm_pcrel_9, accounting for the short-swapped encoding
|
||||
// of Thumb2 instructions.
|
||||
fixup_t2_pcrel_9,
|
||||
// 10-bit PC relative relocation for symbol addresses where the lower 2 bits
|
||||
// are not encoded (so it's encoded as an 8-bit immediate).
|
||||
fixup_thumb_adr_pcrel_10,
|
||||
// 12-bit PC relative relocation for the ADR instruction.
|
||||
fixup_arm_adr_pcrel_12,
|
||||
// 12-bit PC relative relocation for the ADR instruction.
|
||||
fixup_t2_adr_pcrel_12,
|
||||
// 24-bit PC relative relocation for conditional branch instructions.
|
||||
fixup_arm_condbranch,
|
||||
// 24-bit PC relative relocation for branch instructions. (unconditional)
|
||||
fixup_arm_uncondbranch,
|
||||
// 20-bit PC relative relocation for Thumb2 direct uconditional branch
|
||||
// instructions.
|
||||
fixup_t2_condbranch,
|
||||
// 20-bit PC relative relocation for Thumb2 direct branch unconditional branch
|
||||
// instructions.
|
||||
fixup_t2_uncondbranch,
|
||||
|
||||
// 12-bit fixup for Thumb B instructions.
|
||||
fixup_arm_thumb_br,
|
||||
|
||||
// The following fixups handle the ARM BL instructions. These can be
|
||||
// conditionalised; however, the ARM ELF ABI requires a different relocation
|
||||
// in that case: R_ARM_JUMP24 instead of R_ARM_CALL. The difference is that
|
||||
// R_ARM_CALL is allowed to change the instruction to a BLX inline, which has
|
||||
// no conditional version; R_ARM_JUMP24 would have to insert a veneer.
|
||||
//
|
||||
// MachO does not draw a distinction between the two cases, so it will treat
|
||||
// fixup_arm_uncondbl and fixup_arm_condbl as identical fixups.
|
||||
|
||||
// Fixup for unconditional ARM BL instructions.
|
||||
fixup_arm_uncondbl,
|
||||
|
||||
// Fixup for ARM BL instructions with nontrivial conditionalisation.
|
||||
fixup_arm_condbl,
|
||||
|
||||
// Fixup for ARM BLX instructions.
|
||||
fixup_arm_blx,
|
||||
|
||||
// Fixup for Thumb BL instructions.
|
||||
fixup_arm_thumb_bl,
|
||||
|
||||
// Fixup for Thumb BLX instructions.
|
||||
fixup_arm_thumb_blx,
|
||||
|
||||
// Fixup for Thumb branch instructions.
|
||||
fixup_arm_thumb_cb,
|
||||
|
||||
// Fixup for Thumb load/store from constant pool instrs.
|
||||
fixup_arm_thumb_cp,
|
||||
|
||||
// Fixup for Thumb conditional branching instructions.
|
||||
fixup_arm_thumb_bcc,
|
||||
|
||||
// The next two are for the movt/movw pair
|
||||
// the 16bit imm field are split into imm{15-12} and imm{11-0}
|
||||
fixup_arm_movt_hi16, // :upper16:
|
||||
fixup_arm_movw_lo16, // :lower16:
|
||||
fixup_t2_movt_hi16, // :upper16:
|
||||
fixup_t2_movw_lo16, // :lower16:
|
||||
|
||||
// Fixup for mod_imm
|
||||
fixup_arm_mod_imm,
|
||||
|
||||
// Fixup for Thumb2 8-bit rotated operand
|
||||
fixup_t2_so_imm,
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
};
|
||||
}
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -1,114 +0,0 @@
|
||||
//===-- ARMMCAsmInfo.cpp - ARM asm properties -----------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declarations of the ARMMCAsmInfo properties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ARMMCAsmInfo.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void ARMMCAsmInfoDarwin::anchor() { }
|
||||
|
||||
ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin(const Triple &TheTriple) {
|
||||
if ((TheTriple.getArch() == Triple::armeb) ||
|
||||
(TheTriple.getArch() == Triple::thumbeb))
|
||||
IsLittleEndian = false;
|
||||
|
||||
Data64bitsDirective = nullptr;
|
||||
CommentString = "@";
|
||||
Code16Directive = ".code\t16";
|
||||
Code32Directive = ".code\t32";
|
||||
UseDataRegionDirectives = true;
|
||||
|
||||
SupportsDebugInformation = true;
|
||||
|
||||
// Exceptions handling
|
||||
ExceptionsType = (TheTriple.isOSDarwin() && !TheTriple.isWatchABI())
|
||||
? ExceptionHandling::SjLj
|
||||
: ExceptionHandling::DwarfCFI;
|
||||
|
||||
UseIntegratedAssembler = true;
|
||||
}
|
||||
|
||||
void ARMELFMCAsmInfo::anchor() { }
|
||||
|
||||
ARMELFMCAsmInfo::ARMELFMCAsmInfo(const Triple &TheTriple) {
|
||||
if ((TheTriple.getArch() == Triple::armeb) ||
|
||||
(TheTriple.getArch() == Triple::thumbeb))
|
||||
IsLittleEndian = false;
|
||||
|
||||
// ".comm align is in bytes but .align is pow-2."
|
||||
AlignmentIsInBytes = false;
|
||||
|
||||
Data64bitsDirective = nullptr;
|
||||
CommentString = "@";
|
||||
Code16Directive = ".code\t16";
|
||||
Code32Directive = ".code\t32";
|
||||
|
||||
SupportsDebugInformation = true;
|
||||
|
||||
// Exceptions handling
|
||||
switch (TheTriple.getOS()) {
|
||||
case Triple::NetBSD:
|
||||
ExceptionsType = ExceptionHandling::DwarfCFI;
|
||||
break;
|
||||
default:
|
||||
ExceptionsType = ExceptionHandling::ARM;
|
||||
break;
|
||||
}
|
||||
|
||||
// foo(plt) instead of foo@plt
|
||||
UseParensForSymbolVariant = true;
|
||||
|
||||
UseIntegratedAssembler = true;
|
||||
}
|
||||
|
||||
void ARMELFMCAsmInfo::setUseIntegratedAssembler(bool Value) {
|
||||
UseIntegratedAssembler = Value;
|
||||
if (!UseIntegratedAssembler) {
|
||||
// gas doesn't handle VFP register names in cfi directives,
|
||||
// so don't use register names with external assembler.
|
||||
// See https://sourceware.org/bugzilla/show_bug.cgi?id=16694
|
||||
DwarfRegNumForCFI = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ARMCOFFMCAsmInfoMicrosoft::anchor() { }
|
||||
|
||||
ARMCOFFMCAsmInfoMicrosoft::ARMCOFFMCAsmInfoMicrosoft() {
|
||||
AlignmentIsInBytes = false;
|
||||
ExceptionsType = ExceptionHandling::WinEH;
|
||||
PrivateGlobalPrefix = "$M";
|
||||
PrivateLabelPrefix = "$M";
|
||||
CommentString = ";";
|
||||
}
|
||||
|
||||
void ARMCOFFMCAsmInfoGNU::anchor() { }
|
||||
|
||||
ARMCOFFMCAsmInfoGNU::ARMCOFFMCAsmInfoGNU() {
|
||||
AlignmentIsInBytes = false;
|
||||
HasSingleParameterDotFile = true;
|
||||
|
||||
CommentString = "@";
|
||||
Code16Directive = ".code\t16";
|
||||
Code32Directive = ".code\t32";
|
||||
PrivateGlobalPrefix = ".L";
|
||||
PrivateLabelPrefix = ".L";
|
||||
|
||||
SupportsDebugInformation = true;
|
||||
ExceptionsType = ExceptionHandling::DwarfCFI;
|
||||
UseParensForSymbolVariant = true;
|
||||
|
||||
UseIntegratedAssembler = true;
|
||||
DwarfRegNumForCFI = false;
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
//===-- ARMMCAsmInfo.h - ARM asm properties --------------------*- 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 the declaration of the ARMMCAsmInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMMCASMINFO_H
|
||||
#define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMMCASMINFO_H
|
||||
|
||||
#include "llvm/MC/MCAsmInfoCOFF.h"
|
||||
#include "llvm/MC/MCAsmInfoDarwin.h"
|
||||
#include "llvm/MC/MCAsmInfoELF.h"
|
||||
|
||||
namespace llvm {
|
||||
class Triple;
|
||||
|
||||
class ARMMCAsmInfoDarwin : public MCAsmInfoDarwin {
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
explicit ARMMCAsmInfoDarwin(const Triple &TheTriple);
|
||||
};
|
||||
|
||||
class ARMELFMCAsmInfo : public MCAsmInfoELF {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
explicit ARMELFMCAsmInfo(const Triple &TT);
|
||||
|
||||
void setUseIntegratedAssembler(bool Value) override;
|
||||
};
|
||||
|
||||
class ARMCOFFMCAsmInfoMicrosoft : public MCAsmInfoMicrosoft {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
explicit ARMCOFFMCAsmInfoMicrosoft();
|
||||
};
|
||||
|
||||
class ARMCOFFMCAsmInfoGNU : public MCAsmInfoGNUCOFF {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
explicit ARMCOFFMCAsmInfoGNU();
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,40 +0,0 @@
|
||||
//===-- ARMMCExpr.cpp - ARM specific MC expression classes ----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ARMMCExpr.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "armmcexpr"
|
||||
|
||||
const ARMMCExpr*
|
||||
ARMMCExpr::create(VariantKind Kind, const MCExpr *Expr,
|
||||
MCContext &Ctx) {
|
||||
return new (Ctx) ARMMCExpr(Kind, Expr);
|
||||
}
|
||||
|
||||
void ARMMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
|
||||
switch (Kind) {
|
||||
default: llvm_unreachable("Invalid kind!");
|
||||
case VK_ARM_HI16: OS << ":upper16:"; break;
|
||||
case VK_ARM_LO16: OS << ":lower16:"; break;
|
||||
}
|
||||
|
||||
const MCExpr *Expr = getSubExpr();
|
||||
if (Expr->getKind() != MCExpr::SymbolRef)
|
||||
OS << '(';
|
||||
Expr->print(OS, MAI);
|
||||
if (Expr->getKind() != MCExpr::SymbolRef)
|
||||
OS << ')';
|
||||
}
|
||||
|
||||
void ARMMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
|
||||
Streamer.visitUsedExpr(*getSubExpr());
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
//===-- ARMMCExpr.h - ARM specific MC expression classes --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMMCEXPR_H
|
||||
#define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMMCEXPR_H
|
||||
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ARMMCExpr : public MCTargetExpr {
|
||||
public:
|
||||
enum VariantKind {
|
||||
VK_ARM_None,
|
||||
VK_ARM_HI16, // The R_ARM_MOVT_ABS relocation (:upper16: in the .s file)
|
||||
VK_ARM_LO16 // The R_ARM_MOVW_ABS_NC relocation (:lower16: in the .s file)
|
||||
};
|
||||
|
||||
private:
|
||||
const VariantKind Kind;
|
||||
const MCExpr *Expr;
|
||||
|
||||
explicit ARMMCExpr(VariantKind Kind, const MCExpr *Expr)
|
||||
: Kind(Kind), Expr(Expr) {}
|
||||
|
||||
public:
|
||||
/// @name Construction
|
||||
/// @{
|
||||
|
||||
static const ARMMCExpr *create(VariantKind Kind, const MCExpr *Expr,
|
||||
MCContext &Ctx);
|
||||
|
||||
static const ARMMCExpr *createUpper16(const MCExpr *Expr, MCContext &Ctx) {
|
||||
return create(VK_ARM_HI16, Expr, Ctx);
|
||||
}
|
||||
|
||||
static const ARMMCExpr *createLower16(const MCExpr *Expr, MCContext &Ctx) {
|
||||
return create(VK_ARM_LO16, Expr, Ctx);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
/// getOpcode - Get the kind of this expression.
|
||||
VariantKind getKind() const { return Kind; }
|
||||
|
||||
/// getSubExpr - Get the child of this expression.
|
||||
const MCExpr *getSubExpr() const { return Expr; }
|
||||
|
||||
/// @}
|
||||
|
||||
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
|
||||
bool evaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const override {
|
||||
return false;
|
||||
}
|
||||
void visitUsedExpr(MCStreamer &Streamer) const override;
|
||||
MCFragment *findAssociatedFragment() const override {
|
||||
return getSubExpr()->findAssociatedFragment();
|
||||
}
|
||||
|
||||
// There are no TLS ARMMCExprs at the moment.
|
||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
|
||||
|
||||
static bool classof(const MCExpr *E) {
|
||||
return E->getKind() == MCExpr::Target;
|
||||
}
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -1,356 +0,0 @@
|
||||
//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides ARM specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ARMMCTargetDesc.h"
|
||||
#include "ARMBaseInfo.h"
|
||||
#include "ARMMCAsmInfo.h"
|
||||
#include "InstPrinter/ARMInstPrinter.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
#include "llvm/MC/MCInstrAnalysis.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TargetParser.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define GET_REGINFO_MC_DESC
|
||||
#include "ARMGenRegisterInfo.inc"
|
||||
|
||||
static bool getMCRDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
|
||||
std::string &Info) {
|
||||
if (STI.getFeatureBits()[llvm::ARM::HasV7Ops] &&
|
||||
(MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) &&
|
||||
(MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) &&
|
||||
// Checks for the deprecated CP15ISB encoding:
|
||||
// mcr p15, #0, rX, c7, c5, #4
|
||||
(MI.getOperand(3).isImm() && MI.getOperand(3).getImm() == 7)) {
|
||||
if ((MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 4)) {
|
||||
if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 5) {
|
||||
Info = "deprecated since v7, use 'isb'";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks for the deprecated CP15DSB encoding:
|
||||
// mcr p15, #0, rX, c7, c10, #4
|
||||
if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10) {
|
||||
Info = "deprecated since v7, use 'dsb'";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Checks for the deprecated CP15DMB encoding:
|
||||
// mcr p15, #0, rX, c7, c10, #5
|
||||
if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10 &&
|
||||
(MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 5)) {
|
||||
Info = "deprecated since v7, use 'dmb'";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getITDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
|
||||
std::string &Info) {
|
||||
if (STI.getFeatureBits()[llvm::ARM::HasV8Ops] && MI.getOperand(1).isImm() &&
|
||||
MI.getOperand(1).getImm() != 8) {
|
||||
Info = "applying IT instruction to more than one subsequent instruction is "
|
||||
"deprecated";
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getARMStoreDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
|
||||
std::string &Info) {
|
||||
assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
|
||||
"cannot predicate thumb instructions");
|
||||
|
||||
assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
|
||||
for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
|
||||
assert(MI.getOperand(OI).isReg() && "expected register");
|
||||
if (MI.getOperand(OI).getReg() == ARM::SP ||
|
||||
MI.getOperand(OI).getReg() == ARM::PC) {
|
||||
Info = "use of SP or PC in the list is deprecated";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getARMLoadDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
|
||||
std::string &Info) {
|
||||
assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
|
||||
"cannot predicate thumb instructions");
|
||||
|
||||
assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
|
||||
bool ListContainsPC = false, ListContainsLR = false;
|
||||
for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
|
||||
assert(MI.getOperand(OI).isReg() && "expected register");
|
||||
switch (MI.getOperand(OI).getReg()) {
|
||||
default:
|
||||
break;
|
||||
case ARM::LR:
|
||||
ListContainsLR = true;
|
||||
break;
|
||||
case ARM::PC:
|
||||
ListContainsPC = true;
|
||||
break;
|
||||
case ARM::SP:
|
||||
Info = "use of SP in the list is deprecated";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ListContainsPC && ListContainsLR) {
|
||||
Info = "use of LR and PC simultaneously in the list is deprecated";
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define GET_INSTRINFO_MC_DESC
|
||||
#include "ARMGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_MC_DESC
|
||||
#include "ARMGenSubtargetInfo.inc"
|
||||
|
||||
std::string ARM_MC::ParseARMTriple(const Triple &TT, StringRef CPU) {
|
||||
std::string ARMArchFeature;
|
||||
|
||||
ARM::ArchKind ArchID = ARM::parseArch(TT.getArchName());
|
||||
if (ArchID != ARM::ArchKind::INVALID && (CPU.empty() || CPU == "generic"))
|
||||
ARMArchFeature = (ARMArchFeature + "+" + ARM::getArchName(ArchID)).str();
|
||||
|
||||
if (TT.isThumb()) {
|
||||
if (ARMArchFeature.empty())
|
||||
ARMArchFeature = "+thumb-mode,+v4t";
|
||||
else
|
||||
ARMArchFeature += ",+thumb-mode,+v4t";
|
||||
}
|
||||
|
||||
if (TT.isOSNaCl()) {
|
||||
if (ARMArchFeature.empty())
|
||||
ARMArchFeature = "+nacl-trap";
|
||||
else
|
||||
ARMArchFeature += ",+nacl-trap";
|
||||
}
|
||||
|
||||
return ARMArchFeature;
|
||||
}
|
||||
|
||||
MCSubtargetInfo *ARM_MC::createARMMCSubtargetInfo(const Triple &TT,
|
||||
StringRef CPU, StringRef FS) {
|
||||
std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
|
||||
if (!FS.empty()) {
|
||||
if (!ArchFS.empty())
|
||||
ArchFS = (Twine(ArchFS) + "," + FS).str();
|
||||
else
|
||||
ArchFS = FS;
|
||||
}
|
||||
|
||||
return createARMMCSubtargetInfoImpl(TT, CPU, ArchFS);
|
||||
}
|
||||
|
||||
static MCInstrInfo *createARMMCInstrInfo() {
|
||||
MCInstrInfo *X = new MCInstrInfo();
|
||||
InitARMMCInstrInfo(X);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCRegisterInfo *createARMMCRegisterInfo(const Triple &Triple) {
|
||||
MCRegisterInfo *X = new MCRegisterInfo();
|
||||
InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI,
|
||||
const Triple &TheTriple) {
|
||||
MCAsmInfo *MAI;
|
||||
if (TheTriple.isOSDarwin() || TheTriple.isOSBinFormatMachO())
|
||||
MAI = new ARMMCAsmInfoDarwin(TheTriple);
|
||||
else if (TheTriple.isWindowsMSVCEnvironment())
|
||||
MAI = new ARMCOFFMCAsmInfoMicrosoft();
|
||||
else if (TheTriple.isOSWindows())
|
||||
MAI = new ARMCOFFMCAsmInfoGNU();
|
||||
else
|
||||
MAI = new ARMELFMCAsmInfo(TheTriple);
|
||||
|
||||
unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true);
|
||||
MAI->addInitialFrameState(MCCFIInstruction::createDefCfa(nullptr, Reg, 0));
|
||||
|
||||
return MAI;
|
||||
}
|
||||
|
||||
static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx,
|
||||
std::unique_ptr<MCAsmBackend> &&MAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> &&Emitter,
|
||||
bool RelaxAll) {
|
||||
return createARMELFStreamer(
|
||||
Ctx, std::move(MAB), OS, std::move(Emitter), false,
|
||||
(T.getArch() == Triple::thumb || T.getArch() == Triple::thumbeb));
|
||||
}
|
||||
|
||||
static MCStreamer *
|
||||
createARMMachOStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&MAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll,
|
||||
bool DWARFMustBeAtTheEnd) {
|
||||
return createMachOStreamer(Ctx, std::move(MAB), OS, std::move(Emitter), false,
|
||||
DWARFMustBeAtTheEnd);
|
||||
}
|
||||
|
||||
static MCInstPrinter *createARMMCInstPrinter(const Triple &T,
|
||||
unsigned SyntaxVariant,
|
||||
const MCAsmInfo &MAI,
|
||||
const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI) {
|
||||
if (SyntaxVariant == 0)
|
||||
return new ARMInstPrinter(MAI, MII, MRI);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static MCRelocationInfo *createARMMCRelocationInfo(const Triple &TT,
|
||||
MCContext &Ctx) {
|
||||
if (TT.isOSBinFormatMachO())
|
||||
return createARMMachORelocationInfo(Ctx);
|
||||
// Default to the stock relocation info.
|
||||
return llvm::createMCRelocationInfo(TT, Ctx);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ARMMCInstrAnalysis : public MCInstrAnalysis {
|
||||
public:
|
||||
ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
|
||||
|
||||
bool isUnconditionalBranch(const MCInst &Inst) const override {
|
||||
// BCCs with the "always" predicate are unconditional branches.
|
||||
if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
|
||||
return true;
|
||||
return MCInstrAnalysis::isUnconditionalBranch(Inst);
|
||||
}
|
||||
|
||||
bool isConditionalBranch(const MCInst &Inst) const override {
|
||||
// BCCs with the "always" predicate are unconditional branches.
|
||||
if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
|
||||
return false;
|
||||
return MCInstrAnalysis::isConditionalBranch(Inst);
|
||||
}
|
||||
|
||||
bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
|
||||
uint64_t Size, uint64_t &Target) const override {
|
||||
// We only handle PCRel branches for now.
|
||||
if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
|
||||
return false;
|
||||
|
||||
int64_t Imm = Inst.getOperand(0).getImm();
|
||||
Target = Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class ThumbMCInstrAnalysis : public ARMMCInstrAnalysis {
|
||||
public:
|
||||
ThumbMCInstrAnalysis(const MCInstrInfo *Info) : ARMMCInstrAnalysis(Info) {}
|
||||
|
||||
bool evaluateBranch(const MCInst &Inst, uint64_t Addr,
|
||||
uint64_t Size, uint64_t &Target) const override {
|
||||
// We only handle PCRel branches for now.
|
||||
if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL)
|
||||
return false;
|
||||
|
||||
int64_t Imm = Inst.getOperand(0).getImm();
|
||||
Target = Addr+Imm+4; // In Thumb mode the PC is always off by 4 bytes.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) {
|
||||
return new ARMMCInstrAnalysis(Info);
|
||||
}
|
||||
|
||||
static MCInstrAnalysis *createThumbMCInstrAnalysis(const MCInstrInfo *Info) {
|
||||
return new ThumbMCInstrAnalysis(Info);
|
||||
}
|
||||
|
||||
// Force static initialization.
|
||||
extern "C" void LLVMInitializeARMTargetMC() {
|
||||
for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget(),
|
||||
&getTheThumbLETarget(), &getTheThumbBETarget()}) {
|
||||
// Register the MC asm info.
|
||||
RegisterMCAsmInfoFn X(*T, createARMMCAsmInfo);
|
||||
|
||||
// Register the MC instruction info.
|
||||
TargetRegistry::RegisterMCInstrInfo(*T, createARMMCInstrInfo);
|
||||
|
||||
// Register the MC register info.
|
||||
TargetRegistry::RegisterMCRegInfo(*T, createARMMCRegisterInfo);
|
||||
|
||||
// Register the MC subtarget info.
|
||||
TargetRegistry::RegisterMCSubtargetInfo(*T,
|
||||
ARM_MC::createARMMCSubtargetInfo);
|
||||
|
||||
TargetRegistry::RegisterELFStreamer(*T, createELFStreamer);
|
||||
TargetRegistry::RegisterCOFFStreamer(*T, createARMWinCOFFStreamer);
|
||||
TargetRegistry::RegisterMachOStreamer(*T, createARMMachOStreamer);
|
||||
|
||||
// Register the obj target streamer.
|
||||
TargetRegistry::RegisterObjectTargetStreamer(*T,
|
||||
createARMObjectTargetStreamer);
|
||||
|
||||
// Register the asm streamer.
|
||||
TargetRegistry::RegisterAsmTargetStreamer(*T, createARMTargetAsmStreamer);
|
||||
|
||||
// Register the null TargetStreamer.
|
||||
TargetRegistry::RegisterNullTargetStreamer(*T, createARMNullTargetStreamer);
|
||||
|
||||
// Register the MCInstPrinter.
|
||||
TargetRegistry::RegisterMCInstPrinter(*T, createARMMCInstPrinter);
|
||||
|
||||
// Register the MC relocation info.
|
||||
TargetRegistry::RegisterMCRelocationInfo(*T, createARMMCRelocationInfo);
|
||||
}
|
||||
|
||||
// Register the MC instruction analyzer.
|
||||
for (Target *T : {&getTheARMLETarget(), &getTheARMBETarget()})
|
||||
TargetRegistry::RegisterMCInstrAnalysis(*T, createARMMCInstrAnalysis);
|
||||
for (Target *T : {&getTheThumbLETarget(), &getTheThumbBETarget()})
|
||||
TargetRegistry::RegisterMCInstrAnalysis(*T, createThumbMCInstrAnalysis);
|
||||
|
||||
// Register the MC Code Emitter
|
||||
for (Target *T : {&getTheARMLETarget(), &getTheThumbLETarget()})
|
||||
TargetRegistry::RegisterMCCodeEmitter(*T, createARMLEMCCodeEmitter);
|
||||
for (Target *T : {&getTheARMBETarget(), &getTheThumbBETarget()})
|
||||
TargetRegistry::RegisterMCCodeEmitter(*T, createARMBEMCCodeEmitter);
|
||||
|
||||
// Register the asm backend.
|
||||
TargetRegistry::RegisterMCAsmBackend(getTheARMLETarget(),
|
||||
createARMLEAsmBackend);
|
||||
TargetRegistry::RegisterMCAsmBackend(getTheARMBETarget(),
|
||||
createARMBEAsmBackend);
|
||||
TargetRegistry::RegisterMCAsmBackend(getTheThumbLETarget(),
|
||||
createThumbLEAsmBackend);
|
||||
TargetRegistry::RegisterMCAsmBackend(getTheThumbBETarget(),
|
||||
createThumbBEAsmBackend);
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
//===-- ARMMCTargetDesc.h - ARM Target Descriptions -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides ARM specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMMCTARGETDESC_H
|
||||
#define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMMCTARGETDESC_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class formatted_raw_ostream;
|
||||
class MCAsmBackend;
|
||||
class MCCodeEmitter;
|
||||
class MCContext;
|
||||
class MCInstrInfo;
|
||||
class MCInstPrinter;
|
||||
class MCObjectWriter;
|
||||
class MCRegisterInfo;
|
||||
class MCSubtargetInfo;
|
||||
class MCStreamer;
|
||||
class MCTargetOptions;
|
||||
class MCRelocationInfo;
|
||||
class MCTargetStreamer;
|
||||
class StringRef;
|
||||
class Target;
|
||||
class Triple;
|
||||
class raw_ostream;
|
||||
class raw_pwrite_stream;
|
||||
|
||||
Target &getTheARMLETarget();
|
||||
Target &getTheThumbLETarget();
|
||||
Target &getTheARMBETarget();
|
||||
Target &getTheThumbBETarget();
|
||||
|
||||
namespace ARM_MC {
|
||||
std::string ParseARMTriple(const Triple &TT, StringRef CPU);
|
||||
|
||||
/// Create a ARM MCSubtargetInfo instance. This is exposed so Asm parser, etc.
|
||||
/// do not need to go through TargetRegistry.
|
||||
MCSubtargetInfo *createARMMCSubtargetInfo(const Triple &TT, StringRef CPU,
|
||||
StringRef FS);
|
||||
}
|
||||
|
||||
MCTargetStreamer *createARMNullTargetStreamer(MCStreamer &S);
|
||||
MCTargetStreamer *createARMTargetAsmStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS,
|
||||
MCInstPrinter *InstPrint,
|
||||
bool isVerboseAsm);
|
||||
MCTargetStreamer *createARMObjectTargetStreamer(MCStreamer &S,
|
||||
const MCSubtargetInfo &STI);
|
||||
|
||||
MCCodeEmitter *createARMLEMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx);
|
||||
|
||||
MCCodeEmitter *createARMBEMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx);
|
||||
|
||||
MCAsmBackend *createARMAsmBackend(const Target &T, const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCTargetOptions &Options,
|
||||
bool IsLittleEndian);
|
||||
|
||||
MCAsmBackend *createARMLEAsmBackend(const Target &T, const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCTargetOptions &Options);
|
||||
|
||||
MCAsmBackend *createARMBEAsmBackend(const Target &T, const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCTargetOptions &Options);
|
||||
|
||||
MCAsmBackend *createThumbLEAsmBackend(const Target &T,
|
||||
const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCTargetOptions &Options);
|
||||
|
||||
MCAsmBackend *createThumbBEAsmBackend(const Target &T,
|
||||
const MCSubtargetInfo &STI,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCTargetOptions &Options);
|
||||
|
||||
// Construct a PE/COFF machine code streamer which will generate a PE/COFF
|
||||
// object file.
|
||||
MCStreamer *createARMWinCOFFStreamer(MCContext &Context,
|
||||
std::unique_ptr<MCAsmBackend> &&MAB,
|
||||
raw_pwrite_stream &OS,
|
||||
std::unique_ptr<MCCodeEmitter> &&Emitter,
|
||||
bool RelaxAll,
|
||||
bool IncrementalLinkerCompatible);
|
||||
|
||||
/// Construct an ELF Mach-O object writer.
|
||||
std::unique_ptr<MCObjectWriter> createARMELFObjectWriter(raw_pwrite_stream &OS,
|
||||
uint8_t OSABI,
|
||||
bool IsLittleEndian);
|
||||
|
||||
/// Construct an ARM Mach-O object writer.
|
||||
std::unique_ptr<MCObjectWriter> createARMMachObjectWriter(raw_pwrite_stream &OS,
|
||||
bool Is64Bit,
|
||||
uint32_t CPUType,
|
||||
uint32_t CPUSubtype);
|
||||
|
||||
/// Construct an ARM PE/COFF object writer.
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createARMWinCOFFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit);
|
||||
|
||||
/// Construct ARM Mach-O relocation info.
|
||||
MCRelocationInfo *createARMMachORelocationInfo(MCContext &Ctx);
|
||||
} // End llvm namespace
|
||||
|
||||
// Defines symbolic names for ARM registers. This defines a mapping from
|
||||
// register name to register number.
|
||||
//
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "ARMGenRegisterInfo.inc"
|
||||
|
||||
// Defines symbolic names for the ARM instructions.
|
||||
//
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "ARMGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_ENUM
|
||||
#include "ARMGenSubtargetInfo.inc"
|
||||
|
||||
#endif
|
@ -1,43 +0,0 @@
|
||||
//===- ARMMachORelocationInfo.cpp -----------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ARMMCExpr.h"
|
||||
#include "MCTargetDesc/ARMMCTargetDesc.h"
|
||||
#include "llvm-c/Disassembler.h"
|
||||
#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class ARMMachORelocationInfo : public MCRelocationInfo {
|
||||
public:
|
||||
ARMMachORelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {}
|
||||
|
||||
const MCExpr *createExprForCAPIVariantKind(const MCExpr *SubExpr,
|
||||
unsigned VariantKind) override {
|
||||
switch(VariantKind) {
|
||||
case LLVMDisassembler_VariantKind_ARM_HI16:
|
||||
return ARMMCExpr::createUpper16(SubExpr, Ctx);
|
||||
case LLVMDisassembler_VariantKind_ARM_LO16:
|
||||
return ARMMCExpr::createLower16(SubExpr, Ctx);
|
||||
default:
|
||||
return MCRelocationInfo::createExprForCAPIVariantKind(SubExpr,
|
||||
VariantKind);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
/// createARMMachORelocationInfo - Construct an ARM Mach-O RelocationInfo.
|
||||
MCRelocationInfo *llvm::createARMMachORelocationInfo(MCContext &Ctx) {
|
||||
return new ARMMachORelocationInfo(Ctx);
|
||||
}
|
@ -1,493 +0,0 @@
|
||||
//===-- ARMMachObjectWriter.cpp - ARM Mach Object Writer ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/ARMBaseInfo.h"
|
||||
#include "MCTargetDesc/ARMFixupKinds.h"
|
||||
#include "MCTargetDesc/ARMMCTargetDesc.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/MC/MCAsmLayout.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCFixupKindInfo.h"
|
||||
#include "llvm/MC/MCMachObjectWriter.h"
|
||||
#include "llvm/MC/MCSection.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class ARMMachObjectWriter : public MCMachObjectTargetWriter {
|
||||
void RecordARMScatteredRelocation(MachObjectWriter *Writer,
|
||||
const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup,
|
||||
MCValue Target,
|
||||
unsigned Type,
|
||||
unsigned Log2Size,
|
||||
uint64_t &FixedValue);
|
||||
void RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
|
||||
const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue);
|
||||
|
||||
bool requiresExternRelocation(MachObjectWriter *Writer,
|
||||
const MCAssembler &Asm,
|
||||
const MCFragment &Fragment, unsigned RelocType,
|
||||
const MCSymbol &S, uint64_t FixedValue);
|
||||
|
||||
public:
|
||||
ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype)
|
||||
: MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {}
|
||||
|
||||
void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout, const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue) override;
|
||||
};
|
||||
}
|
||||
|
||||
static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
|
||||
unsigned &Log2Size) {
|
||||
RelocType = unsigned(MachO::ARM_RELOC_VANILLA);
|
||||
Log2Size = ~0U;
|
||||
|
||||
switch (Kind) {
|
||||
default:
|
||||
return false;
|
||||
|
||||
case FK_Data_1:
|
||||
Log2Size = llvm::Log2_32(1);
|
||||
return true;
|
||||
case FK_Data_2:
|
||||
Log2Size = llvm::Log2_32(2);
|
||||
return true;
|
||||
case FK_Data_4:
|
||||
Log2Size = llvm::Log2_32(4);
|
||||
return true;
|
||||
case FK_Data_8:
|
||||
Log2Size = llvm::Log2_32(8);
|
||||
return true;
|
||||
|
||||
// These fixups are expected to always be resolvable at assembly time and
|
||||
// have no relocations supported.
|
||||
case ARM::fixup_arm_ldst_pcrel_12:
|
||||
case ARM::fixup_arm_pcrel_10:
|
||||
case ARM::fixup_arm_adr_pcrel_12:
|
||||
case ARM::fixup_arm_thumb_br:
|
||||
return false;
|
||||
|
||||
// Handle 24-bit branch kinds.
|
||||
case ARM::fixup_arm_condbranch:
|
||||
case ARM::fixup_arm_uncondbranch:
|
||||
case ARM::fixup_arm_uncondbl:
|
||||
case ARM::fixup_arm_condbl:
|
||||
case ARM::fixup_arm_blx:
|
||||
RelocType = unsigned(MachO::ARM_RELOC_BR24);
|
||||
// Report as 'long', even though that is not quite accurate.
|
||||
Log2Size = llvm::Log2_32(4);
|
||||
return true;
|
||||
|
||||
case ARM::fixup_t2_uncondbranch:
|
||||
case ARM::fixup_arm_thumb_bl:
|
||||
case ARM::fixup_arm_thumb_blx:
|
||||
RelocType = unsigned(MachO::ARM_THUMB_RELOC_BR22);
|
||||
Log2Size = llvm::Log2_32(4);
|
||||
return true;
|
||||
|
||||
// For movw/movt r_type relocations they always have a pair following them and
|
||||
// the r_length bits are used differently. The encoding of the r_length is as
|
||||
// follows:
|
||||
// low bit of r_length:
|
||||
// 0 - :lower16: for movw instructions
|
||||
// 1 - :upper16: for movt instructions
|
||||
// high bit of r_length:
|
||||
// 0 - arm instructions
|
||||
// 1 - thumb instructions
|
||||
case ARM::fixup_arm_movt_hi16:
|
||||
RelocType = unsigned(MachO::ARM_RELOC_HALF);
|
||||
Log2Size = 1;
|
||||
return true;
|
||||
case ARM::fixup_t2_movt_hi16:
|
||||
RelocType = unsigned(MachO::ARM_RELOC_HALF);
|
||||
Log2Size = 3;
|
||||
return true;
|
||||
|
||||
case ARM::fixup_arm_movw_lo16:
|
||||
RelocType = unsigned(MachO::ARM_RELOC_HALF);
|
||||
Log2Size = 0;
|
||||
return true;
|
||||
case ARM::fixup_t2_movw_lo16:
|
||||
RelocType = unsigned(MachO::ARM_RELOC_HALF);
|
||||
Log2Size = 2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ARMMachObjectWriter::
|
||||
RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
|
||||
const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup,
|
||||
MCValue Target,
|
||||
uint64_t &FixedValue) {
|
||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||
unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
|
||||
unsigned Type = MachO::ARM_RELOC_HALF;
|
||||
|
||||
// See <reloc.h>.
|
||||
const MCSymbol *A = &Target.getSymA()->getSymbol();
|
||||
|
||||
if (!A->getFragment()) {
|
||||
Asm.getContext().reportError(Fixup.getLoc(),
|
||||
"symbol '" + A->getName() +
|
||||
"' can not be undefined in a subtraction expression");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t Value = Writer->getSymbolAddress(*A, Layout);
|
||||
uint32_t Value2 = 0;
|
||||
uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent());
|
||||
FixedValue += SecAddr;
|
||||
|
||||
if (const MCSymbolRefExpr *B = Target.getSymB()) {
|
||||
const MCSymbol *SB = &B->getSymbol();
|
||||
|
||||
if (!SB->getFragment()) {
|
||||
Asm.getContext().reportError(Fixup.getLoc(),
|
||||
"symbol '" + B->getSymbol().getName() +
|
||||
"' can not be undefined in a subtraction expression");
|
||||
return;
|
||||
}
|
||||
|
||||
// Select the appropriate difference relocation type.
|
||||
Type = MachO::ARM_RELOC_HALF_SECTDIFF;
|
||||
Value2 = Writer->getSymbolAddress(B->getSymbol(), Layout);
|
||||
FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent());
|
||||
}
|
||||
|
||||
// Relocations are written out in reverse order, so the PAIR comes first.
|
||||
// ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
|
||||
//
|
||||
// For these two r_type relocations they always have a pair following them and
|
||||
// the r_length bits are used differently. The encoding of the r_length is as
|
||||
// follows:
|
||||
// low bit of r_length:
|
||||
// 0 - :lower16: for movw instructions
|
||||
// 1 - :upper16: for movt instructions
|
||||
// high bit of r_length:
|
||||
// 0 - arm instructions
|
||||
// 1 - thumb instructions
|
||||
// the other half of the relocated expression is in the following pair
|
||||
// relocation entry in the low 16 bits of r_address field.
|
||||
unsigned ThumbBit = 0;
|
||||
unsigned MovtBit = 0;
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
default: break;
|
||||
case ARM::fixup_arm_movt_hi16:
|
||||
MovtBit = 1;
|
||||
// The thumb bit shouldn't be set in the 'other-half' bit of the
|
||||
// relocation, but it will be set in FixedValue if the base symbol
|
||||
// is a thumb function. Clear it out here.
|
||||
if (Asm.isThumbFunc(A))
|
||||
FixedValue &= 0xfffffffe;
|
||||
break;
|
||||
case ARM::fixup_t2_movt_hi16:
|
||||
if (Asm.isThumbFunc(A))
|
||||
FixedValue &= 0xfffffffe;
|
||||
MovtBit = 1;
|
||||
LLVM_FALLTHROUGH;
|
||||
case ARM::fixup_t2_movw_lo16:
|
||||
ThumbBit = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
|
||||
uint32_t OtherHalf = MovtBit
|
||||
? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);
|
||||
|
||||
MachO::any_relocation_info MRE;
|
||||
MRE.r_word0 = ((OtherHalf << 0) |
|
||||
(MachO::ARM_RELOC_PAIR << 24) |
|
||||
(MovtBit << 28) |
|
||||
(ThumbBit << 29) |
|
||||
(IsPCRel << 30) |
|
||||
MachO::R_SCATTERED);
|
||||
MRE.r_word1 = Value2;
|
||||
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
|
||||
}
|
||||
|
||||
MachO::any_relocation_info MRE;
|
||||
MRE.r_word0 = ((FixupOffset << 0) |
|
||||
(Type << 24) |
|
||||
(MovtBit << 28) |
|
||||
(ThumbBit << 29) |
|
||||
(IsPCRel << 30) |
|
||||
MachO::R_SCATTERED);
|
||||
MRE.r_word1 = Value;
|
||||
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
|
||||
}
|
||||
|
||||
void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
|
||||
const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup,
|
||||
MCValue Target,
|
||||
unsigned Type,
|
||||
unsigned Log2Size,
|
||||
uint64_t &FixedValue) {
|
||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||
unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
|
||||
|
||||
// See <reloc.h>.
|
||||
const MCSymbol *A = &Target.getSymA()->getSymbol();
|
||||
|
||||
if (!A->getFragment()) {
|
||||
Asm.getContext().reportError(Fixup.getLoc(),
|
||||
"symbol '" + A->getName() +
|
||||
"' can not be undefined in a subtraction expression");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t Value = Writer->getSymbolAddress(*A, Layout);
|
||||
uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent());
|
||||
FixedValue += SecAddr;
|
||||
uint32_t Value2 = 0;
|
||||
|
||||
if (const MCSymbolRefExpr *B = Target.getSymB()) {
|
||||
assert(Type == MachO::ARM_RELOC_VANILLA && "invalid reloc for 2 symbols");
|
||||
const MCSymbol *SB = &B->getSymbol();
|
||||
|
||||
if (!SB->getFragment()) {
|
||||
Asm.getContext().reportError(Fixup.getLoc(),
|
||||
"symbol '" + B->getSymbol().getName() +
|
||||
"' can not be undefined in a subtraction expression");
|
||||
return;
|
||||
}
|
||||
|
||||
// Select the appropriate difference relocation type.
|
||||
Type = MachO::ARM_RELOC_SECTDIFF;
|
||||
Value2 = Writer->getSymbolAddress(B->getSymbol(), Layout);
|
||||
FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent());
|
||||
}
|
||||
|
||||
// Relocations are written out in reverse order, so the PAIR comes first.
|
||||
if (Type == MachO::ARM_RELOC_SECTDIFF ||
|
||||
Type == MachO::ARM_RELOC_LOCAL_SECTDIFF) {
|
||||
MachO::any_relocation_info MRE;
|
||||
MRE.r_word0 = ((0 << 0) |
|
||||
(MachO::ARM_RELOC_PAIR << 24) |
|
||||
(Log2Size << 28) |
|
||||
(IsPCRel << 30) |
|
||||
MachO::R_SCATTERED);
|
||||
MRE.r_word1 = Value2;
|
||||
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
|
||||
}
|
||||
|
||||
MachO::any_relocation_info MRE;
|
||||
MRE.r_word0 = ((FixupOffset << 0) |
|
||||
(Type << 24) |
|
||||
(Log2Size << 28) |
|
||||
(IsPCRel << 30) |
|
||||
MachO::R_SCATTERED);
|
||||
MRE.r_word1 = Value;
|
||||
Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
|
||||
}
|
||||
|
||||
bool ARMMachObjectWriter::requiresExternRelocation(MachObjectWriter *Writer,
|
||||
const MCAssembler &Asm,
|
||||
const MCFragment &Fragment,
|
||||
unsigned RelocType,
|
||||
const MCSymbol &S,
|
||||
uint64_t FixedValue) {
|
||||
// Most cases can be identified purely from the symbol.
|
||||
if (Writer->doesSymbolRequireExternRelocation(S))
|
||||
return true;
|
||||
int64_t Value = (int64_t)FixedValue; // The displacement is signed.
|
||||
int64_t Range;
|
||||
switch (RelocType) {
|
||||
default:
|
||||
return false;
|
||||
case MachO::ARM_RELOC_BR24:
|
||||
// An ARM call might be to a Thumb function, in which case the offset may
|
||||
// not be encodable in the instruction and we must use an external
|
||||
// relocation that explicitly mentions the function. Not a problem if it's
|
||||
// to a temporary "Lwhatever" symbol though, and in fact trying to use an
|
||||
// external relocation there causes more issues.
|
||||
if (!S.isTemporary())
|
||||
return true;
|
||||
|
||||
// PC pre-adjustment of 8 for these instructions.
|
||||
Value -= 8;
|
||||
// ARM BL/BLX has a 25-bit offset.
|
||||
Range = 0x1ffffff;
|
||||
break;
|
||||
case MachO::ARM_THUMB_RELOC_BR22:
|
||||
// PC pre-adjustment of 4 for these instructions.
|
||||
Value -= 4;
|
||||
// Thumb BL/BLX has a 24-bit offset.
|
||||
Range = 0xffffff;
|
||||
}
|
||||
// BL/BLX also use external relocations when an internal relocation
|
||||
// would result in the target being out of range. This gives the linker
|
||||
// enough information to generate a branch island.
|
||||
Value += Writer->getSectionAddress(&S.getSection());
|
||||
Value -= Writer->getSectionAddress(Fragment.getParent());
|
||||
// If the resultant value would be out of range for an internal relocation,
|
||||
// use an external instead.
|
||||
if (Value > Range || Value < -(Range + 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ARMMachObjectWriter::recordRelocation(MachObjectWriter *Writer,
|
||||
MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue) {
|
||||
unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
|
||||
unsigned Log2Size;
|
||||
unsigned RelocType = MachO::ARM_RELOC_VANILLA;
|
||||
if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) {
|
||||
// If we failed to get fixup kind info, it's because there's no legal
|
||||
// relocation type for the fixup kind. This happens when it's a fixup that's
|
||||
// expected to always be resolvable at assembly time and not have any
|
||||
// relocations needed.
|
||||
Asm.getContext().reportError(Fixup.getLoc(),
|
||||
"unsupported relocation on symbol");
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is a difference or a defined symbol plus an offset, then we need a
|
||||
// scattered relocation entry. Differences always require scattered
|
||||
// relocations.
|
||||
if (Target.getSymB()) {
|
||||
if (RelocType == MachO::ARM_RELOC_HALF)
|
||||
return RecordARMScatteredHalfRelocation(Writer, Asm, Layout, Fragment,
|
||||
Fixup, Target, FixedValue);
|
||||
return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
|
||||
Target, RelocType, Log2Size,
|
||||
FixedValue);
|
||||
}
|
||||
|
||||
// Get the symbol data, if any.
|
||||
const MCSymbol *A = nullptr;
|
||||
if (Target.getSymA())
|
||||
A = &Target.getSymA()->getSymbol();
|
||||
|
||||
// FIXME: For other platforms, we need to use scattered relocations for
|
||||
// internal relocations with offsets. If this is an internal relocation with
|
||||
// an offset, it also needs a scattered relocation entry.
|
||||
//
|
||||
// Is this right for ARM?
|
||||
uint32_t Offset = Target.getConstant();
|
||||
if (IsPCRel && RelocType == MachO::ARM_RELOC_VANILLA)
|
||||
Offset += 1 << Log2Size;
|
||||
if (Offset && A && !Writer->doesSymbolRequireExternRelocation(*A) &&
|
||||
RelocType != MachO::ARM_RELOC_HALF)
|
||||
return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
|
||||
Target, RelocType, Log2Size,
|
||||
FixedValue);
|
||||
|
||||
// See <reloc.h>.
|
||||
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
|
||||
unsigned Index = 0;
|
||||
unsigned Type = 0;
|
||||
const MCSymbol *RelSymbol = nullptr;
|
||||
|
||||
if (Target.isAbsolute()) { // constant
|
||||
// FIXME!
|
||||
report_fatal_error("FIXME: relocations to absolute targets "
|
||||
"not yet implemented");
|
||||
} else {
|
||||
// Resolve constant variables.
|
||||
if (A->isVariable()) {
|
||||
int64_t Res;
|
||||
if (A->getVariableValue()->evaluateAsAbsolute(
|
||||
Res, Layout, Writer->getSectionAddressMap())) {
|
||||
FixedValue = Res;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether we need an external or internal relocation.
|
||||
if (requiresExternRelocation(Writer, Asm, *Fragment, RelocType, *A,
|
||||
FixedValue)) {
|
||||
RelSymbol = A;
|
||||
|
||||
// For external relocations, make sure to offset the fixup value to
|
||||
// compensate for the addend of the symbol address, if it was
|
||||
// undefined. This occurs with weak definitions, for example.
|
||||
if (!A->isUndefined())
|
||||
FixedValue -= Layout.getSymbolOffset(*A);
|
||||
} else {
|
||||
// The index is the section ordinal (1-based).
|
||||
const MCSection &Sec = A->getSection();
|
||||
Index = Sec.getOrdinal() + 1;
|
||||
FixedValue += Writer->getSectionAddress(&Sec);
|
||||
}
|
||||
if (IsPCRel)
|
||||
FixedValue -= Writer->getSectionAddress(Fragment->getParent());
|
||||
|
||||
// The type is determined by the fixup kind.
|
||||
Type = RelocType;
|
||||
}
|
||||
|
||||
// struct relocation_info (8 bytes)
|
||||
MachO::any_relocation_info MRE;
|
||||
MRE.r_word0 = FixupOffset;
|
||||
MRE.r_word1 =
|
||||
(Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
|
||||
|
||||
// Even when it's not a scattered relocation, movw/movt always uses
|
||||
// a PAIR relocation.
|
||||
if (Type == MachO::ARM_RELOC_HALF) {
|
||||
// The entire addend is needed to correctly apply a relocation. One half is
|
||||
// extracted from the instruction itself, the other comes from this
|
||||
// PAIR. I.e. it's correct that we insert the high bits of the addend in the
|
||||
// MOVW case here. relocation entries.
|
||||
uint32_t Value = 0;
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
default: break;
|
||||
case ARM::fixup_arm_movw_lo16:
|
||||
case ARM::fixup_t2_movw_lo16:
|
||||
Value = (FixedValue >> 16) & 0xffff;
|
||||
break;
|
||||
case ARM::fixup_arm_movt_hi16:
|
||||
case ARM::fixup_t2_movt_hi16:
|
||||
Value = FixedValue & 0xffff;
|
||||
break;
|
||||
}
|
||||
MachO::any_relocation_info MREPair;
|
||||
MREPair.r_word0 = Value;
|
||||
MREPair.r_word1 = ((0xffffff << 0) |
|
||||
(Log2Size << 25) |
|
||||
(MachO::ARM_RELOC_PAIR << 28));
|
||||
|
||||
Writer->addRelocation(nullptr, Fragment->getParent(), MREPair);
|
||||
}
|
||||
|
||||
Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
llvm::createARMMachObjectWriter(raw_pwrite_stream &OS, bool Is64Bit,
|
||||
uint32_t CPUType, uint32_t CPUSubtype) {
|
||||
return createMachObjectWriter(
|
||||
llvm::make_unique<ARMMachObjectWriter>(Is64Bit, CPUType, CPUSubtype), OS,
|
||||
/*IsLittleEndian=*/true);
|
||||
}
|
@ -1,258 +0,0 @@
|
||||
//===- ARMTargetStreamer.cpp - ARMTargetStreamer class --*- C++ -*---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the ARMTargetStreamer class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ARMTargetMachine.h"
|
||||
#include "llvm/MC/ConstantPools.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/ARMBuildAttributes.h"
|
||||
#include "llvm/Support/TargetParser.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
//
|
||||
// ARMTargetStreamer Implemenation
|
||||
//
|
||||
|
||||
ARMTargetStreamer::ARMTargetStreamer(MCStreamer &S)
|
||||
: MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {}
|
||||
|
||||
ARMTargetStreamer::~ARMTargetStreamer() = default;
|
||||
|
||||
// The constant pool handling is shared by all ARMTargetStreamer
|
||||
// implementations.
|
||||
const MCExpr *ARMTargetStreamer::addConstantPoolEntry(const MCExpr *Expr, SMLoc Loc) {
|
||||
return ConstantPools->addEntry(Streamer, Expr, 4, Loc);
|
||||
}
|
||||
|
||||
void ARMTargetStreamer::emitCurrentConstantPool() {
|
||||
ConstantPools->emitForCurrentSection(Streamer);
|
||||
ConstantPools->clearCacheForCurrentSection(Streamer);
|
||||
}
|
||||
|
||||
// finish() - write out any non-empty assembler constant pools.
|
||||
void ARMTargetStreamer::finish() { ConstantPools->emitAll(Streamer); }
|
||||
|
||||
// reset() - Reset any state
|
||||
void ARMTargetStreamer::reset() {}
|
||||
|
||||
// The remaining callbacks should be handled separately by each
|
||||
// streamer.
|
||||
void ARMTargetStreamer::emitFnStart() {}
|
||||
void ARMTargetStreamer::emitFnEnd() {}
|
||||
void ARMTargetStreamer::emitCantUnwind() {}
|
||||
void ARMTargetStreamer::emitPersonality(const MCSymbol *Personality) {}
|
||||
void ARMTargetStreamer::emitPersonalityIndex(unsigned Index) {}
|
||||
void ARMTargetStreamer::emitHandlerData() {}
|
||||
void ARMTargetStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
|
||||
int64_t Offset) {}
|
||||
void ARMTargetStreamer::emitMovSP(unsigned Reg, int64_t Offset) {}
|
||||
void ARMTargetStreamer::emitPad(int64_t Offset) {}
|
||||
void ARMTargetStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
|
||||
bool isVector) {}
|
||||
void ARMTargetStreamer::emitUnwindRaw(int64_t StackOffset,
|
||||
const SmallVectorImpl<uint8_t> &Opcodes) {
|
||||
}
|
||||
void ARMTargetStreamer::switchVendor(StringRef Vendor) {}
|
||||
void ARMTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {}
|
||||
void ARMTargetStreamer::emitTextAttribute(unsigned Attribute,
|
||||
StringRef String) {}
|
||||
void ARMTargetStreamer::emitIntTextAttribute(unsigned Attribute,
|
||||
unsigned IntValue,
|
||||
StringRef StringValue) {}
|
||||
void ARMTargetStreamer::emitArch(ARM::ArchKind Arch) {}
|
||||
void ARMTargetStreamer::emitArchExtension(unsigned ArchExt) {}
|
||||
void ARMTargetStreamer::emitObjectArch(ARM::ArchKind Arch) {}
|
||||
void ARMTargetStreamer::emitFPU(unsigned FPU) {}
|
||||
void ARMTargetStreamer::finishAttributeSection() {}
|
||||
void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {}
|
||||
void
|
||||
ARMTargetStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) {}
|
||||
void ARMTargetStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {}
|
||||
|
||||
static ARMBuildAttrs::CPUArch getArchForCPU(const MCSubtargetInfo &STI) {
|
||||
if (STI.getCPU() == "xscale")
|
||||
return ARMBuildAttrs::v5TEJ;
|
||||
|
||||
if (STI.hasFeature(ARM::HasV8Ops)) {
|
||||
if (STI.hasFeature(ARM::FeatureRClass))
|
||||
return ARMBuildAttrs::v8_R;
|
||||
return ARMBuildAttrs::v8_A;
|
||||
} else if (STI.hasFeature(ARM::HasV8MMainlineOps))
|
||||
return ARMBuildAttrs::v8_M_Main;
|
||||
else if (STI.hasFeature(ARM::HasV7Ops)) {
|
||||
if (STI.hasFeature(ARM::FeatureMClass) && STI.hasFeature(ARM::FeatureDSP))
|
||||
return ARMBuildAttrs::v7E_M;
|
||||
return ARMBuildAttrs::v7;
|
||||
} else if (STI.hasFeature(ARM::HasV6T2Ops))
|
||||
return ARMBuildAttrs::v6T2;
|
||||
else if (STI.hasFeature(ARM::HasV8MBaselineOps))
|
||||
return ARMBuildAttrs::v8_M_Base;
|
||||
else if (STI.hasFeature(ARM::HasV6MOps))
|
||||
return ARMBuildAttrs::v6S_M;
|
||||
else if (STI.hasFeature(ARM::HasV6Ops))
|
||||
return ARMBuildAttrs::v6;
|
||||
else if (STI.hasFeature(ARM::HasV5TEOps))
|
||||
return ARMBuildAttrs::v5TE;
|
||||
else if (STI.hasFeature(ARM::HasV5TOps))
|
||||
return ARMBuildAttrs::v5T;
|
||||
else if (STI.hasFeature(ARM::HasV4TOps))
|
||||
return ARMBuildAttrs::v4T;
|
||||
else
|
||||
return ARMBuildAttrs::v4;
|
||||
}
|
||||
|
||||
static bool isV8M(const MCSubtargetInfo &STI) {
|
||||
// Note that v8M Baseline is a subset of v6T2!
|
||||
return (STI.hasFeature(ARM::HasV8MBaselineOps) &&
|
||||
!STI.hasFeature(ARM::HasV6T2Ops)) ||
|
||||
STI.hasFeature(ARM::HasV8MMainlineOps);
|
||||
}
|
||||
|
||||
/// Emit the build attributes that only depend on the hardware that we expect
|
||||
// /to be available, and not on the ABI, or any source-language choices.
|
||||
void ARMTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {
|
||||
switchVendor("aeabi");
|
||||
|
||||
const StringRef CPUString = STI.getCPU();
|
||||
if (!CPUString.empty() && !CPUString.startswith("generic")) {
|
||||
// FIXME: remove krait check when GNU tools support krait cpu
|
||||
if (STI.hasFeature(ARM::ProcKrait)) {
|
||||
emitTextAttribute(ARMBuildAttrs::CPU_name, "cortex-a9");
|
||||
// We consider krait as a "cortex-a9" + hwdiv CPU
|
||||
// Enable hwdiv through ".arch_extension idiv"
|
||||
if (STI.hasFeature(ARM::FeatureHWDivThumb) ||
|
||||
STI.hasFeature(ARM::FeatureHWDivARM))
|
||||
emitArchExtension(ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM);
|
||||
} else {
|
||||
emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString);
|
||||
}
|
||||
}
|
||||
|
||||
emitAttribute(ARMBuildAttrs::CPU_arch, getArchForCPU(STI));
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureAClass)) {
|
||||
emitAttribute(ARMBuildAttrs::CPU_arch_profile,
|
||||
ARMBuildAttrs::ApplicationProfile);
|
||||
} else if (STI.hasFeature(ARM::FeatureRClass)) {
|
||||
emitAttribute(ARMBuildAttrs::CPU_arch_profile,
|
||||
ARMBuildAttrs::RealTimeProfile);
|
||||
} else if (STI.hasFeature(ARM::FeatureMClass)) {
|
||||
emitAttribute(ARMBuildAttrs::CPU_arch_profile,
|
||||
ARMBuildAttrs::MicroControllerProfile);
|
||||
}
|
||||
|
||||
emitAttribute(ARMBuildAttrs::ARM_ISA_use, STI.hasFeature(ARM::FeatureNoARM)
|
||||
? ARMBuildAttrs::Not_Allowed
|
||||
: ARMBuildAttrs::Allowed);
|
||||
|
||||
if (isV8M(STI)) {
|
||||
emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
|
||||
ARMBuildAttrs::AllowThumbDerived);
|
||||
} else if (STI.hasFeature(ARM::FeatureThumb2)) {
|
||||
emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
|
||||
ARMBuildAttrs::AllowThumb32);
|
||||
} else if (STI.hasFeature(ARM::HasV4TOps)) {
|
||||
emitAttribute(ARMBuildAttrs::THUMB_ISA_use, ARMBuildAttrs::Allowed);
|
||||
}
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureNEON)) {
|
||||
/* NEON is not exactly a VFP architecture, but GAS emit one of
|
||||
* neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */
|
||||
if (STI.hasFeature(ARM::FeatureFPARMv8)) {
|
||||
if (STI.hasFeature(ARM::FeatureCrypto))
|
||||
emitFPU(ARM::FK_CRYPTO_NEON_FP_ARMV8);
|
||||
else
|
||||
emitFPU(ARM::FK_NEON_FP_ARMV8);
|
||||
} else if (STI.hasFeature(ARM::FeatureVFP4))
|
||||
emitFPU(ARM::FK_NEON_VFPV4);
|
||||
else
|
||||
emitFPU(STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_NEON_FP16
|
||||
: ARM::FK_NEON);
|
||||
// Emit Tag_Advanced_SIMD_arch for ARMv8 architecture
|
||||
if (STI.hasFeature(ARM::HasV8Ops))
|
||||
emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
|
||||
STI.hasFeature(ARM::HasV8_1aOps)
|
||||
? ARMBuildAttrs::AllowNeonARMv8_1a
|
||||
: ARMBuildAttrs::AllowNeonARMv8);
|
||||
} else {
|
||||
if (STI.hasFeature(ARM::FeatureFPARMv8))
|
||||
// FPv5 and FP-ARMv8 have the same instructions, so are modeled as one
|
||||
// FPU, but there are two different names for it depending on the CPU.
|
||||
emitFPU(STI.hasFeature(ARM::FeatureD16)
|
||||
? (STI.hasFeature(ARM::FeatureVFPOnlySP) ? ARM::FK_FPV5_SP_D16
|
||||
: ARM::FK_FPV5_D16)
|
||||
: ARM::FK_FP_ARMV8);
|
||||
else if (STI.hasFeature(ARM::FeatureVFP4))
|
||||
emitFPU(STI.hasFeature(ARM::FeatureD16)
|
||||
? (STI.hasFeature(ARM::FeatureVFPOnlySP) ? ARM::FK_FPV4_SP_D16
|
||||
: ARM::FK_VFPV4_D16)
|
||||
: ARM::FK_VFPV4);
|
||||
else if (STI.hasFeature(ARM::FeatureVFP3))
|
||||
emitFPU(
|
||||
STI.hasFeature(ARM::FeatureD16)
|
||||
// +d16
|
||||
? (STI.hasFeature(ARM::FeatureVFPOnlySP)
|
||||
? (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3XD_FP16
|
||||
: ARM::FK_VFPV3XD)
|
||||
: (STI.hasFeature(ARM::FeatureFP16)
|
||||
? ARM::FK_VFPV3_D16_FP16
|
||||
: ARM::FK_VFPV3_D16))
|
||||
// -d16
|
||||
: (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3_FP16
|
||||
: ARM::FK_VFPV3));
|
||||
else if (STI.hasFeature(ARM::FeatureVFP2))
|
||||
emitFPU(ARM::FK_VFPV2);
|
||||
}
|
||||
|
||||
// ABI_HardFP_use attribute to indicate single precision FP.
|
||||
if (STI.hasFeature(ARM::FeatureVFPOnlySP))
|
||||
emitAttribute(ARMBuildAttrs::ABI_HardFP_use,
|
||||
ARMBuildAttrs::HardFPSinglePrecision);
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureFP16))
|
||||
emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP);
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureMP))
|
||||
emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP);
|
||||
|
||||
// Hardware divide in ARM mode is part of base arch, starting from ARMv8.
|
||||
// If only Thumb hwdiv is present, it must also be in base arch (ARMv7-R/M).
|
||||
// It is not possible to produce DisallowDIV: if hwdiv is present in the base
|
||||
// arch, supplying -hwdiv downgrades the effective arch, via ClearImpliedBits.
|
||||
// AllowDIVExt is only emitted if hwdiv isn't available in the base arch;
|
||||
// otherwise, the default value (AllowDIVIfExists) applies.
|
||||
if (STI.hasFeature(ARM::FeatureHWDivARM) && !STI.hasFeature(ARM::HasV8Ops))
|
||||
emitAttribute(ARMBuildAttrs::DIV_use, ARMBuildAttrs::AllowDIVExt);
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureDSP) && isV8M(STI))
|
||||
emitAttribute(ARMBuildAttrs::DSP_extension, ARMBuildAttrs::Allowed);
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureStrictAlign))
|
||||
emitAttribute(ARMBuildAttrs::CPU_unaligned_access,
|
||||
ARMBuildAttrs::Not_Allowed);
|
||||
else
|
||||
emitAttribute(ARMBuildAttrs::CPU_unaligned_access,
|
||||
ARMBuildAttrs::Allowed);
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureTrustZone) &&
|
||||
STI.hasFeature(ARM::FeatureVirtualization))
|
||||
emitAttribute(ARMBuildAttrs::Virtualization_use,
|
||||
ARMBuildAttrs::AllowTZVirtualization);
|
||||
else if (STI.hasFeature(ARM::FeatureTrustZone))
|
||||
emitAttribute(ARMBuildAttrs::Virtualization_use, ARMBuildAttrs::AllowTZ);
|
||||
else if (STI.hasFeature(ARM::FeatureVirtualization))
|
||||
emitAttribute(ARMBuildAttrs::Virtualization_use,
|
||||
ARMBuildAttrs::AllowVirtualization);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user