bool parseDirectiveSet();
bool parseDirectiveMipsHackStocg();
bool parseDirectiveMipsHackELFFlags();
+ bool parseDirectiveOption();
bool parseSetAtDirective();
bool parseSetNoAtDirective();
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) {
StringRef IDVal = DirectiveID.getString();
if (IDVal == ".mips_hack_elf_flags")
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;
}
#include "MipsMCAsmInfo.h"
#include "MipsTargetStreamer.h"
#include "llvm/MC/MCCodeGenInfo.h"
-#include "llvm/MC/MCELF.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/ELF.h"
using namespace llvm;
static cl::opt<bool> PrintHackDirectives("print-hack-directives",
cl::init(false), cl::Hidden);
-// pin vtable to this file
+// Pin vtable to this file.
void MipsTargetStreamer::anchor() {}
MipsTargetAsmStreamer::MipsTargetAsmStreamer(formatted_raw_ostream &OS)
OS << Val;
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() {
return static_cast<MCELFStreamer &>(*Streamer);
MCA.setELFHeaderEFlags(Flags);
}
-// Set a symbol's STO flags
+// Set a symbol's STO flags.
void MipsTargetELFStreamer::emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val) {
MCSymbolData &Data = getStreamer().getOrCreateSymbolData(Sym);
// The "other" values are stored in the last 6 bits of the second byte
// the shift to pack it.
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);
+}
// TODO: Need to add -mabicalls and -mno-abicalls flags.
// Currently we assume that -mabicalls is the default.
- if (OutStreamer.hasRawTextSupport()) {
- OutStreamer.EmitRawText(StringRef("\t.abicalls"));
- Reloc::Model RM = Subtarget->getRelocationModel();
- if (RM == Reloc::Static && !Subtarget->hasMips64())
- OutStreamer.EmitRawText(StringRef("\t.option\tpic0"));
- }
+ getTargetStreamer().emitDirectiveAbiCalls();
+ Reloc::Model RM = Subtarget->getRelocationModel();
+ if (RM == Reloc::Static && !Subtarget->hasMips64())
+ getTargetStreamer().emitDirectiveOptionPic0();
// Tell the assembler which ABI we are using
if (OutStreamer.hasRawTextSupport())
public:
virtual void emitMipsHackELFFlags(unsigned Flags) = 0;
virtual void emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val) = 0;
+ virtual void emitDirectiveAbiCalls() = 0;
+ virtual void emitDirectiveOptionPic0() = 0;
};
// This part is for ascii assembly output
MipsTargetAsmStreamer(formatted_raw_ostream &OS);
virtual void emitMipsHackELFFlags(unsigned Flags);
virtual void emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val);
+ virtual void emitDirectiveAbiCalls();
+ virtual void emitDirectiveOptionPic0();
};
// This part is for ELF object output
class MipsTargetELFStreamer : public MipsTargetStreamer {
public:
MCELFStreamer &getStreamer();
+ MipsTargetELFStreamer();
+ // FIXME: emitMipsHackELFFlags() will be removed from this class.
virtual void emitMipsHackELFFlags(unsigned Flags);
virtual void emitMipsHackSTOCG(MCSymbol *Sym, unsigned Val);
+ virtual void emitDirectiveAbiCalls();
+ virtual void emitDirectiveOptionPic0();
};
}
-
#endif
; 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
-
+
; 32(R1) bit with NO_REORDER and static
; CHECK-BE32: .mips_hack_elf_flags 0x50001005
;
// 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)
+
+ .abicalls
+
+ .option pic0
#
# CHECK: .text
# CHECK: $BB0_2:
+# CHECK: .abicalls
$BB0_2:
.ent directives_test
+ .abicalls
.frame $sp,0,$ra
.mask 0x00000000,0
.fmask 0x00000000,0
--- /dev/null
+# 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: ^