diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index 2c35c3678a0..bcbc83d965e 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -17,6 +17,7 @@ add_llvm_target(MipsCodeGen MipsISelLowering.cpp MipsFrameLowering.cpp MipsMCAsmInfo.cpp + MipsMCSymbolRefExpr.cpp MipsRegisterInfo.cpp MipsSubtarget.cpp MipsTargetMachine.cpp diff --git a/lib/Target/Mips/MipsMCSymbolRefExpr.cpp b/lib/Target/Mips/MipsMCSymbolRefExpr.cpp new file mode 100644 index 00000000000..9a2bdae0e33 --- /dev/null +++ b/lib/Target/Mips/MipsMCSymbolRefExpr.cpp @@ -0,0 +1,63 @@ +//===-- MipsMCSymbolRefExpr.cpp - Mips 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. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mipsmcsymbolrefexpr" +#include "MipsMCSymbolRefExpr.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +using namespace llvm; + +const MipsMCSymbolRefExpr* +MipsMCSymbolRefExpr::Create(VariantKind Kind, const MCSymbol *Symbol, + int Offset, MCContext &Ctx) { + return new (Ctx) MipsMCSymbolRefExpr(Kind, Symbol, Offset); +} + +void MipsMCSymbolRefExpr::PrintImpl(raw_ostream &OS) const { + switch (Kind) { + default: assert(0 && "Invalid kind!"); + case VK_Mips_None: break; + case VK_Mips_GPREL: OS << "%gp_rel("; break; + case VK_Mips_GOT_CALL: OS << "%call16("; break; + case VK_Mips_GOT: OS << "%got("; break; + case VK_Mips_ABS_HI: OS << "%hi("; break; + case VK_Mips_ABS_LO: OS << "%lo("; break; + case VK_Mips_TLSGD: OS << "%tlsgd("; break; + case VK_Mips_GOTTPREL: OS << "%gottprel("; break; + case VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; + case VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; + } + + OS << *Symbol; + + if (Offset) { + if (Offset > 0) + OS << '+'; + OS << Offset; + } + + if (Kind != VK_Mips_None) + OS << ')'; +} + +bool +MipsMCSymbolRefExpr::EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const { + return false; +} + +void MipsMCSymbolRefExpr::AddValueSymbols(MCAssembler *Asm) const { + Asm->getOrCreateSymbolData(*Symbol); +} + +const MCSection *MipsMCSymbolRefExpr::FindAssociatedSection() const { + return Symbol->isDefined() ? &Symbol->getSection() : NULL; +} + diff --git a/lib/Target/Mips/MipsMCSymbolRefExpr.h b/lib/Target/Mips/MipsMCSymbolRefExpr.h new file mode 100644 index 00000000000..3e695963709 --- /dev/null +++ b/lib/Target/Mips/MipsMCSymbolRefExpr.h @@ -0,0 +1,62 @@ +//===-- MipsMCSymbolRefExpr.h - Mips specific MCSymbolRefExpr class -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSMCSYMBOLREFEXPR_H +#define MIPSMCSYMBOLREFEXPR_H +#include "llvm/MC/MCExpr.h" + +namespace llvm { + +class MipsMCSymbolRefExpr : public MCTargetExpr { +public: + enum VariantKind { + VK_Mips_None, + VK_Mips_GPREL, + VK_Mips_GOT_CALL, + VK_Mips_GOT, + VK_Mips_ABS_HI, + VK_Mips_ABS_LO, + VK_Mips_TLSGD, + VK_Mips_GOTTPREL, + VK_Mips_TPREL_HI, + VK_Mips_TPREL_LO + }; + +private: + const VariantKind Kind; + const MCSymbol *Symbol; + int Offset; + + explicit MipsMCSymbolRefExpr(VariantKind _Kind, const MCSymbol *_Symbol, + int _Offset) + : Kind(_Kind), Symbol(_Symbol), Offset(_Offset) {} + +public: + static const MipsMCSymbolRefExpr *Create(VariantKind Kind, + const MCSymbol *Symbol, int Offset, + MCContext &Ctx); + + void PrintImpl(raw_ostream &OS) const; + bool EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const; + void AddValueSymbols(MCAssembler *) const; + const MCSection *FindAssociatedSection() const; + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } + + static bool classof(const MipsMCSymbolRefExpr *) { return true; } + + int getOffset() const { return Offset; } + void setOffset(int O) { Offset = O; } +}; +} // end namespace llvm + +#endif