diff options
author | Erich Keane <erich.keane@intel.com> | 2019-05-30 15:38:02 +0000 |
---|---|---|
committer | Erich Keane <erich.keane@intel.com> | 2019-05-30 15:38:02 +0000 |
commit | d0f34fd19850c79f8741301c3bfe0312ca24324c (patch) | |
tree | d11a14843235915243dc65478eb97f80753ceb8c /clang/lib | |
parent | e6ddde57e27e03054fd0a7cd627ce7917559a690 (diff) | |
download | bcm5719-llvm-d0f34fd19850c79f8741301c3bfe0312ca24324c.tar.gz bcm5719-llvm-d0f34fd19850c79f8741301c3bfe0312ca24324c.zip |
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
llvm-svn: 362106
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 10 | ||||
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 29 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 20 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 74 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 126 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmtAsm.cpp | 68 | ||||
-rw-r--r-- | clang/lib/Sema/JumpDiagnostics.cpp | 114 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmtAsm.cpp | 48 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 16 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 4 |
12 files changed, 135 insertions, 384 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 1f1ec1d687c..2e4c304b3de 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -5592,17 +5592,12 @@ ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { return InputOrErr.takeError(); } - SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs() + - S->getNumLabels()); + SmallVector<Expr *, 4> 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/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 0a4d403106b..68a5a2d6ab0 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/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<AddrLabelExpr>(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<AsmStringPiece>&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/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 563095f89b9..7fe0be5217d 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/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/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index c5da5bfda9c..93bdcac8b54 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/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/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index b53bfcca37c..1d833593415 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/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<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { E = BackpatchBlocks.end(); I != E; ++I ) { CFGBlock *B = I->block; - if (auto *G = dyn_cast<GotoStmt>(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<GCCAsmStmt>(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<GotoStmt>(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<GotoStmt>(S)); - case Stmt::GCCAsmStmtClass: - return VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc); - case Stmt::IfStmtClass: return VisitIfStmt(cast<IfStmt>(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/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 5c24db70925..c617b198d76 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/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<llvm::Type *> &ResultRegTypes, - CodeGenFunction &CGF, - std::vector<llvm::Value *> &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<GCCAsmStmt>(&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<llvm::BasicBlock *, 16> Transfer; - llvm::BasicBlock *Fallthrough = nullptr; - bool IsGCCAsmGoto = false; - if (const auto *GS = dyn_cast<GCCAsmStmt>(&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<GCCAsmStmt>(&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<llvm::Value*> RegResults; - if (IsGCCAsmGoto) { - llvm::CallBrInst *Result = - Builder.CreateCallBr(IA, Fallthrough, Transfer, Args); - UpdateAsmCallInst(cast<llvm::CallBase>(*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<llvm::CallBase>(*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/clang/lib/Parse/ParseStmtAsm.cpp b/clang/lib/Parse/ParseStmtAsm.cpp index 75f3ac396e1..c63808a472b 100644 --- a/clang/lib/Parse/ParseStmtAsm.cpp +++ b/clang/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/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp index c8743df90e3..2234d6ba9b1 100644 --- a/clang/lib/Sema/JumpDiagnostics.cpp +++ b/clang/lib/Sema/JumpDiagnostics.cpp @@ -65,10 +65,8 @@ class JumpScopeChecker { llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes; SmallVector<Stmt*, 16> Jumps; - SmallVector<Stmt*, 4> IndirectJumps; - SmallVector<Stmt*, 4> AsmJumps; + SmallVector<IndirectGotoStmt*, 4> IndirectJumps; SmallVector<LabelDecl*, 4> IndirectJumpTargets; - SmallVector<LabelDecl*, 4> 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<unsigned> 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<IndirectGotoStmt>(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<GCCAsmStmt>(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<IfStmt>(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<Stmt*, 4> GotoJumps = IsAsmGoto ? AsmJumps : IndirectJumps; - if (GotoJumps.empty()) - return; - SmallVector<LabelDecl *, 4> 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<unsigned, Stmt*> JumpScope; + typedef std::pair<unsigned, IndirectGotoStmt*> JumpScope; SmallVector<JumpScope, 32> JumpScopes; { - llvm::DenseMap<unsigned, Stmt*> JumpScopesMap; - for (SmallVectorImpl<Stmt *>::iterator I = GotoJumps.begin(), - E = GotoJumps.end(); - I != E; ++I) { - Stmt *IG = *I; + llvm::DenseMap<unsigned, IndirectGotoStmt*> JumpScopesMap; + for (SmallVectorImpl<IndirectGotoStmt*>::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<unsigned, Stmt *>::iterator I = JumpScopesMap.begin(), - E = JumpScopesMap.end(); - I != E; ++I) + for (llvm::DenseMap<unsigned, IndirectGotoStmt*>::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<unsigned, LabelDecl*> TargetScopes; - for (SmallVectorImpl<LabelDecl *>::iterator I = JumpTargets.begin(), - E = JumpTargets.end(); + for (SmallVectorImpl<LabelDecl*>::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<GCCAsmStmt>(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<unsigned> 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<GCCAsmStmt>(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/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index ec8958c3c5f..8c6012573c6 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/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<GCCAsmStmt::AsmStringPiece, 8> 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<StringRef , Expr *> NamedOperand; - SmallVector<NamedOperand, 4> 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<NamedOperand, 4>::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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 609a3cfcfca..6620885f239 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/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<Derived>::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<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) { S->isVolatile(), S->getNumOutputs(), S->getNumInputs(), Names.data(), Constraints, Exprs, AsmString.get(), - Clobbers, S->getNumLabels(), - S->getRParenLoc()); + Clobbers, S->getRParenLoc()); } template<typename Derived> diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 52aa3d961d2..4d879b46e1a 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/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<StringLiteral>(Record.readSubStmt())); unsigned NumOutputs = S->getNumOutputs(); unsigned NumInputs = S->getNumInputs(); unsigned NumClobbers = S->getNumClobbers(); - unsigned NumLabels = S->getNumLabels(); // Outputs and inputs SmallVector<IdentifierInfo *, 16> Names; @@ -394,14 +392,9 @@ void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) { for (unsigned I = 0; I != NumClobbers; ++I) Clobbers.push_back(cast_or_null<StringLiteral>(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/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 776aab6bf51..b0a35cf2f56 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/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; } |