aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/SemaStmtAsm.cpp396
1 files changed, 179 insertions, 217 deletions
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index 017cdb90f6..339ff7a953 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -331,34 +331,11 @@ static StringRef getSpelling(Sema &SemaRef, Token AsmTok) {
return Asm;
}
-// Break the AsmString into pieces (i.e., mnemonic and operands).
-static void buildMSAsmPieces(StringRef Asm, std::vector<StringRef> &Pieces) {
- std::pair<StringRef,StringRef> Split = Asm.split(' ');
-
- // Mnemonic
- Pieces.push_back(Split.first);
- Asm = Split.second;
-
- // Operands
- while (!Asm.empty()) {
- Split = Asm.split(", ");
- Pieces.push_back(Split.first);
- Asm = Split.second;
- }
-}
-
-static void buildMSAsmPieces(std::vector<std::string> &AsmStrings,
- std::vector<std::vector<StringRef> > &Pieces) {
- for (unsigned i = 0, e = AsmStrings.size(); i != e; ++i)
- buildMSAsmPieces(AsmStrings[i], Pieces[i]);
-}
-
-// Build the individual assembly instruction(s) and place them in the AsmStrings
-// vector. These strings are fed to the AsmParser. Returns true on error.
-static bool buildMSAsmStrings(Sema &SemaRef,
- SourceLocation AsmLoc,
- ArrayRef<Token> AsmToks,
- std::vector<std::string> &AsmStrings) {
+// Build the inline assembly string. Returns true on error.
+static bool buildMSAsmString(Sema &SemaRef,
+ SourceLocation AsmLoc,
+ ArrayRef<Token> AsmToks,
+ std::string &AsmString) {
assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
SmallString<512> Asm;
@@ -366,18 +343,17 @@ static bool buildMSAsmStrings(Sema &SemaRef,
bool isNewAsm = ((i == 0) ||
AsmToks[i].isAtStartOfLine() ||
AsmToks[i].is(tok::kw_asm));
-
if (isNewAsm) {
- if (i) {
- AsmStrings.push_back(Asm.str());
- Asm.clear();
- }
+ if (i != 0)
+ Asm += "\n\t";
+
if (AsmToks[i].is(tok::kw_asm)) {
i++; // Skip __asm
if (i == e) {
SemaRef.Diag(AsmLoc, diag::err_asm_empty);
return true;
}
+
}
}
@@ -387,47 +363,59 @@ static bool buildMSAsmStrings(Sema &SemaRef,
StringRef Spelling = getSpelling(SemaRef, AsmToks[i]);
Asm += Spelling;
}
- AsmStrings.push_back(Asm.str());
-
+ AsmString = Asm.str();
return false;
}
-#define DEF_SIMPLE_MSASM(STR) \
- MSAsmStmt *NS = \
- new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, \
- /*IsVolatile*/ true, AsmToks, Inputs, Outputs, \
- InputExprs, OutputExprs, STR, Constraints, \
- Clobbers, EndLoc);
+namespace {
+enum AsmOpRewriteKind {
+ AOK_Imm,
+ AOK_Input,
+ AOK_Output
+};
+
+struct AsmOpRewrite {
+ AsmOpRewriteKind Kind;
+ llvm::SMLoc Loc;
+ unsigned Len;
+
+public:
+ AsmOpRewrite(AsmOpRewriteKind kind, llvm::SMLoc loc, unsigned len)
+ : Kind(kind), Loc(loc), Len(len) { }
+};
+
+}
StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
ArrayRef<Token> AsmToks,SourceLocation EndLoc) {
- SmallVector<StringRef, 4> Constraints;
- std::vector<std::string> InputConstraints;
- std::vector<std::string> OutputConstraints;
- SmallVector<StringRef, 4> Clobbers;
- std::set<std::string> ClobberRegs;
-
- // FIXME: Use a struct to hold the various expression information.
SmallVector<IdentifierInfo*, 4> Inputs;
SmallVector<IdentifierInfo*, 4> Outputs;
SmallVector<Expr*, 4> InputExprs;
SmallVector<Expr*, 4> OutputExprs;
- SmallVector<std::string, 4> InputExprNames;
- SmallVector<std::string, 4> OutputExprNames;
- SmallVector<unsigned, 4> InputExprStrIdx;
- SmallVector<unsigned, 4> OutputExprStrIdx;
+ SmallVector<StringRef, 4> Constraints;
+ SmallVector<std::string, 4> InputConstraints;
+ SmallVector<std::string, 4> OutputConstraints;
+
+ SmallVector<StringRef, 4> Clobbers;
+ std::set<std::string> ClobberRegs;
+
+ SmallVector<struct AsmOpRewrite, 4> AsmStrRewrites;
// Empty asm statements don't need to instantiate the AsmParser, etc.
- StringRef EmptyAsmStr;
- if (AsmToks.empty()) { DEF_SIMPLE_MSASM(EmptyAsmStr); return Owned(NS); }
+ if (AsmToks.empty()) {
+ StringRef EmptyAsmStr;
+ MSAsmStmt *NS =
+ new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
+ /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
+ InputExprs, OutputExprs, EmptyAsmStr, Constraints,
+ Clobbers, EndLoc);
+ return Owned(NS);
+ }
- std::vector<std::string> AsmStrings;
- if (buildMSAsmStrings(*this, AsmLoc, AsmToks, AsmStrings))
+ std::string AsmString;
+ if (buildMSAsmString(*this, AsmLoc, AsmToks, AsmString))
return StmtError();
- std::vector<std::vector<StringRef> > Pieces(AsmStrings.size());
- buildMSAsmPieces(AsmStrings, Pieces);
-
// Get the target specific parser.
std::string Error;
const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
@@ -439,113 +427,111 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
OwningPtr<llvm::MCSubtargetInfo>
STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
- for (unsigned StrIdx = 0, e = AsmStrings.size(); StrIdx != e; ++StrIdx) {
- llvm::SourceMgr SrcMgr;
- llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
- llvm::MemoryBuffer *Buffer =
- llvm::MemoryBuffer::getMemBuffer(AsmStrings[StrIdx], "<inline asm>");
-
- // Tell SrcMgr about this buffer, which is what the parser will pick up.
- SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
-
- OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
- OwningPtr<llvm::MCAsmParser>
- Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
- OwningPtr<llvm::MCTargetAsmParser>
- TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
- // Change to the Intel dialect.
- Parser->setAssemblerDialect(1);
- Parser->setTargetParser(*TargetParser.get());
+ llvm::SourceMgr SrcMgr;
+ llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
+ llvm::MemoryBuffer *Buffer =
+ llvm::MemoryBuffer::getMemBuffer(AsmString, "<inline asm>");
+
+ // Tell SrcMgr about this buffer, which is what the parser will pick up.
+ SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
+
+ OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
+ OwningPtr<llvm::MCAsmParser>
+ Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
+ OwningPtr<llvm::MCTargetAsmParser>
+ TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
Parser->setParsingInlineAsm(true);
- // Prime the lexer.
- Parser->Lex();
-
- // Parse the opcode.
- StringRef IDVal;
- Parser->ParseIdentifier(IDVal);
-
- // Canonicalize the opcode to lower case.
- SmallString<128> OpcodeStr;
- for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
- OpcodeStr.push_back(tolower(IDVal[i]));
- // FIXME: Convert to a StmtError.
- assert(TargetParser->mnemonicIsValid(OpcodeStr) && "Invalid mnemonic!");
-
- // Parse the operands.
- llvm::SMLoc IDLoc;
- SmallVector<llvm::MCParsedAsmOperand*, 8> Operands;
- bool HadError = TargetParser->ParseInstruction(OpcodeStr.str(), IDLoc,
- Operands);
- // If we had an error parsing the operands, fail gracefully.
- if (HadError) { DEF_SIMPLE_MSASM(EmptyAsmStr); return Owned(NS); }
-
- // Match the MCInstr.
- unsigned Opcode;
- unsigned ErrorInfo;
- HadError = TargetParser->MatchAndEmitInstruction(IDLoc, Opcode, Operands,
- *Str.get(), 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.
- const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
- 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) {
- // Skip immediates.
- if (Operands[i]->isImm())
- continue;
-
- // Register.
- if (Operands[i]->isReg()) {
- // Clobber.
- if (NumDefs && (Operands[i]->getMCOperandNum() < NumDefs)) {
- std::string Reg;
- llvm::raw_string_ostream OS(Reg);
- 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);
+ // Get the instruction descriptor.
+ const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
+ llvm::MCInstPrinter *IP =
+ TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
+
+ // Change to the Intel dialect.
+ Parser->setAssemblerDialect(1);
+ Parser->setTargetParser(*TargetParser.get());
+ Parser->setParsingInlineAsm(true);
+
+ // Prime the lexer.
+ Parser->Lex();
+
+ // While we have input, parse each statement.
+ unsigned InputIdx = 0;
+ unsigned OutputIdx = 0;
+ while (Parser->getLexer().isNot(llvm::AsmToken::Eof)) {
+ if (Parser->ParseStatement()) {
+ // FIXME: The AsmParser should report errors, but we could potentially be
+ // more verbose here.
+ break;
+ }
+
+ if (Parser->isInstruction()) {
+ const llvm::MCInstrDesc &Desc = MII->get(Parser->getOpcode());
+
+ // Build the list of clobbers, outputs and inputs.
+ for (unsigned i = 1, e = Parser->getNumParsedOperands(); i != e; ++i) {
+ llvm::MCParsedAsmOperand &Operand = Parser->getParsedOperand(i);
+
+ // Immediate.
+ if (Operand.isImm()) {
+ AsmStrRewrites.push_back(AsmOpRewrite(AOK_Imm,
+ Operand.getStartLoc(),
+ Operand.getNameLen()));
+ continue;
}
- continue;
- }
- // Expr/Input or Output.
- StringRef Name = Pieces[StrIdx][i];
- if (IdentifierInfo *II = &Context.Idents.get(Name)) {
- CXXScopeSpec SS;
- UnqualifiedId Id;
- SourceLocation Loc;
- Id.setIdentifier(II, AsmLoc);
- ExprResult Result = ActOnIdExpression(getCurScope(), SS, Loc, Id,
- false, false);
- if (!Result.isInvalid()) {
- 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 = "=" + Operands[i]->getConstraint().str();
- 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(Operands[i]->getConstraint());
+
+ // Register operand.
+ if (Operand.isReg()) {
+ unsigned NumDefs = Desc.getNumDefs();
+ // Clobber.
+ if (NumDefs && Operand.getMCOperandNum() < NumDefs) {
+ std::string Reg;
+ llvm::raw_string_ostream OS(Reg);
+ IP->printRegName(OS, Operand.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.
+ StringRef Name = Operand.getName();
+ if (IdentifierInfo *II = &Context.Idents.get(Name)) {
+ CXXScopeSpec SS;
+ UnqualifiedId Id;
+ SourceLocation Loc;
+ Id.setIdentifier(II, AsmLoc);
+ ExprResult Result = ActOnIdExpression(getCurScope(), SS, Loc, Id,
+ false, false);
+ if (!Result.isInvalid()) {
+ bool isOutput = (i == 1) && Desc.mayStore();
+ if (isOutput) {
+ std::string Constraint = "=";
+ ++InputIdx;
+ Outputs.push_back(II);
+ OutputExprs.push_back(Result.take());
+ Constraint += Operand.getConstraint().str();
+ OutputConstraints.push_back(Constraint);
+ AsmStrRewrites.push_back(AsmOpRewrite(AOK_Output,
+ Operand.getStartLoc(),
+ Operand.getNameLen()));
+ } else {
+ Inputs.push_back(II);
+ InputExprs.push_back(Result.take());
+ InputConstraints.push_back(Operand.getConstraint().str());
+ AsmStrRewrites.push_back(AsmOpRewrite(AOK_Input,
+ Operand.getStartLoc(),
+ Operand.getNameLen()));
+ }
}
}
}
+ Parser->freeParsedOperands();
}
}
for (std::set<std::string>::iterator I = ClobberRegs.begin(),
@@ -554,75 +540,51 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
// Merge the output and input constraints. Output constraints are expected
// first.
- for (std::vector<std::string>::iterator I = OutputConstraints.begin(),
+ for (SmallVectorImpl<std::string>::iterator I = OutputConstraints.begin(),
E = OutputConstraints.end(); I != E; ++I)
Constraints.push_back(*I);
- for (std::vector<std::string>::iterator I = InputConstraints.begin(),
+ for (SmallVectorImpl<std::string>::iterator I = InputConstraints.begin(),
E = InputConstraints.end(); I != E; ++I)
Constraints.push_back(*I);
- // Enumerate the AsmString expressions.
- unsigned OpNum = 0;
- for (unsigned i = 0, e = OutputExprNames.size(); i != e; ++i, ++OpNum) {
- unsigned StrIdx = OutputExprStrIdx[i];
- // Iterate over the assembly instruction pieces, skipping the mnemonic.
- for (unsigned j = 1, f = Pieces[StrIdx].size(); j != f; ++j) {
- // If the operand and the expression name match, then rewrite the operand.
- if (OutputExprNames[i] == Pieces[StrIdx][j]) {
- SmallString<32> Res;
- llvm::raw_svector_ostream OS(Res);
- OS << '$' << OpNum;
- OutputExprNames[i] = OS.str();
- Pieces[StrIdx][j] = OutputExprNames[i];
- break;
- }
- }
- }
- for (unsigned i = 0, e = InputExprNames.size(); i != e; ++i, ++OpNum) {
- unsigned StrIdx = InputExprStrIdx[i];
- // Iterate over the assembly instruction pieces, skipping the mnemonic.
- for (unsigned j = 1, f = Pieces[StrIdx].size(); j != f; ++j) {
- // If the operand and the expression name match, then rewrite the operand.
- if (InputExprNames[i] == Pieces[StrIdx][j]) {
- SmallString<32> Res;
- llvm::raw_svector_ostream OS(Res);
- OS << '$' << OpNum;
- InputExprNames[i] = OS.str();
- Pieces[StrIdx][j] = InputExprNames[i];
- break;
- }
+ // Build the IR assembly string.
+ std::string AsmStringIR;
+ llvm::raw_string_ostream OS(AsmStringIR);
+ const char *Start = AsmString.c_str();
+ for (SmallVectorImpl<struct AsmOpRewrite>::iterator I = AsmStrRewrites.begin(),
+ E = AsmStrRewrites.end(); I != E; ++I) {
+ const char *Loc = (*I).Loc.getPointer();
+
+ // Emit everything up to the immediate/expression.
+ OS << StringRef(Start, Loc - Start);
+
+ // Rewrite expressions in $N notation.
+ switch ((*I).Kind) {
+ case AOK_Imm:
+ OS << Twine("$$") + StringRef(Loc, (*I).Len);
+ break;
+ case AOK_Input:
+ OS << '$';
+ OS << InputIdx++;
+ break;
+ case AOK_Output:
+ OS << '$';
+ OS << OutputIdx++;
+ break;
}
- }
-
- // Emit the IR assembly string.
- std::string AsmString;
- for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
- // Skip empty asm stmts.
- if (Pieces[i].empty()) continue;
-
- if (i > 0)
- AsmString += "\n\t";
- // Emit the mnemonic.
- AsmString += Pieces[i][0];
- if (Pieces[i].size() > 1)
- AsmString += ' ';
-
- // Emit the operands adding $$ to constants.
- for (unsigned j = 1, f = Pieces[i].size(); j != f; ++j) {
- if (j > 1) AsmString += ", ";
- unsigned Val;
- if (!Pieces[i][j].getAsInteger(0, Val))
- AsmString += "$$";
-
- AsmString += Pieces[i][j];
- }
+ // Skip the original expression.
+ Start = Loc + (*I).Len;
}
+ // Emit the remainder of the asm string.
+ const char *AsmEnd = AsmString.c_str() + AsmString.size();
+ if (Start != AsmEnd)
+ OS << StringRef(Start, AsmEnd - Start);
- bool IsSimple = Inputs.size() != 0 || Outputs.size() != 0;
+ AsmString = OS.str();
MSAsmStmt *NS =
- new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
+ new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ false,
/*IsVolatile*/ true, AsmToks, Inputs, Outputs,
InputExprs, OutputExprs, AsmString, Constraints,
Clobbers, EndLoc);