[cfe-commits] r162132 - in /cfe/trunk/lib/Sema: CMakeLists.txt SemaStmt.cpp SemaStmtAsm.cpp
Matt Beaumont-Gay
matthewbg at google.com
Fri Aug 24 16:08:25 PDT 2012
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.
>
> --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