forked from OSchip/llvm-project
[x86/MIR] Implement support for pre- and post-instruction symbols, as
well as MIR parsing support for `MCSymbol` `MachineOperand`s. The only real way to test pre- and post-instruction symbol support is to use them in operands, so I ended up implementing that within the patch as well. I can split out the operand support if folks really want but it doesn't really seem worth it. The functional implementation of pre- and post-instruction symbols is now *completely trivial*. Two tiny bits of code in the (misnamed) AsmPrinter. It should be completely target independent as well. We emit these exactly the same way as we emit basic block labels. Most of the code here is to give full dumping, MIR printing, and MIR parsing support so that we can write useful tests. The MIR parsing of MC symbol operands still isn't 100%, as it forces the symbols to be non-temporary and non-local symbols with names. However, those names often can encode most (if not all) of the special semantics desired, and unnamed symbols seem especially annoying to serialize and de-serialize. While this isn't perfect or full support, it seems plenty to write tests that exercise usage of these kinds of operands. The MIR support for pre-and post-instruction symbols was quite straightforward. I chose to print them out in an as-if-operand syntax similar to debug locations as this seemed the cleanest way and let me use nice introducer tokens rather than inventing more magic punctuation like we use for memoperands. However, supporting MIR-based parsing of these symbols caused me to change the design of the symbol support to allow setting arbitrary symbols. Without this, I don't see any reasonable way to test things with MIR. Differential Revision: https://reviews.llvm.org/D50833 llvm-svn: 339962
This commit is contained in:
parent
103018e9d9
commit
75ca6be1c1
|
@ -135,7 +135,7 @@ can serialize:
|
|||
- The target-specific ``MachineConstantPoolValue`` subclasses (in the ARM and
|
||||
SystemZ backends) aren't serialized at the moment.
|
||||
|
||||
- The ``MCSymbol`` machine operands are only printed, they can't be parsed.
|
||||
- The ``MCSymbol`` machine operands don't support temporary or local symbols.
|
||||
|
||||
- A lot of the state in ``MachineModuleInfo`` isn't serialized - only the CFI
|
||||
instructions and the variable debug information from MMI is serialized right
|
||||
|
@ -143,9 +143,9 @@ can serialize:
|
|||
|
||||
These limitations impose restrictions on what you can test with the MIR format.
|
||||
For now, tests that would like to test some behaviour that depends on the state
|
||||
of certain ``MCSymbol`` operands or the exception handling state in MMI, can't
|
||||
use the MIR format. As well as that, tests that test some behaviour that
|
||||
depends on the state of the target specific ``MachineFunctionInfo`` or
|
||||
of temporary or local ``MCSymbol`` operands or the exception handling state in
|
||||
MMI, can't use the MIR format. As well as that, tests that test some behaviour
|
||||
that depends on the state of the target specific ``MachineFunctionInfo`` or
|
||||
``MachineConstantPoolValue`` subclasses can't use the MIR format at the moment.
|
||||
|
||||
High Level Structure
|
||||
|
@ -439,9 +439,8 @@ is preferred.
|
|||
Machine Operands
|
||||
----------------
|
||||
|
||||
There are seventeen different kinds of machine operands, and all of them, except
|
||||
the ``MCSymbol`` operand, can be serialized. The ``MCSymbol`` operands are
|
||||
just printed out - they can't be parsed back yet.
|
||||
There are seventeen different kinds of machine operands, and all of them can be
|
||||
serialized.
|
||||
|
||||
Immediate Operands
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -1493,17 +1493,19 @@ public:
|
|||
void cloneMergedMemRefs(MachineFunction &MF,
|
||||
ArrayRef<const MachineInstr *> MIs);
|
||||
|
||||
/// Get or create a temporary symbol that will be emitted just prior to the
|
||||
/// instruction itself.
|
||||
/// Set a symbol that will be emitted just prior to the instruction itself.
|
||||
///
|
||||
/// Setting this to a null pointer will remove any such symbol.
|
||||
///
|
||||
/// FIXME: This is not fully implemented yet.
|
||||
MCSymbol *getOrCreatePreInstrTempSymbol(MCContext &MCCtx);
|
||||
void setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol);
|
||||
|
||||
/// Get or create a temporary symbol that will be emitted just after the
|
||||
/// instruction itself.
|
||||
/// Set a symbol that will be emitted just after the instruction itself.
|
||||
///
|
||||
/// Setting this to a null pointer will remove any such symbol.
|
||||
///
|
||||
/// FIXME: This is not fully implemented yet.
|
||||
MCSymbol *getOrCreatePostInstrTempSymbol(MCContext &MCCtx);
|
||||
void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol);
|
||||
|
||||
/// Return the MIFlags which represent both MachineInstrs. This
|
||||
/// should be used when merging two MachineInstrs into one. This routine does
|
||||
|
|
|
@ -1066,6 +1066,10 @@ void AsmPrinter::EmitFunctionBody() {
|
|||
++NumInstsInFunction;
|
||||
}
|
||||
|
||||
// If there is a pre-instruction symbol, emit a label for it here.
|
||||
if (MCSymbol *S = MI.getPreInstrSymbol())
|
||||
OutStreamer->EmitLabel(S);
|
||||
|
||||
if (ShouldPrintDebugScopes) {
|
||||
for (const HandlerInfo &HI : Handlers) {
|
||||
NamedRegionTimer T(HI.TimerName, HI.TimerDescription,
|
||||
|
@ -1117,6 +1121,10 @@ void AsmPrinter::EmitFunctionBody() {
|
|||
break;
|
||||
}
|
||||
|
||||
// If there is a post-instruction symbol, emit a label for it here.
|
||||
if (MCSymbol *S = MI.getPostInstrSymbol())
|
||||
OutStreamer->EmitLabel(S);
|
||||
|
||||
if (ShouldPrintDebugScopes) {
|
||||
for (const HandlerInfo &HI : Handlers) {
|
||||
NamedRegionTimer T(HI.TimerName, HI.TimerDescription,
|
||||
|
|
|
@ -245,6 +245,8 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
|
|||
.Case("successors", MIToken::kw_successors)
|
||||
.Case("floatpred", MIToken::kw_floatpred)
|
||||
.Case("intpred", MIToken::kw_intpred)
|
||||
.Case("pre-instr-symbol", MIToken::kw_pre_instr_symbol)
|
||||
.Case("post-instr-symbol", MIToken::kw_post_instr_symbol)
|
||||
.Default(MIToken::Identifier);
|
||||
}
|
||||
|
||||
|
@ -460,6 +462,53 @@ static Cursor maybeLexExternalSymbol(Cursor C, MIToken &Token,
|
|||
ErrorCallback);
|
||||
}
|
||||
|
||||
static Cursor maybeLexMCSymbol(Cursor C, MIToken &Token,
|
||||
ErrorCallbackType ErrorCallback) {
|
||||
const StringRef Rule = "<mcsymbol ";
|
||||
if (!C.remaining().startswith(Rule))
|
||||
return None;
|
||||
auto Start = C;
|
||||
C.advance(Rule.size());
|
||||
|
||||
// Try a simple unquoted name.
|
||||
if (C.peek() != '"') {
|
||||
while (isIdentifierChar(C.peek()))
|
||||
C.advance();
|
||||
StringRef String = Start.upto(C).drop_front(Rule.size());
|
||||
if (C.peek() != '>') {
|
||||
ErrorCallback(C.location(),
|
||||
"expected the '<mcsymbol ...' to be closed by a '>'");
|
||||
Token.reset(MIToken::Error, Start.remaining());
|
||||
return Start;
|
||||
}
|
||||
C.advance();
|
||||
|
||||
Token.reset(MIToken::MCSymbol, Start.upto(C)).setStringValue(String);
|
||||
return C;
|
||||
}
|
||||
|
||||
// Otherwise lex out a quoted name.
|
||||
Cursor R = lexStringConstant(C, ErrorCallback);
|
||||
if (!R) {
|
||||
ErrorCallback(C.location(),
|
||||
"unable to parse quoted string from opening quote");
|
||||
Token.reset(MIToken::Error, Start.remaining());
|
||||
return Start;
|
||||
}
|
||||
StringRef String = Start.upto(R).drop_front(Rule.size());
|
||||
if (R.peek() != '>') {
|
||||
ErrorCallback(R.location(),
|
||||
"expected the '<mcsymbol ...' to be closed by a '>'");
|
||||
Token.reset(MIToken::Error, Start.remaining());
|
||||
return Start;
|
||||
}
|
||||
R.advance();
|
||||
|
||||
Token.reset(MIToken::MCSymbol, Start.upto(R))
|
||||
.setOwnedStringValue(unescapeQuotedString(String));
|
||||
return R;
|
||||
}
|
||||
|
||||
static bool isValidHexFloatingPointPrefix(char C) {
|
||||
return C == 'H' || C == 'K' || C == 'L' || C == 'M';
|
||||
}
|
||||
|
@ -657,6 +706,8 @@ StringRef llvm::lexMIToken(StringRef Source, MIToken &Token,
|
|||
return R.remaining();
|
||||
if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
|
||||
return R.remaining();
|
||||
if (Cursor R = maybeLexMCSymbol(C, Token, ErrorCallback))
|
||||
return R.remaining();
|
||||
if (Cursor R = maybeLexHexadecimalLiteral(C, Token))
|
||||
return R.remaining();
|
||||
if (Cursor R = maybeLexNumericalLiteral(C, Token))
|
||||
|
|
|
@ -113,6 +113,8 @@ struct MIToken {
|
|||
kw_successors,
|
||||
kw_floatpred,
|
||||
kw_intpred,
|
||||
kw_pre_instr_symbol,
|
||||
kw_post_instr_symbol,
|
||||
|
||||
// Named metadata keywords
|
||||
md_tbaa,
|
||||
|
@ -132,6 +134,7 @@ struct MIToken {
|
|||
NamedGlobalValue,
|
||||
GlobalValue,
|
||||
ExternalSymbol,
|
||||
MCSymbol,
|
||||
|
||||
// Other tokens
|
||||
IntegerLiteral,
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/IR/ValueSymbolTable.h"
|
||||
#include "llvm/MC/LaneBitmask.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCDwarf.h"
|
||||
#include "llvm/MC/MCInstrDesc.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
|
@ -221,6 +222,7 @@ public:
|
|||
bool parseSubRegisterIndexOperand(MachineOperand &Dest);
|
||||
bool parseJumpTableIndexOperand(MachineOperand &Dest);
|
||||
bool parseExternalSymbolOperand(MachineOperand &Dest);
|
||||
bool parseMCSymbolOperand(MachineOperand &Dest);
|
||||
bool parseMDNode(MDNode *&Node);
|
||||
bool parseDIExpression(MDNode *&Expr);
|
||||
bool parseMetadataOperand(MachineOperand &Dest);
|
||||
|
@ -250,6 +252,7 @@ public:
|
|||
bool parseOptionalScope(LLVMContext &Context, SyncScope::ID &SSID);
|
||||
bool parseOptionalAtomicOrdering(AtomicOrdering &Order);
|
||||
bool parseMachineMemoryOperand(MachineMemOperand *&Dest);
|
||||
bool parsePreOrPostInstrSymbol(MCSymbol *&Symbol);
|
||||
|
||||
private:
|
||||
/// Convert the integer literal in the current token into an unsigned integer.
|
||||
|
@ -346,6 +349,9 @@ private:
|
|||
/// Return true if the name isn't a name of a target MMO flag.
|
||||
bool getMMOTargetFlag(StringRef Name, MachineMemOperand::Flags &Flag);
|
||||
|
||||
/// Get or create an MCSymbol for a given name.
|
||||
MCSymbol *getOrCreateMCSymbol(StringRef Name);
|
||||
|
||||
/// parseStringConstant
|
||||
/// ::= StringConstant
|
||||
bool parseStringConstant(std::string &Result);
|
||||
|
@ -737,7 +743,9 @@ bool MIParser::parse(MachineInstr *&MI) {
|
|||
return true;
|
||||
|
||||
// Parse the remaining machine operands.
|
||||
while (!Token.isNewlineOrEOF() && Token.isNot(MIToken::kw_debug_location) &&
|
||||
while (!Token.isNewlineOrEOF() && Token.isNot(MIToken::kw_pre_instr_symbol) &&
|
||||
Token.isNot(MIToken::kw_post_instr_symbol) &&
|
||||
Token.isNot(MIToken::kw_debug_location) &&
|
||||
Token.isNot(MIToken::coloncolon) && Token.isNot(MIToken::lbrace)) {
|
||||
auto Loc = Token.location();
|
||||
Optional<unsigned> TiedDefIdx;
|
||||
|
@ -753,6 +761,15 @@ bool MIParser::parse(MachineInstr *&MI) {
|
|||
lex();
|
||||
}
|
||||
|
||||
MCSymbol *PreInstrSymbol = nullptr;
|
||||
if (Token.is(MIToken::kw_pre_instr_symbol))
|
||||
if (parsePreOrPostInstrSymbol(PreInstrSymbol))
|
||||
return true;
|
||||
MCSymbol *PostInstrSymbol = nullptr;
|
||||
if (Token.is(MIToken::kw_post_instr_symbol))
|
||||
if (parsePreOrPostInstrSymbol(PostInstrSymbol))
|
||||
return true;
|
||||
|
||||
DebugLoc DebugLocation;
|
||||
if (Token.is(MIToken::kw_debug_location)) {
|
||||
lex();
|
||||
|
@ -795,9 +812,12 @@ bool MIParser::parse(MachineInstr *&MI) {
|
|||
MI->addOperand(MF, Operand.Operand);
|
||||
if (assignRegisterTies(*MI, Operands))
|
||||
return true;
|
||||
if (MemOperands.empty())
|
||||
return false;
|
||||
MI->setMemRefs(MF, MemOperands);
|
||||
if (PreInstrSymbol)
|
||||
MI->setPreInstrSymbol(MF, PreInstrSymbol);
|
||||
if (PostInstrSymbol)
|
||||
MI->setPostInstrSymbol(MF, PostInstrSymbol);
|
||||
if (!MemOperands.empty())
|
||||
MI->setMemRefs(MF, MemOperands);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1570,6 +1590,16 @@ bool MIParser::parseExternalSymbolOperand(MachineOperand &Dest) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::parseMCSymbolOperand(MachineOperand &Dest) {
|
||||
assert(Token.is(MIToken::MCSymbol));
|
||||
MCSymbol *Symbol = getOrCreateMCSymbol(Token.stringValue());
|
||||
lex();
|
||||
Dest = MachineOperand::CreateMCSymbol(Symbol);
|
||||
if (parseOperandsOffset(Dest))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::parseSubRegisterIndexOperand(MachineOperand &Dest) {
|
||||
assert(Token.is(MIToken::SubRegisterIndex));
|
||||
StringRef Name = Token.stringValue();
|
||||
|
@ -2047,6 +2077,8 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest,
|
|||
return parseJumpTableIndexOperand(Dest);
|
||||
case MIToken::ExternalSymbol:
|
||||
return parseExternalSymbolOperand(Dest);
|
||||
case MIToken::MCSymbol:
|
||||
return parseMCSymbolOperand(Dest);
|
||||
case MIToken::SubRegisterIndex:
|
||||
return parseSubRegisterIndexOperand(Dest);
|
||||
case MIToken::md_diexpr:
|
||||
|
@ -2526,6 +2558,24 @@ bool MIParser::parseMachineMemoryOperand(MachineMemOperand *&Dest) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::parsePreOrPostInstrSymbol(MCSymbol *&Symbol) {
|
||||
assert((Token.is(MIToken::kw_pre_instr_symbol) ||
|
||||
Token.is(MIToken::kw_post_instr_symbol)) &&
|
||||
"Invalid token for a pre- post-instruction symbol!");
|
||||
lex();
|
||||
if (Token.isNot(MIToken::MCSymbol))
|
||||
return error("expected a symbol after 'pre-instr-symbol'");
|
||||
Symbol = getOrCreateMCSymbol(Token.stringValue());
|
||||
lex();
|
||||
if (Token.isNewlineOrEOF() || Token.is(MIToken::coloncolon) ||
|
||||
Token.is(MIToken::lbrace))
|
||||
return false;
|
||||
if (Token.isNot(MIToken::comma))
|
||||
return error("expected ',' before the next machine operand");
|
||||
lex();
|
||||
return false;
|
||||
}
|
||||
|
||||
void MIParser::initNames2InstrOpCodes() {
|
||||
if (!Names2InstrOpCodes.empty())
|
||||
return;
|
||||
|
@ -2756,6 +2806,15 @@ bool MIParser::getMMOTargetFlag(StringRef Name,
|
|||
return false;
|
||||
}
|
||||
|
||||
MCSymbol *MIParser::getOrCreateMCSymbol(StringRef Name) {
|
||||
// FIXME: Currently we can't recognize temporary or local symbols and call all
|
||||
// of the appropriate forms to create them. However, this handles basic cases
|
||||
// well as most of the special aspects are recognized by a prefix on their
|
||||
// name, and the input names should already be unique. For test cases, keeping
|
||||
// the symbol name out of the symbol table isn't terribly important.
|
||||
return MF.getContext().getOrCreateSymbol(Name);
|
||||
}
|
||||
|
||||
bool MIParser::parseStringConstant(std::string &Result) {
|
||||
if (Token.isNot(MIToken::StringConstant))
|
||||
return error("expected string constant");
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "llvm/IR/ModuleSlotTracker.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/MC/LaneBitmask.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCDwarf.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/AtomicOrdering.h"
|
||||
|
@ -708,6 +709,23 @@ void MIPrinter::print(const MachineInstr &MI) {
|
|||
NeedComma = true;
|
||||
}
|
||||
|
||||
// Print any optional symbols attached to this instruction as-if they were
|
||||
// operands.
|
||||
if (MCSymbol *PreInstrSymbol = MI.getPreInstrSymbol()) {
|
||||
if (NeedComma)
|
||||
OS << ',';
|
||||
OS << " pre-instr-symbol ";
|
||||
MachineOperand::printSymbol(OS, *PreInstrSymbol);
|
||||
NeedComma = true;
|
||||
}
|
||||
if (MCSymbol *PostInstrSymbol = MI.getPostInstrSymbol()) {
|
||||
if (NeedComma)
|
||||
OS << ',';
|
||||
OS << " post-instr-symbol ";
|
||||
MachineOperand::printSymbol(OS, *PostInstrSymbol);
|
||||
NeedComma = true;
|
||||
}
|
||||
|
||||
if (const DebugLoc &DL = MI.getDebugLoc()) {
|
||||
if (NeedComma)
|
||||
OS << ',';
|
||||
|
|
|
@ -447,45 +447,68 @@ void MachineInstr::cloneMergedMemRefs(MachineFunction &MF,
|
|||
setMemRefs(MF, MergedMMOs);
|
||||
}
|
||||
|
||||
MCSymbol *MachineInstr::getOrCreatePreInstrTempSymbol(MCContext &MCCtx) {
|
||||
MCSymbol *S = getPreInstrSymbol();
|
||||
if (S)
|
||||
return S;
|
||||
void MachineInstr::setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol) {
|
||||
MCSymbol *OldSymbol = getPreInstrSymbol();
|
||||
if (OldSymbol == Symbol)
|
||||
return;
|
||||
if (OldSymbol && !Symbol) {
|
||||
// We're removing a symbol rather than adding one. Try to clean up any
|
||||
// extra info carried around.
|
||||
if (Info.is<EIIK_PreInstrSymbol>()) {
|
||||
Info.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new temp symbol.
|
||||
S = MCCtx.createTempSymbol();
|
||||
if (memoperands_empty()) {
|
||||
assert(getPostInstrSymbol() &&
|
||||
"Should never have only a single symbol allocated out-of-line!");
|
||||
Info.set<EIIK_PostInstrSymbol>(getPostInstrSymbol());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Info) {
|
||||
// Otherwise fallback on the generic update.
|
||||
} else if (!Info || Info.is<EIIK_PreInstrSymbol>()) {
|
||||
// If we don't have any other extra info, we can store this inline.
|
||||
Info.set<EIIK_PreInstrSymbol>(S);
|
||||
return S;
|
||||
Info.set<EIIK_PreInstrSymbol>(Symbol);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, allocate a fully set of extra info.
|
||||
// Otherwise, allocate a full new set of extra info.
|
||||
// FIXME: Maybe we should make the symbols in the extra info mutable?
|
||||
Info.set<EIIK_OutOfLine>(
|
||||
getMF()->createMIExtraInfo(memoperands(), S, getPostInstrSymbol()));
|
||||
|
||||
return S;
|
||||
MF.createMIExtraInfo(memoperands(), Symbol, getPostInstrSymbol()));
|
||||
}
|
||||
|
||||
MCSymbol *MachineInstr::getOrCreatePostInstrTempSymbol(MCContext &MCCtx) {
|
||||
MCSymbol *S = getPostInstrSymbol();
|
||||
if (S)
|
||||
return S;
|
||||
void MachineInstr::setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol) {
|
||||
MCSymbol *OldSymbol = getPostInstrSymbol();
|
||||
if (OldSymbol == Symbol)
|
||||
return;
|
||||
if (OldSymbol && !Symbol) {
|
||||
// We're removing a symbol rather than adding one. Try to clean up any
|
||||
// extra info carried around.
|
||||
if (Info.is<EIIK_PostInstrSymbol>()) {
|
||||
Info.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new temp symbol.
|
||||
S = MCCtx.createTempSymbol();
|
||||
if (memoperands_empty()) {
|
||||
assert(getPreInstrSymbol() &&
|
||||
"Should never have only a single symbol allocated out-of-line!");
|
||||
Info.set<EIIK_PreInstrSymbol>(getPreInstrSymbol());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Info) {
|
||||
// Otherwise fallback on the generic update.
|
||||
} else if (!Info || Info.is<EIIK_PostInstrSymbol>()) {
|
||||
// If we don't have any other extra info, we can store this inline.
|
||||
Info.set<EIIK_PostInstrSymbol>(S);
|
||||
return S;
|
||||
Info.set<EIIK_PostInstrSymbol>(Symbol);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, allocate a fully set of extra info.
|
||||
// Otherwise, allocate a full new set of extra info.
|
||||
// FIXME: Maybe we should make the symbols in the extra info mutable?
|
||||
Info.set<EIIK_OutOfLine>(
|
||||
getMF()->createMIExtraInfo(memoperands(), getPreInstrSymbol(), S));
|
||||
return S;
|
||||
MF.createMIExtraInfo(memoperands(), getPreInstrSymbol(), Symbol));
|
||||
}
|
||||
|
||||
uint16_t MachineInstr::mergeFlagsWith(const MachineInstr &Other) const {
|
||||
|
@ -1592,6 +1615,25 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
|||
}
|
||||
}
|
||||
|
||||
// Print any optional symbols attached to this instruction as-if they were
|
||||
// operands.
|
||||
if (MCSymbol *PreInstrSymbol = getPreInstrSymbol()) {
|
||||
if (!FirstOp) {
|
||||
FirstOp = false;
|
||||
OS << ',';
|
||||
}
|
||||
OS << " pre-instr-symbol ";
|
||||
MachineOperand::printSymbol(OS, *PreInstrSymbol);
|
||||
}
|
||||
if (MCSymbol *PostInstrSymbol = getPostInstrSymbol()) {
|
||||
if (!FirstOp) {
|
||||
FirstOp = false;
|
||||
OS << ',';
|
||||
}
|
||||
OS << " post-instr-symbol ";
|
||||
MachineOperand::printSymbol(OS, *PostInstrSymbol);
|
||||
}
|
||||
|
||||
if (!SkipDebugLoc) {
|
||||
if (const DebugLoc &DL = getDebugLoc()) {
|
||||
if (!FirstOp)
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
# RUN: llc -march=x86-64 -run-pass none -o - %s | FileCheck %s
|
||||
# This test ensures that the MIR parser parses pre- and post-instruction symbols
|
||||
# and MCSymbol operands correctly.
|
||||
|
||||
--- |
|
||||
declare void @f(i32 %x) nounwind
|
||||
|
||||
declare void @g(i32 %x) nounwind
|
||||
|
||||
declare void @h(i32 %x) nounwind
|
||||
|
||||
define i64 @test(i32 %x) nounwind {
|
||||
entry:
|
||||
call void @f(i32 %x)
|
||||
call void @g(i32 %x)
|
||||
call void @h(i32 %x), !dbg !9
|
||||
ret i64 undef
|
||||
}
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!6, !7}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
|
||||
!1 = !DIFile(filename: "test.ll", directory: "")
|
||||
!2 = !{}
|
||||
!4 = distinct !DISubprogram(name: "test", scope: !5, file: !5, line: 4, type: !2, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
|
||||
!5 = !DIFile(filename: "test.c", directory: "")
|
||||
!6 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!7 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!9 = !DILocation(line: 1, scope: !4)
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
# CHECK-LABEL: name: test
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
hasCalls: true
|
||||
body: |
|
||||
bb.0.entry:
|
||||
liveins: $edi
|
||||
|
||||
%0:gr32 = COPY $edi
|
||||
%1:gr32 = COPY killed %0
|
||||
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
$edi = COPY %1
|
||||
|
||||
CALL64pcrel32 @f, csr_64, implicit $rsp, implicit $ssp, implicit $edi, pre-instr-symbol <mcsymbol .Lpre_f>, post-instr-symbol <mcsymbol .Lpost_f>
|
||||
; CHECK: CALL64pcrel32 @f, {{.*}}, pre-instr-symbol <mcsymbol .Lpre_f>, post-instr-symbol <mcsymbol .Lpost_f>
|
||||
|
||||
ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
$edi = COPY %1
|
||||
|
||||
CALL64pcrel32 @g, csr_64, implicit $rsp, implicit $ssp, implicit $edi, pre-instr-symbol <mcsymbol .Lpre_g>
|
||||
; CHECK: CALL64pcrel32 @g, {{.*}}, pre-instr-symbol <mcsymbol .Lpre_g>
|
||||
|
||||
ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
$edi = COPY %1
|
||||
|
||||
CALL64pcrel32 @h, csr_64, implicit $rsp, implicit $ssp, implicit $edi, post-instr-symbol <mcsymbol .Lpost_h>, debug-location !9
|
||||
; CHECK: CALL64pcrel32 @h, {{.*}}, post-instr-symbol <mcsymbol .Lpost_h>, debug-location
|
||||
|
||||
ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
|
||||
%2:gr64 = MOV64ri32 <mcsymbol .Lpre_f>
|
||||
%3:gr64 = MOV64ri32 <mcsymbol .Lpost_f>
|
||||
%4:gr64 = MOV64ri32 <mcsymbol .Lpre_g>
|
||||
%5:gr64 = MOV64ri32 <mcsymbol .Lpost_h>
|
||||
; CHECK: %2:gr64 = MOV64ri32 <mcsymbol .Lpre_f>
|
||||
; CHECK: %3:gr64 = MOV64ri32 <mcsymbol .Lpost_f>
|
||||
; CHECK: %4:gr64 = MOV64ri32 <mcsymbol .Lpre_g>
|
||||
; CHECK: %5:gr64 = MOV64ri32 <mcsymbol .Lpost_h>
|
||||
|
||||
%6:gr64 = ADD64rr killed %2, killed %3, implicit-def $eflags
|
||||
%7:gr64 = ADD64rr killed %4, killed %5, implicit-def $eflags
|
||||
%8:gr64 = ADD64rr killed %6, killed %7, implicit-def $eflags
|
||||
$rax = COPY %8
|
||||
RETQ implicit $rax
|
||||
|
||||
...
|
|
@ -0,0 +1,74 @@
|
|||
# RUN: llc -march=x86-64 -o - %s | FileCheck %s
|
||||
#
|
||||
# Test the emission of pre- and post-instruction labels.
|
||||
|
||||
--- |
|
||||
declare void @f(i32 %x) nounwind
|
||||
|
||||
declare void @g(i32 %x) nounwind
|
||||
|
||||
declare void @h(i32 %x) nounwind
|
||||
|
||||
define i64 @test(i32 %x) nounwind {
|
||||
entry:
|
||||
call void @f(i32 %x)
|
||||
call void @g(i32 %x)
|
||||
call void @h(i32 %x)
|
||||
ret i64 undef
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
# CHECK-LABEL: {{^}}test:
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
hasCalls: true
|
||||
body: |
|
||||
bb.0.entry:
|
||||
liveins: $edi
|
||||
|
||||
%0:gr32 = COPY $edi
|
||||
%1:gr32 = COPY killed %0
|
||||
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
$edi = COPY %1
|
||||
|
||||
CALL64pcrel32 @f, csr_64, implicit $rsp, implicit $ssp, implicit $edi, pre-instr-symbol <mcsymbol .Lpre_f>, post-instr-symbol <mcsymbol .Lpost_f>
|
||||
; CHECK: .Lpre_f:
|
||||
; CHECK-NEXT: callq f
|
||||
; CHECK-NEXT: .Lpost_f:
|
||||
|
||||
ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
$edi = COPY %1
|
||||
|
||||
CALL64pcrel32 @g, csr_64, implicit $rsp, implicit $ssp, implicit $edi, pre-instr-symbol <mcsymbol .Lpre_g>
|
||||
; CHECK: .Lpre_g:
|
||||
; CHECK-NEXT: callq g
|
||||
|
||||
ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
$edi = COPY %1
|
||||
|
||||
CALL64pcrel32 @h, csr_64, implicit $rsp, implicit $ssp, implicit $edi, post-instr-symbol <mcsymbol .Lpost_h>
|
||||
; CHECK: callq h
|
||||
; CHECK-NEXT: .Lpost_h:
|
||||
|
||||
ADJCALLSTACKUP64 0, 0, implicit-def $rsp, implicit-def $eflags, implicit-def $ssp, implicit $rsp, implicit $ssp
|
||||
|
||||
%2:gr64 = MOV64ri32 <mcsymbol .Lpre_f>
|
||||
%3:gr64 = MOV64ri32 <mcsymbol .Lpost_f>
|
||||
%4:gr64 = MOV64ri32 <mcsymbol .Lpre_g>
|
||||
%5:gr64 = MOV64ri32 <mcsymbol .Lpost_h>
|
||||
; CHECK: movq $.Lpre_f, %{{.*}}
|
||||
; CHECK-NEXT: movq $.Lpost_f, %{{.*}}
|
||||
; CHECK-NEXT: movq $.Lpre_g, %{{.*}}
|
||||
; CHECK-NEXT: movq $.Lpost_h, %{{.*}}
|
||||
|
||||
%6:gr64 = ADD64rr killed %2, killed %3, implicit-def $eflags
|
||||
%7:gr64 = ADD64rr killed %4, killed %5, implicit-def $eflags
|
||||
%8:gr64 = ADD64rr killed %6, killed %7, implicit-def $eflags
|
||||
$rax = COPY %8
|
||||
RETQ implicit $rax
|
||||
|
||||
...
|
Loading…
Reference in New Issue