mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-26 05:25:47 +00:00
[Mips] TargetStreamer Support for .abicalls and .set pic0.
This patch adds .abicalls and .set pic0 support which affects the ELF ABI and its flags. In addition the patch uses a common interface for both the MipsTargetSteamer and MipsObjectStreamer that both the integrated and standalone assemblers will use for the output for these directives. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198646 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -196,6 +196,7 @@ class MipsAsmParser : public MCTargetAsmParser {
|
|||||||
bool parseDirectiveSet();
|
bool parseDirectiveSet();
|
||||||
bool parseDirectiveMipsHackStocg();
|
bool parseDirectiveMipsHackStocg();
|
||||||
bool parseDirectiveMipsHackELFFlags();
|
bool parseDirectiveMipsHackELFFlags();
|
||||||
|
bool parseDirectiveOption();
|
||||||
|
|
||||||
bool parseSetAtDirective();
|
bool parseSetAtDirective();
|
||||||
bool parseSetNoAtDirective();
|
bool parseSetNoAtDirective();
|
||||||
@@ -2468,6 +2469,35 @@ bool MipsAsmParser::parseDirectiveGpWord() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MipsAsmParser::parseDirectiveOption() {
|
||||||
|
// Get the option token.
|
||||||
|
AsmToken Tok = Parser.getTok();
|
||||||
|
// At the moment only identifiers are supported.
|
||||||
|
if (Tok.isNot(AsmToken::Identifier)) {
|
||||||
|
Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
|
||||||
|
Parser.eatToEndOfStatement();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef Option = Tok.getIdentifier();
|
||||||
|
|
||||||
|
if (Option == "pic0") {
|
||||||
|
getTargetStreamer().emitDirectiveOptionPic0();
|
||||||
|
Parser.Lex();
|
||||||
|
if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
|
||||||
|
Error(Parser.getTok().getLoc(),
|
||||||
|
"unexpected token in .option pic0 directive");
|
||||||
|
Parser.eatToEndOfStatement();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown option.
|
||||||
|
Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
|
||||||
|
Parser.eatToEndOfStatement();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
|
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||||
|
|
||||||
StringRef IDVal = DirectiveID.getString();
|
StringRef IDVal = DirectiveID.getString();
|
||||||
@@ -2523,6 +2553,19 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
|
|||||||
if (IDVal == ".mips_hack_elf_flags")
|
if (IDVal == ".mips_hack_elf_flags")
|
||||||
return parseDirectiveMipsHackELFFlags();
|
return parseDirectiveMipsHackELFFlags();
|
||||||
|
|
||||||
|
if (IDVal == ".option")
|
||||||
|
return parseDirectiveOption();
|
||||||
|
|
||||||
|
if (IDVal == ".abicalls") {
|
||||||
|
getTargetStreamer().emitDirectiveAbiCalls();
|
||||||
|
if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
|
||||||
|
Error(Parser.getTok().getLoc(), "unexpected token in directive");
|
||||||
|
// Clear line
|
||||||
|
Parser.eatToEndOfStatement();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
#include "MipsMCAsmInfo.h"
|
#include "MipsMCAsmInfo.h"
|
||||||
#include "MipsTargetStreamer.h"
|
#include "MipsTargetStreamer.h"
|
||||||
#include "llvm/MC/MCCodeGenInfo.h"
|
#include "llvm/MC/MCCodeGenInfo.h"
|
||||||
#include "llvm/MC/MCELF.h"
|
|
||||||
#include "llvm/MC/MCELFStreamer.h"
|
#include "llvm/MC/MCELFStreamer.h"
|
||||||
#include "llvm/MC/MCInstrInfo.h"
|
#include "llvm/MC/MCInstrInfo.h"
|
||||||
#include "llvm/MC/MCRegisterInfo.h"
|
#include "llvm/MC/MCRegisterInfo.h"
|
||||||
|
@@ -17,13 +17,14 @@
|
|||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/FormattedStream.h"
|
#include "llvm/Support/FormattedStream.h"
|
||||||
|
#include "llvm/Support/ELF.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
static cl::opt<bool> PrintHackDirectives("print-hack-directives",
|
static cl::opt<bool> PrintHackDirectives("print-hack-directives",
|
||||||
cl::init(false), cl::Hidden);
|
cl::init(false), cl::Hidden);
|
||||||
|
|
||||||
// pin vtable to this file
|
// Pin vtable to this file.
|
||||||
void MipsTargetStreamer::anchor() {}
|
void MipsTargetStreamer::anchor() {}
|
||||||
|
|
||||||
MipsTargetAsmStreamer::MipsTargetAsmStreamer(formatted_raw_ostream &OS)
|
MipsTargetAsmStreamer::MipsTargetAsmStreamer(formatted_raw_ostream &OS)
|
||||||
@@ -47,6 +48,13 @@ void MipsTargetAsmStreamer::emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val) {
|
|||||||
OS << Val;
|
OS << Val;
|
||||||
OS << '\n';
|
OS << '\n';
|
||||||
}
|
}
|
||||||
|
void MipsTargetAsmStreamer::emitDirectiveAbiCalls() { OS << "\t.abicalls\n"; }
|
||||||
|
void MipsTargetAsmStreamer::emitDirectiveOptionPic0() {
|
||||||
|
OS << "\t.option\tpic0\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// This part is for ELF object output.
|
||||||
|
MipsTargetELFStreamer::MipsTargetELFStreamer() {}
|
||||||
|
|
||||||
MCELFStreamer &MipsTargetELFStreamer::getStreamer() {
|
MCELFStreamer &MipsTargetELFStreamer::getStreamer() {
|
||||||
return static_cast<MCELFStreamer &>(*Streamer);
|
return static_cast<MCELFStreamer &>(*Streamer);
|
||||||
@@ -57,7 +65,7 @@ void MipsTargetELFStreamer::emitMipsHackELFFlags(unsigned Flags) {
|
|||||||
MCA.setELFHeaderEFlags(Flags);
|
MCA.setELFHeaderEFlags(Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a symbol's STO flags
|
// Set a symbol's STO flags.
|
||||||
void MipsTargetELFStreamer::emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val) {
|
void MipsTargetELFStreamer::emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val) {
|
||||||
MCSymbolData &Data = getStreamer().getOrCreateSymbolData(Sym);
|
MCSymbolData &Data = getStreamer().getOrCreateSymbolData(Sym);
|
||||||
// The "other" values are stored in the last 6 bits of the second byte
|
// The "other" values are stored in the last 6 bits of the second byte
|
||||||
@@ -65,3 +73,15 @@ void MipsTargetELFStreamer::emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val) {
|
|||||||
// the shift to pack it.
|
// the shift to pack it.
|
||||||
MCELF::setOther(Data, Val >> 2);
|
MCELF::setOther(Data, Val >> 2);
|
||||||
}
|
}
|
||||||
|
void MipsTargetELFStreamer::emitDirectiveAbiCalls() {
|
||||||
|
MCAssembler &MCA = getStreamer().getAssembler();
|
||||||
|
unsigned Flags = MCA.getELFHeaderEFlags();
|
||||||
|
Flags |= ELF::EF_MIPS_CPIC;
|
||||||
|
MCA.setELFHeaderEFlags(Flags);
|
||||||
|
}
|
||||||
|
void MipsTargetELFStreamer::emitDirectiveOptionPic0() {
|
||||||
|
MCAssembler &MCA = getStreamer().getAssembler();
|
||||||
|
unsigned Flags = MCA.getELFHeaderEFlags();
|
||||||
|
Flags &= ~ELF::EF_MIPS_PIC;
|
||||||
|
MCA.setELFHeaderEFlags(Flags);
|
||||||
|
}
|
||||||
|
@@ -608,12 +608,10 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
|
|||||||
|
|
||||||
// TODO: Need to add -mabicalls and -mno-abicalls flags.
|
// TODO: Need to add -mabicalls and -mno-abicalls flags.
|
||||||
// Currently we assume that -mabicalls is the default.
|
// Currently we assume that -mabicalls is the default.
|
||||||
if (OutStreamer.hasRawTextSupport()) {
|
getTargetStreamer().emitDirectiveAbiCalls();
|
||||||
OutStreamer.EmitRawText(StringRef("\t.abicalls"));
|
Reloc::Model RM = Subtarget->getRelocationModel();
|
||||||
Reloc::Model RM = Subtarget->getRelocationModel();
|
if (RM == Reloc::Static && !Subtarget->hasMips64())
|
||||||
if (RM == Reloc::Static && !Subtarget->hasMips64())
|
getTargetStreamer().emitDirectiveOptionPic0();
|
||||||
OutStreamer.EmitRawText(StringRef("\t.option\tpic0"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell the assembler which ABI we are using
|
// Tell the assembler which ABI we are using
|
||||||
if (OutStreamer.hasRawTextSupport())
|
if (OutStreamer.hasRawTextSupport())
|
||||||
|
@@ -20,6 +20,8 @@ class MipsTargetStreamer : public MCTargetStreamer {
|
|||||||
public:
|
public:
|
||||||
virtual void emitMipsHackELFFlags(unsigned Flags) = 0;
|
virtual void emitMipsHackELFFlags(unsigned Flags) = 0;
|
||||||
virtual void emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val) = 0;
|
virtual void emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val) = 0;
|
||||||
|
virtual void emitDirectiveAbiCalls() = 0;
|
||||||
|
virtual void emitDirectiveOptionPic0() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This part is for ascii assembly output
|
// This part is for ascii assembly output
|
||||||
@@ -30,15 +32,20 @@ public:
|
|||||||
MipsTargetAsmStreamer(formatted_raw_ostream &OS);
|
MipsTargetAsmStreamer(formatted_raw_ostream &OS);
|
||||||
virtual void emitMipsHackELFFlags(unsigned Flags);
|
virtual void emitMipsHackELFFlags(unsigned Flags);
|
||||||
virtual void emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val);
|
virtual void emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val);
|
||||||
|
virtual void emitDirectiveAbiCalls();
|
||||||
|
virtual void emitDirectiveOptionPic0();
|
||||||
};
|
};
|
||||||
|
|
||||||
// This part is for ELF object output
|
// This part is for ELF object output
|
||||||
class MipsTargetELFStreamer : public MipsTargetStreamer {
|
class MipsTargetELFStreamer : public MipsTargetStreamer {
|
||||||
public:
|
public:
|
||||||
MCELFStreamer &getStreamer();
|
MCELFStreamer &getStreamer();
|
||||||
|
MipsTargetELFStreamer();
|
||||||
|
// FIXME: emitMipsHackELFFlags() will be removed from this class.
|
||||||
virtual void emitMipsHackELFFlags(unsigned Flags);
|
virtual void emitMipsHackELFFlags(unsigned Flags);
|
||||||
virtual void emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val);
|
virtual void emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val);
|
||||||
|
virtual void emitDirectiveAbiCalls();
|
||||||
|
virtual void emitDirectiveOptionPic0();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
; RUN: llc -mtriple mipsel-unknown-linux -mcpu=mips64r2 -print-hack-directives %s -o - | FileCheck -check-prefix=CHECK-BE64R2_PIC %s
|
; RUN: llc -mtriple mipsel-unknown-linux -mcpu=mips64r2 -print-hack-directives %s -o - | FileCheck -check-prefix=CHECK-BE64R2_PIC %s
|
||||||
|
|
||||||
; RUN: llc -mtriple mipsel-unknown-linux -mcpu=mips32r2 -mattr=+mips16 -relocation-model=pic -print-hack-directives %s -o - | FileCheck -check-prefix=CHECK-LE32R2-MIPS16 %s
|
; RUN: llc -mtriple mipsel-unknown-linux -mcpu=mips32r2 -mattr=+mips16 -relocation-model=pic -print-hack-directives %s -o - | FileCheck -check-prefix=CHECK-LE32R2-MIPS16 %s
|
||||||
|
|
||||||
; 32(R1) bit with NO_REORDER and static
|
; 32(R1) bit with NO_REORDER and static
|
||||||
; CHECK-BE32: .mips_hack_elf_flags 0x50001005
|
; CHECK-BE32: .mips_hack_elf_flags 0x50001005
|
||||||
;
|
;
|
||||||
|
@@ -1,5 +1,12 @@
|
|||||||
// RUN: llvm-mc -filetype=obj -triple mipsel-unknown-linux %s -o -| llvm-readobj -h | FileCheck %s
|
// RUN: llvm-mc -filetype=obj -triple mipsel-unknown-linux %s -o -| llvm-readobj -h | FileCheck %s
|
||||||
|
// The initial value will be set at 0x50001003 and
|
||||||
|
// we will override that with the negation of 0x2 (option pic0
|
||||||
|
// the addition of 0x4 (.abicalls)
|
||||||
|
|
||||||
.mips_hack_elf_flags 0x50001005
|
.mips_hack_elf_flags 0x50001003
|
||||||
|
|
||||||
// CHECK: Flags [ (0x50001005)
|
// CHECK: Flags [ (0x50001005)
|
||||||
|
|
||||||
|
.abicalls
|
||||||
|
|
||||||
|
.option pic0
|
||||||
|
@@ -2,8 +2,10 @@
|
|||||||
#
|
#
|
||||||
# CHECK: .text
|
# CHECK: .text
|
||||||
# CHECK: $BB0_2:
|
# CHECK: $BB0_2:
|
||||||
|
# CHECK: .abicalls
|
||||||
$BB0_2:
|
$BB0_2:
|
||||||
.ent directives_test
|
.ent directives_test
|
||||||
|
.abicalls
|
||||||
.frame $sp,0,$ra
|
.frame $sp,0,$ra
|
||||||
.mask 0x00000000,0
|
.mask 0x00000000,0
|
||||||
.fmask 0x00000000,0
|
.fmask 0x00000000,0
|
||||||
|
49
test/MC/Mips/mips_directives_bad.s
Normal file
49
test/MC/Mips/mips_directives_bad.s
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Error checking for malformed directives
|
||||||
|
# RUN: not llvm-mc -triple mips-unknown-unknown %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
|
.abicalls should have no operands
|
||||||
|
# CHECK: :{{[0-9]+}}:{{[0-9]+}}: error: unexpected token in directive
|
||||||
|
# CHECK-NEXT: .abicalls should have no operands
|
||||||
|
# CHECK-NEXT: ^
|
||||||
|
|
||||||
|
# We don't know yet how to represent a list of options
|
||||||
|
# pic2 will eventually be legal so we will probably want
|
||||||
|
# to change it to something silly.
|
||||||
|
|
||||||
|
# Blank option operand
|
||||||
|
.option
|
||||||
|
# CHECK-NEXT: :{{[0-9]+}}:{{[0-9]+}}: error: unexpected token in .option directive
|
||||||
|
# CHECK-NEXT: .option
|
||||||
|
# CHECK-NEXT: ^
|
||||||
|
|
||||||
|
# Numeric option operand
|
||||||
|
.option 2
|
||||||
|
# CHECK-NEXT: :{{[0-9]+}}:{{[0-9]+}}: error: unexpected token in .option directive
|
||||||
|
# CHECK-NEXT: .option 2
|
||||||
|
# CHECK-NEXT: ^
|
||||||
|
|
||||||
|
# Register option operand
|
||||||
|
.option $2
|
||||||
|
# CHECK-NEXT: :{{[0-9]+}}:{{[0-9]+}}: error: unexpected token in .option directive
|
||||||
|
# CHECK-NEXT: .option $2
|
||||||
|
# CHECK-NEXT: ^
|
||||||
|
|
||||||
|
.option WithBadOption
|
||||||
|
# CHECK-NEXT: :{{[0-9]+}}:{{[0-9]+}}: warning: unknown option in .option directive
|
||||||
|
# CHECK-NEXT: .option WithBadOption
|
||||||
|
# CHECK-NEXT: ^
|
||||||
|
|
||||||
|
.option pic0,
|
||||||
|
# CHECK-NEXT: :{{[0-9]+}}:{{[0-9]+}}: error: unexpected token in .option pic0 directive
|
||||||
|
# CHECK-NEXT: .option pic0,
|
||||||
|
# CHECK-NEXT: ^
|
||||||
|
|
||||||
|
.option pic0,pic2
|
||||||
|
# CHECK-NEXT: :{{[0-9]+}}:{{[0-9]+}}: error: unexpected token in .option pic0 directive
|
||||||
|
# CHECK-NEXT: .option pic0,pic2
|
||||||
|
# CHECK-NEXT: ^
|
||||||
|
|
||||||
|
.option pic0 pic2
|
||||||
|
# CHECK-NEXT: :{{[0-9]+}}:{{[0-9]+}}: error: unexpected token in .option pic0 directive
|
||||||
|
# CHECK-NEXT: .option pic0 pic2
|
||||||
|
# CHECK-NEXT: ^
|
Reference in New Issue
Block a user