mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
[AArch64] Add support for the .inst directive.
This has been implement using the MCTargetStreamer interface as is done in the ARM, Mips and PPC backends. Phabricator: http://reviews.llvm.org/D5891 PR20964 llvm-svn: 220422
This commit is contained in:
parent
995034d1b1
commit
19ef65a831
@ -91,7 +91,6 @@ public:
|
||||
AArch64TargetStreamer(MCStreamer &S);
|
||||
~AArch64TargetStreamer();
|
||||
|
||||
|
||||
void finish() override;
|
||||
|
||||
/// Callback used to implement the ldr= pseudo.
|
||||
@ -103,6 +102,9 @@ public:
|
||||
/// Emit contents of constant pool for the current section.
|
||||
void emitCurrentConstantPool();
|
||||
|
||||
/// Callback used to implement the .inst directive.
|
||||
virtual void emitInst(uint32_t Inst);
|
||||
|
||||
private:
|
||||
std::unique_ptr<AssemblerConstantPools> ConstantPools;
|
||||
};
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCObjectFileInfo.h"
|
||||
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
||||
#include "llvm/MC/MCParser/MCAsmParser.h"
|
||||
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
||||
@ -74,6 +75,8 @@ private:
|
||||
bool showMatchError(SMLoc Loc, unsigned ErrCode);
|
||||
|
||||
bool parseDirectiveWord(unsigned Size, SMLoc L);
|
||||
bool parseDirectiveInst(SMLoc L);
|
||||
|
||||
bool parseDirectiveTLSDescCall(SMLoc L);
|
||||
|
||||
bool parseDirectiveLOH(StringRef LOH, SMLoc L);
|
||||
@ -3912,6 +3915,11 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
|
||||
/// ParseDirective parses the arm specific directives
|
||||
bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
const MCObjectFileInfo::Environment Format =
|
||||
getContext().getObjectFileInfo()->getObjectFileType();
|
||||
bool IsMachO = Format == MCObjectFileInfo::IsMachO;
|
||||
bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
|
||||
|
||||
StringRef IDVal = DirectiveID.getIdentifier();
|
||||
SMLoc Loc = DirectiveID.getLoc();
|
||||
if (IDVal == ".hword")
|
||||
@ -3927,6 +3935,11 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
if (IDVal == ".unreq")
|
||||
return parseDirectiveUnreq(DirectiveID.getLoc());
|
||||
|
||||
if (!IsMachO && !IsCOFF) {
|
||||
if (IDVal == ".inst")
|
||||
return parseDirectiveInst(Loc);
|
||||
}
|
||||
|
||||
return parseDirectiveLOH(IDVal, Loc);
|
||||
}
|
||||
|
||||
@ -3955,6 +3968,46 @@ bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveInst
|
||||
/// ::= .inst opcode [, ...]
|
||||
bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
|
||||
if (getLexer().is(AsmToken::EndOfStatement)) {
|
||||
Parser.eatToEndOfStatement();
|
||||
Error(Loc, "expected expression following directive");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
const MCExpr *Expr;
|
||||
|
||||
if (getParser().parseExpression(Expr)) {
|
||||
Error(Loc, "expected expression");
|
||||
return false;
|
||||
}
|
||||
|
||||
const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
|
||||
if (!Value) {
|
||||
Error(Loc, "expected constant expression");
|
||||
return false;
|
||||
}
|
||||
|
||||
getTargetStreamer().emitInst(Value->getValue());
|
||||
|
||||
if (getLexer().is(AsmToken::EndOfStatement))
|
||||
break;
|
||||
|
||||
if (getLexer().isNot(AsmToken::Comma)) {
|
||||
Error(Loc, "unexpected token in directive");
|
||||
return false;
|
||||
}
|
||||
|
||||
Parser.Lex(); // Eat comma.
|
||||
}
|
||||
|
||||
Parser.Lex();
|
||||
return false;
|
||||
}
|
||||
|
||||
// parseDirectiveTLSDescCall:
|
||||
// ::= .tlsdesccall symbol
|
||||
bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
|
||||
|
@ -15,8 +15,10 @@
|
||||
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
@ -34,12 +36,42 @@
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class AArch64ELFStreamer;
|
||||
|
||||
class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
|
||||
formatted_raw_ostream &OS;
|
||||
|
||||
void emitInst(uint32_t Inst) override;
|
||||
|
||||
public:
|
||||
AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
|
||||
};
|
||||
|
||||
AArch64TargetAsmStreamer::AArch64TargetAsmStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS)
|
||||
: AArch64TargetStreamer(S), OS(OS) {}
|
||||
|
||||
void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) {
|
||||
OS << "\t.inst\t0x" << utohexstr(Inst) << "\n";
|
||||
}
|
||||
|
||||
class AArch64TargetELFStreamer : public AArch64TargetStreamer {
|
||||
private:
|
||||
AArch64ELFStreamer &getStreamer();
|
||||
|
||||
void emitInst(uint32_t Inst) override;
|
||||
|
||||
public:
|
||||
AArch64TargetELFStreamer(MCStreamer &S) : AArch64TargetStreamer(S) {}
|
||||
};
|
||||
|
||||
/// Extend the generic ELFStreamer class so that it can emit mapping symbols at
|
||||
/// the appropriate points in the object files. These symbols are defined in the
|
||||
/// AArch64 ELF ABI:
|
||||
@ -55,6 +87,8 @@ namespace {
|
||||
/// by MachO. Beware!
|
||||
class AArch64ELFStreamer : public MCELFStreamer {
|
||||
public:
|
||||
friend class AArch64TargetELFStreamer;
|
||||
|
||||
AArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
|
||||
MCCodeEmitter *Emitter)
|
||||
: MCELFStreamer(Context, TAB, OS, Emitter), MappingSymbolCounter(0),
|
||||
@ -82,6 +116,18 @@ public:
|
||||
MCELFStreamer::EmitInstruction(Inst, STI);
|
||||
}
|
||||
|
||||
void emitInst(uint32_t Inst) {
|
||||
char Buffer[4];
|
||||
const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian();
|
||||
|
||||
EmitA64MappingSymbol();
|
||||
for (unsigned II = 0; II != 4; ++II) {
|
||||
const unsigned I = LittleEndian ? (4 - II - 1) : II;
|
||||
Buffer[4 - II - 1] = uint8_t(Inst >> I * CHAR_BIT);
|
||||
}
|
||||
MCELFStreamer::EmitBytes(StringRef(Buffer, 4));
|
||||
}
|
||||
|
||||
/// This is one of the functions used to emit data into an ELF section, so the
|
||||
/// AArch64 streamer overrides it to add the appropriate mapping symbol ($d)
|
||||
/// if necessary.
|
||||
@ -144,13 +190,33 @@ private:
|
||||
|
||||
/// @}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() {
|
||||
return static_cast<AArch64ELFStreamer &>(Streamer);
|
||||
}
|
||||
|
||||
void AArch64TargetELFStreamer::emitInst(uint32_t Inst) {
|
||||
getStreamer().emitInst(Inst);
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
MCStreamer *
|
||||
createAArch64MCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
|
||||
bool isVerboseAsm, bool useDwarfDirectory,
|
||||
MCInstPrinter *InstPrint, MCCodeEmitter *CE,
|
||||
MCAsmBackend *TAB, bool ShowInst) {
|
||||
MCStreamer *S = llvm::createAsmStreamer(
|
||||
Ctx, OS, isVerboseAsm, useDwarfDirectory, InstPrint, CE, TAB, ShowInst);
|
||||
new AArch64TargetAsmStreamer(*S, OS);
|
||||
return S;
|
||||
}
|
||||
|
||||
MCELFStreamer *createAArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB,
|
||||
raw_ostream &OS, MCCodeEmitter *Emitter,
|
||||
bool RelaxAll) {
|
||||
AArch64ELFStreamer *S = new AArch64ELFStreamer(Context, TAB, OS, Emitter);
|
||||
new AArch64TargetELFStreamer(*S);
|
||||
if (RelaxAll)
|
||||
S->getAssembler().setRelaxAll(true);
|
||||
return S;
|
||||
|
@ -198,6 +198,14 @@ extern "C" void LLVMInitializeAArch64TargetMC() {
|
||||
createMCStreamer);
|
||||
TargetRegistry::RegisterMCObjectStreamer(TheARM64Target, createMCStreamer);
|
||||
|
||||
// Register the asm streamer.
|
||||
TargetRegistry::RegisterAsmStreamer(TheAArch64leTarget,
|
||||
createAArch64MCAsmStreamer);
|
||||
TargetRegistry::RegisterAsmStreamer(TheAArch64beTarget,
|
||||
createAArch64MCAsmStreamer);
|
||||
TargetRegistry::RegisterAsmStreamer(TheARM64Target,
|
||||
createAArch64MCAsmStreamer);
|
||||
|
||||
// Register the MCInstPrinter.
|
||||
TargetRegistry::RegisterMCInstPrinter(TheAArch64leTarget,
|
||||
createAArch64MCInstPrinter);
|
||||
|
@ -18,12 +18,15 @@
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class formatted_raw_ostream;
|
||||
class MCAsmBackend;
|
||||
class MCCodeEmitter;
|
||||
class MCContext;
|
||||
class MCInstrInfo;
|
||||
class MCInstPrinter;
|
||||
class MCRegisterInfo;
|
||||
class MCObjectWriter;
|
||||
class MCStreamer;
|
||||
class MCSubtargetInfo;
|
||||
class StringRef;
|
||||
class Target;
|
||||
@ -50,6 +53,11 @@ MCObjectWriter *createAArch64ELFObjectWriter(raw_ostream &OS, uint8_t OSABI,
|
||||
MCObjectWriter *createAArch64MachObjectWriter(raw_ostream &OS, uint32_t CPUType,
|
||||
uint32_t CPUSubtype);
|
||||
|
||||
MCStreamer *
|
||||
createAArch64MCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
|
||||
bool isVerboseAsm, bool useDwarfDirectory,
|
||||
MCInstPrinter *InstPrint, MCCodeEmitter *CE,
|
||||
MCAsmBackend *TAB, bool ShowInst);
|
||||
} // End llvm namespace
|
||||
|
||||
// Defines symbolic names for AArch64 registers. This defines a mapping from
|
||||
|
@ -39,3 +39,5 @@ void AArch64TargetStreamer::emitCurrentConstantPool() {
|
||||
|
||||
// finish() - write out any non-empty assembler constant pools.
|
||||
void AArch64TargetStreamer::finish() { ConstantPools->emitAll(Streamer); }
|
||||
|
||||
void AArch64TargetStreamer::emitInst(uint32_t Inst) {}
|
||||
|
19
test/MC/AArch64/inst-directive-diagnostic.s
Normal file
19
test/MC/AArch64/inst-directive-diagnostic.s
Normal file
@ -0,0 +1,19 @@
|
||||
// RUN: not llvm-mc %s -triple=aarch64-none-linux-gnu -filetype asm -o - 2>&1 \
|
||||
// RUN: | FileCheck -check-prefix CHECK-ERROR %s
|
||||
|
||||
.align 2
|
||||
.global diagnostics
|
||||
.type diagnostics,%function
|
||||
diagnostics:
|
||||
.Label:
|
||||
.inst
|
||||
// CHECK-ERROR: expected expression following directive
|
||||
|
||||
.inst 0x5e104020,
|
||||
// CHECK-ERROR: expected expression
|
||||
|
||||
.inst .Label
|
||||
// CHECK-ERROR: expected constant expression
|
||||
|
||||
.inst 0x5e104020 0x5e104020
|
||||
// CHECK-ERROR: unexpected token in directive
|
24
test/MC/AArch64/inst-directive.s
Normal file
24
test/MC/AArch64/inst-directive.s
Normal file
@ -0,0 +1,24 @@
|
||||
// RUN: llvm-mc %s -triple=aarch64-none-linux-gnu -filetype=asm -o - \
|
||||
// RUN: | FileCheck %s --check-prefix=CHECK-ASM
|
||||
// RUN: llvm-mc %s -triple=aarch64-none-linux-gnu -filetype=obj -o - \
|
||||
// RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=CHECK-OBJ
|
||||
|
||||
.section .inst.aarch64_inst
|
||||
|
||||
.align 2
|
||||
.global aarch64_inst
|
||||
.type aarch64_inst,%function
|
||||
aarch64_inst:
|
||||
.inst 0x5e104020
|
||||
|
||||
// CHECK-ASM: .align 2
|
||||
// CHECK-ASM: .globl aarch64_inst
|
||||
// CHECK-ASM: .type aarch64_inst,@function
|
||||
// CHECK-ASM: aarch64_inst:
|
||||
// CHECK-ASM: .inst 0x5E104020
|
||||
|
||||
// CHECK-OBJ: Section {
|
||||
// CHECK-OBJ: Name: .inst.aarch64_inst
|
||||
// CHECK-OBJ: SectionData (
|
||||
// CHECK-OBJ-NEXT: 0000: 2040105E
|
||||
// CHECK-OBJ-NEXT: )
|
Loading…
Reference in New Issue
Block a user