[cfe-commits] r162132 - in /cfe/trunk/lib/Sema: CMakeLists.txt SemaStmt.cpp SemaStmtAsm.cpp
Chad Rosier
mcrosier at apple.com
Fri Aug 24 16:16:38 PDT 2012
On Aug 24, 2012, at 4:08 PM, Matt Beaumont-Gay wrote:
> On Wed, Aug 22, 2012 at 6:37 PM, Sean Silva <silvas at purdue.edu> wrote:
>> + 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'.
>
> For posterity, I fixed this in r162424.
You beat me to it. I renamed the outer 'i' in r162444. Regardless, thanks.
Chad
>
>>
>> --Sean Silva
>>
>> On Fri, Aug 17, 2012 at 5:19 PM, Chad Rosier <mcrosier at apple.com> 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
>>> cfe-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list