1 //===-- MipsMCExpr.cpp - Mips specific MC expression classes --------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "MipsMCExpr.h"
11 #include "llvm/MC/MCAsmInfo.h"
12 #include "llvm/MC/MCAssembler.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCObjectStreamer.h"
15 
16 using namespace llvm;
17 
18 #define DEBUG_TYPE "mipsmcexpr"
19 
isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK,const MCBinaryExpr * BE)20 bool MipsMCExpr::isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK,
21                                        const MCBinaryExpr *BE) {
22   switch (VK) {
23   case MCSymbolRefExpr::VK_Mips_ABS_LO:
24   case MCSymbolRefExpr::VK_Mips_ABS_HI:
25   case MCSymbolRefExpr::VK_Mips_HIGHER:
26   case MCSymbolRefExpr::VK_Mips_HIGHEST:
27     break;
28   default:
29     return false;
30   }
31 
32   // We support expressions of the form "(sym1 binop1 sym2) binop2 const",
33   // where "binop2 const" is optional.
34   if (isa<MCBinaryExpr>(BE->getLHS())) {
35     if (!isa<MCConstantExpr>(BE->getRHS()))
36       return false;
37     BE = cast<MCBinaryExpr>(BE->getLHS());
38   }
39   return (isa<MCSymbolRefExpr>(BE->getLHS())
40           && isa<MCSymbolRefExpr>(BE->getRHS()));
41 }
42 
43 const MipsMCExpr*
create(MCSymbolRefExpr::VariantKind VK,const MCExpr * Expr,MCContext & Ctx)44 MipsMCExpr::create(MCSymbolRefExpr::VariantKind VK, const MCExpr *Expr,
45                    MCContext &Ctx) {
46   VariantKind Kind;
47   switch (VK) {
48   case MCSymbolRefExpr::VK_Mips_ABS_LO:
49     Kind = VK_Mips_LO;
50     break;
51   case MCSymbolRefExpr::VK_Mips_ABS_HI:
52     Kind = VK_Mips_HI;
53     break;
54   case MCSymbolRefExpr::VK_Mips_HIGHER:
55     Kind = VK_Mips_HIGHER;
56     break;
57   case MCSymbolRefExpr::VK_Mips_HIGHEST:
58     Kind = VK_Mips_HIGHEST;
59     break;
60   default:
61     llvm_unreachable("Invalid kind!");
62   }
63 
64   return new (Ctx) MipsMCExpr(Kind, Expr);
65 }
66 
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const67 void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
68   switch (Kind) {
69   default: llvm_unreachable("Invalid kind!");
70   case VK_Mips_LO: OS << "%lo"; break;
71   case VK_Mips_HI: OS << "%hi"; break;
72   case VK_Mips_HIGHER: OS << "%higher"; break;
73   case VK_Mips_HIGHEST: OS << "%highest"; break;
74   }
75 
76   OS << '(';
77   Expr->print(OS, MAI);
78   OS << ')';
79 }
80 
81 bool
evaluateAsRelocatableImpl(MCValue & Res,const MCAsmLayout * Layout,const MCFixup * Fixup) const82 MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
83                                       const MCAsmLayout *Layout,
84                                       const MCFixup *Fixup) const {
85   return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup);
86 }
87 
visitUsedExpr(MCStreamer & Streamer) const88 void MipsMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
89   Streamer.visitUsedExpr(*getSubExpr());
90 }
91