From a85622d923a899272c7acbd19210ba2f7bb88ab9 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 30 May 2019 15:38:02 +0000 Subject: [PATCH] Revert "clang support gnu asm goto." This reverts commit 954ec09aed4f2be04bb5f4e10dbb4ea8bd19ef9a. Reverting due to test failures as requested by Jennifer Yu. Conflicts: clang/test/CodeGen/asm-goto.c git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@362106 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Stmt.h | 51 +------- include/clang/Basic/DiagnosticParseKinds.td | 4 +- include/clang/Basic/DiagnosticSemaKinds.td | 10 +- include/clang/Sema/Sema.h | 1 - lib/AST/ASTImporter.cpp | 10 +- lib/AST/Stmt.cpp | 29 +---- lib/AST/StmtPrinter.cpp | 20 +--- lib/AST/StmtProfile.cpp | 3 - lib/Analysis/CFG.cpp | 74 +++--------- lib/CodeGen/CGStmt.cpp | 126 +++++++------------- lib/Parse/ParseStmtAsm.cpp | 68 ++--------- lib/Sema/JumpDiagnostics.cpp | 114 +++++++----------- lib/Sema/SemaStmtAsm.cpp | 48 ++------ lib/Sema/TreeTransform.h | 16 +-- lib/Serialization/ASTReaderStmt.cpp | 7 -- lib/Serialization/ASTWriterStmt.cpp | 4 - test/Analysis/asm-goto.cpp | 52 -------- test/CodeGen/asm-goto.c | 19 --- test/CodeGen/asm.c | 12 -- test/CodeGen/inline-asm-mixed-style.c | 10 +- test/Coverage/c-language-features.inc | 4 +- test/PCH/asm.h | 6 +- test/Parser/asm.c | 50 -------- test/Parser/asm.cpp | 51 -------- test/Sema/asm-goto.cpp | 45 ------- test/Sema/asm.c | 21 ---- test/Sema/inline-asm-validate-tmpl.cpp | 10 -- test/Sema/scope-check.c | 16 --- 28 files changed, 148 insertions(+), 733 deletions(-) delete mode 100644 test/Analysis/asm-goto.cpp delete mode 100644 test/CodeGen/asm-goto.c delete mode 100644 test/Sema/asm-goto.cpp diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index fe5d802688..77b2173fcb 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -46,7 +46,6 @@ class Attr; class CapturedDecl; class Decl; class Expr; -class AddrLabelExpr; class LabelDecl; class ODRHash; class PrinterHelper; @@ -2817,15 +2816,13 @@ class GCCAsmStmt : public AsmStmt { StringLiteral **Constraints = nullptr; StringLiteral **Clobbers = nullptr; IdentifierInfo **Names = nullptr; - unsigned NumLabels = 0; public: GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, unsigned numoutputs, unsigned numinputs, IdentifierInfo **names, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, - StringLiteral **clobbers, unsigned numlabels, - SourceLocation rparenloc); + StringLiteral **clobbers, SourceLocation rparenloc); /// Build an empty inline-assembly statement. explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty) {} @@ -2950,51 +2947,6 @@ public: return const_cast(this)->getInputExpr(i); } - //===--- Labels ---===// - - bool isAsmGoto() const { - return NumLabels > 0; - } - - unsigned getNumLabels() const { - return NumLabels; - } - - IdentifierInfo *getLabelIdentifier(unsigned i) const { - return Names[i + NumInputs]; - } - - AddrLabelExpr *getLabelExpr(unsigned i) const; - StringRef getLabelName(unsigned i) const; - using labels_iterator = CastIterator; - using const_labels_iterator = ConstCastIterator; - using labels_range = llvm::iterator_range; - using labels_const_range = llvm::iterator_range; - - labels_iterator begin_labels() { - return &Exprs[0] + NumInputs; - } - - labels_iterator end_labels() { - return &Exprs[0] + NumInputs + NumLabels; - } - - labels_range labels() { - return labels_range(begin_labels(), end_labels()); - } - - const_labels_iterator begin_labels() const { - return &Exprs[0] + NumInputs; - } - - const_labels_iterator end_labels() const { - return &Exprs[0] + NumInputs + NumLabels; - } - - labels_const_range labels() const { - return labels_const_range(begin_labels(), end_labels()); - } - private: void setOutputsAndInputsAndClobbers(const ASTContext &C, IdentifierInfo **Names, @@ -3002,7 +2954,6 @@ private: Stmt **Exprs, unsigned NumOutputs, unsigned NumInputs, - unsigned NumLabels, StringLiteral **Clobbers, unsigned NumClobbers); diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 15a5ecf177..fb281a5be8 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -27,8 +27,8 @@ def err_msasm_unable_to_create_target : Error< "MS-style inline assembly is not available: %0">; def err_gnu_inline_asm_disabled : Error< "GNU-style inline assembly is disabled">; -def err_asm_goto_cannot_have_output : Error< - "'asm goto' cannot have output constraints">; +def err_asm_goto_not_supported_yet : Error< + "'asm goto' constructs are not supported yet">; } let CategoryName = "Parse Issue" in { diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index c5a7b93cec..1beb7fda9b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5070,12 +5070,12 @@ def warn_cxx98_compat_switch_into_protected_scope : Warning< def err_indirect_goto_without_addrlabel : Error< "indirect goto in function with no address-of-label expressions">; def err_indirect_goto_in_protected_scope : Error< - "cannot jump from this %select{indirect|asm}0 goto statement to one of its possible targets">; + "cannot jump from this indirect goto statement to one of its possible targets">; def warn_cxx98_compat_indirect_goto_in_protected_scope : Warning< - "jump from this %select{indirect|asm}0 goto statement to one of its possible targets " + "jump from this indirect goto statement to one of its possible targets " "is incompatible with C++98">, InGroup, DefaultIgnore; def note_indirect_goto_target : Note< - "possible target of %select{indirect|asm}0 goto statement">; + "possible target of indirect goto statement">; def note_protected_by_variable_init : Note< "jump bypasses variable initialization">; def note_protected_by_variable_nontriv_destructor : Note< @@ -7503,10 +7503,6 @@ let CategoryName = "Inline Assembly Issue" in { "use constraint modifier \"%0\"">; def note_asm_input_duplicate_first : Note< "constraint '%0' is already present here">; - def error_duplicate_asm_operand_name : Error< - "duplicate use of asm operand name \"%0\"">; - def note_duplicate_asm_operand_name : Note< - "asm operand name \"%0\" first referenced here">; } def error_inoutput_conflict_with_clobber : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index d25d7decf3..d7486ec1c2 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3971,7 +3971,6 @@ public: unsigned NumInputs, IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, Expr *AsmString, MultiExprArg Clobbers, - unsigned NumLabels, SourceLocation RParenLoc); void FillInlineAsmIdentifierInfo(Expr *Res, diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 1f1ec1d687..2e4c304b3d 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -5592,17 +5592,12 @@ ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { return InputOrErr.takeError(); } - SmallVector Exprs(S->getNumOutputs() + S->getNumInputs() + - S->getNumLabels()); + SmallVector Exprs(S->getNumOutputs() + S->getNumInputs()); if (Error Err = ImportContainerChecked(S->outputs(), Exprs)) return std::move(Err); - if (Error Err = - ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs())) - return std::move(Err); - if (Error Err = ImportArrayChecked( - S->labels(), Exprs.begin() + S->getNumOutputs() + S->getNumInputs())) + S->inputs(), Exprs.begin() + S->getNumOutputs())) return std::move(Err); ExpectedSLoc AsmLocOrErr = import(S->getAsmLoc()); @@ -5628,7 +5623,6 @@ ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { *AsmStrOrErr, S->getNumClobbers(), Clobbers.data(), - S->getNumLabels(), *RParenLocOrErr); } diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 0a4d403106..68a5a2d6ab 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -444,14 +444,6 @@ void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) { Exprs[i + NumOutputs] = E; } -AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const { - return cast(Exprs[i + NumInputs]); -} - -StringRef GCCAsmStmt::getLabelName(unsigned i) const { - return getLabelExpr(i)->getLabel()->getName(); -} - /// getInputConstraint - Return the specified input constraint. Unlike output /// constraints, these can be empty. StringRef GCCAsmStmt::getInputConstraint(unsigned i) const { @@ -464,16 +456,13 @@ void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C, Stmt **Exprs, unsigned NumOutputs, unsigned NumInputs, - unsigned NumLabels, StringLiteral **Clobbers, unsigned NumClobbers) { this->NumOutputs = NumOutputs; this->NumInputs = NumInputs; this->NumClobbers = NumClobbers; - this->NumLabels = NumLabels; - assert(!(NumOutputs && NumLabels) && "asm goto cannot have outputs"); - unsigned NumExprs = NumOutputs + NumInputs + NumLabels; + unsigned NumExprs = NumOutputs + NumInputs; C.Deallocate(this->Names); this->Names = new (C) IdentifierInfo*[NumExprs]; @@ -509,10 +498,6 @@ int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const { if (getInputName(i) == SymbolicName) return getNumOutputs() + NumPlusOperands + i; - for (unsigned i = 0, e = getNumLabels(); i != e; ++i) - if (getLabelName(i) == SymbolicName) - return i + getNumInputs(); - // Not found. return -1; } @@ -630,8 +615,8 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl&Pieces, while (CurPtr != StrEnd && isDigit(*CurPtr)) N = N*10 + ((*CurPtr++)-'0'); - unsigned NumOperands = getNumOutputs() + getNumPlusOperands() + - getNumInputs() + getNumLabels(); + unsigned NumOperands = + getNumOutputs() + getNumPlusOperands() + getNumInputs(); if (N >= NumOperands) { DiagOffs = CurPtr-StrStart-1; return diag::err_asm_invalid_operand_number; @@ -744,12 +729,10 @@ GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, unsigned numinputs, IdentifierInfo **names, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, - StringLiteral **clobbers, unsigned numlabels, - SourceLocation rparenloc) + StringLiteral **clobbers, SourceLocation rparenloc) : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, - numinputs, numclobbers), - RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) { - unsigned NumExprs = NumOutputs + NumInputs + NumLabels; + numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) { + unsigned NumExprs = NumOutputs + NumInputs; Names = new (C) IdentifierInfo*[NumExprs]; std::copy(names, names + NumExprs, Names); diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 563095f89b..7fe0be5217 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -414,15 +414,12 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) { if (Node->isVolatile()) OS << "volatile "; - if (Node->isAsmGoto()) - OS << "goto "; - OS << "("; VisitStringLiteral(Node->getAsmString()); // Outputs if (Node->getNumOutputs() != 0 || Node->getNumInputs() != 0 || - Node->getNumClobbers() != 0 || Node->getNumLabels() != 0) + Node->getNumClobbers() != 0) OS << " : "; for (unsigned i = 0, e = Node->getNumOutputs(); i != e; ++i) { @@ -442,8 +439,7 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) { } // Inputs - if (Node->getNumInputs() != 0 || Node->getNumClobbers() != 0 || - Node->getNumLabels() != 0) + if (Node->getNumInputs() != 0 || Node->getNumClobbers() != 0) OS << " : "; for (unsigned i = 0, e = Node->getNumInputs(); i != e; ++i) { @@ -463,7 +459,7 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) { } // Clobbers - if (Node->getNumClobbers() != 0 || Node->getNumLabels()) + if (Node->getNumClobbers() != 0) OS << " : "; for (unsigned i = 0, e = Node->getNumClobbers(); i != e; ++i) { @@ -473,16 +469,6 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) { VisitStringLiteral(Node->getClobberStringLiteral(i)); } - // Labels - if (Node->getNumLabels() != 0) - OS << " : "; - - for (unsigned i = 0, e = Node->getNumLabels(); i != e; ++i) { - if (i != 0) - OS << ", "; - OS << Node->getLabelName(i); - } - OS << ");"; if (Policy.IncludeNewlines) OS << NL; } diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index c5da5bfda9..93bdcac8b5 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -321,9 +321,6 @@ void StmtProfiler::VisitGCCAsmStmt(const GCCAsmStmt *S) { ID.AddInteger(S->getNumClobbers()); for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I) VisitStringLiteral(S->getClobberStringLiteral(I)); - ID.AddInteger(S->getNumLabels()); - for (auto *L : S->labels()) - VisitDecl(L->getLabel()); } void StmtProfiler::VisitMSAsmStmt(const MSAsmStmt *S) { diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index b53bfcca37..1d83359341 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -549,7 +549,6 @@ private: CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, AddStmtChoice asc); CFGBlock *VisitForStmt(ForStmt *F); CFGBlock *VisitGotoStmt(GotoStmt *G); - CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc); CFGBlock *VisitIfStmt(IfStmt *I); CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc); @@ -1479,38 +1478,22 @@ std::unique_ptr CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { E = BackpatchBlocks.end(); I != E; ++I ) { CFGBlock *B = I->block; - if (auto *G = dyn_cast(B->getTerminator())) { - LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); - // If there is no target for the goto, then we are looking at an - // incomplete AST. Handle this by not registering a successor. - if (LI == LabelMap.end()) - continue; - JumpTarget JT = LI->second; - prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition, - JT.scopePosition); - prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, - JT.scopePosition); - const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator( - B, I->scopePosition, JT.scopePosition); - appendScopeBegin(JT.block, VD, G); - addSuccessor(B, JT.block); - }; - if (auto *G = dyn_cast(B->getTerminator())) { - CFGBlock *Successor = (I+1)->block; - for (auto *L : G->labels()) { - LabelMapTy::iterator LI = LabelMap.find(L->getLabel()); - // If there is no target for the goto, then we are looking at an - // incomplete AST. Handle this by not registering a successor. - if (LI == LabelMap.end()) - continue; - JumpTarget JT = LI->second; - // Successor has been added, so skip it. - if (JT.block == Successor) - continue; - addSuccessor(B, JT.block); - } - I++; - } + const GotoStmt *G = cast(B->getTerminator()); + LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); + + // If there is no target for the goto, then we are looking at an + // incomplete AST. Handle this by not registering a successor. + if (LI == LabelMap.end()) continue; + + JumpTarget JT = LI->second; + prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition, + JT.scopePosition); + prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, + JT.scopePosition); + const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator( + B, I->scopePosition, JT.scopePosition); + appendScopeBegin(JT.block, VD, G); + addSuccessor(B, JT.block); } // Add successors to the Indirect Goto Dispatch block (if we have one). @@ -2159,9 +2142,6 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { case Stmt::GotoStmtClass: return VisitGotoStmt(cast(S)); - case Stmt::GCCAsmStmtClass: - return VisitGCCAsmStmt(cast(S), asc); - case Stmt::IfStmtClass: return VisitIfStmt(cast(S)); @@ -3166,28 +3146,6 @@ CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { return Block; } -CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) { - // Goto is a control-flow statement. Thus we stop processing the current - // block and create a new one. - - if (!G->isAsmGoto()) - return VisitStmt(G, asc); - - if (Block) { - Succ = Block; - if (badCFG) - return nullptr; - } - Block = createBlock(); - Block->setTerminator(G); - // We will backpatch this block later for all the labels. - BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); - // Save "Succ" in BackpatchBlocks. In the backpatch processing, "Succ" is - // used to avoid adding "Succ" again. - BackpatchBlocks.push_back(JumpSource(Succ, ScopePos)); - return Block; -} - CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { CFGBlock *LoopSuccessor = nullptr; diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 5c24db7092..c617b198d7 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -1896,55 +1896,6 @@ static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str, return llvm::MDNode::get(CGF.getLLVMContext(), Locs); } -static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, - bool ReadOnly, bool ReadNone, const AsmStmt &S, - const std::vector &ResultRegTypes, - CodeGenFunction &CGF, - std::vector &RegResults) { - Result.addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); - // Attach readnone and readonly attributes. - if (!HasSideEffect) { - if (ReadNone) - Result.addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadNone); - else if (ReadOnly) - Result.addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadOnly); - } - - // Slap the source location of the inline asm into a !srcloc metadata on the - // call. - if (const auto *gccAsmStmt = dyn_cast(&S)) - Result.setMetadata("srcloc", - getAsmSrcLocInfo(gccAsmStmt->getAsmString(), CGF)); - else { - // At least put the line number on MS inline asm blobs. - llvm::Constant *Loc = llvm::ConstantInt::get(CGF.Int32Ty, - S.getAsmLoc().getRawEncoding()); - Result.setMetadata("srcloc", - llvm::MDNode::get(CGF.getLLVMContext(), - llvm::ConstantAsMetadata::get(Loc))); - } - - if (CGF.getLangOpts().assumeFunctionsAreConvergent()) - // Conservatively, mark all inline asm blocks in CUDA or OpenCL as - // convergent (meaning, they may call an intrinsically convergent op, such - // as bar.sync, and so can't have certain optimizations applied around - // them). - Result.addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::Convergent); - // Extract all of the register value results from the asm. - if (ResultRegTypes.size() == 1) { - RegResults.push_back(&Result); - } else { - for (unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) { - llvm::Value *Tmp = CGF.Builder.CreateExtractValue(&Result, i, "asmresult"); - RegResults.push_back(Tmp); - } - } -} - void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { // Assemble the final asm string. std::string AsmString = S.generateAsmString(getContext()); @@ -2187,29 +2138,6 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { } Constraints += InOutConstraints; - // Labels - SmallVector Transfer; - llvm::BasicBlock *Fallthrough = nullptr; - bool IsGCCAsmGoto = false; - if (const auto *GS = dyn_cast(&S)) { - IsGCCAsmGoto = GS->isAsmGoto(); - if (IsGCCAsmGoto) { - for (auto *E : GS->labels()) { - JumpDest Dest = getJumpDestForLabel(E->getLabel()); - Transfer.push_back(Dest.getBlock()); - llvm::BlockAddress *BA = - llvm::BlockAddress::get(CurFn, Dest.getBlock()); - Args.push_back(BA); - ArgTypes.push_back(BA->getType()); - if (!Constraints.empty()) - Constraints += ','; - Constraints += 'X'; - } - StringRef Name = "asm.fallthrough"; - Fallthrough = createBasicBlock(Name); - } - } - // Clobbers for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) { StringRef Clobber = S.getClobber(i); @@ -2252,18 +2180,52 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { llvm::InlineAsm *IA = llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect, /* IsAlignStack */ false, AsmDialect); + llvm::CallInst *Result = + Builder.CreateCall(IA, Args, getBundlesForFunclet(IA)); + Result->addAttribute(llvm::AttributeList::FunctionIndex, + llvm::Attribute::NoUnwind); + + // Attach readnone and readonly attributes. + if (!HasSideEffect) { + if (ReadNone) + Result->addAttribute(llvm::AttributeList::FunctionIndex, + llvm::Attribute::ReadNone); + else if (ReadOnly) + Result->addAttribute(llvm::AttributeList::FunctionIndex, + llvm::Attribute::ReadOnly); + } + + // Slap the source location of the inline asm into a !srcloc metadata on the + // call. + if (const GCCAsmStmt *gccAsmStmt = dyn_cast(&S)) { + Result->setMetadata("srcloc", getAsmSrcLocInfo(gccAsmStmt->getAsmString(), + *this)); + } else { + // At least put the line number on MS inline asm blobs. + auto Loc = llvm::ConstantInt::get(Int32Ty, S.getAsmLoc().getRawEncoding()); + Result->setMetadata("srcloc", + llvm::MDNode::get(getLLVMContext(), + llvm::ConstantAsMetadata::get(Loc))); + } + + if (getLangOpts().assumeFunctionsAreConvergent()) { + // Conservatively, mark all inline asm blocks in CUDA or OpenCL as + // convergent (meaning, they may call an intrinsically convergent op, such + // as bar.sync, and so can't have certain optimizations applied around + // them). + Result->addAttribute(llvm::AttributeList::FunctionIndex, + llvm::Attribute::Convergent); + } + + // Extract all of the register value results from the asm. std::vector RegResults; - if (IsGCCAsmGoto) { - llvm::CallBrInst *Result = - Builder.CreateCallBr(IA, Fallthrough, Transfer, Args); - UpdateAsmCallInst(cast(*Result), HasSideEffect, ReadOnly, - ReadNone, S, ResultRegTypes, *this, RegResults); - EmitBlock(Fallthrough); + if (ResultRegTypes.size() == 1) { + RegResults.push_back(Result); } else { - llvm::CallInst *Result = - Builder.CreateCall(IA, Args, getBundlesForFunclet(IA)); - UpdateAsmCallInst(cast(*Result), HasSideEffect, ReadOnly, - ReadNone, S, ResultRegTypes, *this, RegResults); + for (unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) { + llvm::Value *Tmp = Builder.CreateExtractValue(Result, i, "asmresult"); + RegResults.push_back(Tmp); + } } assert(RegResults.size() == ResultRegTypes.size()); diff --git a/lib/Parse/ParseStmtAsm.cpp b/lib/Parse/ParseStmtAsm.cpp index 75f3ac396e..c63808a472 100644 --- a/lib/Parse/ParseStmtAsm.cpp +++ b/lib/Parse/ParseStmtAsm.cpp @@ -710,12 +710,12 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { // Remember if this was a volatile asm. bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile; - // Remember if this was a goto asm. - bool isGotoAsm = false; + // TODO: support "asm goto" constructs (PR#9295). if (Tok.is(tok::kw_goto)) { - isGotoAsm = true; - ConsumeToken(); + Diag(Tok, diag::err_asm_goto_not_supported_yet); + SkipUntil(tok::r_paren, StopAtSemi); + return StmtError(); } if (Tok.isNot(tok::l_paren)) { @@ -753,8 +753,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile, /*NumOutputs*/ 0, /*NumInputs*/ 0, nullptr, Constraints, Exprs, AsmString.get(), - Clobbers, /*NumLabels*/ 0, - T.getCloseLocation()); + Clobbers, T.getCloseLocation()); } // Parse Outputs, if present. @@ -764,12 +763,6 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { AteExtraColon = Tok.is(tok::coloncolon); ConsumeToken(); - if (!AteExtraColon && isGotoAsm && Tok.isNot(tok::colon)) { - Diag(Tok, diag::err_asm_goto_cannot_have_output); - SkipUntil(tok::r_paren, StopAtSemi); - return StmtError(); - } - if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs)) return StmtError(); } @@ -796,15 +789,12 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { unsigned NumInputs = Names.size() - NumOutputs; // Parse the clobbers, if present. - if (AteExtraColon || Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { - if (AteExtraColon) - AteExtraColon = false; - else { - AteExtraColon = Tok.is(tok::coloncolon); + if (AteExtraColon || Tok.is(tok::colon)) { + if (!AteExtraColon) ConsumeToken(); - } + // Parse the asm-string list for clobbers if present. - if (!AteExtraColon && isTokenStringLiteral()) { + if (Tok.isNot(tok::r_paren)) { while (1) { ExprResult Clobber(ParseAsmStringLiteral()); @@ -818,49 +808,11 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { } } } - if (!isGotoAsm && (Tok.isNot(tok::r_paren) || AteExtraColon)) { - Diag(Tok, diag::err_expected) << tok::r_paren; - SkipUntil(tok::r_paren, StopAtSemi); - return StmtError(); - } - - // Parse the goto label, if present. - unsigned NumLabels = 0; - if (AteExtraColon || Tok.is(tok::colon)) { - if (!AteExtraColon) - ConsumeToken(); - while (true) { - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; - SkipUntil(tok::r_paren, StopAtSemi); - return StmtError(); - } - LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(), - Tok.getLocation()); - Names.push_back(Tok.getIdentifierInfo()); - if (!LD) { - SkipUntil(tok::r_paren, StopAtSemi); - return StmtError(); - } - ExprResult Res = - Actions.ActOnAddrLabel(Tok.getLocation(), Tok.getLocation(), LD); - Exprs.push_back(Res.get()); - NumLabels++; - ConsumeToken(); - if (!TryConsumeToken(tok::comma)) - break; - } - } else if (isGotoAsm) { - Diag(Tok, diag::err_expected) << tok::colon; - SkipUntil(tok::r_paren, StopAtSemi); - return StmtError(); - } T.consumeClose(); return Actions.ActOnGCCAsmStmt( AsmLoc, false, isVolatile, NumOutputs, NumInputs, Names.data(), - Constraints, Exprs, AsmString.get(), Clobbers, NumLabels, - T.getCloseLocation()); + Constraints, Exprs, AsmString.get(), Clobbers, T.getCloseLocation()); } /// ParseAsmOperands - Parse the asm-operands production as used by diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index c8743df90e..2234d6ba9b 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -65,10 +65,8 @@ class JumpScopeChecker { llvm::DenseMap LabelAndGotoScopes; SmallVector Jumps; - SmallVector IndirectJumps; - SmallVector AsmJumps; + SmallVector IndirectJumps; SmallVector IndirectJumpTargets; - SmallVector AsmJumpTargets; public: JumpScopeChecker(Stmt *Body, Sema &S); private: @@ -78,10 +76,10 @@ private: void BuildScopeInformation(Stmt *S, unsigned &origParentScope); void VerifyJumps(); - void VerifyIndirectOrAsmJumps(bool IsAsmGoto); + void VerifyIndirectJumps(); void NoteJumpIntoScopes(ArrayRef ToScopes); - void DiagnoseIndirectOrAsmJump(Stmt *IG, unsigned IGScope, LabelDecl *Target, - unsigned TargetScope); + void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope, + LabelDecl *Target, unsigned TargetScope); void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, unsigned JumpDiag, unsigned JumpDiagWarning, unsigned JumpDiagCXX98Compat); @@ -105,8 +103,7 @@ JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) // Check that all jumps we saw are kosher. VerifyJumps(); - VerifyIndirectOrAsmJumps(false); - VerifyIndirectOrAsmJumps(true); + VerifyIndirectJumps(); } /// GetDeepestCommonScope - Finds the innermost scope enclosing the @@ -319,7 +316,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, } LabelAndGotoScopes[S] = ParentScope; - IndirectJumps.push_back(S); + IndirectJumps.push_back(cast(S)); break; case Stmt::SwitchStmtClass: @@ -342,18 +339,6 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, Jumps.push_back(S); break; - case Stmt::GCCAsmStmtClass: - if (auto *GS = dyn_cast(S)) - if (GS->isAsmGoto()) { - // Remember both what scope a goto is in as well as the fact that we - // have it. This makes the second scan not have to walk the AST again. - LabelAndGotoScopes[S] = ParentScope; - AsmJumps.push_back(GS); - for (auto *E : GS->labels()) - AsmJumpTargets.push_back(E->getLabel()); - } - break; - case Stmt::IfStmtClass: { IfStmt *IS = cast(S); if (!(IS->isConstexpr() || IS->isObjCAvailabilityCheck())) @@ -644,13 +629,14 @@ void JumpScopeChecker::VerifyJumps() { } } -/// VerifyIndirectOrAsmJumps - Verify whether any possible indirect goto or -/// asm goto jump might cross a protection boundary. Unlike direct jumps, -/// indirect or asm goto jumps count cleanups as protection boundaries: -/// since there's no way to know where the jump is going, we can't implicitly -/// run the right cleanups the way we can with direct jumps. -/// Thus, an indirect/asm jump is "trivial" if it bypasses no -/// initializations and no teardowns. More formally, an indirect/asm jump +/// VerifyIndirectJumps - Verify whether any possible indirect jump +/// might cross a protection boundary. Unlike direct jumps, indirect +/// jumps count cleanups as protection boundaries: since there's no +/// way to know where the jump is going, we can't implicitly run the +/// right cleanups the way we can with direct jumps. +/// +/// Thus, an indirect jump is "trivial" if it bypasses no +/// initializations and no teardowns. More formally, an indirect jump /// from A to B is trivial if the path out from A to DCA(A,B) is /// trivial and the path in from DCA(A,B) to B is trivial, where /// DCA(A,B) is the deepest common ancestor of A and B. @@ -662,41 +648,36 @@ void JumpScopeChecker::VerifyJumps() { /// Under these definitions, this function checks that the indirect /// jump between A and B is trivial for every indirect goto statement A /// and every label B whose address was taken in the function. -void JumpScopeChecker::VerifyIndirectOrAsmJumps(bool IsAsmGoto) { - SmallVector GotoJumps = IsAsmGoto ? AsmJumps : IndirectJumps; - if (GotoJumps.empty()) - return; - SmallVector JumpTargets = - IsAsmGoto ? AsmJumpTargets : IndirectJumpTargets; +void JumpScopeChecker::VerifyIndirectJumps() { + if (IndirectJumps.empty()) return; + // If there aren't any address-of-label expressions in this function, // complain about the first indirect goto. - if (JumpTargets.empty()) { - assert(!IsAsmGoto &&"only indirect goto can get here"); - S.Diag(GotoJumps[0]->getBeginLoc(), + if (IndirectJumpTargets.empty()) { + S.Diag(IndirectJumps[0]->getGotoLoc(), diag::err_indirect_goto_without_addrlabel); return; } + // Collect a single representative of every scope containing an - // indirect or asm goto. For most code bases, this substantially cuts + // indirect goto. For most code bases, this substantially cuts // down on the number of jump sites we'll have to consider later. - typedef std::pair JumpScope; + typedef std::pair JumpScope; SmallVector JumpScopes; { - llvm::DenseMap JumpScopesMap; - for (SmallVectorImpl::iterator I = GotoJumps.begin(), - E = GotoJumps.end(); - I != E; ++I) { - Stmt *IG = *I; + llvm::DenseMap JumpScopesMap; + for (SmallVectorImpl::iterator + I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) { + IndirectGotoStmt *IG = *I; if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(IG))) continue; unsigned IGScope = LabelAndGotoScopes[IG]; - Stmt *&Entry = JumpScopesMap[IGScope]; + IndirectGotoStmt *&Entry = JumpScopesMap[IGScope]; if (!Entry) Entry = IG; } JumpScopes.reserve(JumpScopesMap.size()); - for (llvm::DenseMap::iterator I = JumpScopesMap.begin(), - E = JumpScopesMap.end(); - I != E; ++I) + for (llvm::DenseMap::iterator + I = JumpScopesMap.begin(), E = JumpScopesMap.end(); I != E; ++I) JumpScopes.push_back(*I); } @@ -704,8 +685,8 @@ void JumpScopeChecker::VerifyIndirectOrAsmJumps(bool IsAsmGoto) { // label whose address was taken somewhere in the function. // For most code bases, there will be only one such scope. llvm::DenseMap TargetScopes; - for (SmallVectorImpl::iterator I = JumpTargets.begin(), - E = JumpTargets.end(); + for (SmallVectorImpl::iterator + I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end(); I != E; ++I) { LabelDecl *TheLabel = *I; if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(TheLabel->getStmt()))) @@ -782,7 +763,7 @@ void JumpScopeChecker::VerifyIndirectOrAsmJumps(bool IsAsmGoto) { // Only diagnose if we didn't find something. if (IsReachable) continue; - DiagnoseIndirectOrAsmJump(I->second, I->first, TargetLabel, TargetScope); + DiagnoseIndirectJump(I->second, I->first, TargetLabel, TargetScope); } } } @@ -803,15 +784,12 @@ static bool IsCXX98CompatWarning(Sema &S, unsigned InDiagNote) { } /// Produce primary diagnostic for an indirect jump statement. -static void DiagnoseIndirectOrAsmJumpStmt(Sema &S, Stmt *Jump, - LabelDecl *Target, bool &Diagnosed) { +static void DiagnoseIndirectJumpStmt(Sema &S, IndirectGotoStmt *Jump, + LabelDecl *Target, bool &Diagnosed) { if (Diagnosed) return; - bool IsAsmGoto = isa(Jump); - S.Diag(Jump->getBeginLoc(), diag::err_indirect_goto_in_protected_scope) - << IsAsmGoto; - S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target) - << IsAsmGoto; + S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope); + S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); Diagnosed = true; } @@ -825,9 +803,10 @@ void JumpScopeChecker::NoteJumpIntoScopes(ArrayRef ToScopes) { } /// Diagnose an indirect jump which is known to cross scopes. -void JumpScopeChecker::DiagnoseIndirectOrAsmJump(Stmt *Jump, unsigned JumpScope, - LabelDecl *Target, - unsigned TargetScope) { +void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump, + unsigned JumpScope, + LabelDecl *Target, + unsigned TargetScope) { if (CHECK_PERMISSIVE(JumpScope == TargetScope)) return; @@ -837,7 +816,7 @@ void JumpScopeChecker::DiagnoseIndirectOrAsmJump(Stmt *Jump, unsigned JumpScope, // Walk out the scope chain until we reach the common ancestor. for (unsigned I = JumpScope; I != Common; I = Scopes[I].ParentScope) if (Scopes[I].OutDiag) { - DiagnoseIndirectOrAsmJumpStmt(S, Jump, Target, Diagnosed); + DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed); S.Diag(Scopes[I].Loc, Scopes[I].OutDiag); } @@ -848,18 +827,15 @@ void JumpScopeChecker::DiagnoseIndirectOrAsmJump(Stmt *Jump, unsigned JumpScope, if (IsCXX98CompatWarning(S, Scopes[I].InDiag)) ToScopesCXX98Compat.push_back(I); else if (Scopes[I].InDiag) { - DiagnoseIndirectOrAsmJumpStmt(S, Jump, Target, Diagnosed); + DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed); S.Diag(Scopes[I].Loc, Scopes[I].InDiag); } // Diagnose this jump if it would be ill-formed in C++98. if (!Diagnosed && !ToScopesCXX98Compat.empty()) { - bool IsAsmGoto = isa(Jump); - S.Diag(Jump->getBeginLoc(), - diag::warn_cxx98_compat_indirect_goto_in_protected_scope) - << IsAsmGoto; - S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target) - << IsAsmGoto; + S.Diag(Jump->getGotoLoc(), + diag::warn_cxx98_compat_indirect_goto_in_protected_scope); + S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); NoteJumpIntoScopes(ToScopesCXX98Compat); } } diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index ec8958c3c5..8c6012573c 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -209,12 +209,11 @@ static StringRef extractRegisterName(const Expr *Expression, static SourceLocation getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints, StringLiteral **Clobbers, int NumClobbers, - unsigned NumLabels, const TargetInfo &Target, ASTContext &Cont) { llvm::StringSet<> InOutVars; // Collect all the input and output registers from the extended asm // statement in order to check for conflicts with the clobber list - for (unsigned int i = 0; i < Exprs.size() - NumLabels; ++i) { + for (unsigned int i = 0; i < Exprs.size(); ++i) { StringRef Constraint = Constraints[i]->getString(); StringRef InOutReg = Target.getConstraintRegister( Constraint, extractRegisterName(Exprs[i], Target)); @@ -242,7 +241,6 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, unsigned NumInputs, IdentifierInfo **Names, MultiExprArg constraints, MultiExprArg Exprs, Expr *asmString, MultiExprArg clobbers, - unsigned NumLabels, SourceLocation RParenLoc) { unsigned NumClobbers = clobbers.size(); StringLiteral **Constraints = @@ -271,7 +269,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, return new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs.data(), AsmString, - NumClobbers, Clobbers, NumLabels, RParenLoc); + NumClobbers, Clobbers, RParenLoc); } ExprResult ER = CheckPlaceholderExpr(Exprs[i]); @@ -332,7 +330,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, return new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs.data(), AsmString, - NumClobbers, Clobbers, NumLabels, RParenLoc); + NumClobbers, Clobbers, RParenLoc); } } @@ -354,7 +352,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, return new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs.data(), AsmString, - NumClobbers, Clobbers, NumLabels, RParenLoc); + NumClobbers, Clobbers, RParenLoc); } ExprResult ER = CheckPlaceholderExpr(Exprs[i]); @@ -453,15 +451,14 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, return new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs.data(), AsmString, - NumClobbers, Clobbers, NumLabels, RParenLoc); + NumClobbers, Clobbers, RParenLoc); } } GCCAsmStmt *NS = new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs.data(), - AsmString, NumClobbers, Clobbers, NumLabels, - RParenLoc); + AsmString, NumClobbers, Clobbers, RParenLoc); // Validate the asm string, ensuring it makes sense given the operands we // have. SmallVector Pieces; @@ -479,10 +476,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, // Look for the correct constraint index. unsigned ConstraintIdx = Piece.getOperandNo(); - // Labels are the last in the Exprs list. - if (NS->isAsmGoto() && ConstraintIdx >= NS->getNumInputs()) - continue; unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs(); + // Look for the (ConstraintIdx - NumOperands + 1)th constraint with // modifier '+'. if (ConstraintIdx >= NumOperands) { @@ -665,39 +660,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, // Check for conflicts between clobber list and input or output lists SourceLocation ConstraintLoc = getClobberConflictLocation(Exprs, Constraints, Clobbers, NumClobbers, - NumLabels, Context.getTargetInfo(), Context); if (ConstraintLoc.isValid()) targetDiag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber); - // Check for duplicate asm operand name between input, output and label lists. - typedef std::pair NamedOperand; - SmallVector NamedOperandList; - for (unsigned i = 0, e = NumOutputs + NumInputs + NumLabels; i != e; ++i) - if (Names[i]) - NamedOperandList.emplace_back( - std::make_pair(Names[i]->getName(), Exprs[i])); - // Sort NamedOperandList. - std::stable_sort(NamedOperandList.begin(), NamedOperandList.end(), - [](const NamedOperand &LHS, const NamedOperand &RHS) { - return LHS.first < RHS.first; - }); - // Find adjacent duplicate operand. - SmallVector::iterator Found = - std::adjacent_find(begin(NamedOperandList), end(NamedOperandList), - [](const NamedOperand &LHS, const NamedOperand &RHS) { - return LHS.first == RHS.first; - }); - if (Found != NamedOperandList.end()) { - Diag((Found + 1)->second->getBeginLoc(), - diag::error_duplicate_asm_operand_name) - << (Found + 1)->first; - Diag(Found->second->getBeginLoc(), diag::note_duplicate_asm_operand_name) - << Found->first; - return StmtError(); - } - if (NS->isAsmGoto()) - setFunctionHasBranchIntoScope(); return NS; } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 609a3cfcfc..6620885f23 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1373,11 +1373,10 @@ public: unsigned NumInputs, IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, Expr *AsmString, MultiExprArg Clobbers, - unsigned NumLabels, SourceLocation RParenLoc) { return getSema().ActOnGCCAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs, - AsmString, Clobbers, NumLabels, RParenLoc); + AsmString, Clobbers, RParenLoc); } /// Build a new MS style inline asm statement. @@ -7052,16 +7051,6 @@ TreeTransform::TransformGCCAsmStmt(GCCAsmStmt *S) { Exprs.push_back(Result.get()); } - // Go through the Labels. - for (unsigned I = 0, E = S->getNumLabels(); I != E; ++I) { - Names.push_back(S->getLabelIdentifier(I)); - - ExprResult Result = getDerived().TransformExpr(S->getLabelExpr(I)); - if (Result.isInvalid()) - return StmtError(); - ExprsChanged |= Result.get() != S->getLabelExpr(I); - Exprs.push_back(Result.get()); - } if (!getDerived().AlwaysRebuild() && !ExprsChanged) return S; @@ -7075,8 +7064,7 @@ TreeTransform::TransformGCCAsmStmt(GCCAsmStmt *S) { S->isVolatile(), S->getNumOutputs(), S->getNumInputs(), Names.data(), Constraints, Exprs, AsmString.get(), - Clobbers, S->getNumLabels(), - S->getRParenLoc()); + Clobbers, S->getRParenLoc()); } template diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 52aa3d961d..4d879b46e1 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -370,14 +370,12 @@ void ASTStmtReader::VisitAsmStmt(AsmStmt *S) { void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) { VisitAsmStmt(S); - S->NumLabels = Record.readInt(); S->setRParenLoc(ReadSourceLocation()); S->setAsmString(cast_or_null(Record.readSubStmt())); unsigned NumOutputs = S->getNumOutputs(); unsigned NumInputs = S->getNumInputs(); unsigned NumClobbers = S->getNumClobbers(); - unsigned NumLabels = S->getNumLabels(); // Outputs and inputs SmallVector Names; @@ -394,14 +392,9 @@ void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) { for (unsigned I = 0; I != NumClobbers; ++I) Clobbers.push_back(cast_or_null(Record.readSubStmt())); - // Labels - for (unsigned I = 0, N = NumLabels; I != N; ++I) - Exprs.push_back(Record.readSubStmt()); - S->setOutputsAndInputsAndClobbers(Record.getContext(), Names.data(), Constraints.data(), Exprs.data(), NumOutputs, NumInputs, - NumLabels, Clobbers.data(), NumClobbers); } diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 776aab6bf5..b0a35cf2f5 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -283,7 +283,6 @@ void ASTStmtWriter::VisitAsmStmt(AsmStmt *S) { void ASTStmtWriter::VisitGCCAsmStmt(GCCAsmStmt *S) { VisitAsmStmt(S); - Record.push_back(S->getNumLabels()); Record.AddSourceLocation(S->getRParenLoc()); Record.AddStmt(S->getAsmString()); @@ -305,9 +304,6 @@ void ASTStmtWriter::VisitGCCAsmStmt(GCCAsmStmt *S) { for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I) Record.AddStmt(S->getClobberStringLiteral(I)); - // Labels - for (auto *E : S->labels()) Record.AddStmt(E); - Code = serialization::STMT_GCCASM; } diff --git a/test/Analysis/asm-goto.cpp b/test/Analysis/asm-goto.cpp deleted file mode 100644 index 3d4babc57b..0000000000 --- a/test/Analysis/asm-goto.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s - -int foo(int cond) -{ -label_true: - asm goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop); - return 0; -loop: - return 0; -} - -// CHECK-LABEL: loop -// CHECK-NEXT: 0 -// CHECK-NEXT: return -// CHECK-NEXT: Preds (1): B3 -// CHECK-NEXT: Succs (1): B0 - -// CHECK-LABEL: label_true -// CHECK-NEXT: asm goto -// CHECK-NEXT: Preds (2): B3 B4 -// CHECK-NEXT: Succs (3): B2 B3 B1 - - -int bar(int cond) -{ - asm goto("testl %0, %0; jne %l1;" :: "r"(cond)::L1, L2); - return 0; -L1: -L2: - return 0; -} - -// CHECK: [B4] -// CHECK-NEXT: asm goto -// CHECK-NEXT: Preds (1): B5 -// CHECK-NEXT: Succs (3): B3 B2 B1 - -int zoo(int n) -{ -A5: -A1: - asm goto("testl %0, %0; jne %l1;" :: "r"(n)::A1, A2, A3, A4, A5); -A2: -A3: -A4: - return 0; -} - -// CHECK-LABEL: A1 -// CHECK-NEXT: asm goto -// CHECK-NEXT: Preds (2): B5 B4 -// CHECK-NEXT: Succs (5): B3 B4 B2 B1 B5 diff --git a/test/CodeGen/asm-goto.c b/test/CodeGen/asm-goto.c deleted file mode 100644 index 99e97f2a41..0000000000 --- a/test/CodeGen/asm-goto.c +++ /dev/null @@ -1,19 +0,0 @@ -// REQUIRES: x86-registered-target -// RUN: %clang_cc1 -triple x86_64 -O0 -emit-llvm %s -o - | FileCheck %s - -int foo(int cond) -{ - // CHECK: callbr void asm sideeffect - // CHECK: to label %asm.fallthrough [label %label_true, label %loop], !srcloc !2 - // CHECK: asm.fallthrough: - asm volatile goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop); - asm volatile goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop); - // CHECK: callbr void asm sideeffect - // CHECK: to label %asm.fallthrough1 [label %label_true, label %loop], !srcloc !3 - // CHECK: asm.fallthrough1: - return 0; -loop: - return 0; -label_true: - return 1; -} diff --git a/test/CodeGen/asm.c b/test/CodeGen/asm.c index 7de79639bf..038d346e99 100644 --- a/test/CodeGen/asm.c +++ b/test/CodeGen/asm.c @@ -262,15 +262,3 @@ void t31(int len) { // CHECK: @t31 // CHECK: call void asm sideeffect "", "=*%rm,=*rm,0,1,~{dirflag},~{fpsr},~{flags}" } - -// CHECK: @t32 -int t32(int cond) -{ - asm goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop); - // CHECK: callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,X,X,~{dirflag},~{fpsr},~{flags}"(i32 %0, i8* blockaddress(@t32, %label_true), i8* blockaddress(@t32, %loop)) #1 - return 0; -loop: - return 0; -label_true: - return 1; -} diff --git a/test/CodeGen/inline-asm-mixed-style.c b/test/CodeGen/inline-asm-mixed-style.c index a9e111cd5d..6b830d9fa7 100644 --- a/test/CodeGen/inline-asm-mixed-style.c +++ b/test/CodeGen/inline-asm-mixed-style.c @@ -1,3 +1,4 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -fsyntax-only -verify %s -DCHECK_ASM_GOTO // RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -O0 -emit-llvm -S %s -o - | FileCheck %s // REQUIRES: x86-registered-target @@ -19,11 +20,10 @@ void f() { // CHECK: movl %ebx, %eax // CHECK: movl %ecx, %edx - __asm volatile goto ("movl %ecx, %edx"); - // CHECK: movl %ecx, %edx +#ifdef CHECK_ASM_GOTO + __asm volatile goto ("movl %ecx, %edx"); // expected-error {{'asm goto' constructs are not supported yet}} __asm mov eax, ebx - __asm goto ("movl %ecx, %edx"); - // CHECK: movl %ebx, %eax - // CHECK: movl %ecx, %edx + __asm goto ("movl %ecx, %edx"); // expected-error {{'asm goto' constructs are not supported yet}} +#endif } diff --git a/test/Coverage/c-language-features.inc b/test/Coverage/c-language-features.inc index ea3b96f600..356687907d 100644 --- a/test/Coverage/c-language-features.inc +++ b/test/Coverage/c-language-features.inc @@ -71,9 +71,7 @@ theif: } asm ("nop"); - int cond; - asm goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true); -label_true: + return; } diff --git a/test/PCH/asm.h b/test/PCH/asm.h index 5a7268eff6..a568058d58 100644 --- a/test/PCH/asm.h +++ b/test/PCH/asm.h @@ -1,14 +1,10 @@ // Header for the PCH test asm.c void f() { - int i,cond; + int i; asm ("foo\n" : : "a" (i + 2)); asm ("foo\n" : [symbolic_name] "=a" (i) : "[symbolic_name]" (i)); - asm volatile goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop); -label_true: -loop: - return; } void clobbers() { diff --git a/test/Parser/asm.c b/test/Parser/asm.c index 489b545ebe..637f9d7ed4 100644 --- a/test/Parser/asm.c +++ b/test/Parser/asm.c @@ -21,56 +21,6 @@ void f2() { } -int a, b, c, d, e, f, g, h, i, j, k, l; - -void -fgoto1 (void) -{ - __asm__ volatile goto ("" - :: [a] "r" (a), [b] "r" (b), [c] "r" (c), [d] "r" (d), - [e] "r" (e), [f] "r" (f), [g] "r" (g), [h] "r" (h), - [i] "r" (i), [j] "r" (j), [k] "r" (k), [l] "r" (l) - ::lab1,lab2); -lab1: return; -lab2: return; -} - -void -fgoto2 (void) -{ - __asm__ volatile goto ("" - :: [a] "r,m" (a), [b] "r,m" (b), [c] "r,m" (c), [d] "r,m" (d), - [e] "r,m" (e), [f] "r,m" (f), [g] "r,m" (g), [h] "r,m" (h), - [i] "r,m" (i), [j] "r,m" (j), [k] "r,m" (k), [l] "r,m" (l) - :: lab); - lab: return; -} - -int zoo () -{ - int x,cond,*e; - // expected-error@+1 {{expected ')'}} - asm ("mov %[e], %[e]" : : [e] "rm" (*e)::a) - // expected-error@+1 {{'asm goto' cannot have output constraints}} - asm goto ("decl %0; jnz %l[a]" :"=r"(x): "m"(x) : "memory" : a); - // expected-error@+1 {{expected identifie}} - asm goto ("decl %0;" :: "m"(x) : "memory" : ); - // expected-error@+1 {{expected ':'}} - asm goto ("decl %0;" :: "m"(x) : "memory" ); - // expected-error@+1 {{use of undeclared label 'x'}} - asm goto ("decl %0;" :: "m"(x) : "memory" :x); - // expected-error@+1 {{use of undeclared label 'b'}} - asm goto ("decl %0;" :: "m"(x) : "memory" :b); - // expected-error@+1 {{invalid operand number in inline asm string}} - asm goto ("testl %0, %0; jne %l3;" :: "r"(cond)::label_true, loop); - // expected-error@+1 {{unknown symbolic operand name in inline assembly string}} - asm goto ("decl %0; jnz %l[b]" :: "m"(x) : "memory" : a); -a: -label_true: -loop: - return 0; -} - // rdar://5952468 __asm ; // expected-error {{expected '(' after 'asm'}} diff --git a/test/Parser/asm.cpp b/test/Parser/asm.cpp index 9c4d62a255..9f64dfea47 100644 --- a/test/Parser/asm.cpp +++ b/test/Parser/asm.cpp @@ -7,54 +7,3 @@ int foo4 asm (u"bar4"); // expected-error {{cannot use unicode string literal in int foo5 asm (U"bar5"); // expected-error {{cannot use unicode string literal in 'asm'}} int foo6 asm ("bar6"_x); // expected-error {{string literal with user-defined suffix cannot be used here}} int foo6 asm ("" L"bar7"); // expected-error {{cannot use wide string literal in 'asm'}} - -int zoo () -{ - int x,cond,*e; - // expected-error@+1 {{expected ')'}} - asm ("mov %[e], %[e]" : : [e] "rm" (*e)::a) - // expected-error@+1 {{'asm goto' cannot have output constraints}} - asm goto ("decl %0; jnz %l[a]" :"=r"(x): "m"(x) : "memory" : a); - // expected-error@+1 {{expected identifie}} - asm goto ("decl %0;" :: "m"(x) : "memory" : ); - // expected-error@+1 {{expected ':'}} - asm goto ("decl %0;" :: "m"(x) : "memory" ); - // expected-error@+1 {{use of undeclared label 'x'}} - asm goto ("decl %0;" :: "m"(x) : "memory" :x); - // expected-error@+1 {{use of undeclared label 'b'}} - asm goto ("decl %0;" :: "m"(x) : "memory" :b); - // expected-error@+1 {{invalid operand number in inline asm string}} - asm goto ("testl %0, %0; jne %l3;" :: "r"(cond)::label_true, loop); - // expected-error@+1 {{unknown symbolic operand name in inline assembly string}} - asm goto ("decl %0; jnz %l[b]" :: "m"(x) : "memory" : a); -label_true: -loop: -a: - return 0; -} - - -int a, b, c, d, e, f, g, h, i, j, k, l; - -void -fgoto1 (void) -{ - __asm__ volatile goto ("" - :: [a] "r" (a), [b] "r" (b), [c] "r" (c), [d] "r" (d), - [e] "r" (e), [f] "r" (f), [g] "r" (g), [h] "r" (h), - [i] "r" (i), [j] "r" (j), [k] "r" (k), [l] "r" (l) - ::lab1,lab2); -lab1: return; -lab2: return; -} - -void -fgoto2 (void) -{ - __asm__ volatile goto ("" - :: [a] "r,m" (a), [b] "r,m" (b), [c] "r,m" (c), [d] "r,m" (d), - [e] "r,m" (e), [f] "r,m" (f), [g] "r,m" (g), [h] "r,m" (h), - [i] "r,m" (i), [j] "r,m" (j), [k] "r,m" (k), [l] "r,m" (l) - :: lab); - lab: return; -} diff --git a/test/Sema/asm-goto.cpp b/test/Sema/asm-goto.cpp deleted file mode 100644 index f61a8096b8..0000000000 --- a/test/Sema/asm-goto.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// RUN: %clang_cc1 %s -triple i386-pc-linux-gnu -verify -fsyntax-only - -struct NonTrivial { - ~NonTrivial(); - int f(int); -private: - int k; -}; -void JumpDiagnostics(int n) { -// expected-error@+1 {{cannot jump from this goto statement to its label}} - goto DirectJump; -// expected-note@+1 {{jump bypasses variable with a non-trivial destructor}} - NonTrivial tnp1; - -DirectJump: -// expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}} - asm goto("jmp %l0;" ::::Later); -// expected-note@+1 {{jump bypasses variable with a non-trivial destructor}} - NonTrivial tnp2; -// expected-note@+1 {{possible target of asm goto statement}} -Later: - return; -} - -struct S { ~S(); }; -void foo(int a) { - if (a) { -FOO: -// expected-note@+2 {{jump exits scope of variable with non-trivial destructor}} -// expected-note@+1 {{jump exits scope of variable with non-trivial destructor}} - S s; - void *p = &&BAR; -// expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}} - asm goto("jmp %l0;" ::::BAR); -// expected-error@+1 {{cannot jump from this indirect goto statement to one of its possible targets}} - goto *p; - p = &&FOO; - goto *p; - return; - } -// expected-note@+2 {{possible target of asm goto statement}} -// expected-note@+1 {{possible target of indirect goto statement}} -BAR: - return; -} diff --git a/test/Sema/asm.c b/test/Sema/asm.c index 29a55c610d..67da197426 100644 --- a/test/Sema/asm.c +++ b/test/Sema/asm.c @@ -295,24 +295,3 @@ int test17(int t0) return r0 + r1; } -void test18() -{ - // expected-error@+2 {{duplicate use of asm operand name "lab"}} - // expected-note@+1 {{asm operand name "lab" first referenced here}} - asm goto ("" : : : : lab, lab, lab2, lab); - // expected-error@+2 {{duplicate use of asm operand name "lab"}} - // expected-note@+1 {{asm operand name "lab" first referenced here}} - asm goto ("xorw %[lab], %[lab]; je %l[lab]" : : [lab] "i" (0) : : lab); -lab:; -lab2:; - int x,x1; - // expected-error@+2 {{duplicate use of asm operand name "lab"}} - // expected-note@+1 {{asm operand name "lab" first referenced here}} - asm ("" : [lab] "=r" (x),[lab] "+r" (x) : [lab1] "r" (x)); - // expected-error@+2 {{duplicate use of asm operand name "lab"}} - // expected-note@+1 {{asm operand name "lab" first referenced here}} - asm ("" : [lab] "=r" (x1) : [lab] "r" (x)); - // expected-error@+1 {{invalid operand number in inline asm string}} - asm ("jne %l0":::); - asm goto ("jne %l0"::::lab); -} diff --git a/test/Sema/inline-asm-validate-tmpl.cpp b/test/Sema/inline-asm-validate-tmpl.cpp index 9e234caa9c..cf7eac3d83 100644 --- a/test/Sema/inline-asm-validate-tmpl.cpp +++ b/test/Sema/inline-asm-validate-tmpl.cpp @@ -23,13 +23,3 @@ template void testc(int value) asm("rol %1, %0" :"=r"(value): "I"(N + 1)); } int foo() { testc<2>(10); } - -// these should compile without error -template bool testd() -{ - __asm goto ("" : : : : lab); - return true; -lab: - return false; -} -bool foox() { return testd<0> (); } diff --git a/test/Sema/scope-check.c b/test/Sema/scope-check.c index 0622450e2e..fa37d10d07 100644 --- a/test/Sema/scope-check.c +++ b/test/Sema/scope-check.c @@ -232,19 +232,3 @@ void test15(int n, void *pc) { // rdar://9024687 int test16(int [sizeof &&z]); // expected-error {{use of address-of-label extension outside of a function body}} - -//Asm goto: -int test16(int n) -{ - // expected-error@+2 {{cannot jump from this asm goto statement to one of its possible targets}} - // expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}} - asm volatile goto("testl %0, %0; jne %l1;" :: "r"(n)::label_true, loop); - // expected-note@+2 {{jump bypasses initialization of variable length array}} - // expected-note@+1 {{possible target of asm goto statement}} - return ({int a[n];label_true: 2;}); - // expected-note@+1 {{jump bypasses initialization of variable length array}} - int b[n]; -// expected-note@+1 {{possible target of asm goto statement}} -loop: - return 0; -} -- 2.40.0