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