Merge commit f596f4507 from llvm git (by Sam Elliott):

[RISCV] Add Custom Parser for Atomic Memory Operands

  Summary:
  GCC Accepts both (reg) and 0(reg) for atomic instruction memory
  operands. These instructions do not allow for an offset in their
  encoding, so in the latter case, the 0 is silently dropped.

  Due to how we have structured the RISCVAsmParser, the easiest way to
  add support for parsing this offset is to add a custom AsmOperand and
  parser. This parser drops all the parens, and just keeps the
  register.

  This commit also adds a custom printer for these operands, which
  matches the GCC canonical printer, printing both `(a0)` and `0(a0)`
  as `(a0)`.

  Reviewers: asb, lewis-revill

  Reviewed By: asb

  Subscribers: s.egerton, hiraditya, rbar, johnrusso, simoncook,
  apazos, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, MaskRay,
  zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o,
  rkruppe, jfb, PkmX, jocewei, psnobl, benna, Jim, llvm-commits

  Tags: #llvm

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

  llvm-svn: 367553

Merge commit f596f4507 from llvm git (by Sam Elliott):

  [RISCV] Add FreeBSD targets

  Reviewers: asb

  Reviewed By: asb

  Subscribers: simoncook, s.egerton, lenary, psnobl, benna, mhorne,
  emaste, kito-cheng, shiva0217, rogfer01, rkruppe, cfe-commits

  Tags: #clang

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

  Patch by James Clarke (jrtc27)

  llvm-svn: 367557

Merge commit f596f4507 from llvm git (by Hsiangkai Wang):

  [DebugInfo] Generate fixups as emitting DWARF .debug_frame/.eh_frame.

  It is necessary to generate fixups in .debug_frame or .eh_frame as
  relaxation is enabled due to the address delta may be changed after
  relaxation.

  There is an opcode with 6-bits data in debug frame encoding. So, we
  also need 6-bits fixup types.

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

  llvm-svn: 366524

Merge commit f596f4507 from llvm git (by Hsiangkai Wang):

  [DebugInfo] Some fields do not need relocations even relax is enabled.

  In debug frame information, some fields, e.g., Length in CIE/FDE and
  Offset in FDE are attributes to describe the structure of CIE/FDE.
  They are not related to the relaxed code. However, these attributes
  are symbol differences. So, in current design, these attributes will
  be filled as zero and LLVM generates relocations for them.

  We only need to generate relocations for symbols in executable
  sections.  So, if the symbols are not located in executable sections,
  we still evaluate their values under relaxation.

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

  llvm-svn: 366531

Merge commit f596f4507 from llvm git (by Alex Bradbury):

  [RISCV] Don't force absolute FK_Data_X fixups to relocs

  The current behavior of shouldForceRelocation forces relocations for
  the majority of fixups when relaxation is enabled. This makes sense
  for fixups which incorporate symbols but is unnecessary for simple
  data fixups where the fixup target is already resolved to an absolute
  value.

  Differential Revision: https://reviews.llvm.org/D63404
  Patch by Edward Jones.

  llvm-svn: 369257

Merge commit f596f4507 from llvm git (by Alex Bradbury):

  [RISCV] Implement getExprForFDESymbol to ensure RISCV_32_PCREL is
  used for the FDE location

  Follow binutils in using RISCV_32_PCREL for the FDE initial location.
  As explained in the relevant binutils commit
  <a6cbf936e3>,
  the ADD/SUB pair of relocations is problematic in the presence of
  linker relaxation.

  This patch has the same end goal as D64715 but includes test changes
  and avoids adding a new global VariantKind to MCExpr.h (preferring
  RISCVMCExpr VKs like the rest of the RISC-V backend).

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

  llvm-svn: 369375

This series of merges will permit riscv64 kernels and riscv64sf worlds
to build with clang instead of gcc (but still using the bfd linker).

Requested by:	jhb
Obtained from:	https://github.com/freebsd/freebsd/compare/master...bsdjhb:riscv_clang
MFC after:	1 month
X-MFC-With:	r353358
This commit is contained in:
Dimitry Andric 2019-11-07 19:54:08 +00:00
parent 4940bf264a
commit 22a93864b8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=354469
24 changed files with 367 additions and 98 deletions

View File

@ -69,7 +69,7 @@ class CFIProgram {
/// starting at *Offset and ending at EndOffset. *Offset is updated
/// to EndOffset upon successful parsing, or indicates the offset
/// where a problem occurred in case an error is returned.
Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset);
Error parse(DWARFDataExtractor Data, uint32_t *Offset, uint32_t EndOffset);
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
unsigned IndentLevel = 1) const;

View File

