diff options
Diffstat (limited to 'lib/Sema/SemaStmtAsm.cpp')
-rw-r--r-- | lib/Sema/SemaStmtAsm.cpp | 341 |
1 files changed, 65 insertions, 276 deletions
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 3e9606e467..fce95bebd1 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -22,18 +22,6 @@ #include "clang/Sema/ScopeInfo.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/MCObjectFileInfo.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" using namespace clang; using namespace sema; @@ -124,11 +112,14 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, // Check that the output exprs are valid lvalues. Expr *OutputExpr = Exprs[i]; - if (CheckAsmLValue(OutputExpr, *this)) { + if (CheckAsmLValue(OutputExpr, *this)) return StmtError(Diag(OutputExpr->getLocStart(), - diag::err_asm_invalid_lvalue_in_output) - << OutputExpr->getSourceRange()); - } + diag::err_asm_invalid_lvalue_in_output) + << OutputExpr->getSourceRange()); + + if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(), + diag::err_dereference_incomplete_type)) + return StmtError(); OutputConstraintInfos.push_back(Info); } @@ -181,9 +172,14 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, InputConstraintInfos.push_back(Info); const Type *Ty = Exprs[i]->getType().getTypePtr(); - if (Ty->isDependentType() || Ty->isIncompleteType()) + if (Ty->isDependentType()) continue; + if (!Ty->isVoidType() || !Info.allowsMemory()) + if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(), + diag::err_dereference_incomplete_type)) + return StmtError(); + unsigned Size = Context.getTypeSize(Ty); if (!Context.getTargetInfo().validateInputSize(Literal->getString(), Size)) @@ -373,160 +369,60 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, return Owned(NS); } -// getSpelling - Get the spelling of the AsmTok token. -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; -} +ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + UnqualifiedId &Id, + InlineAsmIdentifierInfo &Info, + bool IsUnevaluatedContext) { + Info.clear(); -// Build the inline assembly string. Returns true on error. -static bool buildMSAsmString(Sema &SemaRef, - SourceLocation AsmLoc, - ArrayRef<Token> AsmToks, - SmallVectorImpl<unsigned> &TokOffsets, - std::string &AsmString) { - assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); - - 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) { - if (i != 0) - Asm += "\n\t"; - - if (AsmToks[i].is(tok::kw_asm)) { - i++; // Skip __asm - if (i == e) { - SemaRef.Diag(AsmLoc, diag::err_asm_empty); - return true; - } + if (IsUnevaluatedContext) + PushExpressionEvaluationContext(UnevaluatedAbstract, + ReuseLambdaContextDecl); - } - } + ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id, + /*trailing lparen*/ false, + /*is & operand*/ false); - if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) - Asm += ' '; + if (IsUnevaluatedContext) + PopExpressionEvaluationContext(); - StringRef Spelling = getSpelling(SemaRef, AsmToks[i]); - Asm += Spelling; - TokOffsets.push_back(Asm.size()); - } - AsmString = Asm.str(); - return false; -} + if (!Result.isUsable()) return Result; -namespace { - -class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback { - Sema &SemaRef; - SourceLocation AsmLoc; - ArrayRef<Token> AsmToks; - ArrayRef<unsigned> TokOffsets; - -public: - MCAsmParserSemaCallbackImpl(Sema &Ref, SourceLocation Loc, - ArrayRef<Token> Toks, - ArrayRef<unsigned> Offsets) - : SemaRef(Ref), AsmLoc(Loc), AsmToks(Toks), TokOffsets(Offsets) { } - ~MCAsmParserSemaCallbackImpl() {} - - void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, - unsigned &Length, unsigned &Size, - unsigned &Type, bool &IsVarDecl){ - SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc); - - NamedDecl *OpDecl = SemaRef.LookupInlineAsmIdentifier(Name, Loc, Length, - Size, Type, - IsVarDecl); - return static_cast<void *>(OpDecl); - } + Result = CheckPlaceholderExpr(Result.take()); + if (!Result.isUsable()) return Result; - bool LookupInlineAsmField(StringRef Base, StringRef Member, - unsigned &Offset) { - return SemaRef.LookupInlineAsmField(Base, Member, Offset, AsmLoc); - } + QualType T = Result.get()->getType(); - static void MSAsmDiagHandlerCallback(const llvm::SMDiagnostic &D, - void *Context) { - ((MCAsmParserSemaCallbackImpl*)Context)->MSAsmDiagHandler(D); + // For now, reject dependent types. + if (T->isDependentType()) { + Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T; + return ExprError(); } - void MSAsmDiagHandler(const llvm::SMDiagnostic &D) { - // Compute an offset into the inline asm buffer. - // FIXME: This isn't right if .macro is involved (but hopefully, no - // real-world code does that). - const llvm::SourceMgr &LSM = *D.getSourceMgr(); - const llvm::MemoryBuffer *LBuf = - LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); - unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); - - // Figure out which token that offset points into. - const unsigned *OffsetPtr = - std::lower_bound(TokOffsets.begin(), TokOffsets.end(), Offset); - unsigned TokIndex = OffsetPtr - TokOffsets.begin(); - - // If we come up with an answer which seems sane, use it; otherwise, - // just point at the __asm keyword. - // FIXME: Assert the answer is sane once we handle .macro correctly. - SourceLocation Loc = AsmLoc; - if (TokIndex < AsmToks.size()) { - const Token *Tok = &AsmToks[TokIndex]; - Loc = Tok->getLocation(); - Loc = Loc.getLocWithOffset(Offset - (*OffsetPtr - Tok->getLength())); - } - SemaRef.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage(); - } -}; - -} -NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc, - unsigned &Length, unsigned &Size, - unsigned &Type, bool &IsVarDecl) { - Length = 1; - Size = 0; - Type = 0; - IsVarDecl = false; - LookupResult Result(*this, &Context.Idents.get(Name), Loc, - Sema::LookupOrdinaryName); - - if (!LookupName(Result, getCurScope())) { - // If we don't find anything, return null; the AsmParser will assume - // it is a label of some sort. - return 0; + // Any sort of function type is fine. + if (T->isFunctionType()) { + return Result; } - if (!Result.isSingleResult()) { - // FIXME: Diagnose result. - return 0; + // Otherwise, it needs to be a complete type. + if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) { + return ExprError(); } - NamedDecl *ND = Result.getFoundDecl(); - if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) { - if (VarDecl *Var = dyn_cast<VarDecl>(ND)) { - Type = Context.getTypeInfo(Var->getType()).first; - QualType Ty = Var->getType(); - if (Ty->isArrayType()) { - const ArrayType *ATy = Context.getAsArrayType(Ty); - Length = Type / Context.getTypeInfo(ATy->getElementType()).first; - Type /= Length; // Type is in terms of a single element. - } - Type /= 8; // Type is in terms of bits, but we want bytes. - Size = Length * Type; - IsVarDecl = true; - } - return ND; + // Compute the type size (and array length if applicable?). + Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity(); + if (T->isArrayType()) { + const ArrayType *ATy = Context.getAsArrayType(T); + Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity(); + Info.Length = Info.Size / Info.Type; } - // FIXME: Handle other kinds of results? (FieldDecl, etc.) - // FIXME: Diagnose if we find something we can't handle, like a typedef. - return 0; + // We can work with the expression as long as it's not an r-value. + if (!Result.get()->isRValue()) + Info.IsVarDecl = true; + + return Result; } bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, @@ -541,13 +437,12 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, if (!BaseResult.isSingleResult()) return true; - NamedDecl *FoundDecl = BaseResult.getFoundDecl(); const RecordType *RT = 0; - if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) { + NamedDecl *FoundDecl = BaseResult.getFoundDecl(); + if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) RT = VD->getType()->getAs<RecordType>(); - } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl)) { + else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl)) RT = TD->getUnderlyingType()->getAs<RecordType>(); - } if (!RT) return true; @@ -574,124 +469,18 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, } StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, - ArrayRef<Token> AsmToks,SourceLocation EndLoc) { - SmallVector<IdentifierInfo*, 4> Names; - SmallVector<StringRef, 4> ConstraintRefs; - SmallVector<Expr*, 4> Exprs; - SmallVector<StringRef, 4> ClobberRefs; - - llvm::Triple TheTriple = Context.getTargetInfo().getTriple(); - llvm::Triple::ArchType ArchTy = TheTriple.getArch(); - bool UnsupportedArch = ArchTy != llvm::Triple::x86 && - ArchTy != llvm::Triple::x86_64; - if (UnsupportedArch) - Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); - - // Empty asm statements don't need to instantiate the AsmParser, etc. - if (UnsupportedArch || AsmToks.empty()) { - StringRef EmptyAsmStr; - MSAsmStmt *NS = - new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, - /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0, - /*NumInputs*/ 0, Names, ConstraintRefs, Exprs, - EmptyAsmStr, ClobberRefs, EndLoc); - return Owned(NS); - } - - std::string AsmString; - SmallVector<unsigned, 8> TokOffsets; - if (buildMSAsmString(*this, AsmLoc, AsmToks, TokOffsets, AsmString)) - return StmtError(); - - // Get the target specific parser. - std::string Error; - const std::string &TT = TheTriple.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, "", "")); - - llvm::SourceMgr SrcMgr; - llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); - llvm::MemoryBuffer *Buffer = - llvm::MemoryBuffer::getMemBuffer(AsmString, "<inline asm>"); - - // Tell SrcMgr about this buffer, which is what the parser will pick up. - SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); - - OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); - OwningPtr<llvm::MCAsmParser> - Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); - OwningPtr<llvm::MCTargetAsmParser> - TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); - - // Get the instruction descriptor. - const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); - llvm::MCInstPrinter *IP = - TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); - - // Change to the Intel dialect. - Parser->setAssemblerDialect(1); - Parser->setTargetParser(*TargetParser.get()); - Parser->setParsingInlineAsm(true); - TargetParser->setParsingInlineAsm(true); - - MCAsmParserSemaCallbackImpl MCAPSI(*this, AsmLoc, AsmToks, TokOffsets); - TargetParser->setSemaCallback(&MCAPSI); - SrcMgr.setDiagHandler(MCAsmParserSemaCallbackImpl::MSAsmDiagHandlerCallback, - &MCAPSI); - - unsigned NumOutputs; - unsigned NumInputs; - std::string AsmStringIR; - SmallVector<std::pair<void *, bool>, 4> OpDecls; - SmallVector<std::string, 4> Constraints; - SmallVector<std::string, 4> Clobbers; - if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, - NumOutputs, NumInputs, OpDecls, Constraints, - Clobbers, MII, IP, MCAPSI)) - return StmtError(); - - // Build the vector of clobber StringRefs. - unsigned NumClobbers = Clobbers.size(); - ClobberRefs.resize(NumClobbers); - for (unsigned i = 0; i != NumClobbers; ++i) - ClobberRefs[i] = StringRef(Clobbers[i]); - - // Recast the void pointers and build the vector of constraint StringRefs. - unsigned NumExprs = NumOutputs + NumInputs; - Names.resize(NumExprs); - ConstraintRefs.resize(NumExprs); - Exprs.resize(NumExprs); - for (unsigned i = 0, e = NumExprs; i != e; ++i) { - NamedDecl *OpDecl = static_cast<NamedDecl *>(OpDecls[i].first); - if (!OpDecl) - return StmtError(); - - DeclarationNameInfo NameInfo(OpDecl->getDeclName(), AsmLoc); - ExprResult OpExpr = BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, - OpDecl); - if (OpExpr.isInvalid()) - return StmtError(); - - // Need address of variable. - if (OpDecls[i].second) - OpExpr = BuildUnaryOp(getCurScope(), AsmLoc, clang::UO_AddrOf, - OpExpr.take()); - - Names[i] = OpDecl->getIdentifier(); - ConstraintRefs[i] = StringRef(Constraints[i]); - Exprs[i] = OpExpr.take(); - } - - bool IsSimple = NumExprs > 0; + ArrayRef<Token> AsmToks, + StringRef AsmString, + unsigned NumOutputs, unsigned NumInputs, + ArrayRef<StringRef> Constraints, + ArrayRef<StringRef> Clobbers, + ArrayRef<Expr*> Exprs, + SourceLocation EndLoc) { + bool IsSimple = (NumOutputs != 0 || NumInputs != 0); MSAsmStmt *NS = new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs, - Names, ConstraintRefs, Exprs, AsmStringIR, - ClobberRefs, EndLoc); + Constraints, Exprs, AsmString, + Clobbers, EndLoc); return Owned(NS); } |