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