@ -40,8 +40,8 @@ class DWARFObject {
virtual const DWARFSection &getLocSection() const { return Dummy; }
virtual const DWARFSection &getLoclistsSection() const { return Dummy; }
virtual StringRef getARangeSection() const { return ""; }
virtual StringRef getDebugFrameSection() const { return ""; }
virtual StringRef getEHFrameSection() const { return ""; }
virtual const DWARFSection &getDebugFrameSection() const { return Dummy; }
virtual const DWARFSection &getEHFrameSection() const { return Dummy; }
virtual const DWARFSection &getLineSection() const { return Dummy; }
virtual StringRef getLineStringSection() const { return ""; }
virtual StringRef getStringSection() const { return ""; }

View File

@ -629,7 +629,8 @@ class MCDwarfFrameEmitter {
static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
raw_ostream &OS);
raw_ostream &OS, uint32_t *Offset = nullptr,
uint32_t *Size = nullptr);
};
} // end namespace llvm

View File

@ -20,35 +20,38 @@ class MCExpr;
/// Extensible enumeration to represent the type of a fixup.
enum MCFixupKind {
FK_NONE = 0, ///< A no-op fixup.
FK_Data_1, ///< A one-byte fixup.
FK_Data_2, ///< A two-byte fixup.
FK_Data_4, ///< A four-byte fixup.
FK_Data_8, ///< A eight-byte fixup.
FK_PCRel_1, ///< A one-byte pc relative fixup.
FK_PCRel_2, ///< A two-byte pc relative fixup.
FK_PCRel_4, ///< A four-byte pc relative fixup.
FK_PCRel_8, ///< A eight-byte pc relative fixup.
FK_GPRel_1, ///< A one-byte gp relative fixup.
FK_GPRel_2, ///< A two-byte gp relative fixup.
FK_GPRel_4, ///< A four-byte gp relative fixup.
FK_GPRel_8, ///< A eight-byte gp relative fixup.
FK_DTPRel_4, ///< A four-byte dtp relative fixup.
FK_DTPRel_8, ///< A eight-byte dtp relative fixup.
FK_TPRel_4, ///< A four-byte tp relative fixup.
FK_TPRel_8, ///< A eight-byte tp relative fixup.
FK_SecRel_1, ///< A one-byte section relative fixup.
FK_SecRel_2, ///< A two-byte section relative fixup.
FK_SecRel_4, ///< A four-byte section relative fixup.
FK_SecRel_8, ///< A eight-byte section relative fixup.
FK_Data_Add_1, ///< A one-byte add fixup.
FK_Data_Add_2, ///< A two-byte add fixup.
FK_Data_Add_4, ///< A four-byte add fixup.
FK_Data_Add_8, ///< A eight-byte add fixup.
FK_Data_Sub_1, ///< A one-byte sub fixup.
FK_Data_Sub_2, ///< A two-byte sub fixup.
FK_Data_Sub_4, ///< A four-byte sub fixup.
FK_Data_Sub_8, ///< A eight-byte sub fixup.
FK_NONE = 0, ///< A no-op fixup.
FK_Data_1, ///< A one-byte fixup.
FK_Data_2, ///< A two-byte fixup.
FK_Data_4, ///< A four-byte fixup.
FK_Data_8, ///< A eight-byte fixup.
FK_Data_6b, ///< A six-bits fixup.
FK_PCRel_1, ///< A one-byte pc relative fixup.
FK_PCRel_2, ///< A two-byte pc relative fixup.
FK_PCRel_4, ///< A four-byte pc relative fixup.
FK_PCRel_8, ///< A eight-byte pc relative fixup.
FK_GPRel_1, ///< A one-byte gp relative fixup.
FK_GPRel_2, ///< A two-byte gp relative fixup.
FK_GPRel_4, ///< A four-byte gp relative fixup.
FK_GPRel_8, ///< A eight-byte gp relative fixup.
FK_DTPRel_4, ///< A four-byte dtp relative fixup.
FK_DTPRel_8, ///< A eight-byte dtp relative fixup.
FK_TPRel_4, ///< A four-byte tp relative fixup.
FK_TPRel_8, ///< A eight-byte tp relative fixup.
FK_SecRel_1, ///< A one-byte section relative fixup.
FK_SecRel_2, ///< A two-byte section relative fixup.
FK_SecRel_4, ///< A four-byte section relative fixup.
FK_SecRel_8, ///< A eight-byte section relative fixup.
FK_Data_Add_1, ///< A one-byte add fixup.
FK_Data_Add_2, ///< A two-byte add fixup.
FK_Data_Add_4, ///< A four-byte add fixup.
FK_Data_Add_8, ///< A eight-byte add fixup.
FK_Data_Add_6b, ///< A six-bits add fixup.
FK_Data_Sub_1, ///< A one-byte sub fixup.
FK_Data_Sub_2, ///< A two-byte sub fixup.
FK_Data_Sub_4, ///< A four-byte sub fixup.
FK_Data_Sub_8, ///< A eight-byte sub fixup.
FK_Data_Sub_6b, ///< A six-bits sub fixup.
FirstTargetFixupKind = 128,
@ -129,13 +132,37 @@ class MCFixup {
/// Return the generic fixup kind for a value with the given size. It
/// is an error to pass an unsupported size.
static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) {
static MCFixupKind getKindForSize(unsigned Size, bool IsPCRel) {
switch (Size) {
default: llvm_unreachable("Invalid generic fixup size!");
case 1: return isPCRel ? FK_PCRel_1 : FK_Data_1;
case 2: return isPCRel ? FK_PCRel_2 : FK_Data_2;
case 4: return isPCRel ? FK_PCRel_4 : FK_Data_4;
case 8: return isPCRel ? FK_PCRel_8 : FK_Data_8;
case 1:
return IsPCRel ? FK_PCRel_1 : FK_Data_1;
case 2:
return IsPCRel ? FK_PCRel_2 : FK_Data_2;
case 4:
return IsPCRel ? FK_PCRel_4 : FK_Data_4;
case 8:
return IsPCRel ? FK_PCRel_8 : FK_Data_8;
}
}
/// Return the generic fixup kind for a value with the given size in bits.
/// It is an error to pass an unsupported size.
static MCFixupKind getKindForSizeInBits(unsigned Size, bool IsPCRel) {
switch (Size) {
default:
llvm_unreachable("Invalid generic fixup size!");
case 6:
assert(!IsPCRel && "Invalid pc-relative fixup size!");
return FK_Data_6b;
case 8:
return IsPCRel ? FK_PCRel_1 : FK_Data_1;
case 16:
return IsPCRel ? FK_PCRel_2 : FK_Data_2;
case 32:
return IsPCRel ? FK_PCRel_4 : FK_Data_4;
case 64:
return IsPCRel ? FK_PCRel_8 : FK_Data_8;
}
}
@ -148,6 +175,7 @@ class MCFixup {
case FK_Data_2: return FK_Data_Add_2;
case FK_Data_4: return FK_Data_Add_4;
case FK_Data_8: return FK_Data_Add_8;
case FK_Data_6b: return FK_Data_Add_6b;
}
}
@ -160,6 +188,7 @@ class MCFixup {
case FK_Data_2: return FK_Data_Sub_2;
case FK_Data_4: return FK_Data_Sub_4;
case FK_Data_8: return FK_Data_Sub_8;
case FK_Data_6b: return FK_Data_Sub_6b;
}
}

