[PATCH] D155894: [BPF] allow external calls

Tamir Duberstein via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 27 16:02:34 PDT 2023


tamird abandoned this revision.
tamird added a comment.

@yonghong-song I have learned some things. If you repeat your experiment (even without this patch) but pass `-fno-builtin` when compiling t1.c, everything works.

Here's the diff in IR:

  diff --git a/t1.ll b/t1-fno-builtin.ll
  index 64d172bf9ab5..324a98687ade 100644
  --- a/t1.ll
  +++ b/t1-fno-builtin.ll
  @@ -3,24 +3,24 @@ source_filename = "t1.c"
   target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
   target triple = "bpf"
   
  -; Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: write)
  -define dso_local void @do_memset(ptr nocapture noundef writeonly %x, i64 noundef %l) local_unnamed_addr #0 !dbg !8 {
  +; Function Attrs: nounwind
  +define dso_local void @do_memset(ptr noundef %x, i64 noundef %l) local_unnamed_addr #0 !dbg !8 {
   entry:
     call void @llvm.dbg.value(metadata ptr %x, metadata !15, metadata !DIExpression()), !dbg !17
     call void @llvm.dbg.value(metadata i64 %l, metadata !16, metadata !DIExpression()), !dbg !17
  -  tail call void @llvm.memset.p0.i64(ptr align 1 %x, i8 0, i64 %l, i1 false), !dbg !18
  +  %call = tail call ptr @memset(ptr noundef %x, i32 noundef 0, i64 noundef %l) #3, !dbg !18
     ret void, !dbg !19
   }
   
  -; Function Attrs: mustprogress nocallback nofree nounwind willreturn memory(argmem: write)
  -declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #1
  +declare !dbg !20 hidden ptr @memset(ptr noundef, i32 noundef, i64 noundef) local_unnamed_addr #1
   
   ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
   declare void @llvm.dbg.value(metadata, metadata, metadata) #2
   
  -attributes #0 = { mustprogress nofree nosync nounwind willreturn memory(argmem: write) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
  -attributes #1 = { mustprogress nocallback nofree nounwind willreturn memory(argmem: write) }
  +attributes #0 = { nounwind "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
  +attributes #1 = { "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
   attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
  +attributes #3 = { nobuiltin nounwind "no-builtins" }
   
   !llvm.dbg.cu = !{!0}
   !llvm.module.flags = !{!2, !3, !4, !5, !6}
  @@ -46,3 +46,12 @@ attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memo
   !17 = !DILocation(line: 0, scope: !8)
   !18 = !DILocation(line: 4, column: 3, scope: !8)
   !19 = !DILocation(line: 5, column: 1, scope: !8)
  +!20 = !DISubprogram(name: "memset", scope: !1, file: !1, line: 2, type: !21, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !25)
  +!21 = !DISubroutineType(types: !22)
  +!22 = !{!23, !23, !24, !13}
  +!23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
  +!24 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
  +!25 = !{!26, !27, !28}
  +!26 = !DILocalVariable(name: "s", arg: 1, scope: !20, file: !1, line: 2, type: !23)
  +!27 = !DILocalVariable(name: "c", arg: 2, scope: !20, file: !1, line: 2, type: !24)
  +!28 = !DILocalVariable(name: "n", arg: 3, scope: !20, file: !1, line: 2, type: !13)

