1//===-- MipsMCAsmInfo.cpp - Mips Asm Properties ---------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the declarations of the MipsMCAsmInfo properties.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MipsMCAsmInfo.h"
14#include "MipsABIInfo.h"
15#include "llvm/MC/MCValue.h"
16#include "llvm/Support/Casting.h"
17#include "llvm/TargetParser/Triple.h"
18
19using namespace llvm;
20
21void MipsELFMCAsmInfo::anchor() {}
22
23MipsELFMCAsmInfo::MipsELFMCAsmInfo(const Triple &TheTriple,
24 const MCTargetOptions &Options) {
25 IsLittleEndian = TheTriple.isLittleEndian();
26
27 MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TT: TheTriple, CPU: "", Options);
28
29 if (TheTriple.isMIPS64() && !ABI.IsN32())
30 CodePointerSize = CalleeSaveStackSlotSize = 8;
31
32 if (ABI.IsO32())
33 PrivateGlobalPrefix = "$";
34 else if (ABI.IsN32() || ABI.IsN64())
35 PrivateGlobalPrefix = ".L";
36 PrivateLabelPrefix = PrivateGlobalPrefix;
37
38 AlignmentIsInBytes = false;
39 Data16bitsDirective = "\t.2byte\t";
40 Data32bitsDirective = "\t.4byte\t";
41 Data64bitsDirective = "\t.8byte\t";
42 CommentString = "#";
43 ZeroDirective = "\t.space\t";
44 UseAssignmentForEHBegin = true;
45 SupportsDebugInformation = true;
46 ExceptionsType = ExceptionHandling::DwarfCFI;
47 DwarfRegNumForCFI = true;
48}
49
50void MipsCOFFMCAsmInfo::anchor() {}
51
52MipsCOFFMCAsmInfo::MipsCOFFMCAsmInfo() {
53 HasSingleParameterDotFile = true;
54 WinEHEncodingType = WinEH::EncodingType::Itanium;
55
56 ExceptionsType = ExceptionHandling::WinEH;
57
58 PrivateGlobalPrefix = ".L";
59 PrivateLabelPrefix = ".L";
60 AllowAtInName = true;
61}
62
63const MCSpecifierExpr *Mips::createGpOff(const MCExpr *Expr, Mips::Specifier S,
64 MCContext &Ctx) {
65 Expr = MCSpecifierExpr::create(Expr, S: Mips::S_GPREL, Ctx);
66 Expr = MCSpecifierExpr::create(Expr, S: Mips::S_NEG, Ctx);
67 return MCSpecifierExpr::create(Expr, S, Ctx);
68}
69
70static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS,
71 const MCSpecifierExpr &Expr) {
72 int64_t AbsVal;
73
74 switch (Expr.getSpecifier()) {
75 case Mips::S_None:
76 case Mips::S_Special:
77 llvm_unreachable("Mips::S_None and MEK_Special are invalid");
78 break;
79 case Mips::S_DTPREL:
80 // Mips::S_DTPREL is used for marking TLS DIEExpr only
81 // and contains a regular sub-expression.
82 MAI.printExpr(OS, *Expr.getSubExpr());
83 return;
84 case Mips::S_CALL_HI16:
85 OS << "%call_hi";
86 break;
87 case Mips::S_CALL_LO16:
88 OS << "%call_lo";
89 break;
90 case Mips::S_DTPREL_HI:
91 OS << "%dtprel_hi";
92 break;
93 case Mips::S_DTPREL_LO:
94 OS << "%dtprel_lo";
95 break;
96 case Mips::S_GOT:
97 OS << "%got";
98 break;
99 case Mips::S_GOTTPREL:
100 OS << "%gottprel";
101 break;
102 case Mips::S_GOT_CALL:
103 OS << "%call16";
104 break;
105 case Mips::S_GOT_DISP:
106 OS << "%got_disp";
107 break;
108 case Mips::S_GOT_HI16:
109 OS << "%got_hi";
110 break;
111 case Mips::S_GOT_LO16:
112 OS << "%got_lo";
113 break;
114 case Mips::S_GOT_PAGE:
115 OS << "%got_page";
116 break;
117 case Mips::S_GOT_OFST:
118 OS << "%got_ofst";
119 break;
120 case Mips::S_GPREL:
121 OS << "%gp_rel";
122 break;
123 case Mips::S_HI:
124 OS << "%hi";
125 break;
126 case Mips::S_HIGHER:
127 OS << "%higher";
128 break;
129 case Mips::S_HIGHEST:
130 OS << "%highest";
131 break;
132 case Mips::S_LO:
133 OS << "%lo";
134 break;
135 case Mips::S_NEG:
136 OS << "%neg";
137 break;
138 case Mips::S_PCREL_HI16:
139 OS << "%pcrel_hi";
140 break;
141 case Mips::S_PCREL_LO16:
142 OS << "%pcrel_lo";
143 break;
144 case Mips::S_TLSGD:
145 OS << "%tlsgd";
146 break;
147 case Mips::S_TLSLDM:
148 OS << "%tlsldm";
149 break;
150 case Mips::S_TPREL_HI:
151 OS << "%tprel_hi";
152 break;
153 case Mips::S_TPREL_LO:
154 OS << "%tprel_lo";
155 break;
156 }
157
158 OS << '(';
159 if (Expr.evaluateAsAbsolute(Res&: AbsVal))
160 OS << AbsVal;
161 else
162 MAI.printExpr(OS, *Expr.getSubExpr());
163 OS << ')';
164}
165
166bool Mips::isGpOff(const MCSpecifierExpr &E) {
167 if (E.getSpecifier() == Mips::S_HI || E.getSpecifier() == Mips::S_LO) {
168 if (const auto *S1 = dyn_cast<const MCSpecifierExpr>(Val: E.getSubExpr())) {
169 if (const auto *S2 = dyn_cast<const MCSpecifierExpr>(Val: S1->getSubExpr())) {
170 if (S1->getSpecifier() == Mips::S_NEG &&
171 S2->getSpecifier() == Mips::S_GPREL) {
172 // S = E.getSpecifier();
173 return true;
174 }
175 }
176 }
177 }
178 return false;
179}
180
181static bool evaluate(const MCSpecifierExpr &Expr, MCValue &Res,
182 const MCAssembler *Asm) {
183 // Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X)))
184 // special cases.
185 if (Mips::isGpOff(E: Expr)) {
186 const MCExpr *SubExpr =
187 cast<MCSpecifierExpr>(
188 Val: cast<MCSpecifierExpr>(Val: Expr.getSubExpr())->getSubExpr())
189 ->getSubExpr();
190 if (!SubExpr->evaluateAsRelocatable(Res, Asm))
191 return false;
192
193 Res.setSpecifier(Mips::S_Special);
194 return true;
195 }
196
197 if (!Expr.getSubExpr()->evaluateAsRelocatable(Res, Asm))
198 return false;
199 Res.setSpecifier(Expr.getSpecifier());
200 return !Res.getSubSym();
201}
202
203void MipsELFMCAsmInfo::printSpecifierExpr(raw_ostream &OS,
204 const MCSpecifierExpr &Expr) const {
205 printImpl(MAI: *this, OS, Expr);
206}
207
208bool MipsELFMCAsmInfo::evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr,
209 MCValue &Res,
210 const MCAssembler *Asm) const {
211 return evaluate(Expr, Res, Asm);
212}
213
214void MipsCOFFMCAsmInfo::printSpecifierExpr(raw_ostream &OS,
215 const MCSpecifierExpr &Expr) const {
216 printImpl(MAI: *this, OS, Expr);
217}
218
219bool MipsCOFFMCAsmInfo::evaluateAsRelocatableImpl(
220 const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const {
221 return evaluate(Expr, Res, Asm);
222}
223