mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
MIR Serialization: Initial serialization of the machine memory operands.
Reviewers: Duncan P. N. Exon Smith llvm-svn: 243915
This commit is contained in:
parent
14ffe51916
commit
1167a86bcb
@ -260,6 +260,16 @@ static Cursor maybeLexIRBlock(
|
||||
Rule.size(), ErrorCallback);
|
||||
}
|
||||
|
||||
static Cursor maybeLexIRValue(
|
||||
Cursor C, MIToken &Token,
|
||||
function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
|
||||
const StringRef Rule = "%ir.";
|
||||
if (!C.remaining().startswith(Rule))
|
||||
return None;
|
||||
return lexName(C, Token, MIToken::NamedIRValue, MIToken::QuotedNamedIRValue,
|
||||
Rule.size(), ErrorCallback);
|
||||
}
|
||||
|
||||
static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
|
||||
auto Range = C;
|
||||
C.advance(); // Skip '%'
|
||||
@ -381,11 +391,17 @@ static MIToken::TokenKind symbolToken(char C) {
|
||||
}
|
||||
|
||||
static Cursor maybeLexSymbol(Cursor C, MIToken &Token) {
|
||||
auto Kind = symbolToken(C.peek());
|
||||
MIToken::TokenKind Kind;
|
||||
unsigned Length = 1;
|
||||
if (C.peek() == ':' && C.peek(1) == ':') {
|
||||
Kind = MIToken::coloncolon;
|
||||
Length = 2;
|
||||
} else
|
||||
Kind = symbolToken(C.peek());
|
||||
if (Kind == MIToken::Error)
|
||||
return None;
|
||||
auto Range = C;
|
||||
C.advance();
|
||||
C.advance(Length);
|
||||
Token = MIToken(Kind, Range.upto(C));
|
||||
return C;
|
||||
}
|
||||
@ -413,6 +429,8 @@ StringRef llvm::lexMIToken(
|
||||
return R.remaining();
|
||||
if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback))
|
||||
return R.remaining();
|
||||
if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback))
|
||||
return R.remaining();
|
||||
if (Cursor R = maybeLexRegister(C, Token))
|
||||
return R.remaining();
|
||||
if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
|
||||
|
@ -36,6 +36,7 @@ struct MIToken {
|
||||
equal,
|
||||
underscore,
|
||||
colon,
|
||||
coloncolon,
|
||||
exclaim,
|
||||
lparen,
|
||||
rparen,
|
||||
@ -82,6 +83,8 @@ struct MIToken {
|
||||
NamedIRBlock,
|
||||
QuotedNamedIRBlock,
|
||||
IRBlock,
|
||||
NamedIRValue,
|
||||
QuotedNamedIRValue,
|
||||
};
|
||||
|
||||
private:
|
||||
@ -120,7 +123,7 @@ public:
|
||||
|
||||
bool isStringValueQuoted() const {
|
||||
return Kind == QuotedNamedGlobalValue || Kind == QuotedExternalSymbol ||
|
||||
Kind == QuotedNamedIRBlock;
|
||||
Kind == QuotedNamedIRBlock || Kind == QuotedNamedIRValue;
|
||||
}
|
||||
|
||||
/// Return the token's raw string value.
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineMemOperand.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
@ -133,6 +134,8 @@ public:
|
||||
bool parseBlockAddressOperand(MachineOperand &Dest);
|
||||
bool parseTargetIndexOperand(MachineOperand &Dest);
|
||||
bool parseMachineOperand(MachineOperand &Dest);
|
||||
bool parseIRValue(Value *&V);
|
||||
bool parseMachineMemoryOperand(MachineMemOperand *&Dest);
|
||||
|
||||
private:
|
||||
/// Convert the integer literal in the current token into an unsigned integer.
|
||||
@ -140,6 +143,11 @@ private:
|
||||
/// Return true if an error occurred.
|
||||
bool getUnsigned(unsigned &Result);
|
||||
|
||||
/// Convert the integer literal in the current token into an uint64.
|
||||
///
|
||||
/// Return true if an error occurred.
|
||||
bool getUint64(uint64_t &Result);
|
||||
|
||||
/// If the current token is of the given kind, consume it and return false.
|
||||
/// Otherwise report an error and return true.
|
||||
bool expectAndConsume(MIToken::TokenKind TokenKind);
|
||||
@ -256,15 +264,16 @@ bool MIParser::parse(MachineInstr *&MI) {
|
||||
if (Token.isError() || parseInstruction(OpCode, Flags))
|
||||
return true;
|
||||
|
||||
// TODO: Parse the bundle instruction flags and memory operands.
|
||||
// TODO: Parse the bundle instruction flags.
|
||||
|
||||
// Parse the remaining machine operands.
|
||||
while (Token.isNot(MIToken::Eof) && Token.isNot(MIToken::kw_debug_location)) {
|
||||
while (Token.isNot(MIToken::Eof) && Token.isNot(MIToken::kw_debug_location) &&
|
||||
Token.isNot(MIToken::coloncolon)) {
|
||||
auto Loc = Token.location();
|
||||
if (parseMachineOperand(MO))
|
||||
return true;
|
||||
Operands.push_back(MachineOperandWithLocation(MO, Loc, Token.location()));
|
||||
if (Token.is(MIToken::Eof))
|
||||
if (Token.is(MIToken::Eof) || Token.is(MIToken::coloncolon))
|
||||
break;
|
||||
if (Token.isNot(MIToken::comma))
|
||||
return error("expected ',' before the next machine operand");
|
||||
@ -282,6 +291,23 @@ bool MIParser::parse(MachineInstr *&MI) {
|
||||
DebugLocation = DebugLoc(Node);
|
||||
}
|
||||
|
||||
// Parse the machine memory operands.
|
||||
SmallVector<MachineMemOperand *, 2> MemOperands;
|
||||
if (Token.is(MIToken::coloncolon)) {
|
||||
lex();
|
||||
while (Token.isNot(MIToken::Eof)) {
|
||||
MachineMemOperand *MemOp = nullptr;
|
||||
if (parseMachineMemoryOperand(MemOp))
|
||||
return true;
|
||||
MemOperands.push_back(MemOp);
|
||||
if (Token.is(MIToken::Eof))
|
||||
break;
|
||||
if (Token.isNot(MIToken::comma))
|
||||
return error("expected ',' before the next machine memory operand");
|
||||
lex();
|
||||
}
|
||||
}
|
||||
|
||||
const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode);
|
||||
if (!MCID.isVariadic()) {
|
||||
// FIXME: Move the implicit operand verification to the machine verifier.
|
||||
@ -294,6 +320,12 @@ bool MIParser::parse(MachineInstr *&MI) {
|
||||
MI->setFlags(Flags);
|
||||
for (const auto &Operand : Operands)
|
||||
MI->addOperand(MF, Operand.Operand);
|
||||
if (MemOperands.empty())
|
||||
return false;
|
||||
MachineInstr::mmo_iterator MemRefs =
|
||||
MF.allocateMemRefsArray(MemOperands.size());
|
||||
std::copy(MemOperands.begin(), MemOperands.end(), MemRefs);
|
||||
MI->setMemRefs(MemRefs, MemRefs + MemOperands.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -929,6 +961,77 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::parseIRValue(Value *&V) {
|
||||
switch (Token.kind()) {
|
||||
case MIToken::NamedIRValue:
|
||||
case MIToken::QuotedNamedIRValue: {
|
||||
StringValueUtility Name(Token);
|
||||
V = MF.getFunction()->getValueSymbolTable().lookup(Name);
|
||||
if (!V)
|
||||
return error(Twine("use of undefined IR value '%ir.") +
|
||||
Token.rawStringValue() + "'");
|
||||
break;
|
||||
}
|
||||
// TODO: Parse unnamed IR value references.
|
||||
default:
|
||||
llvm_unreachable("The current token should be an IR block reference");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::getUint64(uint64_t &Result) {
|
||||
assert(Token.hasIntegerValue());
|
||||
if (Token.integerValue().getActiveBits() > 64)
|
||||
return error("expected 64-bit integer (too large)");
|
||||
Result = Token.integerValue().getZExtValue();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::parseMachineMemoryOperand(MachineMemOperand *&Dest) {
|
||||
if (expectAndConsume(MIToken::lparen))
|
||||
return true;
|
||||
// TODO: Parse the operand's flags.
|
||||
if (Token.isNot(MIToken::Identifier) ||
|
||||
(Token.stringValue() != "load" && Token.stringValue() != "store"))
|
||||
return error("expected 'load' or 'store' memory operation");
|
||||
unsigned Flags = 0;
|
||||
if (Token.stringValue() == "load")
|
||||
Flags |= MachineMemOperand::MOLoad;
|
||||
else
|
||||
Flags |= MachineMemOperand::MOStore;
|
||||
lex();
|
||||
|
||||
if (Token.isNot(MIToken::IntegerLiteral))
|
||||
return error("expected the size integer literal after memory operation");
|
||||
uint64_t Size;
|
||||
if (getUint64(Size))
|
||||
return true;
|
||||
lex();
|
||||
|
||||
const char *Word = Flags & MachineMemOperand::MOLoad ? "from" : "into";
|
||||
if (Token.isNot(MIToken::Identifier) || Token.stringValue() != Word)
|
||||
return error(Twine("expected '") + Word + "'");
|
||||
lex();
|
||||
|
||||
// TODO: Parse pseudo source values.
|
||||
if (Token.isNot(MIToken::NamedIRValue) &&
|
||||
Token.isNot(MIToken::QuotedNamedIRValue))
|
||||
return error("expected an IR value reference");
|
||||
Value *V = nullptr;
|
||||
if (parseIRValue(V))
|
||||
return true;
|
||||
if (!V->getType()->isPointerTy())
|
||||
return error("expected a pointer IR value");
|
||||
lex();
|
||||
// TODO: Parse the base alignment.
|
||||
// TODO: Parse the attached metadata nodes.
|
||||
if (expectAndConsume(MIToken::rparen))
|
||||
return true;
|
||||
|
||||
Dest = MF.getMachineMemOperand(MachinePointerInfo(V), Flags, Size, Size);
|
||||
return false;
|
||||
}
|
||||
|
||||
void MIParser::initNames2InstrOpCodes() {
|
||||
if (!Names2InstrOpCodes.empty())
|
||||
return;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineMemOperand.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/MIRYamlMapping.h"
|
||||
@ -114,8 +115,10 @@ public:
|
||||
void print(const MachineInstr &MI);
|
||||
void printMBBReference(const MachineBasicBlock &MBB);
|
||||
void printIRBlockReference(const BasicBlock &BB);
|
||||
void printIRValueReference(const Value &V);
|
||||
void printStackObjectReference(int FrameIndex);
|
||||
void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
|
||||
void print(const MachineMemOperand &Op);
|
||||
|
||||
void print(const MCCFIInstruction &CFI, const TargetRegisterInfo *TRI);
|
||||
};
|
||||
@ -426,7 +429,7 @@ void MIPrinter::print(const MachineInstr &MI) {
|
||||
if (MI.getFlag(MachineInstr::FrameSetup))
|
||||
OS << "frame-setup ";
|
||||
OS << TII->getName(MI.getOpcode());
|
||||
// TODO: Print the bundling instruction flags, machine mem operands.
|
||||
// TODO: Print the bundling instruction flags.
|
||||
if (I < E)
|
||||
OS << ' ';
|
||||
|
||||
@ -444,6 +447,17 @@ void MIPrinter::print(const MachineInstr &MI) {
|
||||
OS << " debug-location ";
|
||||
MI.getDebugLoc()->printAsOperand(OS, MST);
|
||||
}
|
||||
|
||||
if (!MI.memoperands_empty()) {
|
||||
OS << " :: ";
|
||||
bool NeedComma = false;
|
||||
for (const auto *Op : MI.memoperands()) {
|
||||
if (NeedComma)
|
||||
OS << ", ";
|
||||
print(*Op);
|
||||
NeedComma = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) {
|
||||
@ -467,6 +481,16 @@ void MIPrinter::printIRBlockReference(const BasicBlock &BB) {
|
||||
OS << Slot;
|
||||
}
|
||||
|
||||
void MIPrinter::printIRValueReference(const Value &V) {
|
||||
OS << "%ir.";
|
||||
if (V.hasName()) {
|
||||
printLLVMNameWithoutPrefix(OS, V.getName());
|
||||
return;
|
||||
}
|
||||
// TODO: Serialize the unnamed IR value references.
|
||||
OS << "<unserializable ir value>";
|
||||
}
|
||||
|
||||
void MIPrinter::printStackObjectReference(int FrameIndex) {
|
||||
auto ObjectInfo = StackObjectOperandMapping.find(FrameIndex);
|
||||
assert(ObjectInfo != StackObjectOperandMapping.end() &&
|
||||
@ -581,6 +605,24 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
|
||||
}
|
||||
}
|
||||
|
||||
void MIPrinter::print(const MachineMemOperand &Op) {
|
||||
OS << '(';
|
||||
// TODO: Print operand's other flags.
|
||||
if (Op.isLoad())
|
||||
OS << "load ";
|
||||
else {
|
||||
assert(Op.isStore() && "Non load machine operand must be a store");
|
||||
OS << "store ";
|
||||
}
|
||||
OS << Op.getSize() << (Op.isLoad() ? " from " : " into ");
|
||||
if (const Value *Val = Op.getValue())
|
||||
printIRValueReference(*Val);
|
||||
// TODO: Print PseudoSourceValue.
|
||||
// TODO: Print the base alignment.
|
||||
// TODO: Print the metadata attributes.
|
||||
OS << ')';
|
||||
}
|
||||
|
||||
static void printCFIRegister(unsigned DwarfReg, raw_ostream &OS,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
int Reg = TRI->getLLVMRegNum(DwarfReg, true);
|
||||
|
27
test/CodeGen/MIR/X86/expected-comma-after-memory-operand.mir
Normal file
27
test/CodeGen/MIR/X86/expected-comma-after-memory-operand.mir
Normal file
@ -0,0 +1,27 @@
|
||||
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||
|
||||
--- |
|
||||
|
||||
define void @test(i32* %a) {
|
||||
entry2:
|
||||
%b = load i32, i32* %a
|
||||
%c = add i32 %b, 1
|
||||
store i32 %c, i32* %a
|
||||
ret void
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%rdi' }
|
||||
body:
|
||||
- id: 0
|
||||
name: entry2
|
||||
liveins: [ '%rdi' ]
|
||||
instructions:
|
||||
# CHECK: [[@LINE+1]]:92: expected ',' before the next machine memory operand
|
||||
- 'INC32m killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (store 4 into %ir.a) (load 4 from %ir.a)'
|
||||
- RETQ
|
||||
...
|
26
test/CodeGen/MIR/X86/expected-from-in-memory-operand.mir
Normal file
26
test/CodeGen/MIR/X86/expected-from-in-memory-operand.mir
Normal file
@ -0,0 +1,26 @@
|
||||
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||
|
||||
--- |
|
||||
|
||||
define i32 @test(i32* %a) {
|
||||
entry:
|
||||
%b = load i32, i32* %a
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%rdi' }
|
||||
body:
|
||||
- id: 0
|
||||
name: entry
|
||||
liveins: [ '%rdi' ]
|
||||
instructions:
|
||||
# CHECK: [[@LINE+1]]:60: expected 'from'
|
||||
- '%eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 4 %ir.a)'
|
||||
- 'RETQ %eax'
|
||||
...
|
||||
|
@ -0,0 +1,25 @@
|
||||
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||
|
||||
--- |
|
||||
|
||||
define i32 @test(i32* %a) {
|
||||
entry:
|
||||
%b = load i32, i32* %a
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%rdi' }
|
||||
body:
|
||||
- id: 0
|
||||
name: entry
|
||||
liveins: [ '%rdi' ]
|
||||
instructions:
|
||||
# CHECK: [[@LINE+1]]:53: expected 'load' or 'store' memory operation
|
||||
- '%eax = MOV32rm killed %rdi, 1, _, 0, _ :: (4 from %ir.a)'
|
||||
- 'RETQ %eax'
|
||||
...
|
@ -0,0 +1,26 @@
|
||||
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||
|
||||
--- |
|
||||
|
||||
define i32 @test(i32* %a) {
|
||||
entry:
|
||||
%b = load i32, i32* %a
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%rdi' }
|
||||
body:
|
||||
- id: 0
|
||||
name: entry
|
||||
liveins: [ '%rdi' ]
|
||||
instructions:
|
||||
# CHECK: [[@LINE+1]]:65: expected a pointer IR value
|
||||
- '%eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 4 from %ir.b)'
|
||||
- 'RETQ %eax'
|
||||
...
|
||||
|
@ -0,0 +1,26 @@
|
||||
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||
|
||||
--- |
|
||||
|
||||
define i32 @test(i32* %a) {
|
||||
entry:
|
||||
%b = load i32, i32* %a
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%rdi' }
|
||||
body:
|
||||
- id: 0
|
||||
name: entry
|
||||
liveins: [ '%rdi' ]
|
||||
instructions:
|
||||
# CHECK: [[@LINE+1]]:58: expected the size integer literal after memory operation
|
||||
- '%eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load from %ir.a)'
|
||||
- 'RETQ %eax'
|
||||
...
|
||||
|
26
test/CodeGen/MIR/X86/expected-value-in-memory-operand.mir
Normal file
26
test/CodeGen/MIR/X86/expected-value-in-memory-operand.mir
Normal file
@ -0,0 +1,26 @@
|
||||
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||
|
||||
--- |
|
||||
|
||||
define i32 @test(i32* %a) {
|
||||
entry:
|
||||
%b = load i32, i32* %a
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%rdi' }
|
||||
body:
|
||||
- id: 0
|
||||
name: entry
|
||||
liveins: [ '%rdi' ]
|
||||
instructions:
|
||||
# CHECK: [[@LINE+1]]:65: expected an IR value reference
|
||||
- '%eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 4 from a)'
|
||||
- 'RETQ %eax'
|
||||
...
|
||||
|
26
test/CodeGen/MIR/X86/large-size-in-memory-operand-error.mir
Normal file
26
test/CodeGen/MIR/X86/large-size-in-memory-operand-error.mir
Normal file
@ -0,0 +1,26 @@
|
||||
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||
|
||||
--- |
|
||||
|
||||
define i32 @test(i32* %a) {
|
||||
entry:
|
||||
%b = load i32, i32* %a
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%rdi' }
|
||||
body:
|
||||
- id: 0
|
||||
name: entry
|
||||
liveins: [ '%rdi' ]
|
||||
instructions:
|
||||
# CHECK: [[@LINE+1]]:58: expected 64-bit integer (too large)
|
||||
- '%eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 12345678912345678924218574857 from %ir.a)'
|
||||
- 'RETQ %eax'
|
||||
...
|
||||
|
52
test/CodeGen/MIR/X86/memory-operands.mir
Normal file
52
test/CodeGen/MIR/X86/memory-operands.mir
Normal file
@ -0,0 +1,52 @@
|
||||
# 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 machine memory operands
|
||||
# correctly.
|
||||
|
||||
--- |
|
||||
|
||||
define i32 @test(i32* %a) {
|
||||
entry:
|
||||
%b = load i32, i32* %a
|
||||
store i32 42, i32* %a
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
define void @test2(i32* %"a value") {
|
||||
entry2:
|
||||
%b = load i32, i32* %"a value"
|
||||
%c = add i32 %b, 1
|
||||
store i32 %c, i32* %"a value"
|
||||
ret void
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%rdi' }
|
||||
body:
|
||||
- id: 0
|
||||
name: entry
|
||||
liveins: [ '%rdi' ]
|
||||
instructions:
|
||||
# CHECK: %eax = MOV32rm %rdi, 1, _, 0, _ :: (load 4 from %ir.a)
|
||||
# CHECK-NEXT: MOV32mi killed %rdi, 1, _, 0, _, 42 :: (store 4 into %ir.a)
|
||||
- '%eax = MOV32rm %rdi, 1, _, 0, _ :: (load 4 from %ir.a)'
|
||||
- 'MOV32mi killed %rdi, 1, _, 0, _, 42 :: (store 4 into %ir.a)'
|
||||
- 'RETQ %eax'
|
||||
...
|
||||
---
|
||||
name: test2
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%rdi' }
|
||||
body:
|
||||
- id: 0
|
||||
name: entry2
|
||||
liveins: [ '%rdi' ]
|
||||
instructions:
|
||||
# CHECK: INC32m killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (store 4 into %ir."a value"), (load 4 from %ir."a value")
|
||||
- 'INC32m killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (store 4 into %ir."a value"), (load 4 from %ir."a value")'
|
||||
- RETQ
|
||||
...
|
26
test/CodeGen/MIR/X86/undefined-value-in-memory-operand.mir
Normal file
26
test/CodeGen/MIR/X86/undefined-value-in-memory-operand.mir
Normal file
@ -0,0 +1,26 @@
|
||||
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
|
||||
|
||||
--- |
|
||||
|
||||
define i32 @test(i32* %a) {
|
||||
entry:
|
||||
%b = load i32, i32* %a
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%rdi' }
|
||||
body:
|
||||
- id: 0
|
||||
name: entry
|
||||
liveins: [ '%rdi' ]
|
||||
instructions:
|
||||
# CHECK: [[@LINE+1]]:65: use of undefined IR value '%ir.c'
|
||||
- '%eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 4 from %ir.c)'
|
||||
- 'RETQ %eax'
|
||||
...
|
||||
|
Loading…
x
Reference in New Issue
Block a user