[ms-inline asm] Use the convertToMapAndConstraints() function in the front-end.

Rework the logic to account for the fact that we no longer create a MCInst.

llvm-svn: 164980
This commit is contained in:
Chad Rosier 2012-10-01 23:45:59 +00:00
parent f4e35dc672
commit bb90c414c4
1 changed files with 72 additions and 62 deletions

View File

@ -458,6 +458,28 @@ static bool buildMSAsmStrings(Sema &SemaRef,
return false;
}
// Check to see if the expression is a substring of the asm operand.
static StringRef getMSInlineAsmExprName(StringRef Name) {
// Strip off the size directives.
// E.g., DWORD PTR [V] -> V
if (Name.startswith("BYTE") || Name.startswith("byte") ||
Name.startswith("WORD") || Name.startswith("word") ||
Name.startswith("DWORD") || Name.startswith("dword") ||
Name.startswith("QWORD") || Name.startswith("qword") ||
Name.startswith("XWORD") || Name.startswith("xword") ||
Name.startswith("XMMWORD") || Name.startswith("xmmword") ||
Name.startswith("YMMWORD") || Name.startswith("ymmword")) {
std::pair< StringRef, StringRef > SplitName = Name.split(' ');
assert((SplitName.second.startswith("PTR") ||
SplitName.second.startswith("ptr")) &&
"Expected PTR/ptr!");
SplitName = SplitName.second.split('[');
SplitName = SplitName.second.split(']');
return SplitName.first;
}
return Name;
}
#define DEF_SIMPLE_MSASM(STR) \
MSAsmStmt *NS = \
new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, \
@ -558,92 +580,80 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
// Match the MCInstr.
unsigned Kind;
unsigned Opcode;
unsigned ErrorInfo;
SmallVector<llvm::MCInst, 2> Instrs;
HadError = TargetParser->MatchInstruction(IDLoc, Kind, Operands, Instrs,
SmallVector<std::pair< unsigned, std::string >, 4> MapAndConstraints;
HadError = TargetParser->MatchInstruction(IDLoc, Operands, *Str.get(), Kind,
Opcode, MapAndConstraints,
ErrorInfo,
/*matchingInlineAsm*/ true);
// If we had an error parsing the operands, fail gracefully.
if (HadError) { DEF_SIMPLE_MSASM(EmptyAsmStr); return Owned(NS); }
// Get the instruction descriptor.
llvm::MCInst Inst = Instrs.back();
const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode());
const llvm::MCInstrDesc &Desc = MII->get(Opcode);
llvm::MCInstPrinter *IP =
TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
// Build the list of clobbers, outputs and inputs.
unsigned NumDefs = Desc.getNumDefs();
for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
if (Operands[i]->isToken() || Operands[i]->isImm())
// Skip immediates.
if (Operands[i]->isImm())
continue;
// FIXME: The getMCInstOperandNum() function does not work with tied
// operands or custom converters.
unsigned NumMCOperands;
unsigned MCIdx = TargetParser->getMCInstOperandNum(Kind, Operands, i,
NumMCOperands);
assert (NumMCOperands && "Expected at least 1 MCOperand!");
for (unsigned j = MCIdx, e = MCIdx + NumMCOperands; j != e; ++j) {
const llvm::MCOperand &Op = Inst.getOperand(j);
// Skip immediates.
if (Op.isImm() || Op.isFPImm())
continue;
// Skip invalid register operands.
if (Op.isReg() && Op.getReg() == 0)
continue;
// Register/Clobber.
if (Op.isReg() && NumDefs && (j < NumDefs)) {
// Register.
if (Operands[i]->isReg()) {
// Clobber.
if (NumDefs && (MapAndConstraints[i-1].first < NumDefs)) {
std::string Reg;
llvm::raw_string_ostream OS(Reg);
IP->printRegName(OS, Op.getReg());
IP->printRegName(OS, Operands[i]->getReg());
StringRef Clobber(OS.str());
if (!Context.getTargetInfo().isValidClobber(Clobber))
return StmtError(
Diag(AsmLoc, diag::err_asm_unknown_register_name) << Clobber);
ClobberRegs.insert(Reg);
continue;
}
// Expr/Input or Output.
if (Op.isExpr()) {
const llvm::MCExpr *Expr = Op.getExpr();
const llvm::MCSymbolRefExpr *SymRef;
if ((SymRef = dyn_cast<llvm::MCSymbolRefExpr>(Expr))) {
StringRef Name = SymRef->getSymbol().getName();
IdentifierInfo *II = getIdentifierInfo(Name, AsmToks,
AsmTokRanges[StrIdx].first,
AsmTokRanges[StrIdx].second);
if (II) {
CXXScopeSpec SS;
UnqualifiedId Id;
SourceLocation Loc;
Id.setIdentifier(II, AsmLoc);
ExprResult Result = ActOnIdExpression(getCurScope(), SS, Loc, Id,
false, false);
if (!Result.isInvalid()) {
// FIXME: Determine the proper constraints.
bool isMemDef = (i == 1) && Desc.mayStore();
if (isMemDef) {
Outputs.push_back(II);
OutputExprs.push_back(Result.take());
OutputExprNames.push_back(Name.str());
OutputExprStrIdx.push_back(StrIdx);
OutputConstraints.push_back("=r");
} else {
Inputs.push_back(II);
InputExprs.push_back(Result.take());
InputExprNames.push_back(Name.str());
InputExprStrIdx.push_back(StrIdx);
InputConstraints.push_back("r");
}
}
}
continue;
}
// Expr/Input or Output.
StringRef Name = getMSInlineAsmExprName(Pieces[StrIdx][i]);
// The expr may be a register.
// E.g., DWORD PTR [eax]
if (Context.getTargetInfo().isValidGCCRegisterName(Name))
continue;
IdentifierInfo *II = getIdentifierInfo(Name, AsmToks,
AsmTokRanges[StrIdx].first,
AsmTokRanges[StrIdx].second);
if (II) {
CXXScopeSpec SS;
UnqualifiedId Id;
SourceLocation Loc;
Id.setIdentifier(II, AsmLoc);
ExprResult Result = ActOnIdExpression(getCurScope(), SS, Loc, Id,
false, false);
if (!Result.isInvalid()) {
// FIXME: Determine the proper constraints.
bool isMemDef = (i == 1) && Desc.mayStore();
if (isMemDef) {
Outputs.push_back(II);
OutputExprs.push_back(Result.take());
OutputExprNames.push_back(Name.str());
OutputExprStrIdx.push_back(StrIdx);
std::string Constraint = "=" + MapAndConstraints[i-1].second;
OutputConstraints.push_back(Constraint);
} else {
Inputs.push_back(II);
InputExprs.push_back(Result.take());
InputExprNames.push_back(Name.str());
InputExprStrIdx.push_back(StrIdx);
InputConstraints.push_back(MapAndConstraints[i-1].second);
}
}
}