+ for (unsigned i = 0, e = IDVal.size(); i != e; ++i) + Opcode.push_back(tolower(IDVal[i]));
Hey Chad, sorry for commenting on this rather old email, but this use of 'i' as a variable name inside a loop whose index variable is already 'i' seems questionable, especially since you're using 'j' for another inner loop. I discovered this because GCC just gave me an odd warning over it: SemaStmtAsm.cpp:594:63: warning: name lookup of ‘i’ changed [enabled by default] SemaStmtAsm.cpp:509:17: warning: matches this ‘i’ under ISO standard rules [enabled by default] SemaStmtAsm.cpp:536:19: warning: matches this ‘i’ under old rules [enabled by default] IMO this warning is pointless, but nonetheless, I think it would be good to change the loop variable to be 'j'. --Sean Silva On Fri, Aug 17, 2012 at 5:19 PM, Chad Rosier <[email protected]> wrote: > Author: mcrosier > Date: Fri Aug 17 16:19:40 2012 > New Revision: 162132 > > URL: http://llvm.org/viewvc/llvm-project?rev=162132&view=rev > Log: > [ms-inline asm] Extract AsmStmt handling into a separate file, so as to not > pollute SemaStmt with extraneous asm handling logic. > > Added: > cfe/trunk/lib/Sema/SemaStmtAsm.cpp > Modified: > cfe/trunk/lib/Sema/CMakeLists.txt > cfe/trunk/lib/Sema/SemaStmt.cpp > > Modified: cfe/trunk/lib/Sema/CMakeLists.txt > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=162132&r1=162131&r2=162132&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/CMakeLists.txt (original) > +++ cfe/trunk/lib/Sema/CMakeLists.txt Fri Aug 17 16:19:40 2012 > @@ -39,6 +39,7 @@ > SemaOverload.cpp > SemaPseudoObject.cpp > SemaStmt.cpp > + SemaStmtAsm.cpp > SemaStmtAttr.cpp > SemaTemplate.cpp > SemaTemplateDeduction.cpp > > Modified: cfe/trunk/lib/Sema/SemaStmt.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=162132&r1=162131&r2=162132&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) > +++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Aug 17 16:19:40 2012 > @@ -28,27 +28,10 @@ > #include "clang/Lex/Preprocessor.h" > #include "clang/Basic/TargetInfo.h" > #include "llvm/ADT/ArrayRef.h" > -#include "llvm/ADT/BitVector.h" > #include "llvm/ADT/STLExtras.h" > #include "llvm/ADT/SmallPtrSet.h" > #include "llvm/ADT/SmallString.h" > #include "llvm/ADT/SmallVector.h" > -#include "llvm/ADT/Triple.h" > -#include "llvm/MC/MCAsmInfo.h" > -#include "llvm/MC/MCContext.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/MCTargetAsmParser.h" > -#include "llvm/MC/MCParser/MCAsmLexer.h" > -#include "llvm/MC/MCParser/MCAsmParser.h" > -#include "llvm/Support/SourceMgr.h" > -#include "llvm/Support/TargetRegistry.h" > -#include "llvm/Support/TargetSelect.h" > using namespace clang; > using namespace sema; > > @@ -2485,600 +2468,6 @@ > return Owned(Result); > } > > -/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they > silently > -/// ignore "noop" casts in places where an lvalue is required by an inline > asm. > -/// We emulate this behavior when -fheinous-gnu-extensions is specified, but > -/// provide a strong guidance to not use it. > -/// > -/// This method checks to see if the argument is an acceptable l-value and > -/// returns false if it is a case we can handle. > -static bool CheckAsmLValue(const Expr *E, Sema &S) { > - // Type dependent expressions will be checked during instantiation. > - if (E->isTypeDependent()) > - return false; > - > - if (E->isLValue()) > - return false; // Cool, this is an lvalue. > - > - // Okay, this is not an lvalue, but perhaps it is the result of a cast > that we > - // are supposed to allow. > - const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); > - if (E != E2 && E2->isLValue()) { > - if (!S.getLangOpts().HeinousExtensions) > - S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) > - << E->getSourceRange(); > - else > - S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) > - << E->getSourceRange(); > - // Accept, even if we emitted an error diagnostic. > - return false; > - } > - > - // None of the above, just randomly invalid non-lvalue. > - return true; > -} > - > -/// isOperandMentioned - Return true if the specified operand # is mentioned > -/// anywhere in the decomposed asm string. > -static bool isOperandMentioned(unsigned OpNo, > - ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) { > - for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { > - const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; > - if (!Piece.isOperand()) continue; > - > - // If this is a reference to the input and if the input was the smaller > - // one, then we have to reject this asm. > - if (Piece.getOperandNo() == OpNo) > - return true; > - } > - return false; > -} > - > -StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, > - bool IsVolatile, unsigned NumOutputs, > - unsigned NumInputs, IdentifierInfo **Names, > - MultiExprArg constraints, MultiExprArg exprs, > - Expr *asmString, MultiExprArg clobbers, > - SourceLocation RParenLoc, bool MSAsm) { > - unsigned NumClobbers = clobbers.size(); > - StringLiteral **Constraints = > - reinterpret_cast<StringLiteral**>(constraints.get()); > - Expr **Exprs = exprs.get(); > - StringLiteral *AsmString = cast<StringLiteral>(asmString); > - StringLiteral **Clobbers = > reinterpret_cast<StringLiteral**>(clobbers.get()); > - > - SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; > - > - // The parser verifies that there is a string literal here. > - if (!AsmString->isAscii()) > - return > StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) > - << AsmString->getSourceRange()); > - > - for (unsigned i = 0; i != NumOutputs; i++) { > - StringLiteral *Literal = Constraints[i]; > - if (!Literal->isAscii()) > - return > StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) > - << Literal->getSourceRange()); > - > - StringRef OutputName; > - if (Names[i]) > - OutputName = Names[i]->getName(); > - > - TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); > - if (!Context.getTargetInfo().validateOutputConstraint(Info)) > - return StmtError(Diag(Literal->getLocStart(), > - diag::err_asm_invalid_output_constraint) > - << Info.getConstraintStr()); > - > - // Check that the output exprs are valid lvalues. > - Expr *OutputExpr = Exprs[i]; > - if (CheckAsmLValue(OutputExpr, *this)) { > - return StmtError(Diag(OutputExpr->getLocStart(), > - diag::err_asm_invalid_lvalue_in_output) > - << OutputExpr->getSourceRange()); > - } > - > - OutputConstraintInfos.push_back(Info); > - } > - > - SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; > - > - for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { > - StringLiteral *Literal = Constraints[i]; > - if (!Literal->isAscii()) > - return > StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) > - << Literal->getSourceRange()); > - > - StringRef InputName; > - if (Names[i]) > - InputName = Names[i]->getName(); > - > - TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); > - if > (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), > - NumOutputs, Info)) { > - return StmtError(Diag(Literal->getLocStart(), > - diag::err_asm_invalid_input_constraint) > - << Info.getConstraintStr()); > - } > - > - Expr *InputExpr = Exprs[i]; > - > - // Only allow void types for memory constraints. > - if (Info.allowsMemory() && !Info.allowsRegister()) { > - if (CheckAsmLValue(InputExpr, *this)) > - return StmtError(Diag(InputExpr->getLocStart(), > - diag::err_asm_invalid_lvalue_in_input) > - << Info.getConstraintStr() > - << InputExpr->getSourceRange()); > - } > - > - if (Info.allowsRegister()) { > - if (InputExpr->getType()->isVoidType()) { > - return StmtError(Diag(InputExpr->getLocStart(), > - diag::err_asm_invalid_type_in_input) > - << InputExpr->getType() << Info.getConstraintStr() > - << InputExpr->getSourceRange()); > - } > - } > - > - ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); > - if (Result.isInvalid()) > - return StmtError(); > - > - Exprs[i] = Result.take(); > - InputConstraintInfos.push_back(Info); > - } > - > - // Check that the clobbers are valid. > - for (unsigned i = 0; i != NumClobbers; i++) { > - StringLiteral *Literal = Clobbers[i]; > - if (!Literal->isAscii()) > - return > StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) > - << Literal->getSourceRange()); > - > - StringRef Clobber = Literal->getString(); > - > - if (!Context.getTargetInfo().isValidClobber(Clobber)) > - return StmtError(Diag(Literal->getLocStart(), > - diag::err_asm_unknown_register_name) << Clobber); > - } > - > - AsmStmt *NS = > - new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm, > - NumOutputs, NumInputs, Names, Constraints, Exprs, > - AsmString, NumClobbers, Clobbers, RParenLoc); > - // Validate the asm string, ensuring it makes sense given the operands we > - // have. > - SmallVector<AsmStmt::AsmStringPiece, 8> Pieces; > - unsigned DiagOffs; > - if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { > - Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) > - << AsmString->getSourceRange(); > - return StmtError(); > - } > - > - // Validate tied input operands for type mismatches. > - for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { > - TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; > - > - // If this is a tied constraint, verify that the output and input have > - // either exactly the same type, or that they are int/ptr operands with > the > - // same size (int/long, int*/long, are ok etc). > - if (!Info.hasTiedOperand()) continue; > - > - unsigned TiedTo = Info.getTiedOperand(); > - unsigned InputOpNo = i+NumOutputs; > - Expr *OutputExpr = Exprs[TiedTo]; > - Expr *InputExpr = Exprs[InputOpNo]; > - > - if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) > - continue; > - > - QualType InTy = InputExpr->getType(); > - QualType OutTy = OutputExpr->getType(); > - if (Context.hasSameType(InTy, OutTy)) > - continue; // All types can be tied to themselves. > - > - // Decide if the input and output are in the same domain (integer/ptr or > - // floating point. > - enum AsmDomain { > - AD_Int, AD_FP, AD_Other > - } InputDomain, OutputDomain; > - > - if (InTy->isIntegerType() || InTy->isPointerType()) > - InputDomain = AD_Int; > - else if (InTy->isRealFloatingType()) > - InputDomain = AD_FP; > - else > - InputDomain = AD_Other; > - > - if (OutTy->isIntegerType() || OutTy->isPointerType()) > - OutputDomain = AD_Int; > - else if (OutTy->isRealFloatingType()) > - OutputDomain = AD_FP; > - else > - OutputDomain = AD_Other; > - > - // They are ok if they are the same size and in the same domain. This > - // allows tying things like: > - // void* to int* > - // void* to int if they are the same size. > - // double to long double if they are the same size. > - // > - uint64_t OutSize = Context.getTypeSize(OutTy); > - uint64_t InSize = Context.getTypeSize(InTy); > - if (OutSize == InSize && InputDomain == OutputDomain && > - InputDomain != AD_Other) > - continue; > - > - // If the smaller input/output operand is not mentioned in the asm > string, > - // then we can promote the smaller one to a larger input and the asm > string > - // won't notice. > - bool SmallerValueMentioned = false; > - > - // If this is a reference to the input and if the input was the smaller > - // one, then we have to reject this asm. > - if (isOperandMentioned(InputOpNo, Pieces)) { > - // This is a use in the asm string of the smaller operand. Since we > - // codegen this by promoting to a wider value, the asm will get printed > - // "wrong". > - SmallerValueMentioned |= InSize < OutSize; > - } > - if (isOperandMentioned(TiedTo, Pieces)) { > - // If this is a reference to the output, and if the output is the > larger > - // value, then it's ok because we'll promote the input to the larger > type. > - SmallerValueMentioned |= OutSize < InSize; > - } > - > - // If the smaller value wasn't mentioned in the asm string, and if the > - // output was a register, just extend the shorter one to the size of the > - // larger one. > - if (!SmallerValueMentioned && InputDomain != AD_Other && > - OutputConstraintInfos[TiedTo].allowsRegister()) > - continue; > - > - // Either both of the operands were mentioned or the smaller one was > - // mentioned. One more special case that we'll allow: if the tied input > is > - // integer, unmentioned, and is a constant, then we'll allow truncating > it > - // down to the size of the destination. > - if (InputDomain == AD_Int && OutputDomain == AD_Int && > - !isOperandMentioned(InputOpNo, Pieces) && > - InputExpr->isEvaluatable(Context)) { > - CastKind castKind = > - (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); > - InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); > - Exprs[InputOpNo] = InputExpr; > - NS->setInputExpr(i, InputExpr); > - continue; > - } > - > - Diag(InputExpr->getLocStart(), > - diag::err_asm_tying_incompatible_types) > - << InTy << OutTy << OutputExpr->getSourceRange() > - << InputExpr->getSourceRange(); > - return StmtError(); > - } > - > - return Owned(NS); > -} > - > -// isMSAsmKeyword - Return true if this is an MS-style inline asm keyword. > These > -// require special handling. > -static bool isMSAsmKeyword(StringRef Name) { > - bool Ret = llvm::StringSwitch<bool>(Name) > - .Cases("EVEN", "ALIGN", true) // Alignment directives. > - .Cases("LENGTH", "SIZE", "TYPE", true) // Type and variable sizes. > - .Case("_emit", true) // _emit Pseudoinstruction. > - .Default(false); > - return Ret; > -} > - > -static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { > - StringRef Asm; > - SmallString<512> TokenBuf; > - TokenBuf.resize(512); > - bool StringInvalid = false; > - Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); > - assert (!StringInvalid && "Expected valid string!"); > - return Asm; > -} > - > -static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple, > - SourceLocation AsmLoc, > - ArrayRef<Token> AsmToks, > - const TargetInfo &TI, > - std::vector<llvm::BitVector> &AsmRegs, > - std::vector<llvm::BitVector> &AsmNames, > - std::vector<std::string> &AsmStrings) { > - assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); > - > - // Assume simple asm stmt until we parse a non-register identifer (or we > just > - // need to bail gracefully). > - IsSimple = true; > - > - SmallString<512> Asm; > - unsigned NumAsmStrings = 0; > - for (unsigned i = 0, e = AsmToks.size(); i != e; ++i) { > - > - // Determine if this should be considered a new asm. > - bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || > - AsmToks[i].is(tok::kw_asm); > - > - // Emit the previous asm string. > - if (i && isNewAsm) { > - AsmStrings[NumAsmStrings++] = Asm.c_str(); > - if (AsmToks[i].is(tok::kw_asm)) { > - ++i; // Skip __asm > - assert (i != e && "Expected another token."); > - } > - } > - > - // Start a new asm string with the opcode. > - if (isNewAsm) { > - AsmRegs[NumAsmStrings].resize(AsmToks.size()); > - AsmNames[NumAsmStrings].resize(AsmToks.size()); > - > - StringRef Piece = AsmToks[i].getIdentifierInfo()->getName(); > - // MS-style inline asm keywords require special handling. > - if (isMSAsmKeyword(Piece)) > - IsSimple = false; > - > - // TODO: Verify this is a valid opcode. > - Asm = Piece; > - continue; > - } > - > - if (i && AsmToks[i].hasLeadingSpace()) > - Asm += ' '; > - > - // Check the operand(s). > - switch (AsmToks[i].getKind()) { > - default: > - IsSimple = false; > - Asm += getSpelling(SemaRef, AsmToks[i]); > - break; > - case tok::comma: Asm += ","; break; > - case tok::colon: Asm += ":"; break; > - case tok::l_square: Asm += "["; break; > - case tok::r_square: Asm += "]"; break; > - case tok::l_brace: Asm += "{"; break; > - case tok::r_brace: Asm += "}"; break; > - case tok::numeric_constant: > - Asm += getSpelling(SemaRef, AsmToks[i]); > - break; > - case tok::identifier: { > - IdentifierInfo *II = AsmToks[i].getIdentifierInfo(); > - StringRef Name = II->getName(); > - > - // Valid register? > - if (TI.isValidGCCRegisterName(Name)) { > - AsmRegs[NumAsmStrings].set(i); > - Asm += Name; > - break; > - } > - > - IsSimple = false; > - > - // MS-style inline asm keywords require special handling. > - if (isMSAsmKeyword(Name)) { > - IsSimple = false; > - Asm += Name; > - break; > - } > - > - // FIXME: Why are we missing this segment register? > - if (Name == "fs") { > - Asm += Name; > - break; > - } > - > - // Lookup the identifier. > - // TODO: Someone with more experience with clang should verify this the > - // proper way of doing a symbol lookup. > - DeclarationName DeclName(II); > - Scope *CurScope = SemaRef.getCurScope(); > - LookupResult R(SemaRef, DeclName, AsmLoc, Sema::LookupOrdinaryName); > - if (!SemaRef.LookupName(R, CurScope, false/*AllowBuiltinCreation*/)) > - break; > - > - assert (R.isSingleResult() && "Expected a single result?!"); > - NamedDecl *Decl = R.getFoundDecl(); > - switch (Decl->getKind()) { > - default: > - assert(0 && "Unknown decl kind."); > - break; > - case Decl::Var: { > - case Decl::ParmVar: > - AsmNames[NumAsmStrings].set(i); > - > - VarDecl *Var = cast<VarDecl>(Decl); > - QualType Ty = Var->getType(); > - (void)Ty; // Avoid warning. > - // TODO: Patch identifier with valid operand. One potential idea is > to > - // probe the backend with type information to guess the possible > - // operand. > - break; > - } > - } > - break; > - } > - } > - } > - > - // Emit the final (and possibly only) asm string. > - AsmStrings[NumAsmStrings] = Asm.c_str(); > -} > - > -// Build the unmodified MSAsmString. > -static std::string buildMSAsmString(Sema &SemaRef, > - ArrayRef<Token> AsmToks, > - unsigned &NumAsmStrings) { > - assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); > - NumAsmStrings = 0; > - > - SmallString<512> Asm; > - for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { > - bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || > - AsmToks[i].is(tok::kw_asm); > - > - if (isNewAsm) { > - ++NumAsmStrings; > - if (i) > - Asm += '\n'; > - if (AsmToks[i].is(tok::kw_asm)) { > - i++; // Skip __asm > - assert (i != e && "Expected another token"); > - } > - } > - > - if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) > - Asm += ' '; > - > - Asm += getSpelling(SemaRef, AsmToks[i]); > - } > - return Asm.c_str(); > -} > - > -StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, > - SourceLocation LBraceLoc, > - ArrayRef<Token> AsmToks, > - SourceLocation EndLoc) { > - // MS-style inline assembly is not fully supported, so emit a warning. > - Diag(AsmLoc, diag::warn_unsupported_msasm); > - SmallVector<StringRef,4> Clobbers; > - std::set<std::string> ClobberRegs; > - SmallVector<IdentifierInfo*, 4> Inputs; > - SmallVector<IdentifierInfo*, 4> Outputs; > - > - // Empty asm statements don't need to instantiate the AsmParser, etc. > - if (AsmToks.empty()) { > - StringRef AsmString; > - MSAsmStmt *NS = > - new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, > - /*IsVolatile*/ true, AsmToks, Inputs, Outputs, > - AsmString, Clobbers, EndLoc); > - return Owned(NS); > - } > - > - unsigned NumAsmStrings; > - std::string AsmString = buildMSAsmString(*this, AsmToks, NumAsmStrings); > - > - bool IsSimple; > - std::vector<llvm::BitVector> Regs; > - std::vector<llvm::BitVector> Names; > - std::vector<std::string> PatchedAsmStrings; > - > - Regs.resize(NumAsmStrings); > - Names.resize(NumAsmStrings); > - PatchedAsmStrings.resize(NumAsmStrings); > - > - // Rewrite operands to appease the AsmParser. > - patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks, > - Context.getTargetInfo(), Regs, Names, PatchedAsmStrings); > - > - // patchMSAsmStrings doesn't correctly patch non-simple asm statements. > - if (!IsSimple) { > - MSAsmStmt *NS = > - new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, > - /*IsVolatile*/ true, AsmToks, Inputs, Outputs, > - AsmString, Clobbers, EndLoc); > - return Owned(NS); > - } > - > - // Initialize targets and assembly printers/parsers. > - llvm::InitializeAllTargetInfos(); > - llvm::InitializeAllTargetMCs(); > - llvm::InitializeAllAsmParsers(); > - > - // Get the target specific parser. > - std::string Error; > - const std::string &TT = Context.getTargetInfo().getTriple().getTriple(); > - const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, > Error)); > - > - OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); > - OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); > - OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); > - OwningPtr<llvm::MCSubtargetInfo> > - STI(TheTarget->createMCSubtargetInfo(TT, "", "")); > - > - for (unsigned i = 0, e = PatchedAsmStrings.size(); i != e; ++i) { > - llvm::SourceMgr SrcMgr; > - llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); > - llvm::MemoryBuffer *Buffer = > - llvm::MemoryBuffer::getMemBuffer(PatchedAsmStrings[i], "<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()); > - > - // Prime the lexer. > - Parser->Lex(); > - > - // Parse the opcode. > - StringRef IDVal; > - Parser->ParseIdentifier(IDVal); > - > - // Canonicalize the opcode to lower case. > - SmallString<128> Opcode; > - for (unsigned i = 0, e = IDVal.size(); i != e; ++i) > - Opcode.push_back(tolower(IDVal[i])); > - > - // Parse the operands. > - llvm::SMLoc IDLoc; > - SmallVector<llvm::MCParsedAsmOperand*, 8> Operands; > - bool HadError = TargetParser->ParseInstruction(Opcode.str(), IDLoc, > - Operands); > - assert (!HadError && "Unexpected error parsing instruction"); > - > - // Match the MCInstr. > - SmallVector<llvm::MCInst, 2> Instrs; > - HadError = TargetParser->MatchInstruction(IDLoc, Operands, Instrs); > - assert (!HadError && "Unexpected error matching instruction"); > - assert ((Instrs.size() == 1) && "Expected only a single instruction."); > - > - // Get the instruction descriptor. > - llvm::MCInst Inst = Instrs[0]; > - const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); > - const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode()); > - llvm::MCInstPrinter *IP = > - TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); > - > - // Build the list of clobbers. > - for (unsigned i = 0, e = Desc.getNumDefs(); i != e; ++i) { > - const llvm::MCOperand &Op = Inst.getOperand(i); > - if (!Op.isReg()) > - continue; > - > - std::string Reg; > - llvm::raw_string_ostream OS(Reg); > - IP->printRegName(OS, Op.getReg()); > - > - StringRef Clobber(OS.str()); > - if (!Context.getTargetInfo().isValidClobber(Clobber)) > - return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) << > - Clobber); > - ClobberRegs.insert(Reg); > - } > - } > - for (std::set<std::string>::iterator I = ClobberRegs.begin(), > - E = ClobberRegs.end(); I != E; ++I) > - Clobbers.push_back(*I); > - > - MSAsmStmt *NS = > - new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, > - /*IsVolatile*/ true, AsmToks, Inputs, Outputs, > - AsmString, Clobbers, EndLoc); > - return Owned(NS); > -} > - > StmtResult > Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, > SourceLocation RParen, Decl *Parm, > > Added: cfe/trunk/lib/Sema/SemaStmtAsm.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAsm.cpp?rev=162132&view=auto > ============================================================================== > --- cfe/trunk/lib/Sema/SemaStmtAsm.cpp (added) > +++ cfe/trunk/lib/Sema/SemaStmtAsm.cpp Fri Aug 17 16:19:40 2012 > @@ -0,0 +1,635 @@ > +//===--- SemaStmtAsm.cpp - Semantic Analysis for Statements > ---------------===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +// > +// This file implements semantic analysis for inline asm statements. > +// > +//===----------------------------------------------------------------------===// > + > +#include "clang/Sema/SemaInternal.h" > +#include "clang/Sema/Scope.h" > +#include "clang/Sema/ScopeInfo.h" > +#include "clang/Sema/Initialization.h" > +#include "clang/Sema/Lookup.h" > +#include "clang/AST/TypeLoc.h" > +#include "clang/Lex/Preprocessor.h" > +#include "clang/Basic/TargetInfo.h" > +#include "llvm/ADT/ArrayRef.h" > +#include "llvm/ADT/BitVector.h" > +#include "llvm/ADT/SmallString.h" > +#include "llvm/MC/MCAsmInfo.h" > +#include "llvm/MC/MCContext.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/MCTargetAsmParser.h" > +#include "llvm/MC/MCParser/MCAsmLexer.h" > +#include "llvm/MC/MCParser/MCAsmParser.h" > +#include "llvm/Support/SourceMgr.h" > +#include "llvm/Support/TargetRegistry.h" > +#include "llvm/Support/TargetSelect.h" > +using namespace clang; > +using namespace sema; > + > +/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they > silently > +/// ignore "noop" casts in places where an lvalue is required by an inline > asm. > +/// We emulate this behavior when -fheinous-gnu-extensions is specified, but > +/// provide a strong guidance to not use it. > +/// > +/// This method checks to see if the argument is an acceptable l-value and > +/// returns false if it is a case we can handle. > +static bool CheckAsmLValue(const Expr *E, Sema &S) { > + // Type dependent expressions will be checked during instantiation. > + if (E->isTypeDependent()) > + return false; > + > + if (E->isLValue()) > + return false; // Cool, this is an lvalue. > + > + // Okay, this is not an lvalue, but perhaps it is the result of a cast > that we > + // are supposed to allow. > + const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); > + if (E != E2 && E2->isLValue()) { > + if (!S.getLangOpts().HeinousExtensions) > + S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) > + << E->getSourceRange(); > + else > + S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) > + << E->getSourceRange(); > + // Accept, even if we emitted an error diagnostic. > + return false; > + } > + > + // None of the above, just randomly invalid non-lvalue. > + return true; > +} > + > +/// isOperandMentioned - Return true if the specified operand # is mentioned > +/// anywhere in the decomposed asm string. > +static bool isOperandMentioned(unsigned OpNo, > + ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) { > + for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { > + const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; > + if (!Piece.isOperand()) continue; > + > + // If this is a reference to the input and if the input was the smaller > + // one, then we have to reject this asm. > + if (Piece.getOperandNo() == OpNo) > + return true; > + } > + return false; > +} > + > +StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, > + bool IsVolatile, unsigned NumOutputs, > + unsigned NumInputs, IdentifierInfo **Names, > + MultiExprArg constraints, MultiExprArg exprs, > + Expr *asmString, MultiExprArg clobbers, > + SourceLocation RParenLoc, bool MSAsm) { > + unsigned NumClobbers = clobbers.size(); > + StringLiteral **Constraints = > + reinterpret_cast<StringLiteral**>(constraints.get()); > + Expr **Exprs = exprs.get(); > + StringLiteral *AsmString = cast<StringLiteral>(asmString); > + StringLiteral **Clobbers = > reinterpret_cast<StringLiteral**>(clobbers.get()); > + > + SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; > + > + // The parser verifies that there is a string literal here. > + if (!AsmString->isAscii()) > + return > StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) > + << AsmString->getSourceRange()); > + > + for (unsigned i = 0; i != NumOutputs; i++) { > + StringLiteral *Literal = Constraints[i]; > + if (!Literal->isAscii()) > + return > StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) > + << Literal->getSourceRange()); > + > + StringRef OutputName; > + if (Names[i]) > + OutputName = Names[i]->getName(); > + > + TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); > + if (!Context.getTargetInfo().validateOutputConstraint(Info)) > + return StmtError(Diag(Literal->getLocStart(), > + diag::err_asm_invalid_output_constraint) > + << Info.getConstraintStr()); > + > + // Check that the output exprs are valid lvalues. > + Expr *OutputExpr = Exprs[i]; > + if (CheckAsmLValue(OutputExpr, *this)) { > + return StmtError(Diag(OutputExpr->getLocStart(), > + diag::err_asm_invalid_lvalue_in_output) > + << OutputExpr->getSourceRange()); > + } > + > + OutputConstraintInfos.push_back(Info); > + } > + > + SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; > + > + for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { > + StringLiteral *Literal = Constraints[i]; > + if (!Literal->isAscii()) > + return > StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) > + << Literal->getSourceRange()); > + > + StringRef InputName; > + if (Names[i]) > + InputName = Names[i]->getName(); > + > + TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); > + if > (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), > + NumOutputs, Info)) { > + return StmtError(Diag(Literal->getLocStart(), > + diag::err_asm_invalid_input_constraint) > + << Info.getConstraintStr()); > + } > + > + Expr *InputExpr = Exprs[i]; > + > + // Only allow void types for memory constraints. > + if (Info.allowsMemory() && !Info.allowsRegister()) { > + if (CheckAsmLValue(InputExpr, *this)) > + return StmtError(Diag(InputExpr->getLocStart(), > + diag::err_asm_invalid_lvalue_in_input) > + << Info.getConstraintStr() > + << InputExpr->getSourceRange()); > + } > + > + if (Info.allowsRegister()) { > + if (InputExpr->getType()->isVoidType()) { > + return StmtError(Diag(InputExpr->getLocStart(), > + diag::err_asm_invalid_type_in_input) > + << InputExpr->getType() << Info.getConstraintStr() > + << InputExpr->getSourceRange()); > + } > + } > + > + ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); > + if (Result.isInvalid()) > + return StmtError(); > + > + Exprs[i] = Result.take(); > + InputConstraintInfos.push_back(Info); > + } > + > + // Check that the clobbers are valid. > + for (unsigned i = 0; i != NumClobbers; i++) { > + StringLiteral *Literal = Clobbers[i]; > + if (!Literal->isAscii()) > + return > StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) > + << Literal->getSourceRange()); > + > + StringRef Clobber = Literal->getString(); > + > + if (!Context.getTargetInfo().isValidClobber(Clobber)) > + return StmtError(Diag(Literal->getLocStart(), > + diag::err_asm_unknown_register_name) << Clobber); > + } > + > + AsmStmt *NS = > + new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm, > + NumOutputs, NumInputs, Names, Constraints, Exprs, > + AsmString, NumClobbers, Clobbers, RParenLoc); > + // Validate the asm string, ensuring it makes sense given the operands we > + // have. > + SmallVector<AsmStmt::AsmStringPiece, 8> Pieces; > + unsigned DiagOffs; > + if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { > + Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) > + << AsmString->getSourceRange(); > + return StmtError(); > + } > + > + // Validate tied input operands for type mismatches. > + for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { > + TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; > + > + // If this is a tied constraint, verify that the output and input have > + // either exactly the same type, or that they are int/ptr operands with > the > + // same size (int/long, int*/long, are ok etc). > + if (!Info.hasTiedOperand()) continue; > + > + unsigned TiedTo = Info.getTiedOperand(); > + unsigned InputOpNo = i+NumOutputs; > + Expr *OutputExpr = Exprs[TiedTo]; > + Expr *InputExpr = Exprs[InputOpNo]; > + > + if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) > + continue; > + > + QualType InTy = InputExpr->getType(); > + QualType OutTy = OutputExpr->getType(); > + if (Context.hasSameType(InTy, OutTy)) > + continue; // All types can be tied to themselves. > + > + // Decide if the input and output are in the same domain (integer/ptr or > + // floating point. > + enum AsmDomain { > + AD_Int, AD_FP, AD_Other > + } InputDomain, OutputDomain; > + > + if (InTy->isIntegerType() || InTy->isPointerType()) > + InputDomain = AD_Int; > + else if (InTy->isRealFloatingType()) > + InputDomain = AD_FP; > + else > + InputDomain = AD_Other; > + > + if (OutTy->isIntegerType() || OutTy->isPointerType()) > + OutputDomain = AD_Int; > + else if (OutTy->isRealFloatingType()) > + OutputDomain = AD_FP; > + else > + OutputDomain = AD_Other; > + > + // They are ok if they are the same size and in the same domain. This > + // allows tying things like: > + // void* to int* > + // void* to int if they are the same size. > + // double to long double if they are the same size. > + // > + uint64_t OutSize = Context.getTypeSize(OutTy); > + uint64_t InSize = Context.getTypeSize(InTy); > + if (OutSize == InSize && InputDomain == OutputDomain && > + InputDomain != AD_Other) > + continue; > + > + // If the smaller input/output operand is not mentioned in the asm > string, > + // then we can promote the smaller one to a larger input and the asm > string > + // won't notice. > + bool SmallerValueMentioned = false; > + > + // If this is a reference to the input and if the input was the smaller > + // one, then we have to reject this asm. > + if (isOperandMentioned(InputOpNo, Pieces)) { > + // This is a use in the asm string of the smaller operand. Since we > + // codegen this by promoting to a wider value, the asm will get printed > + // "wrong". > + SmallerValueMentioned |= InSize < OutSize; > + } > + if (isOperandMentioned(TiedTo, Pieces)) { > + // If this is a reference to the output, and if the output is the > larger > + // value, then it's ok because we'll promote the input to the larger > type. > + SmallerValueMentioned |= OutSize < InSize; > + } > + > + // If the smaller value wasn't mentioned in the asm string, and if the > + // output was a register, just extend the shorter one to the size of the > + // larger one. > + if (!SmallerValueMentioned && InputDomain != AD_Other && > + OutputConstraintInfos[TiedTo].allowsRegister()) > + continue; > + > + // Either both of the operands were mentioned or the smaller one was > + // mentioned. One more special case that we'll allow: if the tied input > is > + // integer, unmentioned, and is a constant, then we'll allow truncating > it > + // down to the size of the destination. > + if (InputDomain == AD_Int && OutputDomain == AD_Int && > + !isOperandMentioned(InputOpNo, Pieces) && > + InputExpr->isEvaluatable(Context)) { > + CastKind castKind = > + (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); > + InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); > + Exprs[InputOpNo] = InputExpr; > + NS->setInputExpr(i, InputExpr); > + continue; > + } > + > + Diag(InputExpr->getLocStart(), > + diag::err_asm_tying_incompatible_types) > + << InTy << OutTy << OutputExpr->getSourceRange() > + << InputExpr->getSourceRange(); > + return StmtError(); > + } > + > + return Owned(NS); > +} > + > +// isMSAsmKeyword - Return true if this is an MS-style inline asm keyword. > These > +// require special handling. > +static bool isMSAsmKeyword(StringRef Name) { > + bool Ret = llvm::StringSwitch<bool>(Name) > + .Cases("EVEN", "ALIGN", true) // Alignment directives. > + .Cases("LENGTH", "SIZE", "TYPE", true) // Type and variable sizes. > + .Case("_emit", true) // _emit Pseudoinstruction. > + .Default(false); > + return Ret; > +} > + > +static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { > + StringRef Asm; > + SmallString<512> TokenBuf; > + TokenBuf.resize(512); > + bool StringInvalid = false; > + Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); > + assert (!StringInvalid && "Expected valid string!"); > + return Asm; > +} > + > +static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple, > + SourceLocation AsmLoc, > + ArrayRef<Token> AsmToks, > + const TargetInfo &TI, > + std::vector<llvm::BitVector> &AsmRegs, > + std::vector<llvm::BitVector> &AsmNames, > + std::vector<std::string> &AsmStrings) { > + assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); > + > + // Assume simple asm stmt until we parse a non-register identifer (or we > just > + // need to bail gracefully). > + IsSimple = true; > + > + SmallString<512> Asm; > + unsigned NumAsmStrings = 0; > + for (unsigned i = 0, e = AsmToks.size(); i != e; ++i) { > + > + // Determine if this should be considered a new asm. > + bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || > + AsmToks[i].is(tok::kw_asm); > + > + // Emit the previous asm string. > + if (i && isNewAsm) { > + AsmStrings[NumAsmStrings++] = Asm.c_str(); > + if (AsmToks[i].is(tok::kw_asm)) { > + ++i; // Skip __asm > + assert (i != e && "Expected another token."); > + } > + } > + > + // Start a new asm string with the opcode. > + if (isNewAsm) { > + AsmRegs[NumAsmStrings].resize(AsmToks.size()); > + AsmNames[NumAsmStrings].resize(AsmToks.size()); > + > + StringRef Piece = AsmToks[i].getIdentifierInfo()->getName(); > + // MS-style inline asm keywords require special handling. > + if (isMSAsmKeyword(Piece)) > + IsSimple = false; > + > + // TODO: Verify this is a valid opcode. > + Asm = Piece; > + continue; > + } > + > + if (i && AsmToks[i].hasLeadingSpace()) > + Asm += ' '; > + > + // Check the operand(s). > + switch (AsmToks[i].getKind()) { > + default: > + IsSimple = false; > + Asm += getSpelling(SemaRef, AsmToks[i]); > + break; > + case tok::comma: Asm += ","; break; > + case tok::colon: Asm += ":"; break; > + case tok::l_square: Asm += "["; break; > + case tok::r_square: Asm += "]"; break; > + case tok::l_brace: Asm += "{"; break; > + case tok::r_brace: Asm += "}"; break; > + case tok::numeric_constant: > + Asm += getSpelling(SemaRef, AsmToks[i]); > + break; > + case tok::identifier: { > + IdentifierInfo *II = AsmToks[i].getIdentifierInfo(); > + StringRef Name = II->getName(); > + > + // Valid register? > + if (TI.isValidGCCRegisterName(Name)) { > + AsmRegs[NumAsmStrings].set(i); > + Asm += Name; > + break; > + } > + > + IsSimple = false; > + > + // MS-style inline asm keywords require special handling. > + if (isMSAsmKeyword(Name)) { > + IsSimple = false; > + Asm += Name; > + break; > + } > + > + // FIXME: Why are we missing this segment register? > + if (Name == "fs") { > + Asm += Name; > + break; > + } > + > + // Lookup the identifier. > + // TODO: Someone with more experience with clang should verify this the > + // proper way of doing a symbol lookup. > + DeclarationName DeclName(II); > + Scope *CurScope = SemaRef.getCurScope(); > + LookupResult R(SemaRef, DeclName, AsmLoc, Sema::LookupOrdinaryName); > + if (!SemaRef.LookupName(R, CurScope, false/*AllowBuiltinCreation*/)) > + break; > + > + assert (R.isSingleResult() && "Expected a single result?!"); > + NamedDecl *Decl = R.getFoundDecl(); > + switch (Decl->getKind()) { > + default: > + assert(0 && "Unknown decl kind."); > + break; > + case Decl::Var: { > + case Decl::ParmVar: > + AsmNames[NumAsmStrings].set(i); > + > + VarDecl *Var = cast<VarDecl>(Decl); > + QualType Ty = Var->getType(); > + (void)Ty; // Avoid warning. > + // TODO: Patch identifier with valid operand. One potential idea is > to > + // probe the backend with type information to guess the possible > + // operand. > + break; > + } > + } > + break; > + } > + } > + } > + > + // Emit the final (and possibly only) asm string. > + AsmStrings[NumAsmStrings] = Asm.c_str(); > +} > + > +// Build the unmodified MSAsmString. > +static std::string buildMSAsmString(Sema &SemaRef, > + ArrayRef<Token> AsmToks, > + unsigned &NumAsmStrings) { > + assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); > + NumAsmStrings = 0; > + > + SmallString<512> Asm; > + for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { > + bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || > + AsmToks[i].is(tok::kw_asm); > + > + if (isNewAsm) { > + ++NumAsmStrings; > + if (i) > + Asm += '\n'; > + if (AsmToks[i].is(tok::kw_asm)) { > + i++; // Skip __asm > + assert (i != e && "Expected another token"); > + } > + } > + > + if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) > + Asm += ' '; > + > + Asm += getSpelling(SemaRef, AsmToks[i]); > + } > + return Asm.c_str(); > +} > + > +StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, > + SourceLocation LBraceLoc, > + ArrayRef<Token> AsmToks, > + SourceLocation EndLoc) { > + // MS-style inline assembly is not fully supported, so emit a warning. > + Diag(AsmLoc, diag::warn_unsupported_msasm); > + SmallVector<StringRef,4> Clobbers; > + std::set<std::string> ClobberRegs; > + SmallVector<IdentifierInfo*, 4> Inputs; > + SmallVector<IdentifierInfo*, 4> Outputs; > + > + // Empty asm statements don't need to instantiate the AsmParser, etc. > + if (AsmToks.empty()) { > + StringRef AsmString; > + MSAsmStmt *NS = > + new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, > + /*IsVolatile*/ true, AsmToks, Inputs, Outputs, > + AsmString, Clobbers, EndLoc); > + return Owned(NS); > + } > + > + unsigned NumAsmStrings; > + std::string AsmString = buildMSAsmString(*this, AsmToks, NumAsmStrings); > + > + bool IsSimple; > + std::vector<llvm::BitVector> Regs; > + std::vector<llvm::BitVector> Names; > + std::vector<std::string> PatchedAsmStrings; > + > + Regs.resize(NumAsmStrings); > + Names.resize(NumAsmStrings); > + PatchedAsmStrings.resize(NumAsmStrings); > + > + // Rewrite operands to appease the AsmParser. > + patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks, > + Context.getTargetInfo(), Regs, Names, PatchedAsmStrings); > + > + // patchMSAsmStrings doesn't correctly patch non-simple asm statements. > + if (!IsSimple) { > + MSAsmStmt *NS = > + new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, > + /*IsVolatile*/ true, AsmToks, Inputs, Outputs, > + AsmString, Clobbers, EndLoc); > + return Owned(NS); > + } > + > + // Initialize targets and assembly printers/parsers. > + llvm::InitializeAllTargetInfos(); > + llvm::InitializeAllTargetMCs(); > + llvm::InitializeAllAsmParsers(); > + > + // Get the target specific parser. > + std::string Error; > + const std::string &TT = Context.getTargetInfo().getTriple().getTriple(); > + const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, > Error)); > + > + OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); > + OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); > + OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); > + OwningPtr<llvm::MCSubtargetInfo> > + STI(TheTarget->createMCSubtargetInfo(TT, "", "")); > + > + for (unsigned i = 0, e = PatchedAsmStrings.size(); i != e; ++i) { > + llvm::SourceMgr SrcMgr; > + llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); > + llvm::MemoryBuffer *Buffer = > + llvm::MemoryBuffer::getMemBuffer(PatchedAsmStrings[i], "<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()); > + > + // Prime the lexer. > + Parser->Lex(); > + > + // Parse the opcode. > + StringRef IDVal; > + Parser->ParseIdentifier(IDVal); > + > + // Canonicalize the opcode to lower case. > + SmallString<128> Opcode; > + for (unsigned i = 0, e = IDVal.size(); i != e; ++i) > + Opcode.push_back(tolower(IDVal[i])); > + > + // Parse the operands. > + llvm::SMLoc IDLoc; > + SmallVector<llvm::MCParsedAsmOperand*, 8> Operands; > + bool HadError = TargetParser->ParseInstruction(Opcode.str(), IDLoc, > + Operands); > + assert (!HadError && "Unexpected error parsing instruction"); > + > + // Match the MCInstr. > + SmallVector<llvm::MCInst, 2> Instrs; > + HadError = TargetParser->MatchInstruction(IDLoc, Operands, Instrs); > + assert (!HadError && "Unexpected error matching instruction"); > + assert ((Instrs.size() == 1) && "Expected only a single instruction."); > + > + // Get the instruction descriptor. > + llvm::MCInst Inst = Instrs[0]; > + const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); > + const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode()); > + llvm::MCInstPrinter *IP = > + TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); > + > + // Build the list of clobbers. > + for (unsigned i = 0, e = Desc.getNumDefs(); i != e; ++i) { > + const llvm::MCOperand &Op = Inst.getOperand(i); > + if (!Op.isReg()) > + continue; > + > + std::string Reg; > + llvm::raw_string_ostream OS(Reg); > + IP->printRegName(OS, Op.getReg()); > + > + StringRef Clobber(OS.str()); > + if (!Context.getTargetInfo().isValidClobber(Clobber)) > + return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) << > + Clobber); > + ClobberRegs.insert(Reg); > + } > + } > + for (std::set<std::string>::iterator I = ClobberRegs.begin(), > + E = ClobberRegs.end(); I != E; ++I) > + Clobbers.push_back(*I); > + > + MSAsmStmt *NS = > + new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, > + /*IsVolatile*/ true, AsmToks, Inputs, Outputs, > + AsmString, Clobbers, EndLoc); > + return Owned(NS); > +} > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
