aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuy David <guyda96@gmail.com>2025-09-16 13:08:12 -0700
committerGuy David <guyda96@gmail.com>2025-09-16 13:08:12 -0700
commit1589c07c93ec5c14123e6d5145d25df3a69a37bc (patch)
treeee8c950f78d06db91d6863aeac704d4ec6e39e25
parentb369237c98906891f9e56fd4be4109a25b79e3e9 (diff)
downloadllvm-users/guy-david/separate-indirectbr.zip
llvm-users/guy-david/separate-indirectbr.tar.gz
llvm-users/guy-david/separate-indirectbr.tar.bz2
-rw-r--r--clang/lib/Analysis/CFG.cpp21
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp18
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp11
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h5
4 files changed, 29 insertions, 26 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index d960d51..5d41a4c 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -545,6 +545,9 @@ class CFGBuilder {
using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>;
LabelSetTy AddressTakenLabels;
+ // A list of indirect goto dispatch blocks (one per indirect goto statement).
+ std::vector<CFGBlock *> IndirectGotoBlocks;
+
// Information about the currently visited C++ object construction site.
// This is set in the construction trigger and read when the constructor
// or a function that returns an object by value is being visited.
@@ -1751,8 +1754,8 @@ std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
}
}
- // Add successors to the Indirect Goto Dispatch block (if we have one).
- if (CFGBlock *B = cfg->getIndirectGotoBlock())
+ // Add successors to the Indirect Goto Dispatch blocks (one per indirect goto statement).
+ for (CFGBlock *B : IndirectGotoBlocks) {
for (LabelDecl *LD : AddressTakenLabels) {
// Lookup the target block.
LabelMapTy::iterator LI = LabelMap.find(LD);
@@ -1763,6 +1766,7 @@ std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
addSuccessor(B, LI->second.block);
}
+ }
// Create an empty entry block that has no predecessors.
cfg->setEntry(createBlock());
@@ -5028,13 +5032,8 @@ CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) {
}
CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {
- // Lazily create the indirect-goto dispatch block if there isn't one already.
- CFGBlock *IBlock = cfg->getIndirectGotoBlock();
-
- if (!IBlock) {
- IBlock = createBlock(false);
- cfg->setIndirectGotoBlock(IBlock);
- }
+ // Create a new indirect-goto dispatch block for each statement.
+ CFGBlock *IBlock = createBlock(false);
// IndirectGoto is a control-flow statement. Thus we stop processing the
// current block and create a new one.
@@ -5044,6 +5043,10 @@ CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {
Block = createBlock(false);
Block->setTerminator(I);
addSuccessor(Block, IBlock);
+
+ // Store this dispatch block so we can connect it to labels later
+ IndirectGotoBlocks.push_back(IBlock);
+
return addStmt(I->getTarget());
}
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 031ef73..9d19cdb 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -858,21 +858,17 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
return;
}
- // Ensure that we have an i8* for our PHI node.
+ // Ensure that we have an i8* for the indirect branch.
llvm::Value *V = Builder.CreateBitCast(EmitScalarExpr(S.getTarget()),
Int8PtrTy, "addr");
- llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
-
- // Get the basic block for the indirect goto.
- llvm::BasicBlock *IndGotoBB = GetIndirectGotoBlock();
- // The first instruction in the block has to be the PHI for the switch dest,
- // add an entry for this branch.
- cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB);
+ // Create a new indirect branch instruction for this statement
+ llvm::IndirectBrInst *IndBr = Builder.CreateIndirectBr(V);
- EmitBranch(IndGotoBB);
- if (CurBB && CurBB->getTerminator())
- addInstToCurrentSourceAtom(CurBB->getTerminator(), nullptr);
+ // Add all address-taken labels as possible destinations
+ for (llvm::BasicBlock *BB : AddressTakenLabels) {
+ IndBr->addDestination(BB);
+ }
}
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index b2fe917..73a604f 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2287,14 +2287,13 @@ CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) {
}
llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) {
- // Make sure that there is a block for the indirect goto.
- if (!IndirectBranch)
- GetIndirectGotoBlock();
-
llvm::BasicBlock *BB = getJumpDestForLabel(L).getBlock();
- // Make sure the indirect branch includes all of the address-taken blocks.
- IndirectBranch->addDestination(BB);
+ // Keep track of this address-taken label for indirect goto statements
+ if (llvm::find(AddressTakenLabels, BB) == AddressTakenLabels.end()) {
+ AddressTakenLabels.push_back(BB);
+ }
+
return llvm::BlockAddress::get(CurFn->getType(), BB);
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index c02ac18..fea0a46 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1527,6 +1527,11 @@ private:
/// codegen'd as a jump to the IndirectBranch's basic block.
llvm::IndirectBrInst *IndirectBranch = nullptr;
+ /// AddressTakenLabels - Collection of address-taken labels for indirect gotos.
+ /// Each indirect goto statement will create its own indirectbr instruction
+ /// with all these labels as possible destinations.
+ llvm::SmallVector<llvm::BasicBlock *, 8> AddressTakenLabels;
+
/// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
/// decls.
DeclMapTy LocalDeclMap;