Fangrui Song 4aa23ccd14 MCAsmInfo: Explicitly set AllowDollarAtStartOfIdentifier to false for some targets
The default AllowDollarAtStartOfIdentifier will be changed to true to
align better with GNU Assembler where $ is a valid initial identifier
char.
2025-07-08 23:02:51 -07:00

224 lines
6.0 KiB
C++

//===-- MipsMCAsmInfo.cpp - Mips Asm Properties ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the MipsMCAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#include "MipsMCAsmInfo.h"
#include "MipsABIInfo.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/Casting.h"
#include "llvm/TargetParser/Triple.h"
using namespace llvm;
void MipsELFMCAsmInfo::anchor() {}
MipsELFMCAsmInfo::MipsELFMCAsmInfo(const Triple &TheTriple,
const MCTargetOptions &Options) {
IsLittleEndian = TheTriple.isLittleEndian();
MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TheTriple, "", Options);
if (TheTriple.isMIPS64() && !ABI.IsN32())
CodePointerSize = CalleeSaveStackSlotSize = 8;
if (ABI.IsO32())
PrivateGlobalPrefix = "$";
else if (ABI.IsN32() || ABI.IsN64())
PrivateGlobalPrefix = ".L";
PrivateLabelPrefix = PrivateGlobalPrefix;
AlignmentIsInBytes = false;
Data16bitsDirective = "\t.2byte\t";
Data32bitsDirective = "\t.4byte\t";
Data64bitsDirective = "\t.8byte\t";
CommentString = "#";
AllowDollarAtStartOfIdentifier = false;
ZeroDirective = "\t.space\t";
UseAssignmentForEHBegin = true;
SupportsDebugInformation = true;
ExceptionsType = ExceptionHandling::DwarfCFI;
DwarfRegNumForCFI = true;
}
void MipsCOFFMCAsmInfo::anchor() {}
MipsCOFFMCAsmInfo::MipsCOFFMCAsmInfo() {
HasSingleParameterDotFile = true;
WinEHEncodingType = WinEH::EncodingType::Itanium;
ExceptionsType = ExceptionHandling::WinEH;
PrivateGlobalPrefix = ".L";
PrivateLabelPrefix = ".L";
AllowAtInName = true;
}
const MCSpecifierExpr *Mips::createGpOff(const MCExpr *Expr, Mips::Specifier S,
MCContext &Ctx) {
Expr = MCSpecifierExpr::create(Expr, Mips::S_GPREL, Ctx);
Expr = MCSpecifierExpr::create(Expr, Mips::S_NEG, Ctx);
return MCSpecifierExpr::create(Expr, S, Ctx);
}
static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS,
const MCSpecifierExpr &Expr) {
int64_t AbsVal;
switch (Expr.getSpecifier()) {
case Mips::S_None:
case Mips::S_Special:
llvm_unreachable("Mips::S_None and MEK_Special are invalid");
break;
case Mips::S_DTPREL:
// Mips::S_DTPREL is used for marking TLS DIEExpr only
// and contains a regular sub-expression.
MAI.printExpr(OS, *Expr.getSubExpr());
return;
case Mips::S_CALL_HI16:
OS << "%call_hi";
break;
case Mips::S_CALL_LO16:
OS << "%call_lo";
break;
case Mips::S_DTPREL_HI:
OS << "%dtprel_hi";
break;
case Mips::S_DTPREL_LO:
OS << "%dtprel_lo";
break;
case Mips::S_GOT:
OS << "%got";
break;
case Mips::S_GOTTPREL:
OS << "%gottprel";
break;
case Mips::S_GOT_CALL:
OS << "%call16";
break;
case Mips::S_GOT_DISP:
OS << "%got_disp";
break;
case Mips::S_GOT_HI16:
OS << "%got_hi";
break;
case Mips::S_GOT_LO16:
OS << "%got_lo";
break;
case Mips::S_GOT_PAGE:
OS << "%got_page";
break;
case Mips::S_GOT_OFST:
OS << "%got_ofst";
break;
case Mips::S_GPREL:
OS << "%gp_rel";
break;
case Mips::S_HI:
OS << "%hi";
break;
case Mips::S_HIGHER:
OS << "%higher";
break;
case Mips::S_HIGHEST:
OS << "%highest";
break;
case Mips::S_LO:
OS << "%lo";
break;
case Mips::S_NEG:
OS << "%neg";
break;
case Mips::S_PCREL_HI16:
OS << "%pcrel_hi";
break;
case Mips::S_PCREL_LO16:
OS << "%pcrel_lo";
break;
case Mips::S_TLSGD:
OS << "%tlsgd";
break;
case Mips::S_TLSLDM:
OS << "%tlsldm";
break;
case Mips::S_TPREL_HI:
OS << "%tprel_hi";
break;
case Mips::S_TPREL_LO:
OS << "%tprel_lo";
break;
}
OS << '(';
if (Expr.evaluateAsAbsolute(AbsVal))
OS << AbsVal;
else
MAI.printExpr(OS, *Expr.getSubExpr());
OS << ')';
}
bool Mips::isGpOff(const MCSpecifierExpr &E) {
if (E.getSpecifier() == Mips::S_HI || E.getSpecifier() == Mips::S_LO) {
if (const auto *S1 = dyn_cast<const MCSpecifierExpr>(E.getSubExpr())) {
if (const auto *S2 = dyn_cast<const MCSpecifierExpr>(S1->getSubExpr())) {
if (S1->getSpecifier() == Mips::S_NEG &&
S2->getSpecifier() == Mips::S_GPREL) {
// S = E.getSpecifier();
return true;
}
}
}
}
return false;
}
static bool evaluate(const MCSpecifierExpr &Expr, MCValue &Res,
const MCAssembler *Asm) {
// Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X)))
// special cases.
if (Mips::isGpOff(Expr)) {
const MCExpr *SubExpr =
cast<MCSpecifierExpr>(
cast<MCSpecifierExpr>(Expr.getSubExpr())->getSubExpr())
->getSubExpr();
if (!SubExpr->evaluateAsRelocatable(Res, Asm))
return false;
Res.setSpecifier(Mips::S_Special);
return true;
}
if (!Expr.getSubExpr()->evaluateAsRelocatable(Res, Asm))
return false;
Res.setSpecifier(Expr.getSpecifier());
return !Res.getSubSym();
}
void MipsELFMCAsmInfo::printSpecifierExpr(raw_ostream &OS,
const MCSpecifierExpr &Expr) const {
printImpl(*this, OS, Expr);
}
bool MipsELFMCAsmInfo::evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr,
MCValue &Res,
const MCAssembler *Asm) const {
return evaluate(Expr, Res, Asm);
}
void MipsCOFFMCAsmInfo::printSpecifierExpr(raw_ostream &OS,
const MCSpecifierExpr &Expr) const {
printImpl(*this, OS, Expr);
}
bool MipsCOFFMCAsmInfo::evaluateAsRelocatableImpl(
const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) const {
return evaluate(Expr, Res, Asm);
}