1 //===-- AVRMCExpr.cpp - AVR specific MC expression classes ----------------===//
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 //===----------------------------------------------------------------------===//
11 #include "llvm/MC/MCAsmLayout.h"
12 #include "llvm/MC/MCAssembler.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCStreamer.h"
15 #include "llvm/MC/MCValue.h"
21 const struct ModifierEntry
{
22 const char * const Spelling
;
23 AVRMCExpr::VariantKind VariantKind
;
25 {"lo8", AVRMCExpr::VK_AVR_LO8
}, {"hi8", AVRMCExpr::VK_AVR_HI8
},
26 {"hh8", AVRMCExpr::VK_AVR_HH8
}, // synonym with hlo8
27 {"hlo8", AVRMCExpr::VK_AVR_HH8
}, {"hhi8", AVRMCExpr::VK_AVR_HHI8
},
29 {"pm_lo8", AVRMCExpr::VK_AVR_PM_LO8
}, {"pm_hi8", AVRMCExpr::VK_AVR_PM_HI8
},
30 {"pm_hh8", AVRMCExpr::VK_AVR_PM_HH8
},
32 {"lo8_gs", AVRMCExpr::VK_AVR_LO8_GS
}, {"hi8_gs", AVRMCExpr::VK_AVR_HI8_GS
},
33 {"gs", AVRMCExpr::VK_AVR_GS
},
36 } // end of anonymous namespace
38 const AVRMCExpr
*AVRMCExpr::create(VariantKind Kind
, const MCExpr
*Expr
,
39 bool Negated
, MCContext
&Ctx
) {
40 return new (Ctx
) AVRMCExpr(Kind
, Expr
, Negated
);
43 void AVRMCExpr::printImpl(raw_ostream
&OS
, const MCAsmInfo
*MAI
) const {
44 assert(Kind
!= VK_AVR_None
);
49 OS
<< getName() << '(';
50 getSubExpr()->print(OS
, MAI
);
54 bool AVRMCExpr::evaluateAsConstant(int64_t &Result
) const {
58 getSubExpr()->evaluateAsRelocatable(Value
, nullptr, nullptr);
63 if (Value
.isAbsolute()) {
64 Result
= evaluateAsInt64(Value
.getConstant());
71 bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue
&Result
,
72 const MCAsmLayout
*Layout
,
73 const MCFixup
*Fixup
) const {
75 bool isRelocatable
= SubExpr
->evaluateAsRelocatable(Value
, Layout
, Fixup
);
80 if (Value
.isAbsolute()) {
81 Result
= MCValue::get(evaluateAsInt64(Value
.getConstant()));
83 if (!Layout
) return false;
85 MCContext
&Context
= Layout
->getAssembler().getContext();
86 const MCSymbolRefExpr
*Sym
= Value
.getSymA();
87 MCSymbolRefExpr::VariantKind Modifier
= Sym
->getKind();
88 if (Modifier
!= MCSymbolRefExpr::VK_None
)
91 Sym
= MCSymbolRefExpr::create(&Sym
->getSymbol(), Modifier
, Context
);
92 Result
= MCValue::get(Sym
, Value
.getSymB(), Value
.getConstant());
98 int64_t AVRMCExpr::evaluateAsInt64(int64_t Value
) const {
103 case AVRMCExpr::VK_AVR_LO8
:
106 case AVRMCExpr::VK_AVR_HI8
:
110 case AVRMCExpr::VK_AVR_HH8
:
114 case AVRMCExpr::VK_AVR_HHI8
:
118 case AVRMCExpr::VK_AVR_PM_LO8
:
119 case AVRMCExpr::VK_AVR_LO8_GS
:
120 Value
>>= 1; // Program memory addresses must always be shifted by one.
123 case AVRMCExpr::VK_AVR_PM_HI8
:
124 case AVRMCExpr::VK_AVR_HI8_GS
:
125 Value
>>= 1; // Program memory addresses must always be shifted by one.
129 case AVRMCExpr::VK_AVR_PM_HH8
:
130 Value
>>= 1; // Program memory addresses must always be shifted by one.
134 case AVRMCExpr::VK_AVR_GS
:
135 Value
>>= 1; // Program memory addresses must always be shifted by one.
138 case AVRMCExpr::VK_AVR_None
:
139 llvm_unreachable("Uninitialized expression.");
141 return static_cast<uint64_t>(Value
) & 0xff;
144 AVR::Fixups
AVRMCExpr::getFixupKind() const {
145 AVR::Fixups Kind
= AVR::Fixups::LastTargetFixupKind
;
149 Kind
= isNegated() ? AVR::fixup_lo8_ldi_neg
: AVR::fixup_lo8_ldi
;
152 Kind
= isNegated() ? AVR::fixup_hi8_ldi_neg
: AVR::fixup_hi8_ldi
;
155 Kind
= isNegated() ? AVR::fixup_hh8_ldi_neg
: AVR::fixup_hh8_ldi
;
158 Kind
= isNegated() ? AVR::fixup_ms8_ldi_neg
: AVR::fixup_ms8_ldi
;
162 Kind
= isNegated() ? AVR::fixup_lo8_ldi_pm_neg
: AVR::fixup_lo8_ldi_pm
;
165 Kind
= isNegated() ? AVR::fixup_hi8_ldi_pm_neg
: AVR::fixup_hi8_ldi_pm
;
168 Kind
= isNegated() ? AVR::fixup_hh8_ldi_pm_neg
: AVR::fixup_hh8_ldi_pm
;
171 Kind
= AVR::fixup_16_pm
;
174 Kind
= AVR::fixup_lo8_ldi_gs
;
177 Kind
= AVR::fixup_hi8_ldi_gs
;
181 llvm_unreachable("Uninitialized expression");
187 void AVRMCExpr::visitUsedExpr(MCStreamer
&Streamer
) const {
188 Streamer
.visitUsedExpr(*getSubExpr());
191 const char *AVRMCExpr::getName() const {
192 const auto &Modifier
= std::find_if(
193 std::begin(ModifierNames
), std::end(ModifierNames
),
194 [this](ModifierEntry
const &Mod
) { return Mod
.VariantKind
== Kind
; });
196 if (Modifier
!= std::end(ModifierNames
)) {
197 return Modifier
->Spelling
;
202 AVRMCExpr::VariantKind
AVRMCExpr::getKindByName(StringRef Name
) {
203 const auto &Modifier
= std::find_if(
204 std::begin(ModifierNames
), std::end(ModifierNames
),
205 [&Name
](ModifierEntry
const &Mod
) { return Mod
.Spelling
== Name
; });
207 if (Modifier
!= std::end(ModifierNames
)) {
208 return Modifier
->VariantKind
;
213 } // end of namespace llvm