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