mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
MIR Serialization: Serialize the implicit register flag.
This commit serializes the implicit flag for the register machine operands. It introduces two new keywords into the machine instruction syntax: 'implicit' and 'implicit-def'. The 'implicit' keyword is used for the implicit register operands, and the 'implicit-def' keyword is used for the register operands that have both the implicit and the define flags set. Reviewers: Duncan P. N. Exon Smith Differential Revision: http://reviews.llvm.org/D10709 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241519 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ddf4c989ee
commit
4ec0f60807
@ -12,6 +12,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "MILexer.h"
|
#include "MILexer.h"
|
||||||
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
@ -64,6 +65,14 @@ static bool isIdentifierChar(char C) {
|
|||||||
return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.';
|
return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
|
||||||
|
return StringSwitch<MIToken::TokenKind>(Identifier)
|
||||||
|
.Case("_", MIToken::underscore)
|
||||||
|
.Case("implicit", MIToken::kw_implicit)
|
||||||
|
.Case("implicit-def", MIToken::kw_implicit_define)
|
||||||
|
.Default(MIToken::Identifier);
|
||||||
|
}
|
||||||
|
|
||||||
static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
|
static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
|
||||||
if (!isalpha(C.peek()) && C.peek() != '_')
|
if (!isalpha(C.peek()) && C.peek() != '_')
|
||||||
return None;
|
return None;
|
||||||
@ -71,8 +80,7 @@ static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
|
|||||||
while (isIdentifierChar(C.peek()))
|
while (isIdentifierChar(C.peek()))
|
||||||
C.advance();
|
C.advance();
|
||||||
auto Identifier = Range.upto(C);
|
auto Identifier = Range.upto(C);
|
||||||
Token = MIToken(Identifier == "_" ? MIToken::underscore : MIToken::Identifier,
|
Token = MIToken(getIdentifierKind(Identifier), Identifier);
|
||||||
Identifier);
|
|
||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,10 @@ struct MIToken {
|
|||||||
equal,
|
equal,
|
||||||
underscore,
|
underscore,
|
||||||
|
|
||||||
|
// Keywords
|
||||||
|
kw_implicit,
|
||||||
|
kw_implicit_define,
|
||||||
|
|
||||||
// Identifier tokens
|
// Identifier tokens
|
||||||
Identifier,
|
Identifier,
|
||||||
NamedRegister,
|
NamedRegister,
|
||||||
@ -69,6 +73,10 @@ public:
|
|||||||
return Kind == NamedRegister || Kind == underscore;
|
return Kind == NamedRegister || Kind == underscore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isRegisterFlag() const {
|
||||||
|
return Kind == kw_implicit || Kind == kw_implicit_define;
|
||||||
|
}
|
||||||
|
|
||||||
bool is(TokenKind K) const { return Kind == K; }
|
bool is(TokenKind K) const { return Kind == K; }
|
||||||
|
|
||||||
bool isNot(TokenKind K) const { return Kind != K; }
|
bool isNot(TokenKind K) const { return Kind != K; }
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include "llvm/CodeGen/MachineInstr.h"
|
#include "llvm/CodeGen/MachineInstr.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
@ -67,6 +68,7 @@ public:
|
|||||||
bool parseMBB(MachineBasicBlock *&MBB);
|
bool parseMBB(MachineBasicBlock *&MBB);
|
||||||
|
|
||||||
bool parseRegister(unsigned &Reg);
|
bool parseRegister(unsigned &Reg);
|
||||||
|
bool parseRegisterFlag(unsigned &Flags);
|
||||||
bool parseRegisterOperand(MachineOperand &Dest, bool IsDef = false);
|
bool parseRegisterOperand(MachineOperand &Dest, bool IsDef = false);
|
||||||
bool parseImmediateOperand(MachineOperand &Dest);
|
bool parseImmediateOperand(MachineOperand &Dest);
|
||||||
bool parseMBBReference(MachineBasicBlock *&MBB);
|
bool parseMBBReference(MachineBasicBlock *&MBB);
|
||||||
@ -138,7 +140,7 @@ bool MIParser::parse(MachineInstr *&MI) {
|
|||||||
// TODO: Allow parsing of multiple operands before '='
|
// TODO: Allow parsing of multiple operands before '='
|
||||||
MachineOperand MO = MachineOperand::CreateImm(0);
|
MachineOperand MO = MachineOperand::CreateImm(0);
|
||||||
SmallVector<MachineOperand, 8> Operands;
|
SmallVector<MachineOperand, 8> Operands;
|
||||||
if (Token.isRegister()) {
|
if (Token.isRegister() || Token.isRegisterFlag()) {
|
||||||
if (parseRegisterOperand(MO, /*IsDef=*/true))
|
if (parseRegisterOperand(MO, /*IsDef=*/true))
|
||||||
return true;
|
return true;
|
||||||
Operands.push_back(MO);
|
Operands.push_back(MO);
|
||||||
@ -167,21 +169,8 @@ bool MIParser::parse(MachineInstr *&MI) {
|
|||||||
|
|
||||||
const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode);
|
const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode);
|
||||||
|
|
||||||
// Verify machine operands.
|
// TODO: Check for extraneous machine operands.
|
||||||
if (!MCID.isVariadic()) {
|
// TODO: Check that this instruction has the implicit register operands.
|
||||||
for (size_t I = 0, E = Operands.size(); I < E; ++I) {
|
|
||||||
if (I < MCID.getNumOperands())
|
|
||||||
continue;
|
|
||||||
// Mark this register as implicit to prevent an assertion when it's added
|
|
||||||
// to an instruction. This is a temporary workaround until the implicit
|
|
||||||
// register flag can be parsed.
|
|
||||||
if (Operands[I].isReg())
|
|
||||||
Operands[I].setImplicit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Determine the implicit behaviour when implicit register flags are
|
|
||||||
// parsed.
|
|
||||||
MI = MF.CreateMachineInstr(MCID, DebugLoc(), /*NoImplicit=*/true);
|
MI = MF.CreateMachineInstr(MCID, DebugLoc(), /*NoImplicit=*/true);
|
||||||
for (const auto &Operand : Operands)
|
for (const auto &Operand : Operands)
|
||||||
MI->addOperand(MF, Operand);
|
MI->addOperand(MF, Operand);
|
||||||
@ -229,14 +218,38 @@ bool MIParser::parseRegister(unsigned &Reg) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MIParser::parseRegisterFlag(unsigned &Flags) {
|
||||||
|
switch (Token.kind()) {
|
||||||
|
case MIToken::kw_implicit:
|
||||||
|
Flags |= RegState::Implicit;
|
||||||
|
break;
|
||||||
|
case MIToken::kw_implicit_define:
|
||||||
|
Flags |= RegState::ImplicitDefine;
|
||||||
|
break;
|
||||||
|
// TODO: report an error when we specify the same flag more than once.
|
||||||
|
// TODO: parse the other register flags.
|
||||||
|
default:
|
||||||
|
llvm_unreachable("The current token should be a register flag");
|
||||||
|
}
|
||||||
|
lex();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool MIParser::parseRegisterOperand(MachineOperand &Dest, bool IsDef) {
|
bool MIParser::parseRegisterOperand(MachineOperand &Dest, bool IsDef) {
|
||||||
unsigned Reg;
|
unsigned Reg;
|
||||||
// TODO: Parse register flags.
|
unsigned Flags = IsDef ? RegState::Define : 0;
|
||||||
|
while (Token.isRegisterFlag()) {
|
||||||
|
if (parseRegisterFlag(Flags))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!Token.isRegister())
|
||||||
|
return error("expected a register after register flags");
|
||||||
if (parseRegister(Reg))
|
if (parseRegister(Reg))
|
||||||
return true;
|
return true;
|
||||||
lex();
|
lex();
|
||||||
// TODO: Parse subregister.
|
// TODO: Parse subregister.
|
||||||
Dest = MachineOperand::CreateReg(Reg, IsDef);
|
Dest = MachineOperand::CreateReg(Reg, Flags & RegState::Define,
|
||||||
|
Flags & RegState::Implicit);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,6 +331,8 @@ bool MIParser::parseGlobalAddressOperand(MachineOperand &Dest) {
|
|||||||
|
|
||||||
bool MIParser::parseMachineOperand(MachineOperand &Dest) {
|
bool MIParser::parseMachineOperand(MachineOperand &Dest) {
|
||||||
switch (Token.kind()) {
|
switch (Token.kind()) {
|
||||||
|
case MIToken::kw_implicit:
|
||||||
|
case MIToken::kw_implicit_define:
|
||||||
case MIToken::underscore:
|
case MIToken::underscore:
|
||||||
case MIToken::NamedRegister:
|
case MIToken::NamedRegister:
|
||||||
return parseRegisterOperand(Dest);
|
return parseRegisterOperand(Dest);
|
||||||
|
@ -211,7 +211,9 @@ void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) {
|
|||||||
void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
|
void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
|
||||||
switch (Op.getType()) {
|
switch (Op.getType()) {
|
||||||
case MachineOperand::MO_Register:
|
case MachineOperand::MO_Register:
|
||||||
// TODO: Print register flags.
|
// TODO: Print the other register flags.
|
||||||
|
if (Op.isImplicit())
|
||||||
|
OS << (Op.isDef() ? "implicit-def " : "implicit ");
|
||||||
printReg(Op.getReg(), OS, TRI);
|
printReg(Op.getReg(), OS, TRI);
|
||||||
// TODO: Print sub register.
|
// TODO: Print sub register.
|
||||||
break;
|
break;
|
||||||
|
22
test/CodeGen/MIR/X86/expected-register-after-flags.mir
Normal file
22
test/CodeGen/MIR/X86/expected-register-after-flags.mir
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||||
|
# This test ensures that an error is reported when a register operand doesn't
|
||||||
|
# follow register flags.
|
||||||
|
|
||||||
|
--- |
|
||||||
|
|
||||||
|
define i32 @foo() {
|
||||||
|
entry:
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
---
|
||||||
|
name: foo
|
||||||
|
body:
|
||||||
|
- id: 0
|
||||||
|
name: entry
|
||||||
|
instructions:
|
||||||
|
# CHECK: [[@LINE+1]]:37: expected a register after register flags
|
||||||
|
- '%eax = MOV32r0 implicit-def 2'
|
||||||
|
- 'RETQ %eax'
|
||||||
|
...
|
41
test/CodeGen/MIR/X86/implicit-register-flag.mir
Normal file
41
test/CodeGen/MIR/X86/implicit-register-flag.mir
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
|
||||||
|
# This test ensures that the MIR parser parses the 'implicit' and 'implicit-def'
|
||||||
|
# register flags correctly.
|
||||||
|
|
||||||
|
--- |
|
||||||
|
|
||||||
|
define i32 @foo(i32 %a) {
|
||||||
|
entry:
|
||||||
|
%0 = icmp sle i32 %a, 10
|
||||||
|
br i1 %0, label %less, label %exit
|
||||||
|
|
||||||
|
less:
|
||||||
|
ret i32 0
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ret i32 %a
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
---
|
||||||
|
name: foo
|
||||||
|
body:
|
||||||
|
- id: 0
|
||||||
|
name: entry
|
||||||
|
instructions:
|
||||||
|
# CHECK: - 'CMP32ri8 %edi, 10, implicit-def %eflags'
|
||||||
|
# CHECK-NEXT: - 'JG_1 %bb.2.exit, implicit %eflags'
|
||||||
|
- 'CMP32ri8 %edi, 10, implicit-def %eflags'
|
||||||
|
- 'JG_1 %bb.2.exit, implicit %eflags'
|
||||||
|
- id: 1
|
||||||
|
name: less
|
||||||
|
instructions:
|
||||||
|
# CHECK: - '%eax = MOV32r0 implicit-def %eflags'
|
||||||
|
- '%eax = MOV32r0 implicit-def %eflags'
|
||||||
|
- 'RETQ %eax'
|
||||||
|
- id: 2
|
||||||
|
name: exit
|
||||||
|
instructions:
|
||||||
|
- '%eax = COPY %edi'
|
||||||
|
- 'RETQ %eax'
|
||||||
|
...
|
@ -35,9 +35,9 @@ body:
|
|||||||
name: entry
|
name: entry
|
||||||
instructions:
|
instructions:
|
||||||
# CHECK: - 'PUSH64r %rax
|
# CHECK: - 'PUSH64r %rax
|
||||||
# CHECK-NEXT: - 'CALL64pcrel32 @compute, csr_64, %rsp, %edi, %rsp, %eax'
|
# CHECK-NEXT: - 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax'
|
||||||
- 'PUSH64r %rax'
|
- 'PUSH64r %rax'
|
||||||
- 'CALL64pcrel32 @compute, csr_64, %rsp, %edi, %rsp, %eax'
|
- 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax'
|
||||||
- '%rdx = POP64r'
|
- '%rdx = POP64r'
|
||||||
- 'RETQ %eax'
|
- 'RETQ %eax'
|
||||||
...
|
...
|
||||||
|
Loading…
Reference in New Issue
Block a user