1 //===-- LanaiAsmBackend.cpp - Lanai Assembler Backend ---------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "LanaiFixupKinds.h"
10 #include "MCTargetDesc/LanaiMCTargetDesc.h"
11 #include "llvm/MC/MCAsmBackend.h"
12 #include "llvm/MC/MCAssembler.h"
13 #include "llvm/MC/MCDirectives.h"
14 #include "llvm/MC/MCELFObjectWriter.h"
15 #include "llvm/MC/MCFixupKindInfo.h"
16 #include "llvm/MC/MCObjectWriter.h"
17 #include "llvm/MC/MCSubtargetInfo.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
23 // Prepare value for the target space
24 static unsigned adjustFixupValue(unsigned Kind
, uint64_t Value
) {
31 case Lanai::FIXUP_LANAI_21
:
32 case Lanai::FIXUP_LANAI_21_F
:
33 case Lanai::FIXUP_LANAI_25
:
34 case Lanai::FIXUP_LANAI_32
:
35 case Lanai::FIXUP_LANAI_HI16
:
36 case Lanai::FIXUP_LANAI_LO16
:
39 llvm_unreachable("Unknown fixup kind!");
44 class LanaiAsmBackend
: public MCAsmBackend
{
45 Triple::OSType OSType
;
48 LanaiAsmBackend(const Target
&T
, Triple::OSType OST
)
49 : MCAsmBackend(support::big
), OSType(OST
) {}
51 void applyFixup(const MCAssembler
&Asm
, const MCFixup
&Fixup
,
52 const MCValue
&Target
, MutableArrayRef
<char> Data
,
53 uint64_t Value
, bool IsResolved
,
54 const MCSubtargetInfo
*STI
) const override
;
56 std::unique_ptr
<MCObjectTargetWriter
>
57 createObjectTargetWriter() const override
;
59 // No instruction requires relaxation
60 bool fixupNeedsRelaxation(const MCFixup
& /*Fixup*/, uint64_t /*Value*/,
61 const MCRelaxableFragment
* /*DF*/,
62 const MCAsmLayout
& /*Layout*/) const override
{
66 const MCFixupKindInfo
&getFixupKindInfo(MCFixupKind Kind
) const override
;
68 unsigned getNumFixupKinds() const override
{
69 return Lanai::NumTargetFixupKinds
;
72 bool mayNeedRelaxation(const MCInst
& /*Inst*/,
73 const MCSubtargetInfo
&STI
) const override
{
77 void relaxInstruction(const MCInst
& /*Inst*/,
78 const MCSubtargetInfo
& /*STI*/,
79 MCInst
& /*Res*/) const override
{}
81 bool writeNopData(raw_ostream
&OS
, uint64_t Count
) const override
;
84 bool LanaiAsmBackend::writeNopData(raw_ostream
&OS
, uint64_t Count
) const {
88 for (uint64_t i
= 0; i
< Count
; i
+= 4)
89 OS
.write("\x15\0\0\0", 4);
94 void LanaiAsmBackend::applyFixup(const MCAssembler
&Asm
, const MCFixup
&Fixup
,
95 const MCValue
&Target
,
96 MutableArrayRef
<char> Data
, uint64_t Value
,
98 const MCSubtargetInfo
* /*STI*/) const {
99 MCFixupKind Kind
= Fixup
.getKind();
100 Value
= adjustFixupValue(static_cast<unsigned>(Kind
), Value
);
103 return; // This value doesn't change the encoding
105 // Where in the object and where the number of bytes that need
107 unsigned Offset
= Fixup
.getOffset();
108 unsigned NumBytes
= (getFixupKindInfo(Kind
).TargetSize
+ 7) / 8;
109 unsigned FullSize
= 4;
111 // Grab current value, if any, from bits.
114 // Load instruction and apply value
115 for (unsigned i
= 0; i
!= NumBytes
; ++i
) {
116 unsigned Idx
= (FullSize
- 1 - i
);
117 CurVal
|= static_cast<uint64_t>(static_cast<uint8_t>(Data
[Offset
+ Idx
]))
122 (static_cast<uint64_t>(-1) >> (64 - getFixupKindInfo(Kind
).TargetSize
));
123 CurVal
|= Value
& Mask
;
125 // Write out the fixed up bytes back to the code/data bits.
126 for (unsigned i
= 0; i
!= NumBytes
; ++i
) {
127 unsigned Idx
= (FullSize
- 1 - i
);
128 Data
[Offset
+ Idx
] = static_cast<uint8_t>((CurVal
>> (i
* 8)) & 0xff);
132 std::unique_ptr
<MCObjectTargetWriter
>
133 LanaiAsmBackend::createObjectTargetWriter() const {
134 return createLanaiELFObjectWriter(MCELFObjectTargetWriter::getOSABI(OSType
));
137 const MCFixupKindInfo
&
138 LanaiAsmBackend::getFixupKindInfo(MCFixupKind Kind
) const {
139 static const MCFixupKindInfo Infos
[Lanai::NumTargetFixupKinds
] = {
140 // This table *must* be in same the order of fixup_* kinds in
141 // LanaiFixupKinds.h.
142 // Note: The number of bits indicated here are assumed to be contiguous.
143 // This does not hold true for LANAI_21 and LANAI_21_F which are applied
144 // to bits 0x7cffff and 0x7cfffc, respectively. Since the 'bits' counts
145 // here are used only for cosmetic purposes, we set the size to 16 bits
146 // for these 21-bit relocation as llvm/lib/MC/MCAsmStreamer.cpp checks
147 // no bits are set in the fixup range.
149 // name offset bits flags
150 {"FIXUP_LANAI_NONE", 0, 32, 0},
151 {"FIXUP_LANAI_21", 16, 16 /*21*/, 0},
152 {"FIXUP_LANAI_21_F", 16, 16 /*21*/, 0},
153 {"FIXUP_LANAI_25", 7, 25, 0},
154 {"FIXUP_LANAI_32", 0, 32, 0},
155 {"FIXUP_LANAI_HI16", 16, 16, 0},
156 {"FIXUP_LANAI_LO16", 16, 16, 0}};
158 if (Kind
< FirstTargetFixupKind
)
159 return MCAsmBackend::getFixupKindInfo(Kind
);
161 assert(unsigned(Kind
- FirstTargetFixupKind
) < getNumFixupKinds() &&
163 return Infos
[Kind
- FirstTargetFixupKind
];
168 MCAsmBackend
*llvm::createLanaiAsmBackend(const Target
&T
,
169 const MCSubtargetInfo
&STI
,
170 const MCRegisterInfo
& /*MRI*/,
171 const MCTargetOptions
& /*Options*/) {
172 const Triple
&TT
= STI
.getTargetTriple();
173 if (!TT
.isOSBinFormatELF())
174 llvm_unreachable("OS not supported");
176 return new LanaiAsmBackend(T
, TT
.getOS());