From: Yonghong Song Date: Fri, 22 Nov 2019 16:45:37 +0000 (-0800) Subject: [BPF] Support to emit debugInfo for extern variables X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4448125007712d78fd114997a6fffc44b61b131d;p=platform%2Fupstream%2Fllvm.git [BPF] Support to emit debugInfo for extern variables extern variable usage in BPF is different from traditional pure user space application. Recent discussion in linux bpf mailing list has two use cases where debug info types are required to use extern variables: - extern types are required to have a suitable interface in libbpf (bpf loader) to provide kernel config parameters to bpf programs. https://lore.kernel.org/bpf/CAEf4BzYCNo5GeVGMhp3fhysQ=_axAf=23PtwaZs-yAyafmXC9g@mail.gmail.com/T/#t - extern types are required so kernel bpf verifier can verify program which uses external functions more precisely. This will make later link with actual external function no need to reverify. https://lore.kernel.org/bpf/87eez4odqp.fsf@toke.dk/T/#m8d5c3e87ffe7f2764e02d722cb0d8cbc136880ed This patch added bpf support to consume such info into BTF, which can then be used by bpf loader. Function processFuncPrototypes() only adds extern function definitions into BTF. The functions with actual definition have been added to BTF in some other places. Differential Revision: https://reviews.llvm.org/D70697 --- diff --git a/llvm/lib/Target/BPF/BTF.h b/llvm/lib/Target/BPF/BTF.h index 9f1a9f9..ee06176 100644 --- a/llvm/lib/Target/BPF/BTF.h +++ b/llvm/lib/Target/BPF/BTF.h @@ -180,6 +180,7 @@ struct BTFParam { enum : uint8_t { VAR_STATIC = 0, ///< Linkage: InternalLinkage VAR_GLOBAL_ALLOCATED = 1, ///< Linkage: ExternalLinkage + VAR_GLOBAL_EXTERNAL = 2, ///< Linkage: ExternalLinkage }; /// BTF_KIND_DATASEC are followed by multiple "struct BTFDataSecVar". diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp index 51a6142..9dce734 100644 --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -1055,15 +1055,11 @@ void BTFDebug::processGlobals(bool ProcessingMapDef) { // Collect all types referenced by globals. const Module *M = MMI->getModule(); for (const GlobalVariable &Global : M->globals()) { - // Ignore external globals for now. - if (!Global.hasInitializer() && Global.hasExternalLinkage()) - continue; - // Decide the section name. StringRef SecName; if (Global.hasSection()) { SecName = Global.getSection(); - } else { + } else if (Global.hasInitializer()) { // data, bss, or readonly sections if (Global.isConstant()) SecName = ".rodata"; @@ -1093,25 +1089,33 @@ void BTFDebug::processGlobals(bool ProcessingMapDef) { // Only support the following globals: // . static variables // . non-static weak or non-weak global variables - // Essentially means: - // . .bcc/.data/.rodata DataSec entities only contain static data - // . Other DataSec entities contain static or initialized global data. - // Initialized global data are mostly used for finding map key/value type - // id's. Whether DataSec is readonly or not can be found from - // corresponding ELF section flags. + // . weak or non-weak extern global variables + // Whether DataSec is readonly or not can be found from corresponding ELF + // section flags. Whether a BTF_KIND_VAR is a weak symbol or not + // can be found from the corresponding ELF symbol table. auto Linkage = Global.getLinkage(); if (Linkage != GlobalValue::InternalLinkage && Linkage != GlobalValue::ExternalLinkage && - Linkage != GlobalValue::WeakAnyLinkage) + Linkage != GlobalValue::WeakAnyLinkage && + Linkage != GlobalValue::ExternalWeakLinkage) continue; - uint32_t GVarInfo = Linkage == GlobalValue::InternalLinkage - ? BTF::VAR_STATIC - : BTF::VAR_GLOBAL_ALLOCATED; + uint32_t GVarInfo; + if (Linkage == GlobalValue::InternalLinkage) { + GVarInfo = BTF::VAR_STATIC; + } else if (Global.hasInitializer()) { + GVarInfo = BTF::VAR_GLOBAL_ALLOCATED; + } else { + GVarInfo = BTF::VAR_GLOBAL_EXTERNAL; + } + auto VarEntry = std::make_unique(Global.getName(), GVTypeId, GVarInfo); uint32_t VarId = addType(std::move(VarEntry)); + if (SecName.empty()) + continue; + // Find or create a DataSec if (DataSecEntries.find(SecName) == DataSecEntries.end()) { DataSecEntries[SecName] = std::make_unique(Asm, SecName); @@ -1145,6 +1149,34 @@ bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) { return false; } +void BTFDebug::processFuncPrototypes() { + const Module *M = MMI->getModule(); + for (const Function &F : M->functions()) { + const DISubprogram *SP = F.getSubprogram(); + if (!SP || SP->isDefinition()) + continue; + + uint32_t ProtoTypeId; + const std::unordered_map FuncArgNames; + visitSubroutineType(SP->getType(), false, FuncArgNames, ProtoTypeId); + + auto VarEntry = + std::make_unique(SP->getName(), ProtoTypeId, + BTF::VAR_GLOBAL_EXTERNAL); + uint32_t VarId = addType(std::move(VarEntry)); + + StringRef SecName = F.getSection(); + if (SecName.empty()) + continue; + + if (DataSecEntries.find(SecName) == DataSecEntries.end()) { + DataSecEntries[SecName] = std::make_unique(Asm, SecName); + } + + DataSecEntries[SecName]->addVar(VarId, Asm->getSymbol(&F), 8); + } +} + void BTFDebug::endModule() { // Collect MapDef globals if not collected yet. if (MapDefNotCollected) { @@ -1154,6 +1186,9 @@ void BTFDebug::endModule() { // Collect global types/variables except MapDef globals. processGlobals(false); + + processFuncPrototypes(); + for (auto &DataSec : DataSecEntries) addType(std::move(DataSec.second)); diff --git a/llvm/lib/Target/BPF/BTFDebug.h b/llvm/lib/Target/BPF/BTFDebug.h index c01e0d1..c0d3f36 100644 --- a/llvm/lib/Target/BPF/BTFDebug.h +++ b/llvm/lib/Target/BPF/BTFDebug.h @@ -293,6 +293,9 @@ class BTFDebug : public DebugHandlerBase { /// Generate types and variables for globals. void processGlobals(bool ProcessingMapDef); + /// Generate types for function prototypes. + void processFuncPrototypes(); + /// Generate one offset relocation record. void generateFieldReloc(const MachineInstr *MI, const MCSymbol *ORSym, DIType *RootTy, StringRef AccessPattern); diff --git a/llvm/test/CodeGen/BPF/BTF/extern-var-func-weak-section.ll b/llvm/test/CodeGen/BPF/BTF/extern-var-func-weak-section.ll new file mode 100644 index 0000000..94256c6 --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/extern-var-func-weak-section.ll @@ -0,0 +1,99 @@ +; 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 +; +; Source code: +; extern int global_func(char c) __attribute__((weak, section("abc"))); +; int test() { +; return global_func(0); +; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm test.c + +; Function Attrs: nounwind +define dso_local i32 @test() local_unnamed_addr #0 !dbg !13 { +entry: + %call = tail call i32 @global_func(i8 signext 0) #2, !dbg !16 + ret i32 %call, !dbg !17 +} +declare !dbg !4 extern_weak dso_local i32 @global_func(i8 signext) local_unnamed_addr #1 section "abc" + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 116 +; CHECK-NEXT: .long 116 +; CHECK-NEXT: .long 76 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) +; CHECK-NEXT: .long 218103808 # 0xd000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 5 # BTF_KIND_FUNC(id = 3) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 4) +; CHECK-NEXT: .long 218103809 # 0xd000001 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 55 # BTF_KIND_INT(id = 5) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .long 60 # BTF_KIND_VAR(id = 6) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 72 # BTF_KIND_DATASEC(id = 7) +; CHECK-NEXT: .long 251658241 # 0xf000001 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long global_func +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "test" # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii ".text" # string offset=10 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/home/yhs/work/tests/extern/test.c" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=55 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "global_func" # string offset=60 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "abc" # string offset=72 +; CHECK-NEXT: .byte 0 + +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 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="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 #2 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!9, !10, !11} +!llvm.ident = !{!12} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 71a9518c93fe1dce9611c24bc707e5baf1f39f0d)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/extern") +!2 = !{} +!3 = !{!4} +!4 = !DISubprogram(name: "global_func", scope: !1, file: !1, line: 1, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{!7, !8} +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!9 = !{i32 7, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 71a9518c93fe1dce9611c24bc707e5baf1f39f0d)"} +!13 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 2, type: !14, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!14 = !DISubroutineType(types: !15) +!15 = !{!7} +!16 = !DILocation(line: 3, column: 11, scope: !13) +!17 = !DILocation(line: 3, column: 4, scope: !13) diff --git a/llvm/test/CodeGen/BPF/BTF/extern-var-func-weak.ll b/llvm/test/CodeGen/BPF/BTF/extern-var-func-weak.ll new file mode 100644 index 0000000..e841faf --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/extern-var-func-weak.ll @@ -0,0 +1,91 @@ +; 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 +; +; Source code: +; extern int global_func(char c) __attribute__((weak)); +; int test() { +; return global_func(0); +; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm test.c + +; Function Attrs: nounwind +define dso_local i32 @test() local_unnamed_addr #0 !dbg !13 { +entry: + %call = tail call i32 @global_func(i8 signext 0) #2, !dbg !16 + ret i32 %call, !dbg !17 +} +declare !dbg !4 extern_weak dso_local i32 @global_func(i8 signext) local_unnamed_addr #1 + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 92 +; CHECK-NEXT: .long 92 +; CHECK-NEXT: .long 72 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) +; CHECK-NEXT: .long 218103808 # 0xd000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 5 # BTF_KIND_FUNC(id = 3) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 4) +; CHECK-NEXT: .long 218103809 # 0xd000001 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 55 # BTF_KIND_INT(id = 5) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .long 60 # BTF_KIND_VAR(id = 6) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "test" # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii ".text" # string offset=10 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/home/yhs/work/tests/extern/test.c" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=55 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "global_func" # string offset=60 +; CHECK-NEXT: .byte 0 + +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 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="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 #2 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!9, !10, !11} +!llvm.ident = !{!12} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 71a9518c93fe1dce9611c24bc707e5baf1f39f0d)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/extern") +!2 = !{} +!3 = !{!4} +!4 = !DISubprogram(name: "global_func", scope: !1, file: !1, line: 1, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{!7, !8} +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!9 = !{i32 7, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 71a9518c93fe1dce9611c24bc707e5baf1f39f0d)"} +!13 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 2, type: !14, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!14 = !DISubroutineType(types: !15) +!15 = !{!7} +!16 = !DILocation(line: 3, column: 11, scope: !13) +!17 = !DILocation(line: 3, column: 4, scope: !13) diff --git a/llvm/test/CodeGen/BPF/BTF/extern-var-func.ll b/llvm/test/CodeGen/BPF/BTF/extern-var-func.ll new file mode 100644 index 0000000..a91e1c5 --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/extern-var-func.ll @@ -0,0 +1,92 @@ +; 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 +; +; Source code: +; extern int global_func(char c); +; int test() { +; return global_func(0); +; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm test.c + +; Function Attrs: nounwind +define dso_local i32 @test() local_unnamed_addr #0 !dbg !13 { +entry: + %call = tail call i32 @global_func(i8 signext 0) #2, !dbg !16 + ret i32 %call, !dbg !17 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 92 +; CHECK-NEXT: .long 92 +; CHECK-NEXT: .long 72 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) +; CHECK-NEXT: .long 218103808 # 0xd000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 5 # BTF_KIND_FUNC(id = 3) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 4) +; CHECK-NEXT: .long 218103809 # 0xd000001 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 55 # BTF_KIND_INT(id = 5) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .long 60 # BTF_KIND_VAR(id = 6) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "test" # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii ".text" # string offset=10 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/home/yhs/work/tests/extern/test.c" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=55 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "global_func" # string offset=60 +; CHECK-NEXT: .byte 0 + +declare !dbg !4 dso_local i32 @global_func(i8 signext) local_unnamed_addr #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 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="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 #2 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!9, !10, !11} +!llvm.ident = !{!12} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 77e5c60f04c4597ba5704d3cee61c6d359404ccd)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/extern") +!2 = !{} +!3 = !{!4} +!4 = !DISubprogram(name: "global_func", scope: !1, file: !1, line: 1, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{!7, !8} +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!9 = !{i32 2, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 77e5c60f04c4597ba5704d3cee61c6d359404ccd)"} +!13 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 2, type: !14, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!14 = !DISubroutineType(types: !15) +!15 = !{!7} +!16 = !DILocation(line: 3, column: 10, scope: !13) +!17 = !DILocation(line: 3, column: 3, scope: !13) diff --git a/llvm/test/CodeGen/BPF/BTF/extern-var-section.ll b/llvm/test/CodeGen/BPF/BTF/extern-var-section.ll new file mode 100644 index 0000000..1a9c576 --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/extern-var-section.ll @@ -0,0 +1,123 @@ +; 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 +; +; Source code: +; extern int global_func(char c) __attribute__((section("abc"))); +; extern char ch __attribute__((section("abc"))); +; int test() { +; return global_func(0) + ch; +; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm test.c + +@ch = external dso_local local_unnamed_addr global i8, section "abc", align 1, !dbg !0 + +; Function Attrs: nounwind +define dso_local i32 @test() local_unnamed_addr #0 !dbg !16 { +entry: + %call = tail call i32 @global_func(i8 signext 0) #2, !dbg !19 + %0 = load i8, i8* @ch, align 1, !dbg !20, !tbaa !21 + %conv = sext i8 %0 to i32, !dbg !20 + %add = add nsw i32 %call, %conv, !dbg !24 + ret i32 %add, !dbg !25 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 144 +; CHECK-NEXT: .long 144 +; CHECK-NEXT: .long 79 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) +; CHECK-NEXT: .long 218103808 # 0xd000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 5 # BTF_KIND_FUNC(id = 3) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 55 # BTF_KIND_INT(id = 4) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .long 60 # BTF_KIND_VAR(id = 5) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 6) +; CHECK-NEXT: .long 218103809 # 0xd000001 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 63 # BTF_KIND_VAR(id = 7) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 75 # BTF_KIND_DATASEC(id = 8) +; CHECK-NEXT: .long 251658242 # 0xf000002 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long ch +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long global_func +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "test" # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii ".text" # string offset=10 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/home/yhs/work/tests/extern/test.c" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=55 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "ch" # string offset=60 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "global_func" # string offset=63 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "abc" # string offset=75 +; CHECK-NEXT: .byte 0 + +declare !dbg !6 dso_local i32 @global_func(i8 signext) local_unnamed_addr #1 section "abc" + +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 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="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 #2 = { nounwind } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!12, !13, !14} +!llvm.ident = !{!15} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "ch", scope: !2, file: !3, line: 2, type: !10, isLocal: false, isDefinition: false) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 0ad024346185b3f0b5167438e126568982b1168d)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !11, nameTableKind: None) +!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/extern") +!4 = !{} +!5 = !{!6} +!6 = !DISubprogram(name: "global_func", scope: !3, file: !3, line: 1, type: !7, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !4) +!7 = !DISubroutineType(types: !8) +!8 = !{!9, !10} +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!11 = !{!0} +!12 = !{i32 2, !"Dwarf Version", i32 4} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 4} +!15 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 0ad024346185b3f0b5167438e126568982b1168d)"} +!16 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 3, type: !17, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4) +!17 = !DISubroutineType(types: !18) +!18 = !{!9} +!19 = !DILocation(line: 4, column: 10, scope: !16) +!20 = !DILocation(line: 4, column: 27, scope: !16) +!21 = !{!22, !22, i64 0} +!22 = !{!"omnipotent char", !23, i64 0} +!23 = !{!"Simple C/C++ TBAA"} +!24 = !DILocation(line: 4, column: 25, scope: !16) +!25 = !DILocation(line: 4, column: 3, scope: !16) diff --git a/llvm/test/CodeGen/BPF/BTF/extern-var-struct-weak.ll b/llvm/test/CodeGen/BPF/BTF/extern-var-struct-weak.ll new file mode 100644 index 0000000..1400d4b --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/extern-var-struct-weak.ll @@ -0,0 +1,101 @@ +; 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 +; +; Source code: +; typedef struct t1 { int f1; } __t1; +; extern __t1 global __attribute__((weak)); +; int test() { return global.f1; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm test.c + +%struct.t1 = type { i32 } + +@global = extern_weak dso_local local_unnamed_addr global %struct.t1, align 4, !dbg !0 +; Function Attrs: norecurse nounwind readonly +define dso_local i32 @test() local_unnamed_addr #0 !dbg !15 { +entry: + %0 = load i32, i32* getelementptr (%struct.t1, %struct.t1* @global, i64 0, i32 0), align 4, !dbg !18, !tbaa !19 + ret i32 %0, !dbg !24 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 92 +; CHECK-NEXT: .long 92 +; CHECK-NEXT: .long 73 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) +; CHECK-NEXT: .long 218103808 # 0xd000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 5 # BTF_KIND_FUNC(id = 3) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 55 # BTF_KIND_TYPEDEF(id = 4) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 60 # BTF_KIND_STRUCT(id = 5) +; CHECK-NEXT: .long 67108865 # 0x4000001 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 63 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # 0x0 +; CHECK-NEXT: .long 66 # BTF_KIND_VAR(id = 6) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "test" # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii ".text" # string offset=10 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/home/yhs/work/tests/extern/test.c" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "__t1" # string offset=55 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "t1" # string offset=60 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "f1" # string offset=63 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "global" # string offset=66 +; CHECK-NEXT: .byte 0 + +attributes #0 = { norecurse nounwind readonly "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" } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12, !13} +!llvm.ident = !{!14} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "global", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: false) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 71a9518c93fe1dce9611c24bc707e5baf1f39f0d)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/extern") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "__t1", file: !3, line: 1, baseType: !7) +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", file: !3, line: 1, size: 32, elements: !8) +!8 = !{!9} +!9 = !DIDerivedType(tag: DW_TAG_member, name: "f1", scope: !7, file: !3, line: 1, baseType: !10, size: 32) +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{i32 7, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 1, !"wchar_size", i32 4} +!14 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 71a9518c93fe1dce9611c24bc707e5baf1f39f0d)"} +!15 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 3, type: !16, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4) +!16 = !DISubroutineType(types: !17) +!17 = !{!10} +!18 = !DILocation(line: 3, column: 28, scope: !15) +!19 = !{!20, !21, i64 0} +!20 = !{!"t1", !21, i64 0} +!21 = !{!"int", !22, i64 0} +!22 = !{!"omnipotent char", !23, i64 0} +!23 = !{!"Simple C/C++ TBAA"} +!24 = !DILocation(line: 3, column: 14, scope: !15) diff --git a/llvm/test/CodeGen/BPF/BTF/extern-var-struct.ll b/llvm/test/CodeGen/BPF/BTF/extern-var-struct.ll new file mode 100644 index 0000000..7a354e6 --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/extern-var-struct.ll @@ -0,0 +1,102 @@ +; 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 +; +; Source code: +; typedef struct t1 { int f1; } __t1; +; extern __t1 global; +; int test() { return global.f1; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm test.c + +%struct.t1 = type { i32 } + +@global = external dso_local local_unnamed_addr global %struct.t1, align 4, !dbg !0 + +; Function Attrs: norecurse nounwind readonly +define dso_local i32 @test() local_unnamed_addr #0 !dbg !15 { +entry: + %0 = load i32, i32* getelementptr inbounds (%struct.t1, %struct.t1* @global, i64 0, i32 0), align 4, !dbg !18, !tbaa !19 + ret i32 %0, !dbg !24 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 92 +; CHECK-NEXT: .long 92 +; CHECK-NEXT: .long 73 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) +; CHECK-NEXT: .long 218103808 # 0xd000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 5 # BTF_KIND_FUNC(id = 3) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 55 # BTF_KIND_TYPEDEF(id = 4) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 60 # BTF_KIND_STRUCT(id = 5) +; CHECK-NEXT: .long 67108865 # 0x4000001 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 63 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # 0x0 +; CHECK-NEXT: .long 66 # BTF_KIND_VAR(id = 6) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "test" # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii ".text" # string offset=10 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/home/yhs/work/tests/extern/test.c" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "__t1" # string offset=55 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "t1" # string offset=60 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "f1" # string offset=63 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "global" # string offset=66 +; CHECK-NEXT: .byte 0 + +attributes #0 = { norecurse nounwind readonly "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" } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12, !13} +!llvm.ident = !{!14} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "global", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: false) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 2798d63180f4cc873bdaf689705fd4f9521ae89f)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/extern") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "__t1", file: !3, line: 1, baseType: !7) +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", file: !3, line: 1, size: 32, elements: !8) +!8 = !{!9} +!9 = !DIDerivedType(tag: DW_TAG_member, name: "f1", scope: !7, file: !3, line: 1, baseType: !10, size: 32) +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 1, !"wchar_size", i32 4} +!14 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 2798d63180f4cc873bdaf689705fd4f9521ae89f)"} +!15 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 4, type: !16, scopeLine: 4, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4) +!16 = !DISubroutineType(types: !17) +!17 = !{!10} +!18 = !DILocation(line: 4, column: 28, scope: !15) +!19 = !{!20, !21, i64 0} +!20 = !{!"t1", !21, i64 0} +!21 = !{!"int", !22, i64 0} +!22 = !{!"omnipotent char", !23, i64 0} +!23 = !{!"Simple C/C++ TBAA"} +!24 = !DILocation(line: 4, column: 14, scope: !15) diff --git a/llvm/test/CodeGen/BPF/BTF/extern-var-weak-section.ll b/llvm/test/CodeGen/BPF/BTF/extern-var-weak-section.ll new file mode 100644 index 0000000..1848e7f --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/extern-var-weak-section.ll @@ -0,0 +1,121 @@ +; 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 +; +; Source code: +; extern int global_func(char c) __attribute__((weak, section("abc"))); +; extern char ch __attribute__((weak, section("abc"))); +; int test() { +; return global_func(0) + ch; +; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm test.c + +@ch = extern_weak dso_local local_unnamed_addr global i8, section "abc", align 1, !dbg !0 +; Function Attrs: nounwind +define dso_local i32 @test() local_unnamed_addr #0 !dbg !16 { +entry: + %call = tail call i32 @global_func(i8 signext 0) #2, !dbg !19 + %0 = load i8, i8* @ch, align 1, !dbg !20, !tbaa !21 + %conv = sext i8 %0 to i32, !dbg !20 + %add = add nsw i32 %call, %conv, !dbg !24 + ret i32 %add, !dbg !25 +} +declare !dbg !6 extern_weak dso_local i32 @global_func(i8 signext) local_unnamed_addr #1 section "abc" + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 144 +; CHECK-NEXT: .long 144 +; CHECK-NEXT: .long 79 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) +; CHECK-NEXT: .long 218103808 # 0xd000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 5 # BTF_KIND_FUNC(id = 3) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 55 # BTF_KIND_INT(id = 4) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .long 60 # BTF_KIND_VAR(id = 5) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 6) +; CHECK-NEXT: .long 218103809 # 0xd000001 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 63 # BTF_KIND_VAR(id = 7) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 75 # BTF_KIND_DATASEC(id = 8) +; CHECK-NEXT: .long 251658242 # 0xf000002 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long ch +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long global_func +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "test" # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii ".text" # string offset=10 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/home/yhs/work/tests/extern/test.c" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=55 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "ch" # string offset=60 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "global_func" # string offset=63 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "abc" # string offset=75 +; CHECK-NEXT: .byte 0 + +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 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="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 #2 = { nounwind } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!12, !13, !14} +!llvm.ident = !{!15} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "ch", scope: !2, file: !3, line: 2, type: !10, isLocal: false, isDefinition: false) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 71a9518c93fe1dce9611c24bc707e5baf1f39f0d)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !11, nameTableKind: None) +!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/extern") +!4 = !{} +!5 = !{!6} +!6 = !DISubprogram(name: "global_func", scope: !3, file: !3, line: 1, type: !7, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !4) +!7 = !DISubroutineType(types: !8) +!8 = !{!9, !10} +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!11 = !{!0} +!12 = !{i32 7, !"Dwarf Version", i32 4} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 4} +!15 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 71a9518c93fe1dce9611c24bc707e5baf1f39f0d)"} +!16 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 3, type: !17, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4) +!17 = !DISubroutineType(types: !18) +!18 = !{!9} +!19 = !DILocation(line: 4, column: 10, scope: !16) +!20 = !DILocation(line: 4, column: 27, scope: !16) +!21 = !{!22, !22, i64 0} +!22 = !{!"omnipotent char", !23, i64 0} +!23 = !{!"Simple C/C++ TBAA"} +!24 = !DILocation(line: 4, column: 25, scope: !16) +!25 = !DILocation(line: 4, column: 3, scope: !16)