View File

@ -149,6 +149,7 @@ class MCEncodedFragment : public MCFragment {
case MCFragment::FT_CompactEncodedInst:
case MCFragment::FT_Data:
case MCFragment::FT_Dwarf:
case MCFragment::FT_DwarfFrame:
return true;
}
}
@ -232,7 +233,8 @@ class MCEncodedFragmentWithFixups :
static bool classof(const MCFragment *F) {
MCFragment::FragmentType Kind = F->getKind();
return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf;;
Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
Kind == MCFragment::FT_DwarfFrame;
}
};
@ -543,27 +545,21 @@ class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
}
};
class MCDwarfCallFrameFragment : public MCFragment {
class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
/// AddrDelta - The expression for the difference of the two symbols that
/// make up the address delta between two .cfi_* dwarf directives.
const MCExpr *AddrDelta;
SmallString<8> Contents;
public:
MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
: MCFragment(FT_DwarfFrame, false, Sec), AddrDelta(&AddrDelta) {
Contents.push_back(0);
}
: MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec),
AddrDelta(&AddrDelta) {}
/// \name Accessors
/// @{
const MCExpr &getAddrDelta() const { return *AddrDelta; }
SmallString<8> &getContents() { return Contents; }
const SmallString<8> &getContents() const { return Contents; }
/// @}
static bool classof(const MCFragment *F) {

View File

@ -402,11 +402,11 @@ void DWARFContext::dump(
}
if (const auto *Off = shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
DObj->getDebugFrameSection()))
DObj->getDebugFrameSection().Data))
getDebugFrame()->dump(OS, getRegisterInfo(), *Off);
if (const auto *Off = shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
DObj->getEHFrameSection()))
DObj->getEHFrameSection().Data))
getEHFrame()->dump(OS, getRegisterInfo(), *Off);
if (DumpType & DIDT_DebugMacro) {
@ -766,7 +766,7 @@ const DWARFDebugFrame *DWARFContext::getDebugFrame() {
// provides this information). This problem is fixed in DWARFv4
// See this dwarf-discuss discussion for more details:
// http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
DWARFDataExtractor debugFrameData(DObj->getDebugFrameSection(),
DWARFDataExtractor debugFrameData(*DObj, DObj->getDebugFrameSection(),
isLittleEndian(), DObj->getAddressSize());
DebugFrame.reset(new DWARFDebugFrame(getArch(), false /* IsEH */));
DebugFrame->parse(debugFrameData);
@ -777,8 +777,8 @@ const DWARFDebugFrame *DWARFContext::getEHFrame() {
if (EHFrame)
return EHFrame.get();
DWARFDataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(),
DObj->getAddressSize());
DWARFDataExtractor debugFrameData(*DObj, DObj->getEHFrameSection(),
isLittleEndian(), DObj->getAddressSize());
DebugFrame.reset(new DWARFDebugFrame(getArch(), true /* IsEH */));
DebugFrame->parse(debugFrameData);
return DebugFrame.get();
@ -1385,6 +1385,8 @@ class DWARFObjInMemory final : public DWARFObject {
DWARFSectionMap RnglistsSection;
DWARFSectionMap StringOffsetSection;
DWARFSectionMap LineDWOSection;
DWARFSectionMap DebugFrameSection;
DWARFSectionMap EHFrameSection;
DWARFSectionMap LocDWOSection;
DWARFSectionMap StringOffsetDWOSection;
DWARFSectionMap RangeDWOSection;
@ -1405,6 +1407,8 @@ class DWARFObjInMemory final : public DWARFObject {
.Case("debug_loc", &LocSection)
.Case("debug_loclists", &LocListsSection)
.Case("debug_line", &LineSection)
.Case("debug_frame", &DebugFrameSection)
.Case("eh_frame", &EHFrameSection)
.Case("debug_str_offsets", &StringOffsetSection)
.Case("debug_ranges", &RangeSection)
.Case("debug_rnglists", &RnglistsSection)
@ -1428,8 +1432,6 @@ class DWARFObjInMemory final : public DWARFObject {
StringRef AbbrevSection;
StringRef ARangeSection;
StringRef DebugFrameSection;
StringRef EHFrameSection;
StringRef StringSection;
StringRef MacinfoSection;
StringRef AbbrevDWOSection;
@ -1449,8 +1451,6 @@ class DWARFObjInMemory final : public DWARFObject {
return StringSwitch<StringRef *>(Name)
.Case("debug_abbrev", &AbbrevSection)
.Case("debug_aranges", &ARangeSection)
.Case("debug_frame", &DebugFrameSection)
.Case("eh_frame", &EHFrameSection)
.Case("debug_str", &StringSection)
.Case("debug_macinfo", &MacinfoSection)
.Case("debug_abbrev.dwo", &AbbrevDWOSection)
@ -1747,8 +1747,12 @@ class DWARFObjInMemory final : public DWARFObject {
const DWARFSection &getLocSection() const override { return LocSection; }
const DWARFSection &getLoclistsSection() const override { return LocListsSection; }
StringRef getARangeSection() const override { return ARangeSection; }
StringRef getDebugFrameSection() const override { return DebugFrameSection; }
StringRef getEHFrameSection() const override { return EHFrameSection; }
const DWARFSection &getDebugFrameSection() const override {
return DebugFrameSection;
}
const DWARFSection &getEHFrameSection() const override {
return EHFrameSection;
}
const DWARFSection &getLineSection() const override { return LineSection; }
StringRef getStringSection() const override { return StringSection; }
const DWARFSection &getRangeSection() const override { return RangeSection; }

View File

@ -34,10 +34,10 @@ using namespace dwarf;
const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset,
Error CFIProgram::parse(DWARFDataExtractor Data, uint32_t *Offset,
uint32_t EndOffset) {
while (*Offset < EndOffset) {
uint8_t Opcode = Data.getU8(Offset);
uint8_t Opcode = Data.getRelocatedValue(1, Offset);
// Some instructions have a primary opcode encoded in the top bits.
uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
@ -74,19 +74,19 @@ Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset,
break;
case DW_CFA_set_loc:
// Operands: Address
addInstruction(Opcode, Data.getAddress(Offset));
addInstruction(Opcode, Data.getRelocatedAddress(Offset));
break;
case DW_CFA_advance_loc1:
// Operands: 1-byte delta
addInstruction(Opcode, Data.getU8(Offset));
addInstruction(Opcode, Data.getRelocatedValue(1, Offset));
break;
case DW_CFA_advance_loc2:
// Operands: 2-byte delta
addInstruction(Opcode, Data.getU16(Offset));
addInstruction(Opcode, Data.getRelocatedValue(2, Offset));
break;
case DW_CFA_advance_loc4:
// Operands: 4-byte delta
addInstruction(Opcode, Data.getU32(Offset));
addInstruction(Opcode, Data.getRelocatedValue(4, Offset));
break;
case DW_CFA_restore_extended:
case DW_CFA_undefined:
@ -361,7 +361,7 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
uint32_t StartOffset = Offset;
bool IsDWARF64 = false;
uint64_t Length = Data.getU32(&Offset);
uint64_t Length = Data.getRelocatedValue(4, &Offset);
uint64_t Id;
if (Length == UINT32_MAX) {
@ -369,7 +369,7 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
// field being 0xffffffff. Then, the next 64 bits are the actual entry
// length.
IsDWARF64 = true;
Length = Data.getU64(&Offset);
Length = Data.getRelocatedValue(8, &Offset);
}
// At this point, Offset points to the next field after Length.
@ -512,8 +512,8 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
ReportError(StartOffset, "Parsing augmentation data at %lx failed");
}
} else {
InitialLocation = Data.getAddress(&Offset);
AddressRange = Data.getAddress(&Offset);
InitialLocation = Data.getRelocatedAddress(&Offset);
AddressRange = Data.getRelocatedAddress(&Offset);
}
Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,

View File

@ -73,6 +73,7 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"FK_Data_2", 0, 16, 0},
{"FK_Data_4", 0, 32, 0},
{"FK_Data_8", 0, 64, 0},
{"FK_Data_6b", 0, 6, 0},
{"FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel},
{"FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
{"FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
@ -93,10 +94,12 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"FK_Data_Add_2", 0, 16, 0},
{"FK_Data_Add_4", 0, 32, 0},
{"FK_Data_Add_8", 0, 64, 0},
{"FK_Data_Add_6b", 0, 6, 0},
{"FK_Data_Sub_1", 0, 8, 0},
{"FK_Data_Sub_2", 0, 16, 0},
{"FK_Data_Sub_4", 0, 32, 0},
{"FK_Data_Sub_8", 0, 64, 0}};
{"FK_Data_Sub_8", 0, 64, 0},
{"FK_Data_Sub_6b", 0, 6, 0}};
assert((size_t)Kind <= array_lengthof(Builtins) && "Unknown fixup kind");
return Builtins[Kind];

View File

@ -840,6 +840,10 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
getBackend().shouldInsertFixupForCodeAlign(*this, Layout, *AF);
}
continue;
} else if (auto *FragWithFixups =
dyn_cast<MCDwarfCallFrameFragment>(&Frag)) {
Fixups = FragWithFixups->getFixups();
Contents = FragWithFixups->getContents();
} else
llvm_unreachable("Unknown fragment with fixups!");
for (const MCFixup &Fixup : Fixups) {
@ -969,13 +973,9 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
MCContext &Context = Layout.getAssembler().getContext();
uint64_t OldSize = DF.getContents().size();
int64_t AddrDelta;
bool Abs;
if (getBackend().requiresDiffExpressionRelocations())
Abs = DF.getAddrDelta().evaluateAsAbsolute(AddrDelta, Layout);
else {
Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
assert(Abs && "We created a line delta with an invalid expression");
}
bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
assert(Abs && "We created a line delta with an invalid expression");
(void)Abs;
int64_t LineDelta;
LineDelta = DF.getLineDelta();
SmallVectorImpl<char> &Data = DF.getContents();
@ -983,7 +983,7 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
raw_svector_ostream OSE(Data);
DF.getFixups().clear();
if (Abs) {
if (!getBackend().requiresDiffExpressionRelocations()) {
MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
AddrDelta, OSE);
} else {
@ -1017,10 +1017,25 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout,
bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
assert(Abs && "We created call frame with an invalid expression");
(void) Abs;
SmallString<8> &Data = DF.getContents();
SmallVectorImpl<char> &Data = DF.getContents();
Data.clear();
raw_svector_ostream OSE(Data);
MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE);
DF.getFixups().clear();
if (getBackend().requiresDiffExpressionRelocations()) {
uint32_t Offset;
uint32_t Size;
MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE, &Offset,
&Size);
if (Size) {
DF.getFixups().push_back(MCFixup::create(
Offset, &DF.getAddrDelta(),
MCFixup::getKindForSizeInBits(Size /*In bits.*/, false /*isPCRel*/)));
}
} else {
MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE);
}
return OldSize != Data.size();
}

View File

@ -1897,26 +1897,54 @@ void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer,
}
void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
uint64_t AddrDelta,
raw_ostream &OS) {
uint64_t AddrDelta, raw_ostream &OS,
uint32_t *Offset, uint32_t *Size) {
// Scale the address delta by the minimum instruction length.
AddrDelta = ScaleAddrDelta(Context, AddrDelta);
bool WithFixups = false;
if (Offset && Size)
WithFixups = true;
support::endianness E =
Context.getAsmInfo()->isLittleEndian() ? support::little : support::big;
if (AddrDelta == 0) {
if (WithFixups) {
*Offset = 0;
*Size = 0;
}
} else if (isUIntN(6, AddrDelta)) {
uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
OS << Opcode;
if (WithFixups) {
*Offset = OS.tell();
*Size = 6;
OS << uint8_t(dwarf::DW_CFA_advance_loc);
} else
OS << Opcode;
} else if (isUInt<8>(AddrDelta)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
OS << uint8_t(AddrDelta);
if (WithFixups) {
*Offset = OS.tell();
*Size = 8;
OS.write_zeros(1);
} else
OS << uint8_t(AddrDelta);
} else if (isUInt<16>(AddrDelta)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
support::endian::write<uint16_t>(OS, AddrDelta, E);
if (WithFixups) {
*Offset = OS.tell();
*Size = 16;
OS.write_zeros(2);
} else
support::endian::write<uint16_t>(OS, AddrDelta, E);
} else {
assert(isUInt<32>(AddrDelta));
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
support::endian::write<uint32_t>(OS, AddrDelta, E);
if (WithFixups) {
*Offset = OS.tell();
*Size = 32;
OS.write_zeros(4);
} else
support::endian::write<uint32_t>(OS, AddrDelta, E);
}
}

View File

@ -577,6 +577,24 @@ static void AttemptToFoldSymbolOffsetDifference(
A = B = nullptr;
}
static bool canFold(const MCAssembler *Asm, const MCSymbolRefExpr *A,
const MCSymbolRefExpr *B, bool InSet) {
if (InSet)
return true;
if (!Asm->getBackend().requiresDiffExpressionRelocations())
return true;
const MCSymbol &CheckSym = A ? A->getSymbol() : B->getSymbol();
if (!CheckSym.isInSection())
return true;
if (!CheckSym.getSection().hasInstructions())
return true;
return false;
}
/// Evaluate the result of an add between (conceptually) two MCValues.
///
/// This routine conceptually attempts to construct an MCValue:
@ -617,8 +635,7 @@ EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout,
// the backend requires this to be emitted as individual relocations, unless
// the InSet flag is set to get the current difference anyway (used for
// example to calculate symbol sizes).
if (Asm &&
(InSet || !Asm->getBackend().requiresDiffExpressionRelocations())) {
if (Asm && canFold(Asm, LHS_A, LHS_B, InSet)) {
// First, fold out any differences which are fully resolved. By
// reassociating terms in
// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).

View File

@ -335,6 +335,8 @@ static bool supportsRISCV(uint64_t Type) {
case ELF::R_RISCV_NONE:
case ELF::R_RISCV_32:
case ELF::R_RISCV_64:
case ELF::R_RISCV_SET6:
case ELF::R_RISCV_SUB6:
case ELF::R_RISCV_ADD8:
case ELF::R_RISCV_SUB8:
case ELF::R_RISCV_ADD16:
@ -358,6 +360,10 @@ static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
return (S + RA) & 0xFFFFFFFF;
case ELF::R_RISCV_64:
return S + RA;
case ELF::R_RISCV_SET6:
return (A + (S + RA)) & 0xFF;
case ELF::R_RISCV_SUB6:
return (A - (S + RA)) & 0xFF;
case ELF::R_RISCV_ADD8:
return (A + (S + RA)) & 0xFF;
case ELF::R_RISCV_SUB8:

View File

@ -127,6 +127,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseRegister(OperandVector &Operands,
bool AllowParens = false);
OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
OperandMatchResultTy parseAtomicMemOp(OperandVector &Operands);
OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
OperandMatchResultTy parseBareSymbol(OperandVector &Operands);
OperandMatchResultTy parseCallSymbol(OperandVector &Operands);
@ -575,6 +576,15 @@ struct RISCVOperand : public MCParsedAsmOperand {
bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
bool isImmZero() const {
if (!isImm())
return false;
int64_t Imm;
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;
}
/// getStartLoc - Gets location of the first token of this operand
SMLoc getStartLoc() const override { return StartLoc; }
/// getEndLoc - Gets location of the last token of this operand
@ -1300,6 +1310,73 @@ RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
return MatchOperand_Success;
}
OperandMatchResultTy RISCVAsmParser::parseAtomicMemOp(OperandVector &Operands) {
// Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
// as one of their register operands, such as `(a0)`. This just denotes that
// the register (in this case `a0`) contains a memory address.
//
// Normally, we would be able to parse these by putting the parens into the
// instruction string. However, GNU as also accepts a zero-offset memory
// operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
// with parseImmediate followed by parseMemOpBaseReg, but these instructions
// do not accept an immediate operand, and we do not want to add a "dummy"
// operand that is silently dropped.
//
// Instead, we use this custom parser. This will: allow (and discard) an
// offset if it is zero; require (and discard) parentheses; and add only the
// parsed register operand to `Operands`.
//
// These operands are printed with RISCVInstPrinter::printAtomicMemOp, which
// will only print the register surrounded by parentheses (which GNU as also
// uses as its canonical representation for these operands).
std::unique_ptr<RISCVOperand> OptionalImmOp;
if (getLexer().isNot(AsmToken::LParen)) {
// Parse an Integer token. We do not accept arbritrary constant expressions
// in the offset field (because they may include parens, which complicates
// parsing a lot).
int64_t ImmVal;
SMLoc ImmStart = getLoc();
if (getParser().parseIntToken(ImmVal,
"expected '(' or optional integer offset"))
return MatchOperand_ParseFail;
// Create a RISCVOperand for checking later (so the error messages are
// nicer), but we don't add it to Operands.
SMLoc ImmEnd = getLoc();
OptionalImmOp =
RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
ImmStart, ImmEnd, isRV64());
}
if (getLexer().isNot(AsmToken::LParen)) {
Error(getLoc(), OptionalImmOp ? "expected '(' after optional integer offset"
: "expected '(' or optional integer offset");
return MatchOperand_ParseFail;
}
getParser().Lex(); // Eat '('
if (parseRegister(Operands) != MatchOperand_Success) {
Error(getLoc(), "expected register");
return MatchOperand_ParseFail;
}
if (getLexer().isNot(AsmToken::RParen)) {
Error(getLoc(), "expected ')'");
return MatchOperand_ParseFail;
}
getParser().Lex(); // Eat ')'
// Deferred Handling of non-zero offsets. This makes the error messages nicer.
if (OptionalImmOp && !OptionalImmOp->isImmZero()) {
Error(OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
return MatchOperand_ParseFail;
}
return MatchOperand_Success;
}
/// Looks at a token type and creates the relevant operand from this
/// information, adding to Operands. If operand was parsed, returns false, else
/// true.

View File

@ -33,6 +33,13 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
switch ((unsigned)Fixup.getKind()) {
default:
break;
case FK_Data_1:
case FK_Data_2:
case FK_Data_4:
case FK_Data_8:
if (Target.isAbsolute())
return false;
break;
case RISCV::fixup_riscv_got_hi20:
case RISCV::fixup_riscv_tls_got_hi20:
case RISCV::fixup_riscv_tls_gd_hi20:
@ -186,6 +193,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case FK_Data_2:
case FK_Data_4:
case FK_Data_8:
case FK_Data_6b:
return Value;
case RISCV::fixup_riscv_lo12_i:
case RISCV::fixup_riscv_pcrel_lo12_i:

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/RISCVFixupKinds.h"
#include "MCTargetDesc/RISCVMCExpr.h"
#include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCFixup.h"
@ -47,6 +48,7 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
const MCValue &Target,
const MCFixup &Fixup,
bool IsPCRel) const {
const MCExpr *Expr = Fixup.getValue();
// Determine the type of the relocation
unsigned Kind = Fixup.getKind();
if (IsPCRel) {
@ -87,6 +89,9 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
default:
llvm_unreachable("invalid fixup kind!");
case FK_Data_4:
if (Expr->getKind() == MCExpr::Target &&
cast<RISCVMCExpr>(Expr)->getKind() == RISCVMCExpr::VK_RISCV_32_PCREL)
return ELF::R_RISCV_32_PCREL;
return ELF::R_RISCV_32;
case FK_Data_8:
return ELF::R_RISCV_64;
@ -98,6 +103,8 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_RISCV_ADD32;
case FK_Data_Add_8:
return ELF::R_RISCV_ADD64;
case FK_Data_Add_6b:
return ELF::R_RISCV_SET6;
case FK_Data_Sub_1:
return ELF::R_RISCV_SUB8;
case FK_Data_Sub_2:
@ -106,6 +113,8 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_RISCV_SUB32;
case FK_Data_Sub_8:
return ELF::R_RISCV_SUB64;
case FK_Data_Sub_6b:
return ELF::R_RISCV_SUB6;
case RISCV::fixup_riscv_hi20:
return ELF::R_RISCV_HI20;
case RISCV::fixup_riscv_lo12_i:

View File

@ -112,3 +112,15 @@ void RISCVInstPrinter::printFRMArg(const MCInst *MI, unsigned OpNo,
static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm());
O << RISCVFPRndMode::roundingModeToString(FRMArg);
}
void RISCVInstPrinter::printAtomicMemOp(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNo);
assert(MO.isReg() && "printAtomicMemOp can only print register operands");
O << "(";
printRegName(O, MO.getReg());
O << ")";
return;
}

View File

@ -37,6 +37,8 @@ class RISCVInstPrinter : public MCInstPrinter {
const MCSubtargetInfo &STI, raw_ostream &O);
void printFRMArg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);
void printAtomicMemOp(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O);
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, const MCSubtargetInfo &STI,

View File

@ -11,7 +11,10 @@
//===----------------------------------------------------------------------===//
#include "RISCVMCAsmInfo.h"
#include "MCTargetDesc/RISCVMCExpr.h"
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/MC/MCStreamer.h"
using namespace llvm;
void RISCVMCAsmInfo::anchor() {}
@ -25,3 +28,20 @@ RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) {
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
}
const MCExpr *RISCVMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
unsigned Encoding,
MCStreamer &Streamer) const {
if (!(Encoding & dwarf::DW_EH_PE_pcrel))
return MCAsmInfo::getExprForFDESymbol(Sym, Encoding, Streamer);
// The default symbol subtraction results in an ADD/SUB relocation pair.
// Processing this relocation pair is problematic when linker relaxation is
// enabled, so we follow binutils in using the R_RISCV_32_PCREL relocation
// for the FDE initial location.
MCContext &Ctx = Streamer.getContext();
const MCExpr *ME =
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
assert(Encoding & dwarf::DW_EH_PE_sdata4 && "Unexpected encoding");
return RISCVMCExpr::create(ME, RISCVMCExpr::VK_RISCV_32_PCREL, Ctx);
}

View File

@ -23,6 +23,9 @@ class RISCVMCAsmInfo : public MCAsmInfoELF {
public:
explicit RISCVMCAsmInfo(const Triple &TargetTriple);
const MCExpr *getExprForFDESymbol(const MCSymbol *Sym, unsigned Encoding,
MCStreamer &Streamer) const override;
};
} // namespace llvm

