From ce2bcbf8c0e1368cf04e79fa4bfa3c3bc09a3697 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Thu, 18 Oct 2012 15:49:40 +0000 Subject: [PATCH] [ms-inline asm] Move most of the AsmParsing logic in clang back into the MC layer. Use the new ParseMSInlineAsm() API and add an implementation of the MCAsmParserSemaCallback interface. llvm-svn: 166184 --- clang/include/clang/Sema/Sema.h | 1 + clang/lib/Sema/SemaStmtAsm.cpp | 261 ++++++++++++------------------------- clang/test/CodeGen/ms-inline-asm.c | 17 +++ 3 files changed, 99 insertions(+), 180 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index bdc245e..e74c96b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2601,6 +2601,7 @@ public: Expr *AsmString, MultiExprArg Clobbers, SourceLocation RParenLoc); + NamedDecl *LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc); StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, ArrayRef AsmToks, SourceLocation EndLoc); diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 18a8f73..d36afd6 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -24,19 +24,12 @@ #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" @@ -367,55 +360,73 @@ static bool buildMSAsmString(Sema &SemaRef, return false; } -namespace { -enum AsmOpRewriteKind { - AOK_Imm, - AOK_Input, - AOK_Output -}; - -struct AsmOpRewrite { - AsmOpRewriteKind Kind; - llvm::SMLoc Loc; - unsigned Len; +class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback { + Sema *SemaRef; public: - AsmOpRewrite(AsmOpRewriteKind kind, llvm::SMLoc loc, unsigned len) - : Kind(kind), Loc(loc), Len(len) { } + MCAsmParserSemaCallbackImpl(class Sema *Ref) { SemaRef = Ref; } + ~MCAsmParserSemaCallbackImpl() {} + + void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, + void **IdentifierInfoPtr) { + SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc); + NamedDecl *OpDecl = SemaRef->LookupInlineAsmIdentifier(Name, Loc); + DeclarationNameInfo NameInfo(OpDecl->getDeclName(), Loc); + ExprResult OpExpr = SemaRef->BuildDeclarationNameExpr(CXXScopeSpec(), + NameInfo, + OpDecl); + if (OpExpr.isInvalid()) + return 0; + + *IdentifierInfoPtr = static_cast(OpDecl->getIdentifier()); + return static_cast(OpExpr.take()); + } }; +NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc) { + LookupResult Result(*this, &Context.Idents.get(Name), Loc, + Sema::LookupOrdinaryName); + + if (!LookupName(Result, getCurScope())) { + // If we don't find anything, return null; the AsmParser will assume + // it is a label of some sort. + return 0; + } + + if (!Result.isSingleResult()) { + // FIXME: Diagnose result. + return 0; + } + + NamedDecl *ND = Result.getFoundDecl(); + if (isa(ND) || isa(ND)) { + return ND; + } + + // FIXME: Handle other kinds of results? (FieldDecl, etc.) + // FIXME: Diagnose if we find something we can't handle, like a typedef. + return 0; } StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, ArrayRef AsmToks,SourceLocation EndLoc) { - SmallVector Inputs; - SmallVector Outputs; SmallVector Names; - SmallVector InputConstraints; - SmallVector OutputConstraints; - SmallVector Constraints; - unsigned NumOutputs; - unsigned NumInputs; - SmallVector InputExprs; - SmallVector OutputExprs; + SmallVector ConstraintRefs; SmallVector Exprs; - SmallVector Clobbers; - std::set ClobberRegs; - - SmallVector AsmStrRewrites; + SmallVector ClobberRefs; // Empty asm statements don't need to instantiate the AsmParser, etc. - if (AsmToks.empty()) { + if (AsmToks.empty()) { StringRef EmptyAsmStr; MSAsmStmt *NS = new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0, - /*NumInputs*/ 0, Names, Constraints, Exprs, EmptyAsmStr, - Clobbers, EndLoc); + /*NumInputs*/ 0, Names, ConstraintRefs, Exprs, + EmptyAsmStr, ClobberRefs, EndLoc); return Owned(NS); } - std::string AsmString; + std::string AsmString; if (buildMSAsmString(*this, AsmLoc, AsmToks, AsmString)) return StmtError(); @@ -443,7 +454,6 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); OwningPtr TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); - Parser->setParsingInlineAsm(true); // Get the instruction descriptor. const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); @@ -455,152 +465,43 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, 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; - } - - - // 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(); - } - } - - // Set the number of Outputs and Inputs. - NumOutputs = Outputs.size(); - NumInputs = Inputs.size(); - - // Set the unique clobbers. - for (std::set::iterator I = ClobberRegs.begin(), - E = ClobberRegs.end(); I != E; ++I) - Clobbers.push_back(*I); - - // Merge the various outputs and inputs. Output are expected first. - Names.resize(NumOutputs + NumInputs); - Constraints.resize(NumOutputs + NumInputs); - Exprs.resize(NumOutputs + NumInputs); - for (unsigned i = 0; i < NumOutputs; ++i) { - Names[i] = Outputs[i]; - Constraints[i] = OutputConstraints[i]; - Exprs[i] = OutputExprs[i]; - } - for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) { - Names[j] = Inputs[i]; - Constraints[j] = InputConstraints[i]; - Exprs[j] = InputExprs[i]; - } - - // Build the IR assembly string. + unsigned NumOutputs; + unsigned NumInputs; std::string AsmStringIR; - llvm::raw_string_ostream OS(AsmStringIR); - const char *Start = AsmString.c_str(); - for (SmallVectorImpl::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; - } + SmallVector VoidNames; + SmallVector Constraints; + SmallVector VoidExprs; + SmallVector Clobbers; + MCAsmParserSemaCallbackImpl MCAPSI(this); + if (Parser->ParseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, + NumOutputs, NumInputs, VoidNames, Constraints, + VoidExprs, Clobbers, MII, IP, MCAPSI)) + return StmtError(); - // Skip the original expression. - Start = Loc + (*I).Len; + // Build the vector of clobber StringRefs. + unsigned NumClobbers = Clobbers.size(); + ClobberRefs.resize(NumClobbers); + for (unsigned i = 0; i != NumClobbers; ++i) + ClobberRefs[i] = StringRef(Clobbers[i]); + + // Recast the void pointers and build the vector of constraint StringRefs. + unsigned NumExprs = NumOutputs + NumInputs; + assert (VoidNames.size() == NumExprs && "Unexpected number of names!"); + assert (VoidExprs.size() == NumExprs && "Unexpected number of exprs!"); + Names.resize(NumExprs); + ConstraintRefs.resize(NumExprs); + Exprs.resize(NumExprs); + for (unsigned i = 0, e = NumExprs; i != e; ++i) { + Names[i] = static_cast(VoidNames[i]); + ConstraintRefs[i] = StringRef(Constraints[i]); + Exprs[i] = static_cast(VoidExprs[i]); } - // Emit the remainder of the asm string. - const char *AsmEnd = AsmString.c_str() + AsmString.size(); - if (Start != AsmEnd) - OS << StringRef(Start, AsmEnd - Start); - AsmString = OS.str(); + bool IsSimple = NumExprs > 0; MSAsmStmt *NS = - new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, - /*IsVolatile*/ true, AsmToks, NumOutputs, - NumInputs, Names, Constraints, Exprs, AsmString, - Clobbers, EndLoc); + new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, + /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs, + Names, ConstraintRefs, Exprs, AsmStringIR, + ClobberRefs, EndLoc); return Owned(NS); } diff --git a/clang/test/CodeGen/ms-inline-asm.c b/clang/test/CodeGen/ms-inline-asm.c index 387a49c..f16cd81 100644 --- a/clang/test/CodeGen/ms-inline-asm.c +++ b/clang/test/CodeGen/ms-inline-asm.c @@ -114,3 +114,20 @@ unsigned t12(void) { // CHECK: t12 // CHECK: call void asm sideeffect inteldialect "mov eax, $2\0A\09mov $0, eax\0A\09mov eax, $3\0A\09mov $1, eax", "=*m,=*m,*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) nounwind } + +#if 0 +void t13() { + unsigned i = 1, j = 2; +// __asm mov eax, [ebx] +// __asm mov eax, [4*ecx] +// __asm mov eax, [4] +// __asm mov eax, [ebx + 4*ecx] +// __asm mov eax, [ebx + 4*ecx + 4] + __asm mov eax, [i] + __asm mov eax, [i + 4*ecx] + __asm mov eax, [i + 4*ecx + 4] + __asm mov eax, [4*i] + __asm mov eax, [ebx + 4*i] + __asm mov eax, [ebx + 4*i + 4] +} +#endif -- 2.7.4