The same result is obtained if I annotate `do_memset` with `__attribute__((no_builtin("memset")))`:

  diff --git a/t1.c b/t1-no-builtin.c
  index 2698b334b898..3cded7c57e99 100644
  --- a/t1.c
  +++ b/t1-no-builtin.c
  @@ -1,5 +1,5 @@
   #define __hidden __attribute__((visibility("hidden")))
   __hidden extern void *memset(void *s, int c, unsigned long n);
  -void do_memset(char *x, unsigned long l) {
  +void do_memset(char *x, unsigned long l) __attribute__((no_builtin("memset"))) {
     memset(x, 0, l);
   }

  diff --git a/t1.ll b/t1-no-builtin.ll
  index 64d172bf9ab5..f9a2b088084e 100644
  --- a/t1.ll
  +++ b/t1-no-builtin.ll
  @@ -1,25 +1,25 @@
  -; ModuleID = 't1.c'
  -source_filename = "t1.c"
  +; ModuleID = 't1-no-builtin.c'
  +source_filename = "t1-no-builtin.c"
   target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
   target triple = "bpf"
   
  -; Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: write)
  -define dso_local void @do_memset(ptr nocapture noundef writeonly %x, i64 noundef %l) local_unnamed_addr #0 !dbg !8 {
  +; Function Attrs: mustprogress nofree nounwind willreturn memory(argmem: readwrite)
  +define dso_local void @do_memset(ptr noundef %x, i64 noundef %l) local_unnamed_addr #0 !dbg !8 {
   entry:
     call void @llvm.dbg.value(metadata ptr %x, metadata !15, metadata !DIExpression()), !dbg !17
     call void @llvm.dbg.value(metadata i64 %l, metadata !16, metadata !DIExpression()), !dbg !17
  -  tail call void @llvm.memset.p0.i64(ptr align 1 %x, i8 0, i64 %l, i1 false), !dbg !18
  +  %call = tail call ptr @memset(ptr noundef %x, i32 noundef 0, i64 noundef %l), !dbg !18
     ret void, !dbg !19
   }
   
  -; Function Attrs: mustprogress nocallback nofree nounwind willreturn memory(argmem: write)
  -declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #1
  +; Function Attrs: mustprogress nofree nounwind willreturn memory(argmem: readwrite)
  +declare !dbg !20 hidden ptr @memset(ptr noundef writeonly, i32 noundef, i64 noundef) local_unnamed_addr #1
   
   ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
   declare void @llvm.dbg.value(metadata, metadata, metadata) #2
   
  -attributes #0 = { mustprogress nofree nosync nounwind willreturn memory(argmem: write) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
  -attributes #1 = { mustprogress nocallback nofree nounwind willreturn memory(argmem: write) }
  +attributes #0 = { mustprogress nofree nounwind willreturn memory(argmem: readwrite) "frame-pointer"="all" "no-builtin-memset" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
  +attributes #1 = { mustprogress nofree nounwind willreturn memory(argmem: readwrite) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
   attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
   
   !llvm.dbg.cu = !{!0}
  @@ -27,7 +27,7 @@ attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memo
   !llvm.ident = !{!7}
   
   !0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git 52807ba3836ef30c54622f227c4a23e2eb9375cd)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
  -!1 = !DIFile(filename: "t1.c", directory: "/home/tamird/src/llvm-project-latest/foo", checksumkind: CSK_MD5, checksum: "7d959830f84c1a82a1efb0fbb5b9c592")
  +!1 = !DIFile(filename: "t1-no-builtin.c", directory: "/home/tamird/src/llvm-project-latest/foo", checksumkind: CSK_MD5, checksum: "4a930bd64fe9fcad8934a5f1a66a94d4")
   !2 = !{i32 7, !"Dwarf Version", i32 5}
   !3 = !{i32 2, !"Debug Info Version", i32 3}
   !4 = !{i32 1, !"wchar_size", i32 4}
  @@ -46,3 +46,12 @@ attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memo
   !17 = !DILocation(line: 0, scope: !8)
   !18 = !DILocation(line: 4, column: 3, scope: !8)
   !19 = !DILocation(line: 5, column: 1, scope: !8)
  +!20 = !DISubprogram(name: "memset", scope: !1, file: !1, line: 2, type: !21, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !25)
  +!21 = !DISubroutineType(types: !22)
  +!22 = !{!23, !23, !24, !13}
  +!23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
  +!24 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
  +!25 = !{!26, !27, !28}
  +!26 = !DILocalVariable(name: "s", arg: 1, scope: !20, file: !1, line: 2, type: !23)
  +!27 = !DILocalVariable(name: "c", arg: 2, scope: !20, file: !1, line: 2, type: !24)
  +!28 = !DILocalVariable(name: "n", arg: 3, scope: !20, file: !1, line: 2, type: !13)

`bpftool gen object` works with both of these.

I don't entirely understand the mechanism that causes `memset` to end up not-hidden, but it seems that BPF should always imply `-fno-builtin` for this reason. I've sent a PR to this effect in aya: https://github.com/aya-rs/aya/pull/698.

I'll abandon this, but it may be worthwhile to implement BPF-implies-fno-builtin *in clang*, if possible.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D155894/new/

https://reviews.llvm.org/D155894



More information about the llvm-commits mailing list