Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/AutoUpgrade.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ namespace llvm {
/// module is modified.
LLVM_ABI bool UpgradeModuleFlags(Module &M);

/// Upgrade the cfi.functions metadata node by calculating and inserting
/// the GUID for each function entry if it's missing.
LLVM_ABI bool UpgradeCFIFunctionsMetadata(Module &M);

/// Convert legacy nvvm.annotations metadata to appropriate function
/// attributes.
LLVM_ABI void UpgradeNVVMAnnotations(Module &M);
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/IR/ModuleSummaryIndex.h
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,7 @@ class ModuleSummaryIndex {
// in the way some record are interpreted, like flags for instance.
// Note that incrementing this may require changes in both BitcodeReader.cpp
// and BitcodeWriter.cpp.
static constexpr uint64_t BitcodeSummaryVersion = 13;
static constexpr uint64_t BitcodeSummaryVersion = 14;

// Regular LTO module name for ASM writer
static constexpr const char *getRegularLTOModuleName() {
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
llvm::UpgradeDebugInfo(*M);

UpgradeModuleFlags(*M);
UpgradeCFIFunctionsMetadata(*M);
UpgradeNVVMAnnotations(*M);
UpgradeSectionAttributes(*M);
copyModuleAttrToFunctions(*M);
Expand Down
44 changes: 32 additions & 12 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3979,6 +3979,8 @@ Error BitcodeReader::materializeMetadata() {
}
}

UpgradeCFIFunctionsMetadata(*TheModule);

DeferredMetadataInfo.clear();
return Error::success();
}
Expand Down Expand Up @@ -8149,24 +8151,42 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {

case bitc::FS_CFI_FUNCTION_DEFS: {
auto &CfiFunctionDefs = TheIndex.cfiFunctionDefs();
for (unsigned I = 0; I != Record.size(); I += 2) {
StringRef Name(Strtab.data() + Record[I],
static_cast<size_t>(Record[I + 1]));
GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage(
GlobalValue::dropLLVMManglingEscape(Name));
CfiFunctionDefs.addSymbolWithThinLTOGUID(Name, GUID);
if (Version < 14) {
for (unsigned I = 0; I != Record.size(); I += 2) {
StringRef Name(Strtab.data() + Record[I],
static_cast<size_t>(Record[I + 1]));
GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage(
GlobalValue::dropLLVMManglingEscape(Name));
CfiFunctionDefs.addSymbolWithThinLTOGUID(Name, GUID);
}
} else {
for (unsigned I = 0; I != Record.size(); I += 3) {
GlobalValue::GUID ThinLTOGUID = Record[I];
StringRef Name(Strtab.data() + Record[I + 1],
static_cast<size_t>(Record[I + 2]));
CfiFunctionDefs.addSymbolWithThinLTOGUID(Name, ThinLTOGUID);
}
}
break;
}

case bitc::FS_CFI_FUNCTION_DECLS: {
auto &CfiFunctionDecls = TheIndex.cfiFunctionDecls();
for (unsigned I = 0; I != Record.size(); I += 2) {
StringRef Name(Strtab.data() + Record[I],
static_cast<size_t>(Record[I + 1]));
GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage(
GlobalValue::dropLLVMManglingEscape(Name));
CfiFunctionDecls.addSymbolWithThinLTOGUID(Name, GUID);
if (Version < 14) {
for (unsigned I = 0; I != Record.size(); I += 2) {
StringRef Name(Strtab.data() + Record[I],
static_cast<size_t>(Record[I + 1]));
GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage(
GlobalValue::dropLLVMManglingEscape(Name));
CfiFunctionDecls.addSymbolWithThinLTOGUID(Name, GUID);
}
} else {
for (unsigned I = 0; I != Record.size(); I += 3) {
GlobalValue::GUID ThinLTOGUID = Record[I];
StringRef Name(Strtab.data() + Record[I + 1],
static_cast<size_t>(Record[I + 2]));
CfiFunctionDecls.addSymbolWithThinLTOGUID(Name, ThinLTOGUID);
}
}
break;
}
Expand Down
12 changes: 7 additions & 5 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5323,21 +5323,23 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
getReferencedTypeIds(FS, ReferencedTypeIds);
}

SmallVector<StringRef, 4> Functions;
SmallVector<std::pair<StringRef, GlobalValue::GUID>, 4> Functions;
auto EmitCfiFunctions = [&](const CfiFunctionIndex &CfiIndex,
bitc::GlobalValueSummarySymtabCodes Code) {
if (CfiIndex.empty())
return;
for (GlobalValue::GUID GUID : DefOrUseGUIDs) {
auto Names = CfiIndex.getNamesForGUID(GUID);
llvm::append_range(Functions, Names);
for (StringRef Name : Names)
Functions.push_back({Name, GUID});
}
if (Functions.empty())
return;
llvm::sort(Functions);
for (const auto &S : Functions) {
NameVals.push_back(StrtabBuilder.add(S));
NameVals.push_back(S.size());
for (const auto &Record : Functions) {
NameVals.push_back(Record.second);
NameVals.push_back(StrtabBuilder.add(Record.first));
NameVals.push_back(Record.first.size());
}
Stream.EmitRecord(Code, NameVals);
NameVals.clear();
Expand Down
45 changes: 45 additions & 0 deletions llvm/lib/IR/AutoUpgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/Instruction.h"
Expand Down Expand Up @@ -6359,6 +6360,50 @@ bool llvm::UpgradeModuleFlags(Module &M) {
return Changed;
}

bool llvm::UpgradeCFIFunctionsMetadata(Module &M) {
NamedMDNode *CFIConsts = M.getNamedMetadata("cfi.functions");
// If this metadata has operands, we expect all of them to be either from
// before or from after the format change handled here, so we can bail out
// fast if the first (if any) operands is of the new format.
auto MatchesVersion = [](const MDNode *Op) {
return Op->getNumOperands() >= 3 &&
isa<ConstantAsMetadata>(Op->getOperand(2)) &&
cast<ConstantAsMetadata>(Op->getOperand(2))
->getType()
->isIntegerTy(64);
};

if (!CFIConsts || !CFIConsts->getNumOperands() ||
MatchesVersion(CFIConsts->getOperand(0)))
return false;

bool Changed = false;
for (unsigned I = 0, E = CFIConsts->getNumOperands(); I != E; ++I) {
MDNode *Op = CFIConsts->getOperand(I);
assert(!MatchesVersion(Op) && "Unexpected mix of CFIConstant formats");
assert(Op->getNumOperands() >= 2 &&
"Expected at least 2 operands - name and linkage type");
MDString *NameMD = dyn_cast<MDString>(Op->getOperand(0));
StringRef Name = NameMD->getString();
GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage(
GlobalValue::dropLLVMManglingEscape(Name));

SmallVector<Metadata *, 4> Elts;
Elts.push_back(Op->getOperand(0));
Elts.push_back(Op->getOperand(1));
Elts.push_back(ConstantAsMetadata::get(
ConstantInt::get(Type::getInt64Ty(M.getContext()), GUID)));

for (unsigned J = 2, EJ = Op->getNumOperands(); J != EJ; ++J)
Elts.push_back(Op->getOperand(J));

CFIConsts->setOperand(I, MDNode::get(M.getContext(), Elts));
Changed = true;
}

return Changed;
}

void llvm::UpgradeSectionAttributes(Module &M) {
auto TrimSpaces = [](StringRef Section) -> std::string {
SmallVector<StringRef, 5> Components;
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Transforms/IPO/CrossDSOCFI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ void CrossDSOCFI::buildCFICheck(Module &M) {
NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions");
if (CfiFunctionsMD) {
for (auto *Func : CfiFunctionsMD->operands()) {
assert(Func->getNumOperands() >= 2);
for (unsigned I = 2; I < Func->getNumOperands(); ++I)
assert(Func->getNumOperands() >= 3);
assert(isa<ConstantAsMetadata>(Func->getOperand(2)));
for (unsigned I = 3; I < Func->getNumOperands(); ++I)
if (ConstantInt *TypeId =
extractNumericTypeId(cast<MDNode>(Func->getOperand(I).get())))
TypeIds.insert(TypeId->getZExtValue());
Expand Down
8 changes: 5 additions & 3 deletions llvm/lib/Transforms/IPO/LowerTypeTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2213,8 +2213,10 @@ bool LowerTypeTestsModule::lower() {
->getUniqueInteger()
.getZExtValue());
const GlobalValue::GUID GUID =
GlobalValue::getGUIDAssumingExternalLinkage(
GlobalValue::dropLLVMManglingEscape(FunctionName));
cast<ConstantAsMetadata>(FuncMD->getOperand(2))
->getValue()
->getUniqueInteger()
.getZExtValue();
// Do not emit jumptable entries for functions that are not-live and
// have no live references (and are not exported with cross-DSO CFI.)
if (!ExportSummary->isGUIDLive(GUID))
Expand Down Expand Up @@ -2285,7 +2287,7 @@ bool LowerTypeTestsModule::lower() {
F->setLinkage(GlobalValue::ExternalWeakLinkage);

F->eraseMetadata(LLVMContext::MD_type);
for (unsigned I = 2; I < FuncMD->getNumOperands(); ++I)
for (unsigned I = 3; I < FuncMD->getNumOperands(); ++I)
F->addMetadata(LLVMContext::MD_type,
*cast<MDNode>(FuncMD->getOperand(I).get()));
}
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,11 @@ void splitAndWriteThinLTOBitcode(
Linkage = CFL_Declaration;
Elts.push_back(ConstantAsMetadata::get(
llvm::ConstantInt::get(Type::getInt8Ty(Ctx), Linkage)));
// TODO: use F->getGUID() once #184065 is relanded.
GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage(
GlobalValue::dropLLVMManglingEscape(V->getName()));
Elts.push_back(ConstantAsMetadata::get(
llvm::ConstantInt::get(Type::getInt64Ty(Ctx), GUID)));
append_range(Elts, Types);
CfiFunctionMDs.push_back(MDTuple::get(Ctx, Elts));
}
Expand Down
Binary file added llvm/test/Bitcode/Inputs/cfi-functions-upgrade.bc
Binary file not shown.
Binary file added llvm/test/Bitcode/Inputs/cfi-summary-upgrade.bc
Binary file not shown.
24 changes: 24 additions & 0 deletions llvm/test/Bitcode/cfi-functions-upgrade.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
; RUN: llvm-bcanalyzer -dump %S/Inputs/cfi-summary-upgrade.bc | FileCheck %s --check-prefix=OLD-SUMMARY
; RUN: llvm-dis < %S/Inputs/cfi-summary-upgrade.bc | FileCheck %s --check-prefix=UPGRADED-SUMMARY

; RUN: llvm-bcanalyzer -dump %S/Inputs/cfi-functions-upgrade.bc | FileCheck %s --check-prefix=OLD-METADATA
; RUN: llvm-dis < %S/Inputs/cfi-functions-upgrade.bc | llvm-as | llvm-bcanalyzer -dump | FileCheck %s --check-prefix=UPGRADED-METADATA

; OLD-SUMMARY: <GLOBALVAL_SUMMARY_BLOCK
; OLD-SUMMARY: <VERSION op0=13/>
; OLD-SUMMARY: <CFI_FUNCTION_DEFS op0=0 op1=3/>
; OLD-SUMMARY: <CFI_FUNCTION_DECLS op0=3 op1=3/>

; This just tests that the old summary got loaded successfully. llvm-dis does't
; have a representation for the 2 cfi tables.
; UPGRADED-SUMMARY: ^0 = module:
; UPGRADED-SUMMARY: ^1 = gv: (guid: 6699318081062747564,
; UPGRADED-SUMMARY: ^2 = gv: (guid: 14771895114995649345,
; UPGRADED-SUMMARY: ^3 = typeid: (name: "typeid1",

; This tests a roundtrip of old metadata -> new metadata.
; OLD-METADATA: <METADATA_BLOCK
; OLD-METADATA: <NODE op0={{[0-9]+}} op1={{[0-9]+}} op2={{[0-9]+}}/>

; UPGRADED-METADATA: <METADATA_BLOCK
; UPGRADED-METADATA: <NODE op0={{[0-9]+}} op1={{[0-9]+}} op2={{[0-9]+}} op3={{[0-9]+}}/>
2 changes: 1 addition & 1 deletion llvm/test/Bitcode/summary_version.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
; RUN: opt -module-summary %s -o - | llvm-bcanalyzer -dump | FileCheck %s

; CHECK: <GLOBALVAL_SUMMARY_BLOCK
; CHECK: <VERSION op0=13/>
; CHECK: <VERSION op0=14/>



Expand Down
4 changes: 2 additions & 2 deletions llvm/test/ThinLTO/X86/cfi-icall-only-defuse.ll
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ define i8 @f(i1 %i, ptr %p) {
!0 = !{i64 0, !"t1"}

; FOOBAZ: <GLOBALVAL_SUMMARY_BLOCK
; FOOBAZ: <CFI_FUNCTION_DEFS op0=0 op1=3 op2=3 op3=3 op4=6 op5=3/>
; FOOBAZ: <CFI_FUNCTION_DEFS op0={{.*}} op1=0 op2=3 op3={{.*}} op4=3 op5=3 op6={{.*}} op7=6 op8=3/>
; FOOBAZ: <TYPE_ID op0=9 op1=2 op2=4 op3=7 op4=0 op5=0 op6=0 op7=0/>
; FOOBAZ: </GLOBALVAL_SUMMARY_BLOCK>
; FOOBAZ: <STRTAB_BLOCK
; FOOBAZ-NEXT: <BLOB abbrevid=4/> blob data = 'barbazfoot1'
; FOOBAZ-NEXT: </STRTAB_BLOCK>

; BARQUX: <GLOBALVAL_SUMMARY_BLOCK
; BARQUX: <CFI_FUNCTION_DEFS op0=0 op1=3 op2=3 op3=3 op4=6 op5=3/>
; BARQUX: <CFI_FUNCTION_DEFS op0={{.*}} op1=0 op2=3 op3={{.*}} op4=3 op5=3 op6={{.*}} op7=6 op8=3/>
; BARQUX: <TYPE_ID op0=9 op1=2 op2=4 op3=7 op4=0 op5=0 op6=0 op7=0/>
; BARQUX: </GLOBALVAL_SUMMARY_BLOCK>
; BARQUX: <STRTAB_BLOCK
Expand Down
107 changes: 107 additions & 0 deletions llvm/test/ThinLTO/X86/cfi-icall-thinlto.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
; REQUIRES: x86-registered-target

; RUN: rm -rf %t.dir && split-file %s %t.dir
; RUN: opt -thinlto-bc -thinlto-split-lto-unit %t.dir/lib.ll -o %t.dir/lib.bc
; RUN: opt -thinlto-bc -thinlto-split-lto-unit %t.dir/main.ll -o %t.dir/main.bc
; RUN: llvm-lto2 run -save-temps %t.dir/lib.bc %t.dir/main.bc -o %t.dir/summary \
; RUN: -r=%t.dir/lib.bc,_Z11public_funcv,plx \
; RUN: -r=%t.dir/lib.bc,syscall, \
; RUN: -r=%t.dir/lib.bc,_ZN12_GLOBAL__N_113internal_funcEv.35df87b54cddf81e734207bfc5eea57a,pl \
; RUN: -r=%t.dir/main.bc,main,plx \
; RUN: -r=%t.dir/main.bc,_Z11public_funcv,l
; RUN: llvm-dis %t.dir/summary.2.4.opt.bc -o - | FileCheck %s

; RUN: llvm-lto2 run -thinlto-distributed-indexes %t.dir/lib.bc %t.dir/main.bc \
; RUN: -o %t.dir/distidx \
; RUN: -r=%t.dir/lib.bc,_Z11public_funcv,plx \
; RUN: -r=%t.dir/lib.bc,syscall, \
; RUN: -r=%t.dir/lib.bc,_ZN12_GLOBAL__N_113internal_funcEv.35df87b54cddf81e734207bfc5eea57a,pl \
; RUN: -r=%t.dir/main.bc,main,plx \
; RUN: -r=%t.dir/main.bc,_Z11public_funcv,l
; RUN: llvm-bcanalyzer -dump %t.dir/lib.bc.thinlto.bc | FileCheck %s --check-prefix=DIST

; Verify that the type test is NOT lowered to an unconditional trap,
; and that the initialization path (which calls syscall) is preserved.
; CHECK: define hidden noundef i32 @main()
; CHECK: %[[LOAD:.*]] = load i1, ptr @_ZN12_GLOBAL__N_18lazy_valE.1.llvm.{{.*}}
; CHECK-NEXT: br i1 %[[LOAD]], label %{{.*}}, label %[[LABEL:.*]]
; CHECK: [[LABEL]]:
; CHECK: call i64 (i64, ...) @syscall(i64 noundef 186)
; CHECK-NOT: call void @llvm.ubsantrap

; Verify that the distributed index records CFI_FUNCTION_DEFS with the
; 3-field format [GUID, strtab_offset, name_length]. The promoted internal
; function is listed with its stable pre-promotion GUID.
; DIST: <CFI_FUNCTION_DEFS op0={{[-0-9]+}} op1=0 op2=67/>
; DIST: <STRTAB_BLOCK
; DIST-NEXT: <BLOB abbrevid=4/> blob data = '_ZN12_GLOBAL__N_113internal_funcEv.35df87b54cddf81e734207bfc5eea57a_ZTSFjvE'

;--- lib.ll
target triple = "x86_64-unknown-linux-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

@_ZN12_GLOBAL__N_18lazy_valE.1 = internal unnamed_addr global i1 false, align 4

define hidden void @_Z11public_funcv() local_unnamed_addr #0 !type !10 !type !11 {
%1 = load i1, ptr @_ZN12_GLOBAL__N_18lazy_valE.1, align 1
%2 = zext i1 %1 to i8
%3 = trunc nuw i8 %2 to i1
br i1 %3, label %9, label %4

4: ; preds = %0
%5 = tail call i1 @llvm.type.test(ptr nonnull @_ZN12_GLOBAL__N_113internal_funcEv, metadata !"_ZTSFjvE")
br i1 %5, label %7, label %6
6: ; preds = %4
tail call void @llvm.ubsantrap(i8 2) #5
unreachable

7: ; preds = %4
%8 = tail call i64 (i64, ...) @syscall(i64 noundef 186)
store i1 true, ptr @_ZN12_GLOBAL__N_18lazy_valE.1, align 1
br label %9

9: ; preds = %0, %7
ret void
}

define internal noundef i32 @_ZN12_GLOBAL__N_113internal_funcEv() #1 !type !15 !type !16 {
%1 = tail call i64 (i64, ...) @syscall(i64 noundef 186)
%2 = trunc i64 %1 to i32
ret i32 %2
}

declare i1 @llvm.type.test(ptr, metadata) #2
declare void @llvm.ubsantrap(i8 immarg) #3
declare i64 @syscall(i64 noundef, ...) #4

attributes #0 = { alwaysinline mustprogress nounwind uwtable "target-cpu"="x86-64" }
attributes #1 = { mustprogress nounwind uwtable "target-cpu"="x86-64" }
attributes #2 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #3 = { cold noreturn nounwind memory(inaccessiblemem: write) }
attributes #4 = { nounwind "target-cpu"="x86-64" }
attributes #5 = { nomerge noreturn nounwind }

!10 = !{i64 0, !"_ZTSFvvE"}
!11 = !{i64 0, !"_ZTSFvvE.generalized"}
!15 = !{i64 0, !"_ZTSFjvE"}
!16 = !{i64 0, !"_ZTSFjvE.generalized"}

;--- main.ll
target triple = "x86_64-unknown-linux-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

define hidden noundef i32 @main() local_unnamed_addr #0 !type !8 !type !9 {
tail call void @_Z11public_funcv()
ret i32 0
}

declare !type !11 !type !12 dso_local void @_Z11public_funcv() local_unnamed_addr #1

attributes #0 = { mustprogress norecurse uwtable "target-cpu"="x86-64" }
attributes #1 = { "target-cpu"="x86-64" }

!8 = !{i64 0, !"_ZTSFivE"}
!9 = !{i64 0, !"_ZTSFivE.generalized"}
!11 = !{i64 0, !"_ZTSFvvE"}
!12 = !{i64 0, !"_ZTSFvvE.generalized"}

4 changes: 2 additions & 2 deletions llvm/test/ThinLTO/X86/cfi-icall.ll
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ declare i1 @llvm.type.test(ptr %ptr, metadata %type) nounwind readnone
!0 = !{i64 0, !"typeid1"}

; COMBINED: <GLOBALVAL_SUMMARY_BLOCK
; COMBINED: <CFI_FUNCTION_DEFS op0=0 op1=3/>
; COMBINED: <CFI_FUNCTION_DECLS op0=3 op1=3/>
; COMBINED: <CFI_FUNCTION_DEFS op0={{.*}} op1=0 op2=3/>
; COMBINED: <CFI_FUNCTION_DECLS op0={{.*}} op1=3 op2=3/>
; COMBINED: <TYPE_ID op0=6 op1=7 op2=4 op3=7 op4=0 op5=0 op6=0 op7=0/>
; COMBINED: </GLOBALVAL_SUMMARY_BLOCK>

Expand Down
Loading
Loading