Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -515,12 +515,14 @@ DINode::DIFlags Flags = DINode::FlagZero, unsigned CC = 0); - /// Create a new DIType* with "artificial" flag set. - DIType *createArtificialType(DIType *Ty); + /// Create a new distinct DISubprogram* with "artificial" flag set. + static DISubprogram *createArtificialSubprogram(DISubprogram *SP); - /// Create a new DIType* with the "object pointer" - /// flag set. - DIType *createObjectPointerType(DIType *Ty); + /// Create a new uniqued DIType* with "artificial" flag set. + static DIType *createArtificialType(DIType *Ty); + + /// Create a new uniqued DIType* with the "object pointer" flag set. + static DIType *createObjectPointerType(DIType *Ty); /// Create a permanent forward-declared type. DICompositeType *createForwardDecl(unsigned Tag, StringRef Name, Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -679,9 +679,11 @@ Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs(2); } - void setFlags(DIFlags NewFlags) { - assert(!isUniqued() && "Cannot set flags on uniqued nodes"); - Flags = NewFlags; + /// Returns a new temporary DIType with updated Flags + TempDIType cloneWithFlags(DIFlags NewFlags) const { + auto NewTy = clone(); + NewTy->Flags = NewFlags; + return NewTy; } bool isPrivate() const { @@ -1679,6 +1681,13 @@ TempDISubprogram clone() const { return cloneImpl(); } + /// Returns a new temporary DISubprogram with updated Flags + TempDISubprogram cloneWithFlags(DIFlags NewFlags) const { + auto NewSP = clone(); + NewSP->Flags = NewFlags; + return NewSP; + } + public: unsigned getLine() const { return Line; } unsigned getVirtuality() const { return Virtuality; } Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -535,10 +535,14 @@ return R; } -static DIType *createTypeWithFlags(LLVMContext &Context, DIType *Ty, +DISubprogram *DIBuilder::createArtificialSubprogram(DISubprogram *SP) { + auto NewSP = SP->cloneWithFlags(SP->getFlags() | DINode::FlagArtificial); + return MDNode::replaceWithDistinct(std::move(NewSP)); +} + +static DIType *createTypeWithFlags(const DIType *Ty, DINode::DIFlags FlagsToSet) { - auto NewTy = Ty->clone(); - NewTy->setFlags(NewTy->getFlags() | FlagsToSet); + auto NewTy = Ty->cloneWithFlags(Ty->getFlags() | FlagsToSet); return MDNode::replaceWithUniqued(std::move(NewTy)); } @@ -546,7 +550,7 @@ // FIXME: Restrict this to the nodes where it's valid. if (Ty->isArtificial()) return Ty; - return createTypeWithFlags(VMContext, Ty, DINode::FlagArtificial); + return createTypeWithFlags(Ty, DINode::FlagArtificial); } DIType *DIBuilder::createObjectPointerType(DIType *Ty) { @@ -554,7 +558,7 @@ if (Ty->isObjectPointer()) return Ty; DINode::DIFlags Flags = DINode::FlagObjectPointer | DINode::FlagArtificial; - return createTypeWithFlags(VMContext, Ty, Flags); + return createTypeWithFlags(Ty, Flags); } void DIBuilder::retainType(DIScope *T) { Index: unittests/IR/IRBuilderTest.cpp =================================================================== --- unittests/IR/IRBuilderTest.cpp +++ unittests/IR/IRBuilderTest.cpp @@ -459,6 +459,62 @@ EXPECT_TRUE(verifyModule(*M)); } +TEST_F(IRBuilderTest, createArtificialSubprogram) { + IRBuilder<> Builder(BB); + DIBuilder DIB(*M); + auto File = DIB.createFile("main.c", "/"); + auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "clang", + /*isOptimized=*/true, /*Flags=*/"", + /*Runtime Version=*/0); + auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None)); + auto SP = DIB.createFunction(CU, "foo", /*LinkageName=*/"", File, + /*LineNo=*/1, Type, /*isLocalToUnit=*/false, + /*isDefinition=*/true, /*ScopeLine=*/2, + DINode::FlagZero, /*isOptimized=*/true); + EXPECT_TRUE(SP->isDistinct()); + + F->setSubprogram(SP); + AllocaInst *I = Builder.CreateAlloca(Builder.getInt8Ty()); + ReturnInst *R = Builder.CreateRetVoid(); + I->setDebugLoc(DebugLoc::get(3, 2, SP)); + R->setDebugLoc(DebugLoc::get(4, 2, SP)); + DIB.finalize(); + EXPECT_FALSE(verifyModule(*M)); + + Function *G = Function::Create(F->getFunctionType(), + Function::ExternalLinkage, "", M.get()); + BasicBlock *GBB = BasicBlock::Create(Ctx, "", G); + Builder.SetInsertPoint(GBB); + I->removeFromParent(); + Builder.Insert(I); + Builder.CreateRetVoid(); + EXPECT_FALSE(verifyModule(*M)); + + DISubprogram *GSP = DIBuilder::createArtificialSubprogram(F->getSubprogram()); + EXPECT_EQ(SP->getFile(), GSP->getFile()); + EXPECT_EQ(SP->getType(), GSP->getType()); + EXPECT_EQ(SP->getLine(), GSP->getLine()); + EXPECT_EQ(SP->getScopeLine(), GSP->getScopeLine()); + EXPECT_TRUE(GSP->isDistinct()); + + G->setSubprogram(GSP); + EXPECT_TRUE(verifyModule(*M)); + + auto *InlinedAtNode = + DILocation::getDistinct(Ctx, GSP->getScopeLine(), 0, GSP); + DebugLoc DL = I->getDebugLoc(); + DenseMap IANodes; + auto IA = DebugLoc::appendInlinedAt(DL, InlinedAtNode, Ctx, IANodes); + auto NewDL = DebugLoc::get(DL.getLine(), DL.getCol(), DL.getScope(), IA); + I->setDebugLoc(NewDL); + EXPECT_FALSE(verifyModule(*M)); + + EXPECT_EQ("foo", SP->getName()); + EXPECT_EQ("foo", GSP->getName()); + EXPECT_FALSE(SP->isArtificial()); + EXPECT_TRUE(GSP->isArtificial()); +} + TEST_F(IRBuilderTest, InsertExtractElement) { IRBuilder<> Builder(BB); Index: unittests/IR/MetadataTest.cpp =================================================================== --- unittests/IR/MetadataTest.cpp +++ unittests/IR/MetadataTest.cpp @@ -1051,7 +1051,7 @@ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); } -TEST_F(DITypeTest, setFlags) { +TEST_F(DITypeTest, cloneWithFlags) { // void (void) Metadata *TypesOps[] = {nullptr}; Metadata *Types = MDTuple::get(Context, TypesOps); @@ -1059,17 +1059,15 @@ DIType *D = DISubroutineType::getDistinct(Context, DINode::FlagZero, 0, Types); EXPECT_EQ(DINode::FlagZero, D->getFlags()); - D->setFlags(DINode::FlagRValueReference); - EXPECT_EQ(DINode::FlagRValueReference, D->getFlags()); - D->setFlags(DINode::FlagZero); + TempDIType D2 = D->cloneWithFlags(DINode::FlagRValueReference); + EXPECT_EQ(DINode::FlagRValueReference, D2->getFlags()); EXPECT_EQ(DINode::FlagZero, D->getFlags()); TempDIType T = DISubroutineType::getTemporary(Context, DINode::FlagZero, 0, Types); EXPECT_EQ(DINode::FlagZero, T->getFlags()); - T->setFlags(DINode::FlagRValueReference); - EXPECT_EQ(DINode::FlagRValueReference, T->getFlags()); - T->setFlags(DINode::FlagZero); + TempDIType T2 = T->cloneWithFlags(DINode::FlagRValueReference); + EXPECT_EQ(DINode::FlagRValueReference, T2->getFlags()); EXPECT_EQ(DINode::FlagZero, T->getFlags()); }