This revision was automatically updated to reflect the committed changes. Closed by commit rG6b01b465388b: [BPF] preserve debuginfo types for builtin __builtin__btf_type_id() (authored by yonghong-song).
Changed prior to commit: https://reviews.llvm.org/D74572?vs=262140&id=264256#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D74572/new/ https://reviews.llvm.org/D74572 Files: llvm/lib/Target/BPF/BPF.h llvm/lib/Target/BPF/BPFCORE.h llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp llvm/lib/Target/BPF/BPFPreserveDIType.cpp llvm/lib/Target/BPF/BPFTargetMachine.cpp llvm/lib/Target/BPF/BTFDebug.cpp llvm/lib/Target/BPF/BTFDebug.h llvm/lib/Target/BPF/CMakeLists.txt llvm/test/CodeGen/BPF/BTF/builtin-btf-type-id.ll
Index: llvm/test/CodeGen/BPF/BTF/builtin-btf-type-id.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/BPF/BTF/builtin-btf-type-id.ll @@ -0,0 +1,148 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; +; Source code: +; static int (*bpf_log)(unsigned tid, void *data, int data_size) = (void *)999; +; struct { +; char f1[100]; +; typeof(3) f2; +; } tmp__abc = {1, 3}; +; void prog1() { +; bpf_log(__builtin_btf_type_id(tmp__abc, 0), &tmp__abc, sizeof(tmp__abc)); +; } +; void prog2() { +; bpf_log(__builtin_btf_type_id(&tmp__abc, 1), &tmp__abc, sizeof(tmp__abc)); +; } +; void prog3() { +; bpf_log(__builtin_btf_type_id(tmp__abc.f1[3], 1), &tmp__abc, sizeof(tmp__abc)); +; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm test.c + +%struct.anon = type { [100 x i8], i32 } + +@tmp__abc = dso_local global { <{ i8, i8, [98 x i8] }>, i32 } { <{ i8, i8, [98 x i8] }> <{ i8 1, i8 3, [98 x i8] zeroinitializer }>, i32 0 }, align 4, !dbg !0 + +; Function Attrs: nounwind +define dso_local void @prog1() local_unnamed_addr #0 !dbg !28 { +entry: + %0 = tail call i32 @llvm.bpf.btf.type.id.p0s_struct.anons.i32(%struct.anon* bitcast ({ <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc to %struct.anon*), i32 1, i64 0), !dbg !31, !llvm.preserve.access.index !7 + %call = tail call i32 inttoptr (i64 999 to i32 (i32, i8*, i32)*)(i32 %0, i8* getelementptr inbounds ({ <{ i8, i8, [98 x i8] }>, i32 }, { <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc, i64 0, i32 0, i32 0), i32 104) #2, !dbg !32 + ret void, !dbg !33 +} + +; Function Attrs: nounwind readnone +declare i32 @llvm.bpf.btf.type.id.p0s_struct.anons.i32(%struct.anon*, i32, i64) #1 + +; Function Attrs: nounwind +define dso_local void @prog2() local_unnamed_addr #0 !dbg !34 { +entry: + %0 = tail call i32 @llvm.bpf.btf.type.id.p0s_struct.anons.i32(%struct.anon* bitcast ({ <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc to %struct.anon*), i32 0, i64 1), !dbg !35, !llvm.preserve.access.index !6 + %call = tail call i32 inttoptr (i64 999 to i32 (i32, i8*, i32)*)(i32 %0, i8* getelementptr inbounds ({ <{ i8, i8, [98 x i8] }>, i32 }, { <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc, i64 0, i32 0, i32 0), i32 104) #2, !dbg !36 + ret void, !dbg !37 +} + +; Function Attrs: nounwind +define dso_local void @prog3() local_unnamed_addr #0 !dbg !38 { +entry: + %0 = tail call i32 @llvm.bpf.btf.type.id.p0i8.i32(i8* getelementptr inbounds ({ <{ i8, i8, [98 x i8] }>, i32 }, { <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc, i64 0, i32 0, i32 2, i64 1), i32 1, i64 1), !dbg !39, !llvm.preserve.access.index !11 + %call = tail call i32 inttoptr (i64 999 to i32 (i32, i8*, i32)*)(i32 %0, i8* getelementptr inbounds ({ <{ i8, i8, [98 x i8] }>, i32 }, { <{ i8, i8, [98 x i8] }>, i32 }* @tmp__abc, i64 0, i32 0, i32 0), i32 104) #2, !dbg !40 + ret void, !dbg !41 +} + +; CHECK-LABEL: prog1 +; CHECK: r1 = 3 +; CHECK-LABEL: prog2 +; CHECK: r1 = 10 +; CHECK-LABEL: prog3 +; CHECK: r1 = 4 +; +; CHECK: .long 0 # BTF_KIND_STRUCT(id = 3) +; CHECK-NEXT: .long 67108866 # 0x4000002 +; CHECK-NEXT: .long 104 +; CHECK-NEXT: .long 13 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 0 # 0x0 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 800 # 0x320 +; CHECK-NEXT: .long 19 # BTF_KIND_INT(id = 4) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK: .long 0 # BTF_KIND_PTR(id = 10) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 3 + +; CHECK: .long 16 # FieldReloc +; CHECK-NEXT: .long {{[0-9]+}} # Field reloc section string offset={{[0-9]+}} +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long {{[0-9]+}} +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 10 +; CHECK-NEXT: .long {{[0-9]+}} +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long {{[0-9]+}} +; CHECK-NEXT: .long 7 + + +; Function Attrs: nounwind readnone +declare i32 @llvm.bpf.btf.type.id.p0i8.i32(i8*, i32, i64) #1 + +attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone } +attributes #2 = { nounwind } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!24, !25, !26} +!llvm.ident = !{!27} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "tmp__abc", scope: !2, file: !3, line: 5, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0 (https://github.com/llvm/llvm-project.git 95253d8f16b8085b4b85cb3a6106ccbfe8a6d9b2)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !16, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/core") +!4 = !{} +!5 = !{!6, !11} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3, line: 2, size: 832, elements: !8) +!8 = !{!9, !14} +!9 = !DIDerivedType(tag: DW_TAG_member, name: "f1", scope: !7, file: !3, line: 3, baseType: !10, size: 800) +!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 800, elements: !12) +!11 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!12 = !{!13} +!13 = !DISubrange(count: 100) +!14 = !DIDerivedType(tag: DW_TAG_member, name: "f2", scope: !7, file: !3, line: 4, baseType: !15, size: 32, offset: 800) +!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!16 = !{!0, !17} +!17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression()) +!18 = distinct !DIGlobalVariable(name: "bpf_log", scope: !2, file: !3, line: 1, type: !19, isLocal: true, isDefinition: true) +!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64) +!20 = !DISubroutineType(types: !21) +!21 = !{!15, !22, !23, !15} +!22 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!24 = !{i32 7, !"Dwarf Version", i32 4} +!25 = !{i32 2, !"Debug Info Version", i32 3} +!26 = !{i32 1, !"wchar_size", i32 4} +!27 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git 95253d8f16b8085b4b85cb3a6106ccbfe8a6d9b2)"} +!28 = distinct !DISubprogram(name: "prog1", scope: !3, file: !3, line: 6, type: !29, scopeLine: 6, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4) +!29 = !DISubroutineType(types: !30) +!30 = !{null} +!31 = !DILocation(line: 7, column: 11, scope: !28) +!32 = !DILocation(line: 7, column: 3, scope: !28) +!33 = !DILocation(line: 8, column: 1, scope: !28) +!34 = distinct !DISubprogram(name: "prog2", scope: !3, file: !3, line: 9, type: !29, scopeLine: 9, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4) +!35 = !DILocation(line: 10, column: 11, scope: !34) +!36 = !DILocation(line: 10, column: 3, scope: !34) +!37 = !DILocation(line: 11, column: 1, scope: !34) +!38 = distinct !DISubprogram(name: "prog3", scope: !3, file: !3, line: 12, type: !29, scopeLine: 12, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4) +!39 = !DILocation(line: 13, column: 11, scope: !38) +!40 = !DILocation(line: 13, column: 3, scope: !38) +!41 = !DILocation(line: 14, column: 1, scope: !38) Index: llvm/lib/Target/BPF/CMakeLists.txt =================================================================== --- llvm/lib/Target/BPF/CMakeLists.txt +++ llvm/lib/Target/BPF/CMakeLists.txt @@ -20,6 +20,7 @@ BPFISelDAGToDAG.cpp BPFISelLowering.cpp BPFMCInstLower.cpp + BPFPreserveDIType.cpp BPFRegisterInfo.cpp BPFSelectionDAGInfo.cpp BPFSubtarget.cpp Index: llvm/lib/Target/BPF/BTFDebug.h =================================================================== --- llvm/lib/Target/BPF/BTFDebug.h +++ llvm/lib/Target/BPF/BTFDebug.h @@ -26,6 +26,7 @@ class AsmPrinter; class BTFDebug; class DIType; +class GlobalVariable; class MCStreamer; class MCSymbol; class MachineFunction; @@ -250,7 +251,7 @@ StringMap<std::vector<std::string>> FileContent; std::map<std::string, std::unique_ptr<BTFKindDataSec>> DataSecEntries; std::vector<BTFTypeStruct *> StructTypes; - std::map<std::string, uint32_t> PatchImms; + std::map<const GlobalVariable *, uint32_t> PatchImms; std::map<StringRef, std::pair<bool, std::vector<BTFTypeDerived *>>> FixupDerivedTypes; std::set<const Function *>ProtoFunctions; @@ -300,11 +301,11 @@ void processFuncPrototypes(const Function *); /// Generate one field relocation record. - void generateFieldReloc(const MCSymbol *ORSym, DIType *RootTy, - StringRef AccessPattern); + void generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId, + const GlobalVariable *, bool IsAma); - /// Populating unprocessed struct type. - unsigned populateStructType(const DIType *Ty); + /// Populating unprocessed type on demand. + unsigned populateType(const DIType *Ty); /// Process relocation instructions. void processReloc(const MachineOperand &MO); Index: llvm/lib/Target/BPF/BTFDebug.cpp =================================================================== --- llvm/lib/Target/BPF/BTFDebug.cpp +++ llvm/lib/Target/BPF/BTFDebug.cpp @@ -933,9 +933,9 @@ SecNameOff = 0; } -/// On-demand populate struct types as requested from abstract member -/// accessing. -unsigned BTFDebug::populateStructType(const DIType *Ty) { +/// On-demand populate types as requested from abstract member +/// accessing or preserve debuginfo type. +unsigned BTFDebug::populateType(const DIType *Ty) { unsigned Id; visitTypeEntry(Ty, Id, false, false); for (const auto &TypeEntry : TypeEntries) @@ -944,24 +944,32 @@ } /// Generate a struct member field relocation. -void BTFDebug::generateFieldReloc(const MCSymbol *ORSym, DIType *RootTy, - StringRef AccessPattern) { - unsigned RootId = populateStructType(RootTy); - size_t FirstDollar = AccessPattern.find_first_of('$'); - size_t FirstColon = AccessPattern.find_first_of(':'); - size_t SecondColon = AccessPattern.find_first_of(':', FirstColon + 1); - StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1); - StringRef RelocKindStr = AccessPattern.substr(FirstColon + 1, - SecondColon - FirstColon); - StringRef PatchImmStr = AccessPattern.substr(SecondColon + 1, - FirstDollar - SecondColon); - +void BTFDebug::generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId, + const GlobalVariable *GVar, bool IsAma) { BTFFieldReloc FieldReloc; FieldReloc.Label = ORSym; - FieldReloc.OffsetNameOff = addString(IndexPattern); FieldReloc.TypeID = RootId; - FieldReloc.RelocKind = std::stoull(std::string(RelocKindStr)); - PatchImms[AccessPattern.str()] = std::stoul(std::string(PatchImmStr)); + + StringRef AccessPattern = GVar->getName(); + size_t FirstDollar = AccessPattern.find_first_of('$'); + if (IsAma) { + size_t FirstColon = AccessPattern.find_first_of(':'); + size_t SecondColon = AccessPattern.find_first_of(':', FirstColon + 1); + StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1); + StringRef RelocKindStr = AccessPattern.substr(FirstColon + 1, + SecondColon - FirstColon); + StringRef PatchImmStr = AccessPattern.substr(SecondColon + 1, + FirstDollar - SecondColon); + + FieldReloc.OffsetNameOff = addString(IndexPattern); + FieldReloc.RelocKind = std::stoull(std::string(RelocKindStr)); + PatchImms[GVar] = std::stoul(std::string(PatchImmStr)); + } else { + StringRef RelocStr = AccessPattern.substr(FirstDollar + 1); + FieldReloc.OffsetNameOff = addString("0"); + FieldReloc.RelocKind = std::stoull(std::string(RelocStr)); + PatchImms[GVar] = RootId; + } FieldRelocTable[SecNameOff].push_back(FieldReloc); } @@ -970,14 +978,20 @@ if (MO.isGlobal()) { const GlobalValue *GVal = MO.getGlobal(); auto *GVar = dyn_cast<GlobalVariable>(GVal); - if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) { - MCSymbol *ORSym = OS.getContext().createTempSymbol(); - OS.emitLabel(ORSym); + if (!GVar) + return; - MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index); - DIType *Ty = dyn_cast<DIType>(MDN); - generateFieldReloc(ORSym, Ty, GVar->getName()); - } + if (!GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) && + !GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) + return; + + MCSymbol *ORSym = OS.getContext().createTempSymbol(); + OS.emitLabel(ORSym); + + MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index); + uint32_t RootId = populateType(dyn_cast<DIType>(MDN)); + generatePatchImmReloc(ORSym, RootId, GVar, + GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)); } } @@ -1013,6 +1027,9 @@ // Later, the insn is replaced with "r2 = <offset>" // where "<offset>" equals to the offset based on current // type definitions. + // + // If the insn is "r2 = LD_imm64 @<an TypeIdAttr global>", + // The LD_imm64 result will be replaced with a btf type id. processReloc(MI->getOperand(1)); } else if (MI->getOpcode() == BPF::CORE_MEM || MI->getOpcode() == BPF::CORE_ALU32_MEM || @@ -1145,9 +1162,15 @@ if (MO.isGlobal()) { const GlobalValue *GVal = MO.getGlobal(); auto *GVar = dyn_cast<GlobalVariable>(GVal); - if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) { - // Emit "mov ri, <imm>" for patched immediate. - uint32_t Imm = PatchImms[GVar->getName().str()]; + if (GVar) { + // Emit "mov ri, <imm>" + uint32_t Imm; + if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) || + GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) + Imm = PatchImms[GVar]; + else + return false; + OutMI.setOpcode(BPF::MOV_ri); OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); OutMI.addOperand(MCOperand::createImm(Imm)); @@ -1162,7 +1185,7 @@ const GlobalValue *GVal = MO.getGlobal(); auto *GVar = dyn_cast<GlobalVariable>(GVal); if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) { - uint32_t Imm = PatchImms[GVar->getName().str()]; + uint32_t Imm = PatchImms[GVar]; OutMI.setOpcode(MI->getOperand(1).getImm()); if (MI->getOperand(0).isImm()) OutMI.addOperand(MCOperand::createImm(MI->getOperand(0).getImm())); Index: llvm/lib/Target/BPF/BPFTargetMachine.cpp =================================================================== --- llvm/lib/Target/BPF/BPFTargetMachine.cpp +++ llvm/lib/Target/BPF/BPFTargetMachine.cpp @@ -35,6 +35,7 @@ PassRegistry &PR = *PassRegistry::getPassRegistry(); initializeBPFAbstractMemberAccessPass(PR); + initializeBPFPreserveDITypePass(PR); initializeBPFMIPeepholePass(PR); initializeBPFMIPeepholeTruncElimPass(PR); } @@ -96,6 +97,7 @@ void BPFPassConfig::addIRPasses() { addPass(createBPFAbstractMemberAccess(&getBPFTargetMachine())); + addPass(createBPFPreserveDIType()); TargetPassConfig::addIRPasses(); } Index: llvm/lib/Target/BPF/BPFPreserveDIType.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/BPF/BPFPreserveDIType.cpp @@ -0,0 +1,131 @@ +//===----------- BPFPreserveDIType.cpp - Preserve DebugInfo Types ---------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Preserve Debuginfo types encoded in __builtin_btf_type_id() metadata. +// +//===----------------------------------------------------------------------===// + +#include "BPF.h" +#include "BPFCORE.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/User.h" +#include "llvm/IR/Value.h" +#include "llvm/Pass.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" + +#define DEBUG_TYPE "bpf-preserve-di-type" + +namespace llvm { +const std::string BPFCoreSharedInfo::TypeIdAttr = "btf_type_id"; +} // namespace llvm + +using namespace llvm; + +namespace { + +class BPFPreserveDIType final : public ModulePass { + StringRef getPassName() const override { + return "BPF Preserve DebugInfo Type"; + } + + bool runOnModule(Module &M) override; + +public: + static char ID; + BPFPreserveDIType() : ModulePass(ID) {} + +private: + bool doTransformation(Module &M); +}; +} // End anonymous namespace + +char BPFPreserveDIType::ID = 0; +INITIALIZE_PASS(BPFPreserveDIType, DEBUG_TYPE, "preserve debuginfo type", false, + false) + +ModulePass *llvm::createBPFPreserveDIType() { return new BPFPreserveDIType(); } + +bool BPFPreserveDIType::runOnModule(Module &M) { + LLVM_DEBUG(dbgs() << "********** preserve debuginfo type **********\n"); + + // Bail out if no debug info. + if (M.debug_compile_units().empty()) + return false; + + return doTransformation(M); +} + +bool BPFPreserveDIType::doTransformation(Module &M) { + std::vector<CallInst *> PreserveDITypeCalls; + + for (auto &F : M) { + for (auto &BB : F) { + for (auto &I : BB) { + auto *Call = dyn_cast<CallInst>(&I); + if (!Call) + continue; + + const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand()); + if (!GV) + continue; + + if (GV->getName().startswith("llvm.bpf.btf.type.id")) { + if (!Call->getMetadata(LLVMContext::MD_preserve_access_index)) + report_fatal_error( + "Missing metadata for llvm.bpf.btf.type.id intrinsic"); + PreserveDITypeCalls.push_back(Call); + } + } + } + } + + if (PreserveDITypeCalls.empty()) + return false; + + std::string BaseName = "llvm.btf_type_id."; + int Count = 0; + for (auto Call : PreserveDITypeCalls) { + const ConstantInt *Flag = dyn_cast<ConstantInt>(Call->getArgOperand(2)); + assert(Flag); + uint64_t FlagValue = Flag->getValue().getZExtValue(); + + if (FlagValue >= BPFCoreSharedInfo::MAX_BTF_TYPE_ID_FLAG) + report_fatal_error("Incorrect flag for llvm.bpf.btf.type.id intrinsic"); + + uint32_t Reloc; + if (FlagValue == BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL_RELOC) + Reloc = BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL; + else + Reloc = BPFCoreSharedInfo::BTF_TYPE_ID_REMOTE; + + BasicBlock *BB = Call->getParent(); + IntegerType *VarType = Type::getInt32Ty(BB->getContext()); + std::string GVName = BaseName + std::to_string(Count) + "$" + + std::to_string(Reloc); + GlobalVariable *GV = + new GlobalVariable(M, VarType, false, GlobalVariable::ExternalLinkage, + NULL, GVName); + GV->addAttribute(BPFCoreSharedInfo::TypeIdAttr); + MDNode *MD = Call->getMetadata(LLVMContext::MD_preserve_access_index); + GV->setMetadata(LLVMContext::MD_preserve_access_index, MD); + + // Load the global variable which represents the type info. + auto *LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "", + Call); + Call->replaceAllUsesWith(LDInst); + Call->eraseFromParent(); + Count++; + } + + return true; +} Index: llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp =================================================================== --- llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp +++ llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp @@ -22,6 +22,9 @@ // r1 = <calculated field_info> // add r3, struct_base_reg, r1 // +// This pass also removes the intermediate load generated in IR pass for +// __builtin_btf_type_id() intrinsic. +// //===----------------------------------------------------------------------===// #include "BPF.h" @@ -55,10 +58,10 @@ bool removeLD(void); void processCandidate(MachineRegisterInfo *MRI, MachineBasicBlock &MBB, MachineInstr &MI, Register &SrcReg, Register &DstReg, - const GlobalValue *GVal); + const GlobalValue *GVal, bool IsAma); void processDstReg(MachineRegisterInfo *MRI, Register &DstReg, Register &SrcReg, const GlobalValue *GVal, - bool doSrcRegProp); + bool doSrcRegProp, bool IsAma); void processInst(MachineRegisterInfo *MRI, MachineInstr *Inst, MachineOperand *RelocOp, const GlobalValue *GVal); void checkADDrr(MachineRegisterInfo *MRI, MachineOperand *RelocOp, @@ -155,25 +158,27 @@ void BPFMISimplifyPatchable::processCandidate(MachineRegisterInfo *MRI, MachineBasicBlock &MBB, MachineInstr &MI, Register &SrcReg, - Register &DstReg, const GlobalValue *GVal) { + Register &DstReg, const GlobalValue *GVal, bool IsAma) { if (MRI->getRegClass(DstReg) == &BPF::GPR32RegClass) { - // We can optimize such a pattern: - // %1:gpr = LD_imm64 @"llvm.s:0:4$0:2" - // %2:gpr32 = LDW32 %1:gpr, 0 - // %3:gpr = SUBREG_TO_REG 0, %2:gpr32, %subreg.sub_32 - // %4:gpr = ADD_rr %0:gpr, %3:gpr - // or similar patterns below for non-alu32 case. - auto Begin = MRI->use_begin(DstReg), End = MRI->use_end(); - decltype(End) NextI; - for (auto I = Begin; I != End; I = NextI) { - NextI = std::next(I); - if (!MRI->getUniqueVRegDef(I->getReg())) - continue; - - unsigned Opcode = I->getParent()->getOpcode(); - if (Opcode == BPF::SUBREG_TO_REG) { - Register TmpReg = I->getParent()->getOperand(0).getReg(); - processDstReg(MRI, TmpReg, DstReg, GVal, false); + if (IsAma) { + // We can optimize such a pattern: + // %1:gpr = LD_imm64 @"llvm.s:0:4$0:2" + // %2:gpr32 = LDW32 %1:gpr, 0 + // %3:gpr = SUBREG_TO_REG 0, %2:gpr32, %subreg.sub_32 + // %4:gpr = ADD_rr %0:gpr, %3:gpr + // or similar patterns below for non-alu32 case. + auto Begin = MRI->use_begin(DstReg), End = MRI->use_end(); + decltype(End) NextI; + for (auto I = Begin; I != End; I = NextI) { + NextI = std::next(I); + if (!MRI->getUniqueVRegDef(I->getReg())) + continue; + + unsigned Opcode = I->getParent()->getOpcode(); + if (Opcode == BPF::SUBREG_TO_REG) { + Register TmpReg = I->getParent()->getOperand(0).getReg(); + processDstReg(MRI, TmpReg, DstReg, GVal, false, IsAma); + } } } @@ -183,12 +188,12 @@ } // All uses of DstReg replaced by SrcReg - processDstReg(MRI, DstReg, SrcReg, GVal, true); + processDstReg(MRI, DstReg, SrcReg, GVal, true, IsAma); } void BPFMISimplifyPatchable::processDstReg(MachineRegisterInfo *MRI, Register &DstReg, Register &SrcReg, const GlobalValue *GVal, - bool doSrcRegProp) { + bool doSrcRegProp, bool IsAma) { auto Begin = MRI->use_begin(DstReg), End = MRI->use_end(); decltype(End) NextI; for (auto I = Begin; I != End; I = NextI) { @@ -197,7 +202,7 @@ I->setReg(SrcReg); // The candidate needs to have a unique definition. - if (MRI->getUniqueVRegDef(I->getReg())) + if (IsAma && MRI->getUniqueVRegDef(I->getReg())) processInst(MRI, I->getParent(), &*I, GVal); } } @@ -269,28 +274,26 @@ if (!DefInst) continue; - bool IsCandidate = false; - const GlobalValue *GVal = nullptr; - if (DefInst->getOpcode() == BPF::LD_imm64) { - const MachineOperand &MO = DefInst->getOperand(1); - if (MO.isGlobal()) { - GVal = MO.getGlobal(); - auto *GVar = dyn_cast<GlobalVariable>(GVal); - if (GVar) { - // Global variables representing structure offset or - // patchable extern globals. - if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) { - assert(MI.getOperand(2).getImm() == 0); - IsCandidate = true; - } - } - } - } + if (DefInst->getOpcode() != BPF::LD_imm64) + continue; + + const MachineOperand &MO = DefInst->getOperand(1); + if (!MO.isGlobal()) + continue; + + const GlobalValue *GVal = MO.getGlobal(); + auto *GVar = dyn_cast<GlobalVariable>(GVal); + if (!GVar) + continue; - if (!IsCandidate) + // Global variables representing structure offset or type id. + bool IsAma = false; + if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) + IsAma = true; + else if (!GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) continue; - processCandidate(MRI, MBB, MI, SrcReg, DstReg, GVal); + processCandidate(MRI, MBB, MI, SrcReg, DstReg, GVal, IsAma); ToErase = &MI; Changed = true; Index: llvm/lib/Target/BPF/BPFCORE.h =================================================================== --- llvm/lib/Target/BPF/BPFCORE.h +++ llvm/lib/Target/BPF/BPFCORE.h @@ -13,18 +13,30 @@ class BPFCoreSharedInfo { public: - enum OffsetRelocKind : uint32_t { + enum PatchableRelocKind : uint32_t { FIELD_BYTE_OFFSET = 0, FIELD_BYTE_SIZE, FIELD_EXISTENCE, FIELD_SIGNEDNESS, FIELD_LSHIFT_U64, FIELD_RSHIFT_U64, + BTF_TYPE_ID_LOCAL, + BTF_TYPE_ID_REMOTE, MAX_FIELD_RELOC_KIND, }; + + enum BTFTypeIdFlag : uint32_t { + BTF_TYPE_ID_LOCAL_RELOC = 0, + BTF_TYPE_ID_REMOTE_RELOC, + + MAX_BTF_TYPE_ID_FLAG, + }; + /// The attribute attached to globals representing a field access static const std::string AmaAttr; + /// The attribute attached to globals representing a type id + static const std::string TypeIdAttr; }; } // namespace llvm Index: llvm/lib/Target/BPF/BPF.h =================================================================== --- llvm/lib/Target/BPF/BPF.h +++ llvm/lib/Target/BPF/BPF.h @@ -16,6 +16,7 @@ class BPFTargetMachine; ModulePass *createBPFAbstractMemberAccess(BPFTargetMachine *TM); +ModulePass *createBPFPreserveDIType(); FunctionPass *createBPFISelDag(BPFTargetMachine &TM); FunctionPass *createBPFMISimplifyPatchablePass(); @@ -25,6 +26,7 @@ FunctionPass *createBPFMIPreEmitCheckingPass(); void initializeBPFAbstractMemberAccessPass(PassRegistry&); +void initializeBPFPreserveDITypePass(PassRegistry&); void initializeBPFMISimplifyPatchablePass(PassRegistry&); void initializeBPFMIPeepholePass(PassRegistry&); void initializeBPFMIPeepholeTruncElimPass(PassRegistry&);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits