mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
Three changes:
1. Introduce some enums and accessors in the InlineAsm class that eliminate a ton of magic numbers when handling inline asm SDNode. 2. Add a new MDNodeSDNode selection dag node type that holds a MDNode (shocking!) 3. Add a new argument to ISD::INLINEASM nodes that hold !srcloc metadata, propagating it to the instruction emitter, which drops it. No functionality change. llvm-svn: 100605
This commit is contained in:
parent
0f513e1c22
commit
dde7376e9d
@ -650,6 +650,9 @@ public:
|
||||
/// getSrcValue - Construct a node to track a Value* through the backend.
|
||||
SDValue getSrcValue(const Value *v);
|
||||
|
||||
/// getMDNode - Return an MDNodeSDNode which holds an MDNode.
|
||||
SDValue getMDNode(const MDNode *MD);
|
||||
|
||||
/// getShiftAmountOperand - Return the specified value casted to
|
||||
/// the target's desired shift amount type.
|
||||
SDValue getShiftAmountOperand(SDValue Op);
|
||||
|
@ -499,9 +499,16 @@ namespace ISD {
|
||||
// return values: a chain and a flag result. The inputs are as follows:
|
||||
// Operand #0 : Input chain.
|
||||
// Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string.
|
||||
// Operand #2n+2: A RegisterNode.
|
||||
// Operand #2n+3: A TargetConstant, indicating if the reg is a use/def
|
||||
// Operand #2 : a MDNodeSDNode with the !srcloc metadata.
|
||||
// After this, it is followed by a list of operands with this format:
|
||||
// ConstantSDNode: Flags that encode whether it is a mem or not, the
|
||||
// of operands that follow, etc. See InlineAsm.h.
|
||||
// ... however many operands ...
|
||||
// Operand #last: Optional, an incoming flag.
|
||||
//
|
||||
// The variable width operands are required to represent target addressing
|
||||
// modes as a single "operand", even though they may have multiple
|
||||
// SDOperands.
|
||||
INLINEASM,
|
||||
|
||||
// EH_LABEL - Represents a label in mid basic block used to track
|
||||
@ -542,6 +549,10 @@ namespace ISD {
|
||||
// SRCVALUE - This is a node type that holds a Value* that is used to
|
||||
// make reference to a value in the LLVM IR.
|
||||
SRCVALUE,
|
||||
|
||||
// MDNODE_SDNODE - This is a node that holdes an MDNode*, which is used to
|
||||
// reference metadata in the IR.
|
||||
MDNODE_SDNODE,
|
||||
|
||||
// PCMARKER - This corresponds to the pcmarker intrinsic.
|
||||
PCMARKER,
|
||||
@ -2053,6 +2064,21 @@ public:
|
||||
return N->getOpcode() == ISD::SRCVALUE;
|
||||
}
|
||||
};
|
||||
|
||||
class MDNodeSDNode : public SDNode {
|
||||
const MDNode *MD;
|
||||
friend class SelectionDAG;
|
||||
explicit MDNodeSDNode(const MDNode *md)
|
||||
: SDNode(ISD::MDNODE_SDNODE, DebugLoc(), getSDVTList(MVT::Other)), MD(md) {}
|
||||
public:
|
||||
|
||||
const MDNode *getMD() const { return MD; }
|
||||
|
||||
static bool classof(const MDNodeSDNode *) { return true; }
|
||||
static bool classof(const SDNode *N) {
|
||||
return N->getOpcode() == ISD::MDNODE_SDNODE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class RegisterSDNode : public SDNode {
|
||||
|
@ -146,6 +146,49 @@ public:
|
||||
return V->getValueID() == Value::InlineAsmVal;
|
||||
}
|
||||
|
||||
|
||||
// These are helper methods for dealing with flags in the INLINEASM SDNode
|
||||
// in the backend.
|
||||
|
||||
enum {
|
||||
Op_InputChain = 0,
|
||||
Op_AsmString = 1,
|
||||
Op_MDNode = 2,
|
||||
Op_FirstOperand = 3,
|
||||
|
||||
Kind_RegUse = 1,
|
||||
Kind_RegDef = 2,
|
||||
Kind_Imm = 3,
|
||||
Kind_Mem = 4,
|
||||
Kind_RegDefEarlyClobber = 6,
|
||||
|
||||
Flag_MatchingOperand = 0x80000000
|
||||
};
|
||||
|
||||
static unsigned getFlagWord(unsigned Kind, unsigned NumOps) {
|
||||
assert(((NumOps << 3) & ~0xffff) == 0 && "Too many inline asm operands!");
|
||||
return Kind | (NumOps << 3);
|
||||
}
|
||||
|
||||
/// getFlagWordForMatchingOp - Augment an existing flag word returned by
|
||||
/// getFlagWord with information indicating that this input operand is tied
|
||||
/// to a previous output operand.
|
||||
static unsigned getFlagWordForMatchingOp(unsigned InputFlag,
|
||||
unsigned MatchedOperandNo) {
|
||||
return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16);
|
||||
}
|
||||
|
||||
static unsigned getKind(unsigned Flags) {
|
||||
return Flags & 7;
|
||||
}
|
||||
|
||||
static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;}
|
||||
static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; }
|
||||
static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; }
|
||||
static bool isRegDefEarlyClobberKind(unsigned Flag) {
|
||||
return getKind(Flag) == Kind_RegDefEarlyClobber;
|
||||
}
|
||||
|
||||
/// getNumOperandRegisters - Extract the number of registers field from the
|
||||
/// inline asm operand flag.
|
||||
static unsigned getNumOperandRegisters(unsigned Flag) {
|
||||
@ -155,9 +198,9 @@ public:
|
||||
/// isUseOperandTiedToDef - Return true if the flag of the inline asm
|
||||
/// operand indicates it is an use operand that's matched to a def operand.
|
||||
static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx) {
|
||||
if ((Flag & 0x80000000) == 0)
|
||||
if ((Flag & Flag_MatchingOperand) == 0)
|
||||
return false;
|
||||
Idx = (Flag & ~0x80000000) >> 16;
|
||||
Idx = (Flag & ~Flag_MatchingOperand) >> 16;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -731,12 +731,12 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned,
|
||||
TII->get(TargetOpcode::INLINEASM));
|
||||
|
||||
// Add the asm string as an external symbol operand.
|
||||
const char *AsmStr =
|
||||
cast<ExternalSymbolSDNode>(Node->getOperand(1))->getSymbol();
|
||||
SDValue AsmStrV = Node->getOperand(InlineAsm::Op_AsmString);
|
||||
const char *AsmStr = cast<ExternalSymbolSDNode>(AsmStrV)->getSymbol();
|
||||
MI->addOperand(MachineOperand::CreateES(AsmStr));
|
||||
|
||||
// Add all of the operand registers to the instruction.
|
||||
for (unsigned i = 2; i != NumOps;) {
|
||||
for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
|
||||
unsigned Flags =
|
||||
cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
|
||||
unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
|
||||
@ -744,24 +744,24 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned,
|
||||
MI->addOperand(MachineOperand::CreateImm(Flags));
|
||||
++i; // Skip the ID value.
|
||||
|
||||
switch (Flags & 7) {
|
||||
switch (InlineAsm::getKind(Flags)) {
|
||||
default: llvm_unreachable("Bad flags!");
|
||||
case 2: // Def of register.
|
||||
case InlineAsm::Kind_RegDef:
|
||||
for (; NumVals; --NumVals, ++i) {
|
||||
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
||||
MI->addOperand(MachineOperand::CreateReg(Reg, true));
|
||||
}
|
||||
break;
|
||||
case 6: // Def of earlyclobber register.
|
||||
case InlineAsm::Kind_RegDefEarlyClobber:
|
||||
for (; NumVals; --NumVals, ++i) {
|
||||
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
||||
MI->addOperand(MachineOperand::CreateReg(Reg, true, false, false,
|
||||
false, false, true));
|
||||
}
|
||||
break;
|
||||
case 1: // Use of register.
|
||||
case 3: // Immediate.
|
||||
case 4: // Addressing mode.
|
||||
case InlineAsm::Kind_RegUse: // Use of register.
|
||||
case InlineAsm::Kind_Imm: // Immediate.
|
||||
case InlineAsm::Kind_Mem: // Addressing mode.
|
||||
// The addressing mode has been selected, just add all of the
|
||||
// operands to the machine instruction.
|
||||
for (; NumVals; --NumVals, ++i)
|
||||
|
@ -17,18 +17,19 @@
|
||||
|
||||
#define DEBUG_TYPE "pre-RA-sched"
|
||||
#include "ScheduleDAGSDNodes.h"
|
||||
#include "llvm/InlineAsm.h"
|
||||
#include "llvm/CodeGen/SchedulerRegistry.h"
|
||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/ADT/PriorityQueue.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <climits>
|
||||
using namespace llvm;
|
||||
@ -647,13 +648,14 @@ bool ScheduleDAGRRList::DelayForLiveRegsBottomUp(SUnit *SU,
|
||||
if (Node->getOperand(NumOps-1).getValueType() == MVT::Flag)
|
||||
--NumOps; // Ignore the flag operand.
|
||||
|
||||
for (unsigned i = 2; i != NumOps;) {
|
||||
for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
|
||||
unsigned Flags =
|
||||
cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
|
||||
unsigned NumVals = (Flags & 0xffff) >> 3;
|
||||
unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
|
||||
|
||||
++i; // Skip the ID value.
|
||||
if ((Flags & 7) == 2 || (Flags & 7) == 6) {
|
||||
if (InlineAsm::isRegDefKind(Flags) ||
|
||||
InlineAsm::isRegDefEarlyClobberKind(Flags)) {
|
||||
// Check for def of register or earlyclobber register.
|
||||
for (; NumVals; --NumVals, ++i) {
|
||||
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
||||
|
@ -59,7 +59,8 @@ namespace llvm {
|
||||
if (isa<JumpTableSDNode>(Node)) return true;
|
||||
if (isa<ExternalSymbolSDNode>(Node)) return true;
|
||||
if (isa<BlockAddressSDNode>(Node)) return true;
|
||||
if (Node->getOpcode() == ISD::EntryToken) return true;
|
||||
if (Node->getOpcode() == ISD::EntryToken ||
|
||||
isa<MDNodeSDNode>(Node)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1356,6 +1356,23 @@ SDValue SelectionDAG::getSrcValue(const Value *V) {
|
||||
return SDValue(N, 0);
|
||||
}
|
||||
|
||||
/// getMDNode - Return an MDNodeSDNode which holds an MDNode.
|
||||
SDValue SelectionDAG::getMDNode(const MDNode *MD) {
|
||||
FoldingSetNodeID ID;
|
||||
AddNodeIDNode(ID, ISD::MDNODE_SDNODE, getVTList(MVT::Other), 0, 0);
|
||||
ID.AddPointer(MD);
|
||||
|
||||
void *IP = 0;
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = new (NodeAllocator) MDNodeSDNode(MD);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
}
|
||||
|
||||
|
||||
/// getShiftAmountOperand - Return the specified value casted to
|
||||
/// the target's desired shift amount type.
|
||||
SDValue SelectionDAG::getShiftAmountOperand(SDValue Op) {
|
||||
@ -5559,6 +5576,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
||||
case ISD::PCMARKER: return "PCMarker";
|
||||
case ISD::READCYCLECOUNTER: return "ReadCycleCounter";
|
||||
case ISD::SRCVALUE: return "SrcValue";
|
||||
case ISD::MDNODE_SDNODE: return "MDNode";
|
||||
case ISD::EntryToken: return "EntryToken";
|
||||
case ISD::TokenFactor: return "TokenFactor";
|
||||
case ISD::AssertSext: return "AssertSext";
|
||||
@ -5927,6 +5945,11 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
|
||||
OS << "<" << M->getValue() << ">";
|
||||
else
|
||||
OS << "<null>";
|
||||
} else if (const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(this)) {
|
||||
if (MD->getMD())
|
||||
OS << "<" << MD->getMD() << ">";
|
||||
else
|
||||
OS << "<null>";
|
||||
} else if (const VTSDNode *N = dyn_cast<VTSDNode>(this)) {
|
||||
OS << ":" << N->getVT().getEVTString();
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ namespace {
|
||||
/// AddInlineAsmOperands - Add this value to the specified inlineasm node
|
||||
/// operand list. This adds the code marker, matching input operand index
|
||||
/// (if applicable), and includes the number of values added into it.
|
||||
void AddInlineAsmOperands(unsigned Code,
|
||||
void AddInlineAsmOperands(unsigned Kind,
|
||||
bool HasMatching, unsigned MatchingIdx,
|
||||
SelectionDAG &DAG,
|
||||
std::vector<SDValue> &Ops) const;
|
||||
@ -4871,14 +4871,13 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl,
|
||||
/// AddInlineAsmOperands - Add this value to the specified inlineasm node
|
||||
/// operand list. This adds the code marker and includes the number of
|
||||
/// values added into it.
|
||||
void RegsForValue::AddInlineAsmOperands(unsigned Code,
|
||||
bool HasMatching,unsigned MatchingIdx,
|
||||
void RegsForValue::AddInlineAsmOperands(unsigned Code, bool HasMatching,
|
||||
unsigned MatchingIdx,
|
||||
SelectionDAG &DAG,
|
||||
std::vector<SDValue> &Ops) const {
|
||||
assert(Regs.size() < (1 << 13) && "Too many inline asm outputs!");
|
||||
unsigned Flag = Code | (Regs.size() << 3);
|
||||
unsigned Flag = InlineAsm::getFlagWord(Code, Regs.size());
|
||||
if (HasMatching)
|
||||
Flag |= 0x80000000 | (MatchingIdx << 16);
|
||||
Flag = InlineAsm::getFlagWordForMatchingOp(Flag, MatchingIdx);
|
||||
SDValue Res = DAG.getTargetConstant(Flag, MVT::i32);
|
||||
Ops.push_back(Res);
|
||||
|
||||
@ -5409,6 +5408,11 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) {
|
||||
DAG.getTargetExternalSymbol(IA->getAsmString().c_str(),
|
||||
TLI.getPointerTy()));
|
||||
|
||||
// If we have a !srcloc metadata node associated with it, we want to attach
|
||||
// this to the ultimately generated inline asm machineinstr. To do this, we
|
||||
// pass in the third operand as this (potentially null) inline asm MDNode.
|
||||
const MDNode *SrcLoc = CS.getInstruction()->getMetadata("srcloc");
|
||||
AsmNodeOperands.push_back(DAG.getMDNode(SrcLoc));
|
||||
|
||||
// Loop over all of the inputs, copying the operand values into the
|
||||
// appropriate registers and processing the output regs.
|
||||
@ -5428,8 +5432,8 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) {
|
||||
assert(OpInfo.isIndirect && "Memory output must be indirect operand");
|
||||
|
||||
// Add information to the INLINEASM node to know about this output.
|
||||
unsigned ResOpType = 4/*MEM*/ | (1<<3);
|
||||
AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType,
|
||||
unsigned OpFlags = InlineAsm::getFlagWord(InlineAsm::Kind_Mem, 1);
|
||||
AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlags,
|
||||
TLI.getPointerTy()));
|
||||
AsmNodeOperands.push_back(OpInfo.CallOperand);
|
||||
break;
|
||||
@ -5439,10 +5443,9 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) {
|
||||
|
||||
// Copy the output from the appropriate register. Find a register that
|
||||
// we can use.
|
||||
if (OpInfo.AssignedRegs.Regs.empty()) {
|
||||
if (OpInfo.AssignedRegs.Regs.empty())
|
||||
llvm_report_error("Couldn't allocate output reg for"
|
||||
" constraint '" + OpInfo.ConstraintCode + "'!");
|
||||
}
|
||||
|
||||
// If this is an indirect operand, store through the pointer after the
|
||||
// asm.
|
||||
@ -5459,8 +5462,8 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) {
|
||||
// Add information to the INLINEASM node to know that this register is
|
||||
// set.
|
||||
OpInfo.AssignedRegs.AddInlineAsmOperands(OpInfo.isEarlyClobber ?
|
||||
6 /* EARLYCLOBBER REGDEF */ :
|
||||
2 /* REGDEF */ ,
|
||||
InlineAsm::Kind_RegDefEarlyClobber :
|
||||
InlineAsm::Kind_RegDef,
|
||||
false,
|
||||
0,
|
||||
DAG,
|
||||
@ -5477,27 +5480,25 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) {
|
||||
|
||||
// Scan until we find the definition we already emitted of this operand.
|
||||
// When we find it, create a RegsForValue operand.
|
||||
unsigned CurOp = 2; // The first operand.
|
||||
unsigned CurOp = InlineAsm::Op_FirstOperand;
|
||||
for (; OperandNo; --OperandNo) {
|
||||
// Advance to the next operand.
|
||||
unsigned OpFlag =
|
||||
cast<ConstantSDNode>(AsmNodeOperands[CurOp])->getZExtValue();
|
||||
assert(((OpFlag & 7) == 2 /*REGDEF*/ ||
|
||||
(OpFlag & 7) == 6 /*EARLYCLOBBER REGDEF*/ ||
|
||||
(OpFlag & 7) == 4 /*MEM*/) &&
|
||||
"Skipped past definitions?");
|
||||
assert((InlineAsm::isRegDefKind(OpFlag) ||
|
||||
InlineAsm::isRegDefEarlyClobberKind(OpFlag) ||
|
||||
InlineAsm::isMemKind(OpFlag)) && "Skipped past definitions?");
|
||||
CurOp += InlineAsm::getNumOperandRegisters(OpFlag)+1;
|
||||
}
|
||||
|
||||
unsigned OpFlag =
|
||||
cast<ConstantSDNode>(AsmNodeOperands[CurOp])->getZExtValue();
|
||||
if ((OpFlag & 7) == 2 /*REGDEF*/
|
||||
|| (OpFlag & 7) == 6 /* EARLYCLOBBER REGDEF */) {
|
||||
if (InlineAsm::isRegDefKind(OpFlag) ||
|
||||
InlineAsm::isRegDefEarlyClobberKind(OpFlag)) {
|
||||
// Add (OpFlag&0xffff)>>3 registers to MatchedRegs.
|
||||
if (OpInfo.isIndirect) {
|
||||
if (OpInfo.isIndirect)
|
||||
llvm_report_error("Don't know how to handle tied indirect "
|
||||
"register inputs yet!");
|
||||
}
|
||||
RegsForValue MatchedRegs;
|
||||
MatchedRegs.TLI = &TLI;
|
||||
MatchedRegs.ValueVTs.push_back(InOperandVal.getValueType());
|
||||
@ -5512,22 +5513,23 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) {
|
||||
// Use the produced MatchedRegs object to
|
||||
MatchedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(),
|
||||
Chain, &Flag);
|
||||
MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/,
|
||||
MatchedRegs.AddInlineAsmOperands(InlineAsm::Kind_RegUse,
|
||||
true, OpInfo.getMatchedOperand(),
|
||||
DAG, AsmNodeOperands);
|
||||
break;
|
||||
} else {
|
||||
assert(((OpFlag & 7) == 4) && "Unknown matching constraint!");
|
||||
assert((InlineAsm::getNumOperandRegisters(OpFlag)) == 1 &&
|
||||
"Unexpected number of operands");
|
||||
// Add information to the INLINEASM node to know about this input.
|
||||
// See InlineAsm.h isUseOperandTiedToDef.
|
||||
OpFlag |= 0x80000000 | (OpInfo.getMatchedOperand() << 16);
|
||||
AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlag,
|
||||
TLI.getPointerTy()));
|
||||
AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(InlineAsm::isMemKind(OpFlag) && "Unknown matching constraint!");
|
||||
assert(InlineAsm::getNumOperandRegisters(OpFlag) == 1 &&
|
||||
"Unexpected number of operands");
|
||||
// Add information to the INLINEASM node to know about this input.
|
||||
// See InlineAsm.h isUseOperandTiedToDef.
|
||||
OpFlag = InlineAsm::getFlagWordForMatchingOp(OpFlag,
|
||||
OpInfo.getMatchedOperand());
|
||||
AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlag,
|
||||
TLI.getPointerTy()));
|
||||
AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (OpInfo.ConstraintType == TargetLowering::C_Other) {
|
||||
@ -5543,18 +5545,21 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) {
|
||||
}
|
||||
|
||||
// Add information to the INLINEASM node to know about this input.
|
||||
unsigned ResOpType = 3 /*IMM*/ | (Ops.size() << 3);
|
||||
unsigned ResOpType =
|
||||
InlineAsm::getFlagWord(InlineAsm::Kind_Imm, Ops.size());
|
||||
AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType,
|
||||
TLI.getPointerTy()));
|
||||
AsmNodeOperands.insert(AsmNodeOperands.end(), Ops.begin(), Ops.end());
|
||||
break;
|
||||
} else if (OpInfo.ConstraintType == TargetLowering::C_Memory) {
|
||||
}
|
||||
|
||||
if (OpInfo.ConstraintType == TargetLowering::C_Memory) {
|
||||
assert(OpInfo.isIndirect && "Operand must be indirect to be a mem!");
|
||||
assert(InOperandVal.getValueType() == TLI.getPointerTy() &&
|
||||
"Memory operands expect pointer values");
|
||||
|
||||
// Add information to the INLINEASM node to know about this input.
|
||||
unsigned ResOpType = 4/*MEM*/ | (1<<3);
|
||||
unsigned ResOpType = InlineAsm::getFlagWord(InlineAsm::Kind_Mem, 1);
|
||||
AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType,
|
||||
TLI.getPointerTy()));
|
||||
AsmNodeOperands.push_back(InOperandVal);
|
||||
@ -5577,7 +5582,7 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) {
|
||||
OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(),
|
||||
Chain, &Flag);
|
||||
|
||||
OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/, false, 0,
|
||||
OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind_RegUse, false, 0,
|
||||
DAG, AsmNodeOperands);
|
||||
break;
|
||||
}
|
||||
@ -5585,7 +5590,8 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) {
|
||||
// Add the clobbered value to the operand list, so that the register
|
||||
// allocator is aware that the physreg got clobbered.
|
||||
if (!OpInfo.AssignedRegs.Regs.empty())
|
||||
OpInfo.AssignedRegs.AddInlineAsmOperands(6 /* EARLYCLOBBER REGDEF */,
|
||||
OpInfo.AssignedRegs.AddInlineAsmOperands(
|
||||
InlineAsm::Kind_RegDefEarlyClobber,
|
||||
false, 0, DAG,
|
||||
AsmNodeOperands);
|
||||
break;
|
||||
@ -5593,7 +5599,7 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) {
|
||||
}
|
||||
}
|
||||
|
||||
// Finish up input operands.
|
||||
// Finish up input operands. Set the input chain and add the flag last.
|
||||
AsmNodeOperands[0] = Chain;
|
||||
if (Flag.getNode()) AsmNodeOperands.push_back(Flag);
|
||||
|
||||
|
@ -1333,16 +1333,17 @@ SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops) {
|
||||
std::vector<SDValue> InOps;
|
||||
std::swap(InOps, Ops);
|
||||
|
||||
Ops.push_back(InOps[0]); // input chain.
|
||||
Ops.push_back(InOps[1]); // input asm string.
|
||||
Ops.push_back(InOps[InlineAsm::Op_InputChain]); // 0
|
||||
Ops.push_back(InOps[InlineAsm::Op_AsmString]); // 1
|
||||
Ops.push_back(InOps[InlineAsm::Op_MDNode]); // 2, !srcloc
|
||||
|
||||
unsigned i = 2, e = InOps.size();
|
||||
unsigned i = InlineAsm::Op_FirstOperand, e = InOps.size();
|
||||
if (InOps[e-1].getValueType() == MVT::Flag)
|
||||
--e; // Don't process a flag operand if it is here.
|
||||
|
||||
while (i != e) {
|
||||
unsigned Flags = cast<ConstantSDNode>(InOps[i])->getZExtValue();
|
||||
if ((Flags & 7) != 4 /*MEM*/) {
|
||||
if (!InlineAsm::isMemKind(Flags)) {
|
||||
// Just skip over this operand, copying the operands verbatim.
|
||||
Ops.insert(Ops.end(), InOps.begin()+i,
|
||||
InOps.begin()+i+InlineAsm::getNumOperandRegisters(Flags) + 1);
|
||||
@ -1352,14 +1353,14 @@ SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops) {
|
||||
"Memory operand with multiple values?");
|
||||
// Otherwise, this is a memory operand. Ask the target to select it.
|
||||
std::vector<SDValue> SelOps;
|
||||
if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps)) {
|
||||
if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps))
|
||||
llvm_report_error("Could not match memory address. Inline asm"
|
||||
" failure!");
|
||||
}
|
||||
|
||||
// Add this to the output node.
|
||||
Ops.push_back(CurDAG->getTargetConstant(4/*MEM*/ | (SelOps.size()<< 3),
|
||||
MVT::i32));
|
||||
unsigned NewFlags =
|
||||
InlineAsm::getFlagWord(InlineAsm::Kind_Mem, SelOps.size());
|
||||
Ops.push_back(CurDAG->getTargetConstant(NewFlags, MVT::i32));
|
||||
Ops.insert(Ops.end(), SelOps.begin(), SelOps.end());
|
||||
i += 2;
|
||||
}
|
||||
@ -2045,6 +2046,7 @@ SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable,
|
||||
//case ISD::VALUETYPE:
|
||||
//case ISD::CONDCODE:
|
||||
case ISD::HANDLENODE:
|
||||
case ISD::MDNODE_SDNODE:
|
||||
case ISD::TargetConstant:
|
||||
case ISD::TargetConstantFP:
|
||||
case ISD::TargetConstantPool:
|
||||
|
Loading…
Reference in New Issue
Block a user