View File

@ -266,6 +266,7 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
switch (RVExpr->getKind()) {
case RISCVMCExpr::VK_RISCV_None:
case RISCVMCExpr::VK_RISCV_Invalid:
case RISCVMCExpr::VK_RISCV_32_PCREL:
llvm_unreachable("Unhandled fixup kind!");
case RISCVMCExpr::VK_RISCV_TPREL_ADD:
// tprel_add is only used to indicate that a relocation should be emitted

View File

@ -36,6 +36,7 @@ class RISCVMCExpr : public MCTargetExpr {
VK_RISCV_TLS_GD_HI,
VK_RISCV_CALL,
VK_RISCV_CALL_PLT,
VK_RISCV_32_PCREL,
VK_RISCV_Invalid
};

View File

@ -11,6 +11,24 @@
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Operand and SDNode transformation definitions.
//===----------------------------------------------------------------------===//
// A parse method for (${gpr}) or 0(${gpr}), where the 0 is be silently ignored.
// Used for GNU as Compatibility.
def AtomicMemOpOperand : AsmOperandClass {
let Name = "AtomicMemOpOperand";
let RenderMethod = "addRegOperands";
let PredicateMethod = "isReg";
let ParserMethod = "parseAtomicMemOp";
}
def GPRMemAtomic : RegisterOperand<GPR> {
let ParserMatchClass = AtomicMemOpOperand;
let PrintMethod = "printAtomicMemOp";
}
//===----------------------------------------------------------------------===//
// Instruction class templates
//===----------------------------------------------------------------------===//
@ -18,8 +36,8 @@
let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
class LR_r<bit aq, bit rl, bits<3> funct3, string opcodestr>
: RVInstRAtomic<0b00010, aq, rl, funct3, OPC_AMO,
(outs GPR:$rd), (ins GPR:$rs1),
opcodestr, "$rd, (${rs1})"> {
(outs GPR:$rd), (ins GPRMemAtomic:$rs1),
opcodestr, "$rd, $rs1"> {
let rs2 = 0;
}
@ -33,8 +51,8 @@ multiclass LR_r_aq_rl<bits<3> funct3, string opcodestr> {
let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in
class AMO_rr<bits<5> funct5, bit aq, bit rl, bits<3> funct3, string opcodestr>
: RVInstRAtomic<funct5, aq, rl, funct3, OPC_AMO,
(outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
opcodestr, "$rd, $rs2, (${rs1})">;
(outs GPR:$rd), (ins GPRMemAtomic:$rs1, GPR:$rs2),
opcodestr, "$rd, $rs2, $rs1">;
multiclass AMO_rr_aq_rl<bits<5> funct5, bits<3> funct3, string opcodestr> {
def "" : AMO_rr<funct5, 0, 0, funct3, opcodestr>;

View File

@ -363,15 +363,26 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new AMDGPUTargetInfo(Triple, Opts);
case llvm::Triple::riscv32:
// TODO: add cases for FreeBSD, NetBSD, RTEMS once tested.
if (os == llvm::Triple::Linux)
// TODO: add cases for NetBSD, RTEMS once tested.
switch (os) {
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<RISCV32TargetInfo>(Triple, Opts);
case llvm::Triple::Linux:
return new LinuxTargetInfo<RISCV32TargetInfo>(Triple, Opts);
return new RISCV32TargetInfo(Triple, Opts);
default:
return new RISCV32TargetInfo(Triple, Opts);
}
case llvm::Triple::riscv64:
// TODO: add cases for FreeBSD, NetBSD, RTEMS once tested.
if (os == llvm::Triple::Linux)
// TODO: add cases for NetBSD, RTEMS once tested.
switch (os) {
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<RISCV64TargetInfo>(Triple, Opts);
case llvm::Triple::Linux:
return new LinuxTargetInfo<RISCV64TargetInfo>(Triple, Opts);
return new RISCV64TargetInfo(Triple, Opts);
default:
return new RISCV64TargetInfo(Triple, Opts);
}
case llvm::Triple::sparc:
switch (os) {

View File

@ -197,6 +197,14 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("elf64ltsmip_fbsd");
break;
case llvm::Triple::riscv32:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32lriscv");
break;
case llvm::Triple::riscv64:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf64lriscv");
break;
default:
break;
}