[PATCH] D53329: Generate DIFile with main program if source is not available

2018-10-16 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added reviewers: vsk, HsiangKai, ABataev.
yonghong-song added a project: debug-info.
Herald added subscribers: cfe-commits, JDevlieghere, aprantl.

A llvm segfault happens when I tried to add "-g -gdwarf-5 -gembed-source"
in bcc in order to get soruce code into IR and dwarf.

A little bit background, bcc (https://github.com/iovisor/bcc)
utilizes llvm MCJIT to generate BPF insns and load them
to the kernel for execution. Several files passed to clang
are memory mapped including the main program /virtual/main.c.

I did some analysis on why segfault happens and whether we did
get all file sources. And I found that we did not get source
for one instance:

  !32 = !DIFile(filename: "/virtual/main.c", directory: 
"/usr/src/kernels/4.11.3-70_fbk18_4116_g1cf3f1a0ca4f")

After some debugging, I found this patch can fix the problem.
Basically, when the source is not available to generate DIFile
use the main program.

You can get more details of the bug, IR, cc1 flags, segfault
stack and how to reproduce at this commit:

  
https://github.com/yonghong-song/bcc/commit/7ac342e05468e60138d61e0e41691ed2f98bd929
  
Signed-off-by: Yonghong Song 


Repository:
  rC Clang

https://reviews.llvm.org/D53329

Files:
  lib/CodeGen/CGDebugInfo.cpp


Index: lib/CodeGen/CGDebugInfo.cpp
===
--- lib/CodeGen/CGDebugInfo.cpp
+++ lib/CodeGen/CGDebugInfo.cpp
@@ -411,6 +411,10 @@
 // If the location is not valid then use main input file.
 return getOrCreateMainFile();
 
+  if (!getSource(SM, SM.getFileID(Loc)))
+// If the source file is not valid then use main input file
+return getOrCreateMainFile();
+
   // Cache the results.
   const char *fname = PLoc.getFilename();
   auto It = DIFileCache.find(fname);


Index: lib/CodeGen/CGDebugInfo.cpp
===
--- lib/CodeGen/CGDebugInfo.cpp
+++ lib/CodeGen/CGDebugInfo.cpp
@@ -411,6 +411,10 @@
 // If the location is not valid then use main input file.
 return getOrCreateMainFile();
 
+  if (!getSource(SM, SM.getFileID(Loc)))
+// If the source file is not valid then use main input file
+return getOrCreateMainFile();
+
   // Cache the results.
   const char *fname = PLoc.getFilename();
   auto It = DIFileCache.find(fname);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-10-16 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

Hi, @vsk @HsiangKai @ABataev I found a bug in clang when trying to use "-g 
-gdwarf-5 -gembed-source" for
bcc MCJIT based clang/llvm compilation. This patch fixed the issue but I am not 
sure whether this is the
correct fix or not. Please help take a look and advise if the fix is not 
correct and there is a better one. Thanks!


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-10-16 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

We already have `-main-file-name` in cc1.
`clang -cc1 -triple x86_64-unknown-linux-gnu ... -main-file-name main.c ... -o 
main.bc -x c /virtual/main.c -faddrsig`
Is this expected?

BTW, we just pass the normal C flags to the driver like

  vector flags_cstr({"-O0", "-O2", "-emit-llvm", "-I", 
dstack.cwd(),
   "-D", "__BPF_TRACING__",
   "-Wno-deprecated-declarations",
   "-Wno-gnu-variable-sized-type-not-at-end",
   "-Wno-pragma-once-outside-header",
   "-Wno-address-of-packed-member",
   "-Wno-unknown-warning-option",
   "-fno-color-diagnostics",
   "-fno-unwind-tables",
   "-fno-asynchronous-unwind-tables",
   "-x", "c", "-c", abs_file.c_str()});
  flags_cstr.push_back("-g");
  flags_cstr.push_back("-gdwarf-5");
  flags_cstr.push_back("-gembed-source");
  // A few other flags

We call drv.BuildCompilation to get the cc1 flags.


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-10-16 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

In the above `/virtual/main.c` is a memory mapped file. The 
`invocation0.getPreprocessorOpts().addRemappedFile(...)` adds the mapping
for the compilation.


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-10-20 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

Sure. Let me provide a little bit more context and what I want to achieve:

  . I have a tool, called bcc (https://github.com/iovisor/bcc) which uses clang 
CompilerInvocation interface and
MCJIT to generates BPF code and load into kernel
  . Several files (the main.c and a few others headers) are clang memory mapped.
  . The particular fix here is related to https://reviews.llvm.org/D53261, 
getting source code into BTF, but
before that, based on that particular implementation, the source code needs 
to be in IR.
What I found is that for the memory mapped /virtual/main.c file, there is 
one DIFile entry in
generated IR, the associated 'source' is empty, which actually caused a seg 
fault later.
  
Not that this bug itself does not need https://reviews.llvm.org/D53261.

So without this fix, bcc tool will seg fault.
With this fix, bcc tool works properly and all DIFile entry has proper source 
codes embedded, which
if coupled with IR->BTF or Dwarf->BTF should generate correct BTF debug info.


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2019-01-14 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@dblaikie @scott.linder Have you got time to look at this issue? Looks like a 
trivial test case will be able to reproduce the problem. I have the simple 
example in the previous comments. Practically, `-gdwarf-5 -gembed-source` is 
broken now.


Repository:
  rC Clang

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

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2019-01-14 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@scott.linder Thanks! It would be good if you could give at least an initial, 
even rough, analysis.


Repository:
  rC Clang

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

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2019-01-28 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@dblaikie As I mentioned in one of my earlier comments, after some analysis, I 
think this patch definitely not the right way to fix the problem. We just 
cannot default to the main file if the DIFile source is not available.

I have a bug filed for the same issue 
(https://bugs.llvm.org/show_bug.cgi?id=40170) Maybe I should close this patch 
and put the information on the bug report. Do you agree?


Repository:
  rC Clang

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

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2019-01-30 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song abandoned this revision.
yonghong-song added a comment.

Abandon this patch as the proposed fix is not correct. I have put relative 
information in the bug https://bugs.llvm.org/show_bug.cgi?id=40170.


Repository:
  rC Clang

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

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-11-06 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@dblaikie This is not blocking me yet since the main BTF support is not in llvm 
yet. I will be in a conference next week. I will dig into this issue the week 
after, to have a smaller test case and try to root cause a little further. Will 
update here as soon as I got anything. Thanks!


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-11-14 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

F7545597: clang-crash.tar 

@dblaikie I got a standalone reproducible test now.

  -bash-4.4$ pwd
  /home/yhs/work/bcc/clang-crash
  -bash-4.4$ ls
  clang-test.cpp  compile.sh  README  ttest.c  ttest.h
  -bash-4.4$

README has details how to reproduce the issue. Basically, step 1, build a llvm 
with x86/bpf support; step 2, run "compile.sh"; step 3, run the binary 
"clang-test" produced in step 2 and you will get IR with missing file content 
and segfault.

I did not investigate further, but my above patch does not really fix the 
issue. So the right fix should be a different one. There could be multiple 
issues with clang remapped files.

It will be great if you or others can help resolve these issues!

2. $ ./compile.sh
3. $ ./clang-test
  
  The test will print IR before JITing for BPF backend.
  The IR has something like:
 ...
  !8 = !DIFile(filename: "/virtual/ttest.h", directory: "/tmp", checksumkind: 
CSK_MD5, checksum: "6a615c0cc48c46cdbe7d9917c635d292", source: "\0A#define 
BPF_PERF_OUTPUT2(_name) \5C\0Astruct _name##_table_t { \5C\0A  int key; \5C\0A  
unsigned leaf; \5C\0A  int (*perf_submit) (void *, void *, unsigned); \5C\0A  
int (*perf_submit_skb) (void *, unsigned, void *, unsigned); \5C\0A  unsigned 
max_entries; \5C\0A}; \5C\0A__attribute__((section(\22maps/perf_output\22))) 
\5C\0Astruct _name##_table_t _name = { .max_entries = 0 }\0A\0Aint g;\0A")
  !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
  !10 = !DIFile(filename: "/virtual/ttest.c", directory: "/tmp")
  !11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"probe_table_t", file: !10, line: 3, size: 256, elements: !12)
 ...
  Segmentation fault (core dumped)

Note that the "!10" DIFile does not have source code.


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-11-14 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

The above segment looks like

  #0  0x00a1 in ?? ()
  #1  0x01490d63 in clang::SourceManager::~SourceManager() ()
  #2  0x005ad0ee in clang::CompilerInstance::~CompilerInstance() ()
  #3  0x0056ad1b in main ()

In my example, I did not implement the customized SourceManager while the real 
bcc implements it
https://github.com/iovisor/bcc/blob/master/src/cc/bpf_module.cc#L73

I will try to implement this later. With the attached tar file, you should be 
still observe the missing
file contents. And my patch does fix this particular issue.


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-11-14 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

If I am using regular files instead of remapped files, I did not see the 
segfault. So is it possible that this is a clang issue?


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-11-14 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

You compiled with the assertion on, which triggered the issue. I should have 
thought about this. Sorry.
For error,

  clang-test: 
/usr/local/google/home/blaikie/dev/llvm/src/lib/ExecutionEngine/MCJIT/MCJIT.cpp:204:
 virtual void llvm::MCJIT::generateCodeForModule(llvm::Module *): Assertion 
`M->getDataLayout() == getDataLayout() && "DataLayout M ismatch"' failed.

It is because the clang compiler flag is compiled with native arch. which is 
x86 and later on it is changed to generatee BPF code. Could you try to 
temporarily build without assertion on? I will try to modify the test (or you 
could do that too) to generate native code to see whether the bug is still 
there or not.


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-11-14 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

F7549230: clang-crash-x86.tar 

Just attached a new test case (clang-crash-x86.tar) which works even if the 
compiler is compiled with assertion on. JIT now generates x86-64 code instead 
of BPF code.

The error message looks like:

  Failure value returned from cantFail wrapped call
  UNREACHABLE executed at /home/yhs/work/llvm/include/llvm/Support/Error.h:732!
  Aborted (core dumped)

The core stack looks like

  Core was generated by `./clang-test'. 
  Program terminated with signal SIGABRT, Aborted. 
  #0  0x7f47542e0277 in raise () from /lib64/libc.so.6 
  (gdb) where
  #0  0x7f47542e0277 in raise () from /lib64/libc.so.6
  #1  0x7f47542e1968 in abort () from /lib64/libc.so.6
  #2  0x045f66b6 in llvm::llvm_unreachable_internal (msg=0x5df9ba0 
"Failure value returned from cantFail wrapped call",  
  file=0x5df9bd8 "/home/yhs/work/llvm/include/llvm/Support/Error.h", 
line=732)
  at /home/yhs/work/llvm/lib/Support/ErrorHandling.cpp:222
  #3  0x032482f1 in llvm::cantFail (ValOrErr=..., 
  Msg=0x5df9ba0 "Failure value returned from cantFail wrapped call") at 
/home/yhs/work/llvm/include/llvm/Support/Error.h:732
  #4  0x03247183 in llvm::MCStreamer::EmitDwarfFileDirective 
(this=0x8625e40, FileNo=0, Directory=..., Filename=..., 
  Checksum=0x8640868, Source=..., CUID=0) at 
/home/yhs/work/llvm/include/llvm/MC/MCStreamer.h:786 
  #5  0x0324184b in llvm::DwarfCompileUnit::getOrCreateSourceID 
(this=0x8630ed0, File=0x861ae80)
  at /home/yhs/work/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp:110
  #6  0x032a1903 in llvm::DwarfUnit::addSourceLine (this=0x8630ed0, 
Die=..., Line=13, File=0x861ae80)
  at /home/yhs/work/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp:395
  #7  0x032a1a95 in llvm::DwarfUnit::addSourceLine (this=0x8630ed0, 
Die=..., G=0x861af10)
  at /home/yhs/work/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp:410 
  #8  0x03241b5c in 
llvm::DwarfCompileUnit::getOrCreateGlobalVariableDIE (this=0x8630ed0, 
GV=0x861af10, GlobalExprs=...)
  at /home/yhs/work/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp:153
  #9  0x0325b5f9 in llvm::DwarfDebug::beginModule (this=0x862ec00)
  at /home/yhs/work/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp:782
  #10 0x0320636d in llvm::AsmPrinter::doInitialization (this=0x8626820, 
M=...) 
  at /home/yhs/work/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp:309
  #11 0x024eeea4 in llvm::X86AsmPrinter::doInitialization 
(this=0x8626820, M=...)
  at /home/yhs/work/llvm/lib/Target/X86/X86AsmPrinter.h:137
  #12 0x044aa4ee in llvm::FPPassManager::doInitialization 
(this=0x8633e10, M=...)
  at /home/yhs/work/llvm/lib/IR/LegacyPassManager.cpp:1688
  #13 0x044aa6a2 in (anonymous namespace)::MPPassManager::runOnModule 
(this=0x868a380, M=...) 
  at /home/yhs/work/llvm/lib/IR/LegacyPassManager.cpp:1720
  #14 0x044ab027 in llvm::legacy::PassManagerImpl::run (this=0x860e710, 
M=...)
  at /home/yhs/work/llvm/lib/IR/LegacyPassManager.cpp:1857
  #15 0x044ab2a7 in llvm::legacy::PassManager::run 
(this=0x7fff67f37fe0, M=...)
  at /home/yhs/work/llvm/lib/IR/LegacyPassManager.cpp:1888
  #16 0x02d4a39b in llvm::MCJIT::emitObject (this=0x862ab00, 
M=0x85a7bd0)
  at /home/yhs/work/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp:169
  #17 0x02d4a669 in llvm::MCJIT::generateCodeForModule (this=0x862ab00, 
M=0x85a7bd0)
  at /home/yhs/work/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp:208
  #18 0x02d4ab68 in llvm::MCJIT::finalizeObject (this=0x862ab00)
  at /home/yhs/work/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp:263
  #19 0x0040ac10 in main ()

This coredump stack matches one of stacks I hit earlier with using bcc 
infrastructure to reproduce the issue.
Thanks!


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-11-16 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

Thanks @scott.linder, actually "all or nothing" is what I wanted here. We 
really want to get the source for these remapped files.


Repository:
  rC Clang

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53329: Generate DIFile with main program if source is not available

2018-11-30 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

F7630900: clang-crash-x86-2.tar 

@scott.linder Actually clang can get source for remapped files. I just uploaded 
another test tarball which may help you debug the issue.
The test script is changed as well since recent llvm/clang requiring linking 
with -ltinfo.

Just give you a summary here.

  -bash-4.2$ cat ttest.h
  
  #define BPF_PERF_OUTPUT2(_name) \
  struct _name##_table_t { \
int key; \
unsigned leaf; \
int (*perf_submit) (void *, void *, unsigned); \
int (*perf_submit_skb) (void *, unsigned, void *, unsigned); \
unsigned max_entries; \
  }; \
  __attribute__((section("maps/perf_output"))) \
  struct _name##_table_t _name = { .max_entries = 0 }
  
  int g;
  -bash-4.2$ cat ttest1.c
  #include "ttest.h"
  
  int main() { return g; }
  -bash-4.2$ cat ttest2.c
  #include "ttest.h"
  
  BPF_PERF_OUTPUT2(probe);
  
  int main() { return g; }
  -bash-4.2$

The header file ttest.h is remapped.
For remapped file ttest1.c, the clang can get the source properly.
For remapped file ttest2.c, the clang cannot get the source.
The difference between two files are macro usage.

  -bash-4.2$ diff ttest1.c ttest2.c
  2a3,4
  > BPF_PERF_OUTPUT2(probe);
  > 
  -bash-4.2$

So macro existence may somehow prevent availability of remapped file source.


Repository:
  rC Clang

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

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61173: [BPF] do not generate predefined macro bpf

2019-04-25 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added a reviewer: ast.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

"DefineStd(Builder, "bpf", Opts)" generates the following three macros:

  bpf
  __bpf
  __bpf__

and the macro "bpf" is due to the fact that the target language
is C which allows GNU extensions.

The name "bpf" could be easily used as variable name or type
field name. For example, in current linux kernel, there are
four places where bpf is used as a field name. If the corresponding
types are included in bpf program, the compilation error will
occur.

This patch removed predefined macro "bpf".


Repository:
  rC Clang

https://reviews.llvm.org/D61173

Files:
  lib/Basic/Targets/BPF.cpp
  test/Preprocessor/bpf-predefined-macros.c


Index: test/Preprocessor/bpf-predefined-macros.c
===
--- /dev/null
+++ test/Preprocessor/bpf-predefined-macros.c
@@ -0,0 +1,20 @@
+// RUN: %clang -E -target bpfel -x c -o - %s | FileCheck %s
+// RUN: %clang -E -target bpfeb -x c -o - %s | FileCheck %s
+
+#ifdef __bpf
+int a;
+#endif
+#ifdef __bpf__
+int b;
+#endif
+#ifdef __BPF__
+int c;
+#endif
+#ifdef bpf
+int d;
+#endif
+
+// CHECK: int a;
+// CHECK: int b;
+// CHECK: int c;
+// CHECK-NOT: int d;
Index: lib/Basic/Targets/BPF.cpp
===
--- lib/Basic/Targets/BPF.cpp
+++ lib/Basic/Targets/BPF.cpp
@@ -20,7 +20,8 @@
 
 void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
  MacroBuilder &Builder) const {
-  DefineStd(Builder, "bpf", Opts);
+  Builder.defineMacro("__bpf");
+  Builder.defineMacro("__bpf__");
   Builder.defineMacro("__BPF__");
 }
 


Index: test/Preprocessor/bpf-predefined-macros.c
===
--- /dev/null
+++ test/Preprocessor/bpf-predefined-macros.c
@@ -0,0 +1,20 @@
+// RUN: %clang -E -target bpfel -x c -o - %s | FileCheck %s
+// RUN: %clang -E -target bpfeb -x c -o - %s | FileCheck %s
+
+#ifdef __bpf
+int a;
+#endif
+#ifdef __bpf__
+int b;
+#endif
+#ifdef __BPF__
+int c;
+#endif
+#ifdef bpf
+int d;
+#endif
+
+// CHECK: int a;
+// CHECK: int b;
+// CHECK: int c;
+// CHECK-NOT: int d;
Index: lib/Basic/Targets/BPF.cpp
===
--- lib/Basic/Targets/BPF.cpp
+++ lib/Basic/Targets/BPF.cpp
@@ -20,7 +20,8 @@
 
 void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
  MacroBuilder &Builder) const {
-  DefineStd(Builder, "bpf", Opts);
+  Builder.defineMacro("__bpf");
+  Builder.defineMacro("__bpf__");
   Builder.defineMacro("__BPF__");
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61173: [BPF] do not generate predefined macro bpf

2019-04-25 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked an inline comment as done.
yonghong-song added inline comments.



Comment at: lib/Basic/Targets/BPF.cpp:23
  MacroBuilder &Builder) const {
-  DefineStd(Builder, "bpf", Opts);
+  Builder.defineMacro("__bpf");
+  Builder.defineMacro("__bpf__");

ast wrote:
> I don't think anyone is using this one.
> May be we can keep ` __bpf__ ` and ` __BPF__ ` only?
We can do this for sure.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61173



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61173: [BPF] do not generate predefined macro bpf

2019-04-25 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 196799.
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

remove __bpf.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61173

Files:
  lib/Basic/Targets/BPF.cpp
  test/Preprocessor/bpf-predefined-macros.c


Index: test/Preprocessor/bpf-predefined-macros.c
===
--- /dev/null
+++ test/Preprocessor/bpf-predefined-macros.c
@@ -0,0 +1,16 @@
+// RUN: %clang -E -target bpfel -x c -o - %s | FileCheck %s
+// RUN: %clang -E -target bpfeb -x c -o - %s | FileCheck %s
+
+#ifdef __bpf__
+int b;
+#endif
+#ifdef __BPF__
+int c;
+#endif
+#ifdef bpf
+int d;
+#endif
+
+// CHECK: int b;
+// CHECK: int c;
+// CHECK-NOT: int d;
Index: lib/Basic/Targets/BPF.cpp
===
--- lib/Basic/Targets/BPF.cpp
+++ lib/Basic/Targets/BPF.cpp
@@ -20,7 +20,7 @@
 
 void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
  MacroBuilder &Builder) const {
-  DefineStd(Builder, "bpf", Opts);
+  Builder.defineMacro("__bpf__");
   Builder.defineMacro("__BPF__");
 }
 


Index: test/Preprocessor/bpf-predefined-macros.c
===
--- /dev/null
+++ test/Preprocessor/bpf-predefined-macros.c
@@ -0,0 +1,16 @@
+// RUN: %clang -E -target bpfel -x c -o - %s | FileCheck %s
+// RUN: %clang -E -target bpfeb -x c -o - %s | FileCheck %s
+
+#ifdef __bpf__
+int b;
+#endif
+#ifdef __BPF__
+int c;
+#endif
+#ifdef bpf
+int d;
+#endif
+
+// CHECK: int b;
+// CHECK: int c;
+// CHECK-NOT: int d;
Index: lib/Basic/Targets/BPF.cpp
===
--- lib/Basic/Targets/BPF.cpp
+++ lib/Basic/Targets/BPF.cpp
@@ -20,7 +20,7 @@
 
 void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
  MacroBuilder &Builder) const {
-  DefineStd(Builder, "bpf", Opts);
+  Builder.defineMacro("__bpf__");
   Builder.defineMacro("__BPF__");
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-06-11 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@rsmith @eli.friedman Ping again. Do you have any comments on my proposed 
clang/IR intrinsics? Thanks!


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-06-19 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked an inline comment as done.
yonghong-song added a comment.

@eli.friedman Sorry for replying late. I am outside US and currently in PTO. 
Will back to US soon to address your comments.

> can we really expect the user to know which expressions to apply this to?

Yes, this is specifically targeting some bpf helper calls like bpf_probe_read. 
So users know which expressions to apply.

> I'd like to see an actual specification for this in 
> docs/LanguageExtensions.rst at some point.

I will find a place to put this into docs/LanguageExtensions.rst.




Comment at: lib/CodeGen/CGExpr.cpp:663
+  while (true) {
+const auto &Parents = getContext().getParents(*E);
+if (Parents.size() != 1)

efriedma wrote:
> I'm not sure you can use getParents like this safely... it's not really meant 
> for use inside of clang semantic analysis/code generation, and I don't think 
> we recompute it as the AST changes.
Good point. Let me check whether I can traverse AST instead.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64598: fix unnamed fiefield issue and add tests for __builtin_preserve_access_index intrinsic

2019-07-11 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added reviewers: eli.friedman, jdoerfert, ast.
Herald added subscribers: kristina, arphaman, aprantl.
Herald added a project: clang.

This is a followup patch for https://reviews.llvm.org/D61809.
Handle unnamed bitfield properly and add more test cases

Fixed the unnamed bitfield issue. The unnamed bitfield is ignored
by debug info, so we need to ignore such a struct/union member
when we try to get the member index in the debug info.

D61809  contains two test cases but not enough 
as it does
not checking generated IRs in the fine grain level, and also
it does not have semantics checking tests.
This patch added unit tests for both code gen and semantics checking for
the new intrinsic.


Repository:
  rC Clang

https://reviews.llvm.org/D64598

Files:
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGen/builtin-preserve-access-index.c
  test/Sema/builtin-preserve-access-index.c

Index: test/Sema/builtin-preserve-access-index.c
===
--- /dev/null
+++ test/Sema/builtin-preserve-access-index.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -x c -triple x86_64-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
+
+const void *invalid1(const int *arg) {
+  return __builtin_preserve_access_index(&arg[1], 1); // expected-error {{too many arguments to function call, expected 1, have 2}}
+}
+
+void *invalid2(const int *arg) {
+  return __builtin_preserve_access_index(&arg[1]); // expected-warning {{returning 'const void *' from a function with result type 'void *' discards qualifiers}}
+}
+
+const void *invalid3(const int *arg) {
+  return __builtin_preserve_access_index(1); // expected-warning {{incompatible integer to pointer conversion passing 'int' to parameter of type 'const void *'}}
+}
Index: test/CodeGen/builtin-preserve-access-index.c
===
--- /dev/null
+++ test/CodeGen/builtin-preserve-access-index.c
@@ -0,0 +1,167 @@
+// RUN: %clang -target x86_64 -emit-llvm -S -g %s -o - | FileCheck %s
+
+#define _(x) (__builtin_preserve_access_index(x))
+
+const void *unit1(const void *arg) {
+  return _(arg);
+}
+// CHECK: define dso_local i8* @unit1(i8* %arg)
+// CHECK-NOT: llvm.preserve.array.access.index
+// CHECK-NOT: llvm.preserve.struct.access.index
+// CHECK-NOT: llvm.preserve.union.access.index
+
+const void *unit2(void) {
+  return _((const void *)0xULL);
+}
+// CHECK: define dso_local i8* @unit2()
+// CHECK-NOT: llvm.preserve.array.access.index
+// CHECK-NOT: llvm.preserve.struct.access.index
+// CHECK-NOT: llvm.preserve.union.access.index
+
+const void *unit3(const int *arg) {
+  return _(arg + 1);
+}
+// CHECK: define dso_local i8* @unit3(i32* %arg)
+// CHECK-NOT: llvm.preserve.array.access.index
+// CHECK-NOT: llvm.preserve.struct.access.index
+// CHECK-NOT: llvm.preserve.union.access.index
+
+const void *unit4(const int *arg) {
+  return _(&arg[1]);
+}
+// CHECK: define dso_local i8* @unit4(i32* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %0, i32 0, i32 1)
+
+const void *unit5(const int *arg[5]) {
+  return _(&arg[1][2]);
+}
+// CHECK: define dso_local i8* @unit5(i32** %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %0, i32 0, i32 1)
+// CHECK-NOT: getelementptr
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %2, i32 0, i32 2)
+
+struct s1 {
+  char a;
+  int b;
+};
+
+struct s2 {
+  char a1:1;
+  char a2:1;
+  int b;
+};
+
+struct s3 {
+  char a1:1;
+  char a2:1;
+  char :6;
+  int b;
+};
+
+const void *unit6(struct s1 *arg) {
+  return _(&arg->a);
+}
+// CHECK: define dso_local i8* @unit6(%struct.s1* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* %0, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
+
+const void *unit7(struct s1 *arg) {
+  return _(&arg->b);
+}
+// CHECK: define dso_local i8* @unit7(%struct.s1* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %0, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
+
+const void *unit8(struct s2 *arg) {
+  return _(&arg->b);
+}
+// CHECK: define dso_local i8* @unit8(%struct.s2* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s2s(%struct.s2* %0, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
+
+const void *unit9(struct s3 *arg) {
+  return _(&arg->b);
+}
+// CHECK: define dso_local i8* @unit9(%struct.s3* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s3s(%struct.s3* %0, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]

[PATCH] D64598: fix unnamed fiefield issue and add tests for __builtin_preserve_access_index intrinsic

2019-07-11 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 209379.
yonghong-song added a subscriber: anakryiko.
yonghong-song added a comment.

change test case so we can test metadata is generated correctly.


Repository:
  rC Clang

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

https://reviews.llvm.org/D64598

Files:
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGen/builtin-preserve-access-index.c
  test/Sema/builtin-preserve-access-index.c

Index: test/Sema/builtin-preserve-access-index.c
===
--- /dev/null
+++ test/Sema/builtin-preserve-access-index.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -x c -triple x86_64-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
+
+const void *invalid1(const int *arg) {
+  return __builtin_preserve_access_index(&arg[1], 1); // expected-error {{too many arguments to function call, expected 1, have 2}}
+}
+
+void *invalid2(const int *arg) {
+  return __builtin_preserve_access_index(&arg[1]); // expected-warning {{returning 'const void *' from a function with result type 'void *' discards qualifiers}}
+}
+
+const void *invalid3(const int *arg) {
+  return __builtin_preserve_access_index(1); // expected-warning {{incompatible integer to pointer conversion passing 'int' to parameter of type 'const void *'}}
+}
Index: test/CodeGen/builtin-preserve-access-index.c
===
--- /dev/null
+++ test/CodeGen/builtin-preserve-access-index.c
@@ -0,0 +1,177 @@
+// RUN: %clang -target x86_64 -emit-llvm -S -g %s -o - | FileCheck %s
+
+#define _(x) (__builtin_preserve_access_index(x))
+
+const void *unit1(const void *arg) {
+  return _(arg);
+}
+// CHECK: define dso_local i8* @unit1(i8* %arg)
+// CHECK-NOT: llvm.preserve.array.access.index
+// CHECK-NOT: llvm.preserve.struct.access.index
+// CHECK-NOT: llvm.preserve.union.access.index
+
+const void *unit2(void) {
+  return _((const void *)0xULL);
+}
+// CHECK: define dso_local i8* @unit2()
+// CHECK-NOT: llvm.preserve.array.access.index
+// CHECK-NOT: llvm.preserve.struct.access.index
+// CHECK-NOT: llvm.preserve.union.access.index
+
+const void *unit3(const int *arg) {
+  return _(arg + 1);
+}
+// CHECK: define dso_local i8* @unit3(i32* %arg)
+// CHECK-NOT: llvm.preserve.array.access.index
+// CHECK-NOT: llvm.preserve.struct.access.index
+// CHECK-NOT: llvm.preserve.union.access.index
+
+const void *unit4(const int *arg) {
+  return _(&arg[1]);
+}
+// CHECK: define dso_local i8* @unit4(i32* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %0, i32 0, i32 1)
+
+const void *unit5(const int *arg[5]) {
+  return _(&arg[1][2]);
+}
+// CHECK: define dso_local i8* @unit5(i32** %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %0, i32 0, i32 1)
+// CHECK-NOT: getelementptr
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %2, i32 0, i32 2)
+
+struct s1 {
+  char a;
+  int b;
+};
+
+struct s2 {
+  char a1:1;
+  char a2:1;
+  int b;
+};
+
+struct s3 {
+  char a1:1;
+  char a2:1;
+  char :6;
+  int b;
+};
+
+const void *unit6(struct s1 *arg) {
+  return _(&arg->a);
+}
+// CHECK: define dso_local i8* @unit6(%struct.s1* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* %0, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]]
+
+const void *unit7(struct s1 *arg) {
+  return _(&arg->b);
+}
+// CHECK: define dso_local i8* @unit7(%struct.s1* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %0, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1]]
+
+const void *unit8(struct s2 *arg) {
+  return _(&arg->b);
+}
+// CHECK: define dso_local i8* @unit8(%struct.s2* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s2s(%struct.s2* %0, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S2:[0-9]+]]
+
+const void *unit9(struct s3 *arg) {
+  return _(&arg->b);
+}
+// CHECK: define dso_local i8* @unit9(%struct.s3* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s3s(%struct.s3* %0, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S3:[0-9]+]]
+
+union u1 {
+  char a;
+  int b;
+};
+
+union u2 {
+  char a;
+  int :32;
+  int b;
+};
+
+const void *unit10(union u1 *arg) {
+  return _(&arg->a);
+}
+// CHECK: define dso_local i8* @unit10(%union.u1* %arg)
+// CHECK-NOT: getelementptr
+// CHECK: call %union.u1* @llvm.preserve.union.access.index.p0s_union.u1s.p0s_union.u1s(%union.u1* %0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U1:[0-9]+]]
+
+const void *unit11(union u1 *arg) {
+  return _(&arg->b);
+

[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-07-11 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

The followup patch for this change is at https://reviews.llvm.org/D64598.


Repository:
  rL LLVM

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64598: fix unnamed fiefield issue and add tests for __builtin_preserve_access_index intrinsic

2019-07-24 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song closed this revision.
yonghong-song added a comment.

The commit has been merged.


Repository:
  rC Clang

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

https://reviews.llvm.org/D64598



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-07-24 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song abandoned this revision.
yonghong-song added a comment.

abandon this one. A revised version with most tests has been merged.


Repository:
  rL LLVM

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65615: [BPF] annotate DIType metadata for builtin preseve_array_access_index()

2019-08-01 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added a reviewer: ast.
Herald added subscribers: kristina, arphaman, aprantl.
Herald added a project: clang.

Previously, debuginfo types are annotated to
IR builtin preserve_struct_access_index() and
preserve_union_access_index(), but not
preserve_array_access_index(). The debug info
is useful to identify the root type name which
later will be used for type comparison.

For user access without explicit type conversions,
the previous scheme works as we can ignore intermediate
compiler generated type conversions (e.g., from union types to
union members) and still generate correct access index string.

The issue comes with user explicit type conversions, e.g.,
converting an array to a structure like below:

  struct t { int a; char b[40]; };
  struct p { int c; int d; };
  struct t *var = ...;
  ... __builtin_preserve_access_index(&(((struct p *)&(var->b[0]))->d)) ...

Although BPF backend can derive the type of &(var->b[0]),
explicit type annotation make checking more consistent
and less error prone.

Another benefit is for multiple dimension array handling.
For example,

  struct p { int c; int d; } g[8][9][10];
  ... __builtin_preserve_access_index(&g[2][3][4].d) ...

It would be possible to calculate the number of "struct p"'s
before accessing its member "d" if array debug info is
available as it contains each dimension range.

This patch enables to annotate IR builtin preserve_array_access_index()
with either debuginfo array type or pointer type,
depending on user expression.


Repository:
  rC Clang

https://reviews.llvm.org/D65615

Files:
  lib/CodeGen/CGExpr.cpp
  test/CodeGen/builtin-preserve-access-index-array.c
  test/CodeGen/builtin-preserve-access-index.c

Index: test/CodeGen/builtin-preserve-access-index.c
===
--- test/CodeGen/builtin-preserve-access-index.c
+++ test/CodeGen/builtin-preserve-access-index.c
@@ -31,16 +31,16 @@
 }
 // CHECK: define dso_local i8* @unit4
 // CHECK-NOT: getelementptr
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1)
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]]
 
 const void *unit5(const int *arg[5]) {
   return _(&arg[1][2]);
 }
 // CHECK: define dso_local i8* @unit5
 // CHECK-NOT: getelementptr
-// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1)
+// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
 // CHECK-NOT: getelementptr
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 2)
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]]
 
 struct s1 {
   char a;
@@ -141,7 +141,7 @@
 // CHECK: define dso_local i8* @unit13
 // CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4:[0-9]+]]
 // CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U:[0-9]+]]
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2)
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
 
 const void *unit14(union u3 *arg) {
   return _(&arg->c.b[2]);
@@ -149,13 +149,13 @@
 // CHECK: define dso_local i8* @unit14
 // CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3:[0-9]+]]
 // CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.ss(%struct.s* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_I_S:[0-9]+]]
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2)
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
 
 const void *unit15(struct s4 *arg) {
   return _(&arg[2].c.a);
 }
 // CHECK: define dso_local i8* @unit15
-// CHECK: call %struct.s4* @llvm.preserve.array.access.index.p0s_struct.s4s.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 0, i32 2)
+// CHECK: call %struct.s4* @llvm.preserve.array.access.index.p0s_struct.s4s.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.ac

[PATCH] D65615: [BPF] annotate DIType metadata for builtin preseve_array_access_index()

2019-08-01 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

The corresponding IR intrinsic interface change is at 
https://reviews.llvm.org/D65617
The BPF backend to utilize this information is at 
https://reviews.llvm.org/D65618


Repository:
  rC Clang

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

https://reviews.llvm.org/D65615



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65615: [BPF] annotate DIType metadata for builtin preseve_array_access_index()

2019-08-01 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked an inline comment as done.
yonghong-song added inline comments.



Comment at: lib/CodeGen/CGExpr.cpp:3402
  QualType eltType, bool inbounds,
- bool signedIndices, SourceLocation loc,
+ bool signedIndices, QualType *arrayType,
+ SourceLocation loc,

ast wrote:
> would it make sense to reorder and make it 'QualType *arrayType = nullptr', 
> so only explicit pointers would be passed and the rest will get 'nullptr' 
> automatically?
Yes, that makes sense. Previous I thought about grouping related fields 
together. But make nullptr as the default is a good idea.


Repository:
  rC Clang

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

https://reviews.llvm.org/D65615



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65615: [BPF] annotate DIType metadata for builtin preseve_array_access_index()

2019-08-01 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 212926.
yonghong-song added a comment.

reorder parameter arrayType to make it with default nullptr and simplifies the 
code.


Repository:
  rC Clang

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

https://reviews.llvm.org/D65615

Files:
  lib/CodeGen/CGExpr.cpp
  test/CodeGen/builtin-preserve-access-index-array.c
  test/CodeGen/builtin-preserve-access-index.c

Index: test/CodeGen/builtin-preserve-access-index.c
===
--- test/CodeGen/builtin-preserve-access-index.c
+++ test/CodeGen/builtin-preserve-access-index.c
@@ -31,16 +31,16 @@
 }
 // CHECK: define dso_local i8* @unit4
 // CHECK-NOT: getelementptr
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1)
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]]
 
 const void *unit5(const int *arg[5]) {
   return _(&arg[1][2]);
 }
 // CHECK: define dso_local i8* @unit5
 // CHECK-NOT: getelementptr
-// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1)
+// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
 // CHECK-NOT: getelementptr
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 2)
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]]
 
 struct s1 {
   char a;
@@ -141,7 +141,7 @@
 // CHECK: define dso_local i8* @unit13
 // CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4:[0-9]+]]
 // CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U:[0-9]+]]
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2)
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
 
 const void *unit14(union u3 *arg) {
   return _(&arg->c.b[2]);
@@ -149,13 +149,13 @@
 // CHECK: define dso_local i8* @unit14
 // CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3:[0-9]+]]
 // CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.ss(%struct.s* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_I_S:[0-9]+]]
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2)
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
 
 const void *unit15(struct s4 *arg) {
   return _(&arg[2].c.a);
 }
 // CHECK: define dso_local i8* @unit15
-// CHECK: call %struct.s4* @llvm.preserve.array.access.index.p0s_struct.s4s.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 0, i32 2)
+// CHECK: call %struct.s4* @llvm.preserve.array.access.index.p0s_struct.s4s.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
 // CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4]]
 // CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U]]
 
@@ -163,15 +163,16 @@
   return _(&arg[2].a);
 }
 // CHECK: define dso_local i8* @unit16
-// CHECK: call %union.u3* @llvm.preserve.array.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0, i32 2)
+// CHECK: call %union.u3* @llvm.preserve.array.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
 // CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3]]
 
+// CHECK: ![[POINTER]] = !DIDerivedType(tag: DW_TAG_pointer_type
+// CHECK: ![[STRUCT_S4]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s4"
+// CHECK: ![[UNION_I_U]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u"
+// CHECK: ![[UNION_U3]] = distinct !DICompositeType(tag: DW_TAG_union_type, na

[PATCH] D65664: [BPF] annotate DIType metadata for builtin preseve_array_access_index()

2019-08-02 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added a reviewer: ast.
Herald added subscribers: llvm-commits, cfe-commits, arphaman, aprantl.
Herald added projects: clang, LLVM.

Previously, debuginfo types are annotated to
IR builtin preserve_struct_access_index() and
preserve_union_access_index(), but not
preserve_array_access_index(). The debug info
is useful to identify the root type name which
later will be used for type comparison.

For user access without explicit type conversions,
the previous scheme works as we can ignore intermediate
compiler generated type conversions (e.g., from union types to
union members) and still generate correct access index string.

The issue comes with user explicit type conversions, e.g.,
converting an array to a structure like below:

  struct t { int a; char b[40]; };
  struct p { int c; int d; };
  struct t *var = ...;
  ... __builtin_preserve_access_index(&(((struct p *)&(var->b[0]))->d)) ...

Although BPF backend can derive the type of &(var->b[0]),
explicit type annotation make checking more consistent
and less error prone.

Another benefit is for multiple dimension array handling.
For example,

  struct p { int c; int d; } g[8][9][10];
  ... __builtin_preserve_access_index(&g[2][3][4].d) ...

It would be possible to calculate the number of "struct p"'s
before accessing its member "d" if array debug info is
available as it contains each dimension range.

This patch enables to annotate IR builtin preserve_array_access_index()
with proper debuginfo type. The unit test case and language reference
is updated as well.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65664

Files:
  clang/lib/CodeGen/CGExpr.cpp
  clang/test/CodeGen/builtin-preserve-access-index-array.c
  clang/test/CodeGen/builtin-preserve-access-index.c
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/IRBuilder.h
  llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll

Index: llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
===
--- llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
+++ llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
@@ -14,7 +14,7 @@
 define dso_local i32 @test(%struct.s* %arg) local_unnamed_addr #0 !dbg !7 {
 entry:
   call void @llvm.dbg.value(metadata %struct.s* %arg, metadata !17, metadata !DIExpression()), !dbg !18
-  %0 = tail call %struct.s* @llvm.preserve.array.access.index.p0s_struct.ss.p0s_struct.ss(%struct.s* %arg, i32 0, i32 2), !dbg !19
+  %0 = tail call %struct.s* @llvm.preserve.array.access.index.p0s_struct.ss.p0s_struct.ss(%struct.s* %arg, i32 0, i32 2), !dbg !19, !llvm.preserve.access.index !11
   %1 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s* %0, i32 1, i32 1), !dbg !19, !llvm.preserve.access.index !12
   %2 = bitcast i32* %1 to i8*, !dbg !19
   %call = tail call i32 @get_value(i8* %2) #4, !dbg !20
Index: llvm/include/llvm/IR/IRBuilder.h
===
--- llvm/include/llvm/IR/IRBuilder.h
+++ llvm/include/llvm/IR/IRBuilder.h
@@ -2484,7 +2484,7 @@
   }
 
   Value *CreatePreserveArrayAccessIndex(Value *Base, unsigned Dimension,
-unsigned LastIndex) {
+unsigned LastIndex, MDNode *DbgInfo) {
 assert(isa(Base->getType()) &&
"Invalid Base ptr type for preserve.array.access.index.");
 auto *BaseType = Base->getType();
@@ -2506,6 +2506,7 @@
 Value *DimV = getInt32(Dimension);
 CallInst *Fn =
 CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV});
+Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
 
 return Fn;
   }
Index: llvm/docs/LangRef.rst
===
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -17395,6 +17395,10 @@
 into the array. The return type ``ret_type`` is a pointer type to the array element.
 The array ``dim`` and ``index`` are preserved which is more robust than
 getelementptr instruction which may be subject to compiler transformation.
+The ``llvm.preserve.access.index`` type of metadata is attached to this call instruction
+to provide array or pointer debuginfo type.
+The metadata is a ``DICompositeType`` or ``DIDerivedType`` representing the
+debuginfo version of ``type``.
 
 Arguments:
 ""
Index: clang/test/CodeGen/builtin-preserve-access-index.c
===
--- clang/test/CodeGen/builtin-preserve-access-index.c
+++ clang/test/CodeGen/builtin-preserve-access-index.c
@@ -31,16 +31,16 @@
 }
 // CHECK: define dso_local i8* @unit4
 // CHECK-NOT: getelementptr
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1)
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]]
 
 co

[PATCH] D65615: [BPF] annotate DIType metadata for builtin preseve_array_access_index()

2019-08-02 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song abandoned this revision.
yonghong-song added a comment.

abandon this one. use git monorepo https://reviews.llvm.org/D65664 since we 
have llvm/clang inter-dependence here.


Repository:
  rC Clang

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

https://reviews.llvm.org/D65615



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65664: [BPF] annotate DIType metadata for builtin preseve_array_access_index()

2019-08-02 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 213122.
yonghong-song added a comment.

set metadata unless metadata is non-NULL. I have not found a case where 
metadata is NULL. But nevertheless, let us do this to avoid set a potential 
NULL metadata.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65664

Files:
  clang/lib/CodeGen/CGExpr.cpp
  clang/test/CodeGen/builtin-preserve-access-index-array.c
  clang/test/CodeGen/builtin-preserve-access-index.c
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/IRBuilder.h
  llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll

Index: llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
===
--- llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
+++ llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
@@ -14,7 +14,7 @@
 define dso_local i32 @test(%struct.s* %arg) local_unnamed_addr #0 !dbg !7 {
 entry:
   call void @llvm.dbg.value(metadata %struct.s* %arg, metadata !17, metadata !DIExpression()), !dbg !18
-  %0 = tail call %struct.s* @llvm.preserve.array.access.index.p0s_struct.ss.p0s_struct.ss(%struct.s* %arg, i32 0, i32 2), !dbg !19
+  %0 = tail call %struct.s* @llvm.preserve.array.access.index.p0s_struct.ss.p0s_struct.ss(%struct.s* %arg, i32 0, i32 2), !dbg !19, !llvm.preserve.access.index !11
   %1 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s* %0, i32 1, i32 1), !dbg !19, !llvm.preserve.access.index !12
   %2 = bitcast i32* %1 to i8*, !dbg !19
   %call = tail call i32 @get_value(i8* %2) #4, !dbg !20
Index: llvm/include/llvm/IR/IRBuilder.h
===
--- llvm/include/llvm/IR/IRBuilder.h
+++ llvm/include/llvm/IR/IRBuilder.h
@@ -2484,7 +2484,7 @@
   }
 
   Value *CreatePreserveArrayAccessIndex(Value *Base, unsigned Dimension,
-unsigned LastIndex) {
+unsigned LastIndex, MDNode *DbgInfo) {
 assert(isa(Base->getType()) &&
"Invalid Base ptr type for preserve.array.access.index.");
 auto *BaseType = Base->getType();
@@ -2506,6 +2506,8 @@
 Value *DimV = getInt32(Dimension);
 CallInst *Fn =
 CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV});
+if (DbgInfo)
+  Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
 
 return Fn;
   }
@@ -2523,7 +2525,8 @@
 Value *DIIndex = getInt32(FieldIndex);
 CallInst *Fn =
 CreateCall(FnPreserveUnionAccessIndex, {Base, DIIndex});
-Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
+if (DbgInfo)
+  Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
 
 return Fn;
   }
@@ -2546,7 +2549,8 @@
 Value *DIIndex = getInt32(FieldIndex);
 CallInst *Fn = CreateCall(FnPreserveStructAccessIndex,
   {Base, GEPIndex, DIIndex});
-Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
+if (DbgInfo)
+  Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
 
 return Fn;
   }
Index: llvm/docs/LangRef.rst
===
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -17395,6 +17395,10 @@
 into the array. The return type ``ret_type`` is a pointer type to the array element.
 The array ``dim`` and ``index`` are preserved which is more robust than
 getelementptr instruction which may be subject to compiler transformation.
+The ``llvm.preserve.access.index`` type of metadata is attached to this call instruction
+to provide array or pointer debuginfo type.
+The metadata is a ``DICompositeType`` or ``DIDerivedType`` representing the
+debuginfo version of ``type``.
 
 Arguments:
 ""
Index: clang/test/CodeGen/builtin-preserve-access-index.c
===
--- clang/test/CodeGen/builtin-preserve-access-index.c
+++ clang/test/CodeGen/builtin-preserve-access-index.c
@@ -31,16 +31,16 @@
 }
 // CHECK: define dso_local i8* @unit4
 // CHECK-NOT: getelementptr
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1)
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]]
 
 const void *unit5(const int *arg[5]) {
   return _(&arg[1][2]);
 }
 // CHECK: define dso_local i8* @unit5
 // CHECK-NOT: getelementptr
-// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1)
+// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
 // CHECK-NOT: getelementptr
-// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 2)
+// CHECK:

[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-06-24 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 206274.
yonghong-song added a comment.

do not use ctx.getParents() to check whether a GEP candidate inside a 
preserve_access_index. instead, mark the region upfront. Add the new clang 
intrinsic into the language doc.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809

Files:
  docs/LanguageExtensions.rst
  include/clang/Basic/Builtins.def
  lib/CodeGen/CGBuilder.h
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/Sema/SemaChecking.cpp
  test/CodeGen/bpf-preserve-access-index-2.c
  test/CodeGen/bpf-preserve-access-index.c

Index: test/CodeGen/bpf-preserve-access-index.c
===
--- /dev/null
+++ test/CodeGen/bpf-preserve-access-index.c
@@ -0,0 +1,28 @@
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -o - | FileCheck --check-prefix=CHECK %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -o - | FileCheck --check-prefix=CHECK %s
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -O2 -o - | FileCheck --check-prefix=CHECK-NODBG %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -O2 -o - | FileCheck --check-prefix=CHECK-NODBG %s
+
+struct t {
+  int i:1;
+  int j:2;
+  union {
+   int a;
+   int b;
+  } c[4];
+};
+
+#define _(x) (__builtin_preserve_access_index(x))
+
+void *test(struct t *arg) {
+  return _(&arg->c[3].b);
+}
+
+// CHECK: llvm.preserve.struct.access.index
+// CHECK: llvm.preserve.array.access.index
+// CHECK: llvm.preserve.union.access.index
+// CHECK-NOT: __builtin_preserve_access_index
+// CHECK-NODBG-NOT: llvm.preserve.struct.access.index
+// CHECK-NODBG-NOT: llvm.preserve.array.access.index
+// CHECK-NODBG-NOT: llvm.preserve.union.access.index
+// CHECK-NODBG-NOT: __builtin_preserve_access_index
Index: test/CodeGen/bpf-preserve-access-index-2.c
===
--- /dev/null
+++ test/CodeGen/bpf-preserve-access-index-2.c
@@ -0,0 +1,22 @@
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -o - | FileCheck %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -o - | FileCheck %s
+
+struct t {
+  int i:1;
+  int j:2;
+  union {
+   int a;
+   int b;
+  } c[4];
+};
+
+#define _(x) (x)
+
+void *test(struct t *arg) {
+  return _(&arg->c[3].b);
+}
+
+// CHECK-NOT: llvm.preserve.struct.access.index
+// CHECK-NOT: llvm.preserve.array.access.index
+// CHECK-NOT: llvm.preserve.union.access.index
+// CHECK-NOT: __builtin_preserve_access_index
Index: lib/Sema/SemaChecking.cpp
===
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -191,6 +191,16 @@
   return false;
 }
 
+/// Check the number of arguments, and set the result type to
+/// the argument type.
+static bool SemaBuiltinPreserveAI(Sema &S, CallExpr *TheCall) {
+  if (checkArgCount(S, TheCall, 1))
+return true;
+
+  TheCall->setType(TheCall->getArg(0)->getType());
+  return false;
+}
+
 static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
   if (checkArgCount(S, TheCall, 3))
 return true;
@@ -1409,6 +1419,10 @@
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_preserve_access_index:
+if (SemaBuiltinPreserveAI(*this, TheCall))
+  return ExprError();
+break;
   case Builtin::BI__builtin_call_with_static_chain:
 if (SemaBuiltinCallWithStaticChain(*this, TheCall))
   return ExprError();
Index: lib/CodeGen/CodeGenFunction.h
===
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -480,6 +480,10 @@
   /// finally block or filter expression.
   bool IsOutlinedSEHHelper = false;
 
+  /// True if CodeGen currently emits code inside presereved access index
+  /// region.
+  bool IsInPreservedAIRegion = false;
+
   const CodeGen::CGBlockInfo *BlockInfo = nullptr;
   llvm::Value *BlockPointer = nullptr;
 
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/NSAPI.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringExtras.h"
@@ -3418,8 +3419,20 @@
   CharUnits eltAlign =
 getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize);
 
-  llvm::Value *eltPtr = emitArraySubscriptGEP(
-  CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name);
+  llvm::Value *eltPtr;
+  auto LastIndex = dyn_cast(indices.back());
+  if (!CGF.IsInPreservedAIRegion || !LastIndex) {
+eltPtr = emitArraySubscriptGEP(
+CGF, addr.getPointer(), indices, inbounds, signedIndices,
+loc, name);
+  } else {
+// Remember the original

[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-06-24 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked an inline comment as not done.
yonghong-song added a comment.

@eli.friedman I removed the usage of astcontext getParents() stuff. Instead, I 
mark the region upfront. I also added the intrinsic 
__builtin_preserve_access_index() into clang
lang extention doc. Could you take a look at new patch? Thanks!


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-06-27 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@eli.friedman Hi, Just ping. I have removed getParents() for ASTContext and 
added description of the new intrinsic in language doc. Could you take a look? 
Thanks!


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-06-27 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked 2 inline comments as done.
yonghong-song added a comment.

@rsmith I have proposed one clang intrinsic and three IR intrinsics for CO-RE. 
Could you take a look and share your opinions as well? Thanks!




Comment at: docs/LanguageExtensions.rst:1958
+array subscript access and structure/union member access are preserved with
+IR intrinsics ``preserve_array_access_index``, ``preserve_union_access_index``
+and ``preserve_struct_access_index``, instead of IR GetElementPtr instructions.

efriedma wrote:
> "preserved with the IR intrinsics" isn't really useful; this is the user's 
> manual, not a developer guide to LLVM internals. Probably better to say what 
> it enables from the user's perspective: the CO-RE feature for BPF targets.
Will reword to be more towards users in the next revision.



Comment at: docs/LanguageExtensions.rst:1960
+and ``preserve_struct_access_index``, instead of IR GetElementPtr instructions.
+``__builtin_preserve_access_index`` takes effect only when debuginfo (typically
+with ``-g``) is available since debuginfo is used as IR intrinsic metadata

efriedma wrote:
> I would rather not have __builtin_preserve_access_index fail to do anything 
> when debug info is disabled. If it's hard to fix, making it a hard error is 
> probably okay.
The IR intrinsics needs to have debuginfo as the metadata so that the 
user-level access info can be reconstructed. If no debug info, just IR 
intrinsics without debuginfo is less useful. So let me make a hard error.

We can relax it later if IR intrinsics without deebuginfo metadata becomes 
workable/useful.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-07-01 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 207475.
yonghong-song added a comment.

reword the lang doc for builtin_preserve_access_index() to be more user focused
treat using builtin_preserve_access_index() without -g or in nested way as 
compiler errors


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809

Files:
  docs/LanguageExtensions.rst
  include/clang/Basic/Builtins.def
  lib/CodeGen/CGBuilder.h
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/Sema/SemaChecking.cpp
  test/CodeGen/bpf-preserve-access-index-2.c
  test/CodeGen/bpf-preserve-access-index.c

Index: test/CodeGen/bpf-preserve-access-index.c
===
--- /dev/null
+++ test/CodeGen/bpf-preserve-access-index.c
@@ -0,0 +1,22 @@
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -o - | FileCheck --check-prefix=CHECK %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -o - | FileCheck --check-prefix=CHECK %s
+
+struct t {
+  int i:1;
+  int j:2;
+  union {
+   int a;
+   int b;
+  } c[4];
+};
+
+#define _(x) (__builtin_preserve_access_index(x))
+
+void *test(struct t *arg) {
+  return _(&arg->c[3].b);
+}
+
+// CHECK: llvm.preserve.struct.access.index
+// CHECK: llvm.preserve.array.access.index
+// CHECK: llvm.preserve.union.access.index
+// CHECK-NOT: __builtin_preserve_access_index
Index: test/CodeGen/bpf-preserve-access-index-2.c
===
--- /dev/null
+++ test/CodeGen/bpf-preserve-access-index-2.c
@@ -0,0 +1,22 @@
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -o - | FileCheck %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -o - | FileCheck %s
+
+struct t {
+  int i:1;
+  int j:2;
+  union {
+   int a;
+   int b;
+  } c[4];
+};
+
+#define _(x) (x)
+
+void *test(struct t *arg) {
+  return _(&arg->c[3].b);
+}
+
+// CHECK-NOT: llvm.preserve.struct.access.index
+// CHECK-NOT: llvm.preserve.array.access.index
+// CHECK-NOT: llvm.preserve.union.access.index
+// CHECK-NOT: __builtin_preserve_access_index
Index: lib/Sema/SemaChecking.cpp
===
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -191,6 +191,16 @@
   return false;
 }
 
+/// Check the number of arguments, and set the result type to
+/// the argument type.
+static bool SemaBuiltinPreserveAI(Sema &S, CallExpr *TheCall) {
+  if (checkArgCount(S, TheCall, 1))
+return true;
+
+  TheCall->setType(TheCall->getArg(0)->getType());
+  return false;
+}
+
 static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
   if (checkArgCount(S, TheCall, 3))
 return true;
@@ -1409,6 +1419,10 @@
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_preserve_access_index:
+if (SemaBuiltinPreserveAI(*this, TheCall))
+  return ExprError();
+break;
   case Builtin::BI__builtin_call_with_static_chain:
 if (SemaBuiltinCallWithStaticChain(*this, TheCall))
   return ExprError();
Index: lib/CodeGen/CodeGenFunction.h
===
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -480,6 +480,10 @@
   /// finally block or filter expression.
   bool IsOutlinedSEHHelper = false;
 
+  /// True if CodeGen currently emits code inside presereved access index
+  /// region.
+  bool IsInPreservedAIRegion = false;
+
   const CodeGen::CGBlockInfo *BlockInfo = nullptr;
   llvm::Value *BlockPointer = nullptr;
 
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/NSAPI.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringExtras.h"
@@ -3418,8 +3419,20 @@
   CharUnits eltAlign =
 getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize);
 
-  llvm::Value *eltPtr = emitArraySubscriptGEP(
-  CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name);
+  llvm::Value *eltPtr;
+  auto LastIndex = dyn_cast(indices.back());
+  if (!CGF.IsInPreservedAIRegion || !LastIndex) {
+eltPtr = emitArraySubscriptGEP(
+CGF, addr.getPointer(), indices, inbounds, signedIndices,
+loc, name);
+  } else {
+// Remember the original array subscript for bpf target
+unsigned idx = LastIndex->getZExtValue();
+eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getPointer(),
+indices.size() - 1,
+idx);
+  }
+
   return Address(eltPtr, eltAlign);
 }
 
@@ -3908,6 +3921,19 @@
   return CGF.Builder.CreateStructGEP(base, idx, field->getName

[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-07-02 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 207644.
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

change `void *__builtin_preserve_access_index(void *)` to `const void * 
_builtin_preserve_access_index(const void *)`.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809

Files:
  docs/LanguageExtensions.rst
  include/clang/Basic/Builtins.def
  lib/CodeGen/CGBuilder.h
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/Sema/SemaChecking.cpp
  test/CodeGen/bpf-preserve-access-index-2.c
  test/CodeGen/bpf-preserve-access-index.c

Index: test/CodeGen/bpf-preserve-access-index.c
===
--- /dev/null
+++ test/CodeGen/bpf-preserve-access-index.c
@@ -0,0 +1,22 @@
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -o - | FileCheck --check-prefix=CHECK %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -o - | FileCheck --check-prefix=CHECK %s
+
+struct t {
+  int i:1;
+  int j:2;
+  union {
+   int a;
+   int b;
+  } c[4];
+};
+
+#define _(x) (__builtin_preserve_access_index(x))
+
+const void *test(struct t *arg) {
+  return _(&arg->c[3].b);
+}
+
+// CHECK: llvm.preserve.struct.access.index
+// CHECK: llvm.preserve.array.access.index
+// CHECK: llvm.preserve.union.access.index
+// CHECK-NOT: __builtin_preserve_access_index
Index: test/CodeGen/bpf-preserve-access-index-2.c
===
--- /dev/null
+++ test/CodeGen/bpf-preserve-access-index-2.c
@@ -0,0 +1,22 @@
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -o - | FileCheck %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -o - | FileCheck %s
+
+struct t {
+  int i:1;
+  int j:2;
+  union {
+   int a;
+   int b;
+  } c[4];
+};
+
+#define _(x) (x)
+
+const void *test(struct t *arg) {
+  return _(&arg->c[3].b);
+}
+
+// CHECK-NOT: llvm.preserve.struct.access.index
+// CHECK-NOT: llvm.preserve.array.access.index
+// CHECK-NOT: llvm.preserve.union.access.index
+// CHECK-NOT: __builtin_preserve_access_index
Index: lib/Sema/SemaChecking.cpp
===
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -191,6 +191,16 @@
   return false;
 }
 
+/// Check the number of arguments, and set the result type to
+/// the argument type.
+static bool SemaBuiltinPreserveAI(Sema &S, CallExpr *TheCall) {
+  if (checkArgCount(S, TheCall, 1))
+return true;
+
+  TheCall->setType(TheCall->getArg(0)->getType());
+  return false;
+}
+
 static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
   if (checkArgCount(S, TheCall, 3))
 return true;
@@ -1409,6 +1419,10 @@
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_preserve_access_index:
+if (SemaBuiltinPreserveAI(*this, TheCall))
+  return ExprError();
+break;
   case Builtin::BI__builtin_call_with_static_chain:
 if (SemaBuiltinCallWithStaticChain(*this, TheCall))
   return ExprError();
Index: lib/CodeGen/CodeGenFunction.h
===
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -480,6 +480,10 @@
   /// finally block or filter expression.
   bool IsOutlinedSEHHelper = false;
 
+  /// True if CodeGen currently emits code inside presereved access index
+  /// region.
+  bool IsInPreservedAIRegion = false;
+
   const CodeGen::CGBlockInfo *BlockInfo = nullptr;
   llvm::Value *BlockPointer = nullptr;
 
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/NSAPI.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringExtras.h"
@@ -3418,8 +3419,20 @@
   CharUnits eltAlign =
 getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize);
 
-  llvm::Value *eltPtr = emitArraySubscriptGEP(
-  CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name);
+  llvm::Value *eltPtr;
+  auto LastIndex = dyn_cast(indices.back());
+  if (!CGF.IsInPreservedAIRegion || !LastIndex) {
+eltPtr = emitArraySubscriptGEP(
+CGF, addr.getPointer(), indices, inbounds, signedIndices,
+loc, name);
+  } else {
+// Remember the original array subscript for bpf target
+unsigned idx = LastIndex->getZExtValue();
+eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getPointer(),
+indices.size() - 1,
+idx);
+  }
+
   return Address(eltPtr, eltAlign);
 }
 
@@ -3908,6 +3921,19 @@
   return CGF.Builder.CreateStructGEP(base, idx, fie

[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-07-02 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 207704.
yonghong-song added a comment.

handle unnamed bitfield properly. these struct/union members are not encoded in 
debuginfo, so skip them during preserve_*_access_index IR intrinsics generation.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809

Files:
  docs/LanguageExtensions.rst
  include/clang/Basic/Builtins.def
  lib/CodeGen/CGBuilder.h
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/Sema/SemaChecking.cpp
  test/CodeGen/bpf-preserve-access-index-2.c
  test/CodeGen/bpf-preserve-access-index.c

Index: test/CodeGen/bpf-preserve-access-index.c
===
--- /dev/null
+++ test/CodeGen/bpf-preserve-access-index.c
@@ -0,0 +1,27 @@
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -o - | FileCheck --check-prefix=CHECK %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -o - | FileCheck --check-prefix=CHECK %s
+
+struct t {
+  int i:1;
+  int j:2;
+  int :3;
+  union {
+   int a;
+   int :32;
+   int b;
+  } c[4];
+};
+
+#define _(x) (__builtin_preserve_access_index(x))
+
+const void *test(struct t *arg) {
+  return _(&arg->c[3].b);
+}
+
+// CHECK: llvm.preserve.struct.access.index
+// CHECK: (%struct.t* %0, i32 1, i32 2)
+// CHECK: llvm.preserve.array.access.index
+// CHECK: ([4 x %union.anon]* %2, i32 1, i32 3)
+// CHECK: llvm.preserve.union.access.index
+// CHECK: (%union.anon* %3, i32 1)
+// CHECK-NOT: __builtin_preserve_access_index
Index: test/CodeGen/bpf-preserve-access-index-2.c
===
--- /dev/null
+++ test/CodeGen/bpf-preserve-access-index-2.c
@@ -0,0 +1,24 @@
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -o - | FileCheck %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -o - | FileCheck %s
+
+struct t {
+  int i:1;
+  int j:2;
+  int :3;
+  union {
+   int a;
+   int :32;
+   int b;
+  } c[4];
+};
+
+#define _(x) (x)
+
+const void *test(struct t *arg) {
+  return _(&arg->c[3].b);
+}
+
+// CHECK-NOT: llvm.preserve.struct.access.index
+// CHECK-NOT: llvm.preserve.array.access.index
+// CHECK-NOT: llvm.preserve.union.access.index
+// CHECK-NOT: __builtin_preserve_access_index
Index: lib/Sema/SemaChecking.cpp
===
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -191,6 +191,16 @@
   return false;
 }
 
+/// Check the number of arguments, and set the result type to
+/// the argument type.
+static bool SemaBuiltinPreserveAI(Sema &S, CallExpr *TheCall) {
+  if (checkArgCount(S, TheCall, 1))
+return true;
+
+  TheCall->setType(TheCall->getArg(0)->getType());
+  return false;
+}
+
 static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
   if (checkArgCount(S, TheCall, 3))
 return true;
@@ -1409,6 +1419,10 @@
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_preserve_access_index:
+if (SemaBuiltinPreserveAI(*this, TheCall))
+  return ExprError();
+break;
   case Builtin::BI__builtin_call_with_static_chain:
 if (SemaBuiltinCallWithStaticChain(*this, TheCall))
   return ExprError();
Index: lib/CodeGen/CodeGenFunction.h
===
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -480,6 +480,10 @@
   /// finally block or filter expression.
   bool IsOutlinedSEHHelper = false;
 
+  /// True if CodeGen currently emits code inside presereved access index
+  /// region.
+  bool IsInPreservedAIRegion = false;
+
   const CodeGen::CGBlockInfo *BlockInfo = nullptr;
   llvm::Value *BlockPointer = nullptr;
 
@@ -2648,6 +2652,9 @@
   /// Converts Location to a DebugLoc, if debug information is enabled.
   llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location);
 
+  /// Get the record field index as represented in debug info.
+  unsigned getDebugInfoFIndex(const RecordDecl *Rec, unsigned FieldIndex);
+
 
   //======//
   //Declaration Emission
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/NSAPI.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringExtras.h"
@@ -3418,8 +3419,20 @@
   CharUnits eltAlign =
 getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize);
 
-  llvm::Value *eltPtr = emitArraySubscriptGEP(
-  CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name);
+  llvm::Value *eltPtr;
+  auto LastIndex = dyn_cast(indices.back());
+  if (!CGF.IsInPreservedAIReg

[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-07-02 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@rsmith Just ping, could you take a look at the clang change? If possible, 
could you share your opinion? Thanks!


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-07-05 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@rsmith Ping again, do you have any comments on this patch? Thanks!


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-07-10 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@jdoerfert Thanks for comments. I will submit another patch to add adequate 
tests for clang frontend as you suggested.


Repository:
  rL LLVM

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve original struct/union type name/access index and array subscripts

2019-05-10 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added reviewers: eli.friedman, ast.
Herald added subscribers: cfe-commits, arphaman, kosarev.
Herald added a project: clang.

For background of BPF CO-RE project, please refer to

  http://vger.kernel.org/bpfconf2019.html

In summary, BPF CO-RE intends to compile bpf programs
adjustable on struct/union layout change so the same
program can run on multiple kernels with adjustment
before loading based on native kernel structures.

In order to do this, we need keep track of GEP(getelementptr)
instruction base and result debuginfo types, so we
can adjust on the host based on kernel BTF info.
Capturing such information as an IR optimization is hard
as various optimization may have tweaked GEP and also
union is replaced by structure it is impossible to track
fieldindex for union member accesses.

An intrinsic function, preserve_di_access_index, is introducted.

  naddr = preserve_di_access_index(addr, base, type_name, access_index)

here,

  addr: the previous getelementptr result, used as the result value do
program semantics are kept intact.
  base: the base of previous getelementptr, used for later
code generation with new relocatable access offset.
  type_name: the struct/union type name if available, can be used to
match corresponding types in debuginfo.
  access_index: the access index based on user/debuginfo types.
  naddr: the result, having the same type as "addr".

For example, for the following example,

  $ cat test.c
  struct sk_buff {
int i;
int b1:1;
int b2:2;
union {
  struct {
int o1;
int o2;
  } o;
  struct {
char flags;
char dev_id;
  } dev;
  int netid;
} u[10];
  };
  
  static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
  = (void *) 4;
  
  int bpf_prog(struct sk_buff *ctx) {
char dev_id;
bpf_probe_read(&dev_id, sizeof(char), &ctx->u[5].dev.dev_id);
return dev_id;
  }
  
  $ clang -target bpf -O2 -g -emit-llvm -S -mllvm -print-before-all test.c >& 
log

The generated IR looks like below:

  ...

define dso_local i32 @bpf_prog(%struct.sk_buff*) #0 !dbg !15 {

  %2 = alloca %struct.sk_buff*, align 8
  %3 = alloca i8, align 1
  store %struct.sk_buff* %0, %struct.sk_buff** %2, align 8, !tbaa !45
  call void @llvm.dbg.declare(metadata %struct.sk_buff** %2, metadata !43, 
metadata !DIExpression()), !dbg !49
  call void @llvm.lifetime.start.p0i8(i64 1, i8* %3) #4, !dbg !50
  call void @llvm.dbg.declare(metadata i8* %3, metadata !44, metadata 
!DIExpression()), !dbg !51
  %4 = load i32 (i8*, i32, i8*)*, i32 (i8*, i32, i8*)** @bpf_probe_read, align 
8, !dbg !52, !tbaa !45
  %5 = load %struct.sk_buff*, %struct.sk_buff** %2, align 8, !dbg !53, !tbaa !45
  %6 = getelementptr inbounds %struct.sk_buff, %struct.sk_buff* %5, i32 0, i32 
2, !dbg !54
  %7 = call [10 x %union.anon]*
   
@llvm.preserve.di.access.index.p0a10s_union.anons.p0a10s_union.anons.p0s_struct.sk_buffs(
   [10 x %union.anon]* %6, %struct.sk_buff* %5,
   i8* getelementptr inbounds ([8 x i8], [8 x i8]* @0, i32 0, i32 0), i32 
3), !dbg !54
  %8 = getelementptr inbounds [10 x %union.anon], [10 x %union.anon]* %7, i64 
0, i64 5, !dbg !53
  %9 = call %union.anon* 
@llvm.preserve.di.access.index.p0s_union.anons.p0s_union.anons.p0a10s_union.anons(
   %union.anon* %8, [10 x %union.anon]* %7,
   i8* getelementptr inbounds ([1 x i8], [1 x i8]* @1, i32 0, i32 0), i32 
5), !dbg !53
  %10 = call %union.anon* 
@llvm.preserve.di.access.index.p0s_union.anons.p0s_union.anons.p0s_union.anons(
%union.anon* %9, %union.anon* %9, i8* getelementptr inbounds ([1 x i8], 
[1 x i8]* @2, i32 0, i32 0), i32 1), !dbg !55
  %11 = bitcast %union.anon* %10 to %struct.anon.0*, !dbg !55
  %12 = getelementptr inbounds %struct.anon.0, %struct.anon.0* %11, i32 0, i32 
1, !dbg !56
  %13 = call i8* 
@llvm.preserve.di.access.index.p0i8.p0i8.p0s_struct.anon.0s(i8* %12, 
%struct.anon.0* %11,
i8* getelementptr inbounds ([1 x i8], [1 x i8]* @3, i32 0, i32 0), i32 
1), !dbg !56
  %14 = call i32 %4(i8* %3, i32 1, i8* %13), !dbg !52
  %15 = load i8, i8* %3, align 1, !dbg !57, !tbaa !58
  %16 = sext i8 %15 to i32, !dbg !57
  call void @llvm.lifetime.end.p0i8(i64 1, i8* %3) #4, !dbg !59
  ret i32 %16, !dbg !60

}

For &ctx->u[5].dev.dev_id,

  . The first getelementptr (%6 = ...) has index 2 based on IR layout, and 
subsequent
preserve_di_access_index (%7 = ...) has index 3 which reflects the 
debuginfo type layout.
  . The second getelementptr (%8 = ...) has index 5 which is the same as 
preserve_di_access_index
(%9 = ...) for array subscript.
  . The instruction "%10 ..." is a call to preserve_di_access_index, which 
encodes the union member
access index "1". Such information is lost in the original IR.
  . The third getelementptr (%12 = ...) has index 1 anonymous struct member 
"dev_id". The
subsequent preserve_di_access_index also has the index "1".

Basic

[PATCH] D61809: [BPF] Preserve original struct/union type name/access index and array subscripts

2019-05-10 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@lebedev.ri Thanks for the comment. This patch is not ready to land yet. Yes, 
tests are missing and I am going to add tests later.
More importantly, I want to get a sense whether what I am implementing here is 
the right direction or not.
The following two other patches are also related to describe our end goal:

  https://reviews.llvm.org/D61810
  https://reviews.llvm.org/D61524  


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve original struct/union type name/access index and array subscripts

2019-05-13 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@rsmith @eli.friedman Thanks for your comments. I fully agree that it seems 
awkward that we have both GEP and intrinsic generation. I will try to do some 
experiments here to only have intrinsic generation. My only concern is possible 
performance degradation. I will post here once I got concrete implementation 
and numbers.

@rsmith regarding to your concerns about struct size change. Yes, the structure 
size may indeed change. Currently, we plan only to support field fields 
(non-struct/union type with 1/2/4/8 bytes, and strings). These are most common 
use cases. Let me explain a little bit more.

Here, we are targeting the bpf_probe_read 
(https://github.com/torvalds/linux/blob/master/include/uapi/linux/bpf.h#L532-L537)

  int bpf_probe_read(void *dst, u32 size, const void *src)

which tries to copy some data from kernel (src pointer) to the stack of the bpf 
program.

Here, if "src" points to a structure, and user intends to copy the whole 
structure out of kernel, then "size" may need to be different for different 
kernels if different kernels indeed have different structure size. 
But first, in all our use cases, users typically do not read the whole 
structure. Second, if "size" does change, we request users to use multiple 
versioning (using patchable global variables) with possibly different "size" 
values for different kernel versions. 
Note that "size" must be constant for bpf verifier to succeed.
(https://github.com/torvalds/linux/blob/master/kernel/trace/bpf_trace.c#L138-L156)

Just gave another two examples here about reading kernel memories in 
iovisor/bcc. Note that
bcc will transform certain pointer access "b->c" to "bpf_probe_read(&dest, 
size, &b->c)" internally.

The bcc tool biosnoop.py contain several bpf probe read:

  https://github.com/iovisor/bcc/blob/master/tools/biosnoop.py#L110
data.len = req->__data_len;
  https://github.com/iovisor/bcc/blob/master/tools/biosnoop.py#L117
data.len = req->__data_len;
  https://github.com/iovisor/bcc/blob/master/tools/biosnoop.py#L118
data.sector = req->__sector;
  https://github.com/iovisor/bcc/blob/master/tools/biosnoop.py#L120
struct gendisk *rq_disk = req->rq_disk;
  https://github.com/iovisor/bcc/blob/master/tools/biosnoop.py#L121-L122
   bpf_probe_read(&data.disk_name, sizeof(data.disk_name),
   rq_disk->disk_name);

They are all primitive types and strings.

Another example for bcc tool tcpconnect.py

  https://github.com/iovisor/bcc/blob/master/tools/tcpconnect.py#L128
u16 dport = skp->__sk_common.skc_dport;
  https://github.com/iovisor/bcc/blob/master/tools/tcpconnect.py#L136-L137
data4.saddr = skp->__sk_common.skc_rcv_saddr;
data4.daddr = skp->__sk_common.skc_daddr;

.

In summary, right now, the to-be-read kernel memory size (through a specific 
bpf_probe_read() call)
won't change between different kernel versions. So we do not need to handle 
structure allocation size change here.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type name/access index

2019-05-16 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 199843.
yonghong-song retitled this revision from "[BPF] Preserve original struct/union 
type name/access index and array subscripts" to "[BPF] Preserve debuginfo 
array/union/struct type name/access index".
yonghong-song edited the summary of this revision.
yonghong-song added reviewers: rsmith, lebedev.ri.
yonghong-song added a comment.

do not generate gep any more, only intrinsics


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809

Files:
  include/clang/Basic/TargetInfo.h
  lib/Basic/Targets/BPF.h
  lib/CodeGen/CGBuilder.h
  lib/CodeGen/CGExpr.cpp
  test/CodeGen/bpf-offsetreloc.c

Index: test/CodeGen/bpf-offsetreloc.c
===
--- /dev/null
+++ test/CodeGen/bpf-offsetreloc.c
@@ -0,0 +1,17 @@
+// RUN: %clang -target bpf -emit-llvm -S -Xclang -target-feature -Xclang +offsetreloc -o - %s > %t1
+// RUN: grep "llvm.preserve.struct.access.index" %t1
+// RUN: grep "llvm.preserve.array.access.index" %t1
+// RUN: grep "llvm.preserve.union.access.index" %t1
+
+struct t {
+  int i:1;
+  int j:2;
+  union {
+   int a;
+   int b;
+  } c[4];
+};
+
+void *test(struct t *arg) {
+  return &arg->c[3].b;
+}
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -3350,8 +3350,17 @@
   CharUnits eltAlign =
 getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize);
 
-  llvm::Value *eltPtr = emitArraySubscriptGEP(
-  CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name);
+  llvm::Value *eltPtr;
+  if (!CGF.getTarget().isPreserveDIAccessIndexNeeded()) {
+eltPtr = emitArraySubscriptGEP(
+CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name);
+  } else {
+// Remember the original array subscript for bpf target
+unsigned idx = cast(indices.back())->getZExtValue();
+eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getPointer(),
+name.str(), idx);
+  }
+
   return Address(eltPtr, eltAlign);
 }
 
@@ -3825,6 +3834,17 @@
   return CGF.Builder.CreateStructGEP(base, idx, field->getName());
 }
 
+static Address emitPreserveStructAccess(CodeGenFunction &CGF, Address base,
+const FieldDecl *field) {
+  const RecordDecl *rec = field->getParent();
+
+  unsigned idx =
+  CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
+
+  return CGF.Builder.CreatePreserveStructAccessIndex(
+  base, field->getName(), rec->getName(), idx, field->getFieldIndex());
+}
+
 static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
   const auto *RD = Type.getTypePtr()->getAsCXXRecordDecl();
   if (!RD)
@@ -3932,9 +3952,21 @@
   // a barrier every time CXXRecord field with vptr is referenced.
   addr = Address(Builder.CreateLaunderInvariantGroup(addr.getPointer()),
  addr.getAlignment());
+
+if (getTarget().isPreserveDIAccessIndexNeeded())
+  // Remember the original union field index
+  addr = Address(
+  Builder.CreatePreserveUnionAccessIndex(
+  addr.getPointer(), rec->getName(), field->getFieldIndex()),
+  addr.getAlignment());
   } else {
-// For structs, we GEP to the field that the record layout suggests.
-addr = emitAddrOfFieldStorage(*this, addr, field);
+
+if (!getTarget().isPreserveDIAccessIndexNeeded())
+  // For structs, we GEP to the field that the record layout suggests.
+  addr = emitAddrOfFieldStorage(*this, addr, field);
+else
+  // Remember the original struct field index
+  addr = emitPreserveStructAccess(*this, addr, field);
 
 // If this is a reference field, load the reference right now.
 if (FieldType->isReferenceType()) {
Index: lib/CodeGen/CGBuilder.h
===
--- lib/CodeGen/CGBuilder.h
+++ lib/CodeGen/CGBuilder.h
@@ -298,6 +298,23 @@
 return CreateMemSet(Dest.getPointer(), Value, Size,
 Dest.getAlignment().getQuantity(), IsVolatile);
   }
+
+  using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
+  Address CreatePreserveStructAccessIndex(Address Addr,
+  const llvm::StringRef &InstName,
+  const llvm::StringRef &StructName,
+  unsigned Index,
+  unsigned FieldIndex) {
+llvm::StructType *ElTy = cast(Addr.getElementType());
+const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
+const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
+auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
+
+return Address(CreatePreserveStructAccessIndex(Add

[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type name/access index

2019-05-16 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@rsmith @eli.friedman Hi, I just implemented a new version which generates 
intrinsics only. Three intrinsics are implemented for array/union/structure 
separately as their handling and parameters are different. Could you take a 
look? Thanks!


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type name/access index

2019-05-16 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked an inline comment as done.
yonghong-song added inline comments.



Comment at: lib/CodeGen/CGExpr.cpp:3359
+// Remember the original array subscript for bpf target
+unsigned idx = cast(indices.back())->getZExtValue();
+eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getPointer(),

efriedma wrote:
> I don't think there's any reason to expect the array subscript is a 
> ConstantInt here?
right.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type name/access index

2019-05-17 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 200117.
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

array index may not be constant and remove inst_name


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809

Files:
  include/clang/Basic/TargetInfo.h
  lib/Basic/Targets/BPF.h
  lib/CodeGen/CGBuilder.h
  lib/CodeGen/CGExpr.cpp
  test/CodeGen/bpf-offsetreloc.c

Index: test/CodeGen/bpf-offsetreloc.c
===
--- /dev/null
+++ test/CodeGen/bpf-offsetreloc.c
@@ -0,0 +1,17 @@
+// RUN: %clang -target bpf -emit-llvm -S -Xclang -target-feature -Xclang +offsetreloc -o - %s > %t1
+// RUN: grep "llvm.preserve.struct.access.index" %t1
+// RUN: grep "llvm.preserve.array.access.index" %t1
+// RUN: grep "llvm.preserve.union.access.index" %t1
+
+struct t {
+  int i:1;
+  int j:2;
+  union {
+   int a;
+   int b;
+  } c[4];
+};
+
+void *test(struct t *arg) {
+  return &arg->c[3].b;
+}
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -3350,8 +3350,19 @@
   CharUnits eltAlign =
 getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize);
 
-  llvm::Value *eltPtr = emitArraySubscriptGEP(
-  CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name);
+  llvm::Value *eltPtr;
+  auto LastIndex = dyn_cast(indices.back());
+  if (!CGF.getTarget().isPreserveDIAccessIndexNeeded() || !LastIndex) {
+eltPtr = emitArraySubscriptGEP(
+CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name);
+  } else {
+// Remember the original array subscript for bpf target
+unsigned idx = LastIndex->getZExtValue();
+eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getPointer(),
+indices.size() - 1,
+idx);
+  }
+
   return Address(eltPtr, eltAlign);
 }
 
@@ -3825,6 +3836,17 @@
   return CGF.Builder.CreateStructGEP(base, idx, field->getName());
 }
 
+static Address emitPreserveStructAccess(CodeGenFunction &CGF, Address base,
+const FieldDecl *field) {
+  const RecordDecl *rec = field->getParent();
+
+  unsigned idx =
+  CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
+
+  return CGF.Builder.CreatePreserveStructAccessIndex(
+  base, rec->getName(), idx, field->getFieldIndex());
+}
+
 static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
   const auto *RD = Type.getTypePtr()->getAsCXXRecordDecl();
   if (!RD)
@@ -3932,9 +3954,21 @@
   // a barrier every time CXXRecord field with vptr is referenced.
   addr = Address(Builder.CreateLaunderInvariantGroup(addr.getPointer()),
  addr.getAlignment());
+
+if (getTarget().isPreserveDIAccessIndexNeeded())
+  // Remember the original union field index
+  addr = Address(
+  Builder.CreatePreserveUnionAccessIndex(
+  addr.getPointer(), rec->getName(), field->getFieldIndex()),
+  addr.getAlignment());
   } else {
-// For structs, we GEP to the field that the record layout suggests.
-addr = emitAddrOfFieldStorage(*this, addr, field);
+
+if (!getTarget().isPreserveDIAccessIndexNeeded())
+  // For structs, we GEP to the field that the record layout suggests.
+  addr = emitAddrOfFieldStorage(*this, addr, field);
+else
+  // Remember the original struct field index
+  addr = emitPreserveStructAccess(*this, addr, field);
 
 // If this is a reference field, load the reference right now.
 if (FieldType->isReferenceType()) {
Index: lib/CodeGen/CGBuilder.h
===
--- lib/CodeGen/CGBuilder.h
+++ lib/CodeGen/CGBuilder.h
@@ -298,6 +298,22 @@
 return CreateMemSet(Dest.getPointer(), Value, Size,
 Dest.getAlignment().getQuantity(), IsVolatile);
   }
+
+  using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
+  Address CreatePreserveStructAccessIndex(Address Addr,
+  llvm::StringRef StructName,
+  unsigned Index,
+  unsigned FieldIndex) {
+llvm::StructType *ElTy = cast(Addr.getElementType());
+const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
+const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
+auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
+
+return Address(CreatePreserveStructAccessIndex(Addr.getPointer(),
+   StructName,
+   Index, FieldIndex),
+   Addr.getAlignment().alignmentAtOffset(Offset));
+  }
 };
 

[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-05-21 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 200639.
yonghong-song retitled this revision from "[BPF] Preserve debuginfo 
array/union/struct type name/access index" to "[BPF] Preserve debuginfo 
array/union/struct type/access index".
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

add clang builtin __builtin_preserve_access_index


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809

Files:
  include/clang/Basic/Builtins.def
  lib/Basic/Targets/BPF.h
  lib/CodeGen/CGBuilder.h
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/Sema/SemaChecking.cpp
  test/CodeGen/bpf-offsetreloc.c

Index: test/CodeGen/bpf-offsetreloc.c
===
--- /dev/null
+++ test/CodeGen/bpf-offsetreloc.c
@@ -0,0 +1,19 @@
+// RUN: %clang -target bpf -emit-llvm -S -g -O2 -o - %s > %t1
+// RUN: grep "llvm.preserve.struct.access.index" %t1
+// RUN: grep "llvm.preserve.array.access.index" %t1
+// RUN: grep "llvm.preserve.union.access.index" %t1
+
+struct t {
+  int i:1;
+  int j:2;
+  union {
+   int a;
+   int b;
+  } c[4];
+};
+
+#define _(x) (__builtin_preserve_access_index(x))
+
+void *test(struct t *arg) {
+  return _(&arg->c[3].b);
+}
Index: lib/Sema/SemaChecking.cpp
===
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -190,6 +190,16 @@
   return false;
 }
 
+/// Check the number of arguments, and set the result type to
+/// the argument type.
+static bool SemaBuiltinPreserveAI(Sema &S, CallExpr *TheCall) {
+  if (checkArgCount(S, TheCall, 1))
+return true;
+
+  TheCall->setType(TheCall->getArg(0)->getType());
+  return false;
+}
+
 static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
   if (checkArgCount(S, TheCall, 3))
 return true;
@@ -1407,6 +1417,10 @@
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_preserve_access_index:
+if (SemaBuiltinPreserveAI(*this, TheCall))
+  return ExprError();
+break;
   case Builtin::BI__builtin_call_with_static_chain:
 if (SemaBuiltinCallWithStaticChain(*this, TheCall))
   return ExprError();
Index: lib/CodeGen/CodeGenFunction.h
===
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -1027,6 +1027,10 @@
 store->setAlignment(addr.getAlignment().getQuantity());
   }
 
+  /// isPreserveDIAccessIndexNeeded - Return true if it is needed to
+  /// preserve the Debuginfo access index.
+  bool isPreserveDIAccessIndexNeeded(const Expr *E);
+
   /// An RAII object to record that we're evaluating a statement
   /// expression.
   class StmtExprEvaluation {
@@ -3545,7 +3549,8 @@
 
   llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
   const ObjCIvarDecl *Ivar);
-  LValue EmitLValueForField(LValue Base, const FieldDecl* Field);
+  LValue EmitLValueForField(LValue Base, const FieldDecl* Field,
+const Expr *E = nullptr);
   LValue EmitLValueForLambdaField(const FieldDecl *Field);
 
   /// EmitLValueForFieldInitialization - Like EmitLValueForField, except that
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/NSAPI.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringExtras.h"
@@ -649,6 +650,52 @@
  SanOpts.has(SanitizerKind::Vptr);
 }
 
+/// The expression E is a candidate for preserving debuginfo access index
+/// if it is inside an __builtin_preserve_access_index intrinsic call.
+bool CodeGenFunction::isPreserveDIAccessIndexNeeded(const Expr *E) {
+  if (!E)
+return false;
+
+  if (!getDebugInfo())
+return false;
+
+  while (true) {
+const auto &Parents = getContext().getParents(*E);
+if (Parents.size() != 1)
+  return false;
+
+E = Parents[0].get();
+if (!E)
+  return false;
+
+// Check whether E is a BI__builtin_preserve_access_index
+// intrinsic call.
+const auto *CE = dyn_cast(E);
+if (CE) {
+  // Callee must a builtin function.
+  const Expr *Callee = CE->getCallee()->IgnoreParens();
+  auto ICE = dyn_cast(Callee);
+  if (!ICE)
+return false;
+  if (ICE->getCastKind() != CK_BuiltinFnToFnPtr)
+return false;
+
+  auto DRE = dyn_cast(ICE->getSubExpr());
+  if (!DRE)
+return false;
+
+  if (auto FD = dyn_cast(DRE->getDecl())) {
+if (FD->getBuiltinID() == Builtin::BI__builtin_preserve_access_index)
+  return true;
+  }
+
+  break;
+}
+  }
+
+  return false;
+}
+
 void CodeGenFunction::EmitTyp

[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-05-23 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked an inline comment as done.
yonghong-song added inline comments.



Comment at: test/CodeGen/bpf-offsetreloc.c:2-4
+// RUN: grep "llvm.preserve.struct.access.index" %t1
+// RUN: grep "llvm.preserve.array.access.index" %t1
+// RUN: grep "llvm.preserve.union.access.index" %t1

lebedev.ri wrote:
> This looks like a bad test.
> Can't you use FileCheck?
> I'd think there is more to test than a single tiny test..
Thanks. I will add more tests with FileCheck once we get an agreement for the 
general approach.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-05-28 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@rsmith @eli.friedman Do you have any comments on the clang intrinsic interface 
in this patch and the llvm intrinsics interface at 
https://reviews.llvm.org/D61810?


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61809: [BPF] Preserve debuginfo array/union/struct type/access index

2019-05-28 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 201793.
yonghong-song added a comment.

remove bpf offsetreloc option and use FileCheck in the test.


Repository:
  rC Clang

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

https://reviews.llvm.org/D61809

Files:
  include/clang/Basic/Builtins.def
  lib/CodeGen/CGBuilder.h
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/Sema/SemaChecking.cpp
  test/CodeGen/bpf-offsetreloc.c

Index: test/CodeGen/bpf-offsetreloc.c
===
--- /dev/null
+++ test/CodeGen/bpf-offsetreloc.c
@@ -0,0 +1,22 @@
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -o - | FileCheck %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -o - | FileCheck %s
+
+struct t {
+  int i:1;
+  int j:2;
+  union {
+   int a;
+   int b;
+  } c[4];
+};
+
+#define _(x) (__builtin_preserve_access_index(x))
+
+void *test(struct t *arg) {
+  return _(&arg->c[3].b);
+}
+
+// CHECK: llvm.preserve.struct.access.index
+// CHECK: llvm.preserve.array.access.index
+// CHECK: llvm.preserve.union.access.index
+// CHECK-NOT: __builtin_preserve_access_index
Index: lib/Sema/SemaChecking.cpp
===
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -190,6 +190,16 @@
   return false;
 }
 
+/// Check the number of arguments, and set the result type to
+/// the argument type.
+static bool SemaBuiltinPreserveAI(Sema &S, CallExpr *TheCall) {
+  if (checkArgCount(S, TheCall, 1))
+return true;
+
+  TheCall->setType(TheCall->getArg(0)->getType());
+  return false;
+}
+
 static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
   if (checkArgCount(S, TheCall, 3))
 return true;
@@ -1407,6 +1417,10 @@
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_preserve_access_index:
+if (SemaBuiltinPreserveAI(*this, TheCall))
+  return ExprError();
+break;
   case Builtin::BI__builtin_call_with_static_chain:
 if (SemaBuiltinCallWithStaticChain(*this, TheCall))
   return ExprError();
Index: lib/CodeGen/CodeGenFunction.h
===
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -1028,6 +1028,10 @@
 store->setAlignment(addr.getAlignment().getQuantity());
   }
 
+  /// isPreserveDIAccessIndexNeeded - Return true if it is needed to
+  /// preserve the Debuginfo access index.
+  bool isPreserveDIAccessIndexNeeded(const Expr *E);
+
   /// An RAII object to record that we're evaluating a statement
   /// expression.
   class StmtExprEvaluation {
@@ -3559,7 +3563,8 @@
 
   llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
   const ObjCIvarDecl *Ivar);
-  LValue EmitLValueForField(LValue Base, const FieldDecl* Field);
+  LValue EmitLValueForField(LValue Base, const FieldDecl* Field,
+const Expr *E = nullptr);
   LValue EmitLValueForLambdaField(const FieldDecl *Field);
 
   /// EmitLValueForFieldInitialization - Like EmitLValueForField, except that
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/NSAPI.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringExtras.h"
@@ -649,6 +650,52 @@
  SanOpts.has(SanitizerKind::Vptr);
 }
 
+/// The expression E is a candidate for preserving debuginfo access index
+/// if it is inside an __builtin_preserve_access_index intrinsic call.
+bool CodeGenFunction::isPreserveDIAccessIndexNeeded(const Expr *E) {
+  if (!E)
+return false;
+
+  if (!getDebugInfo())
+return false;
+
+  while (true) {
+const auto &Parents = getContext().getParents(*E);
+if (Parents.size() != 1)
+  return false;
+
+E = Parents[0].get();
+if (!E)
+  return false;
+
+// Check whether E is a BI__builtin_preserve_access_index
+// intrinsic call.
+const auto *CE = dyn_cast(E);
+if (CE) {
+  // Callee must a builtin function.
+  const Expr *Callee = CE->getCallee()->IgnoreParens();
+  auto ICE = dyn_cast(Callee);
+  if (!ICE)
+return false;
+  if (ICE->getCastKind() != CK_BuiltinFnToFnPtr)
+return false;
+
+  auto DRE = dyn_cast(ICE->getSubExpr());
+  if (!DRE)
+return false;
+
+  if (auto FD = dyn_cast(DRE->getDecl())) {
+if (FD->getBuiltinID() == Builtin::BI__builtin_preserve_access_index)
+  return true;
+  }
+
+  break;
+}
+  }
+
+  return false;
+}
+
 void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
 llvm::Value *Ptr, QualType Ty,

[PATCH] D53329: Generate DIFile with main program if source is not available

2018-12-27 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

I found an easy way to reproduce the issue and also did some preliminary 
analysis. I have filed a bug https://bugs.llvm.org/show_bug.cgi?id=40170. The 
reproducible case and my analysis is  below:

-bash-4.4$ cat ttest2.c
#include "ttest.h"

BPF_PERF_OUTPUT2(probe);

int main() { return g; }
-bash-4.4$ cat ttest.h

#define BPF_PERF_OUTPUT2(_name) \
struct _name##_table_t { \

  int key; \
  unsigned leaf; \
  int (*perf_submit) (void *, void *, unsigned); \
  int (*perf_submit_skb) (void *, unsigned, void *, unsigned); \
  unsigned max_entries; \

}; \
__attribute__((section("maps/perf_output"))) \
struct _name##_table_t _name = { .max_entries = 0 }

int g;
-bash-4.4$ clang -g -O2 -gdwarf-5 -gembed-source -c ttest2.c
inconsistent use of embedded source
fatal error: error in backend: Broken module found, compilation aborted!
clang-8: error: clang frontend command failed with exit code 70 (use -v to see 
invocation)
clang version 8.0.0 (trunk 350092) (llvm/trunk 350084)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/yhs/work/llvm/build/install/bin
clang-8: note: diagnostic msg: PLEASE submit a bug report to 
https://bugs.llvm.org/ and include the crash backtrace, preprocessed source, 
and associated run script.
clang-8: note: diagnostic msg:



PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang-8: note: diagnostic msg: /tmp/ttest2-6c497a.c
clang-8: note: diagnostic msg: /tmp/ttest2-6c497a.sh
clang-8: note: diagnostic msg:



-bash-4.4$

Basically, a simple C file and header file. The C file contains a macro 
expansion. Compiling with -g -gdwarf-5 -gembed-source will cause the
compiler complains:

  fatal error: error in backend: Broken module found, compilation aborted!

When I tried to root cause the bug described in 
https://reviews.llvm.org/D53329, I found a simple test case like the above will 
break clang.

I did some analysis. The following are rough reason.

1. Looks like for macro in the source code, the clang actually will create a 
"FileID" for it. The FileID is not associated with a file. It is actually 
associated with a source location range.
2. In my particular example, the macro defines a global variable and the global

variable needs a file.

3. When clang tries to find the FileID based on source location of the global 
variable, it found a source expansion FileID which does not have source 
associated with it.
4. So clang simply does not have a "source" attribute for the DIFile 
corresponding to the global as in (3) it does not have such information.
5. Later on, IR verification complains embed-source is enabled but all not

DIFile has sources, so aborted.

My above workaround is obviously incorrect. But I am not sure what is the 
correct way to fix this issue. Maybe one of you can help. Thanks!


Repository:
  rC Clang

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

https://reviews.llvm.org/D53329



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67734: [CLANG-BPF] change __builtin_preserve_access_index() signature

2019-09-18 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added a reviewer: ast.
Herald added subscribers: cfe-commits, arphaman.
Herald added a project: clang.

The clang intrinsic __builtin_preserve_access_index() currently
has signature:

  const void * __builtin_preserve_access_index(const void * ptr)

This may cause compiler warning when:

- parameter type is "volatile void *" or "const volatile void *", or
- the assign-to type of the intrinsic does not have "const" qualifier.

These warnings can be suppressed by type casting in the user code.
But let's design the __builtin_preserve_access_index() to be more
user friendly to avoid user casting.

The new signature looks like:

  void * __builtin_preserve_access_index(const volatile void * ptr)

A type casting is generated to "void *" at the end of builtin
codegen. This type casting is typically combined with other subsequent
user casts or optimized away completely and has little impact on
optimized IR.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67734

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/Builtins.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/builtin-preserve-access-index.c


Index: clang/test/Sema/builtin-preserve-access-index.c
===
--- clang/test/Sema/builtin-preserve-access-index.c
+++ clang/test/Sema/builtin-preserve-access-index.c
@@ -4,10 +4,10 @@
   return __builtin_preserve_access_index(&arg[1], 1); // expected-error {{too 
many arguments to function call, expected 1, have 2}}
 }
 
-void *invalid2(const int *arg) {
-  return __builtin_preserve_access_index(&arg[1]); // expected-warning 
{{returning 'const void *' from a function with result type 'void *' discards 
qualifiers}}
+void *valid2(const int *arg) {
+  return __builtin_preserve_access_index(&arg[1]);
 }
 
 const void *invalid3(const int *arg) {
-  return __builtin_preserve_access_index(1); // expected-warning 
{{incompatible integer to pointer conversion passing 'int' to parameter of type 
'const void *'}}
+  return __builtin_preserve_access_index(1); // expected-warning 
{{incompatible integer to pointer conversion passing 'int' to parameter of type 
'const volatile void *'}}
 }
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -197,7 +197,6 @@
   if (checkArgCount(S, TheCall, 1))
 return true;
 
-  TheCall->setType(TheCall->getArg(0)->getType());
   return false;
 }
 
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -1879,6 +1879,8 @@
 
 IsInPreservedAIRegion = true;
 Value *Res = EmitScalarExpr(E->getArg(0));
+unsigned AddrSpace = Res->getType()->getPointerAddressSpace();
+Res = Builder.CreateBitCast(Res, Int8Ty->getPointerTo(AddrSpace));
 IsInPreservedAIRegion = false;
 return RValue::get(Res);
   }
Index: clang/include/clang/Basic/Builtins.def
===
--- clang/include/clang/Basic/Builtins.def
+++ clang/include/clang/Basic/Builtins.def
@@ -1470,7 +1470,7 @@
 BUILTIN(__builtin_operator_delete, "vv*", "tn")
 BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
 BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
-BUILTIN(__builtin_preserve_access_index, "vC*vC*", "nU")
+BUILTIN(__builtin_preserve_access_index, "v*vCD*", "nU")
 
 // Safestack builtins
 BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -2358,7 +2358,7 @@
 
 .. code-block:: c
 
-  const void * __builtin_preserve_access_index(const void * ptr)
+  void * __builtin_preserve_access_index(const volatile void * ptr)
 
 **Example of Use**:
 


Index: clang/test/Sema/builtin-preserve-access-index.c
===
--- clang/test/Sema/builtin-preserve-access-index.c
+++ clang/test/Sema/builtin-preserve-access-index.c
@@ -4,10 +4,10 @@
   return __builtin_preserve_access_index(&arg[1], 1); // expected-error {{too many arguments to function call, expected 1, have 2}}
 }
 
-void *invalid2(const int *arg) {
-  return __builtin_preserve_access_index(&arg[1]); // expected-warning {{returning 'const void *' from a function with result type 'void *' discards qualifiers}}
+void *valid2(const int *arg) {
+  return __builtin_preserve_access_index(&arg[1]);
 }
 
 const void *invalid3(const int *arg) {
-  return __builtin_preserve_access_index(1); // expected-warning {{incompatible integer to pointer conversion passing 'int' to parameter of type 'const void *'}}
+  return __builtin_preserve_access_index(1); /

[PATCH] D67734: [CLANG-BPF] change __builtin_preserve_access_index() signature

2019-09-18 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 220772.
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

does not change arg type and make result type the same as arg type


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67734

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/builtin-preserve-access-index.c

Index: clang/test/Sema/builtin-preserve-access-index.c
===
--- clang/test/Sema/builtin-preserve-access-index.c
+++ clang/test/Sema/builtin-preserve-access-index.c
@@ -4,10 +4,28 @@
   return __builtin_preserve_access_index(&arg[1], 1); // expected-error {{too many arguments to function call, expected 1, have 2}}
 }
 
-void *invalid2(const int *arg) {
-  return __builtin_preserve_access_index(&arg[1]); // expected-warning {{returning 'const void *' from a function with result type 'void *' discards qualifiers}}
+const void *invalid2(const int *arg) {
+  return __builtin_preserve_access_index(1); // expected-error {{__builtin_preserve_access_index argument must a pointer type instead of 'int'}}
 }
 
-const void *invalid3(const int *arg) {
-  return __builtin_preserve_access_index(1); // expected-warning {{incompatible integer to pointer conversion passing 'int' to parameter of type 'const void *'}}
+void *invalid3(const int *arg) {
+  return __builtin_preserve_access_index(&arg[1]); // expected-warning {{returning 'const int *' from a function with result type 'void *' discards qualifiers}}
+}
+
+const void *invalid4(volatile const int *arg) {
+  return __builtin_preserve_access_index(arg); // expected-warning {{returning 'const volatile int *' from a function with result type 'const void *' discards qualifiers}}
+}
+
+int *valid5(int *arg) {
+  return __builtin_preserve_access_index(arg);
+}
+
+int valid6(const volatile int *arg) {
+  return *__builtin_preserve_access_index(arg);
+}
+
+struct s { int a; int b; };
+
+int valid7(struct s *arg) {
+  return *__builtin_preserve_access_index(&arg->b);
 }
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -191,12 +191,22 @@
   return false;
 }
 
-/// Check the number of arguments, and set the result type to
+/// Check the number of arguments and arg type, and set the result type to
 /// the argument type.
 static bool SemaBuiltinPreserveAI(Sema &S, CallExpr *TheCall) {
   if (checkArgCount(S, TheCall, 1))
 return true;
 
+  // The argument type must be a pointer
+  ExprResult Arg = TheCall->getArg(0);
+  QualType Ty = Arg.get()->getType();
+  if (!Ty->isPointerType()) {
+S.Diag(Arg.get()->getBeginLoc(),
+   diag::err_builtin_preserve_access_index_invalid_arg)
+<< Ty << Arg.get()->getSourceRange();
+return true;
+  }
+
   TheCall->setType(TheCall->getArg(0)->getType());
   return false;
 }
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9922,4 +9922,7 @@
   "__builtin_bit_cast %select{source|destination}0 type must be trivially copyable">;
 def err_bit_cast_type_size_mismatch : Error<
   "__builtin_bit_cast source size does not equal destination size (%0 vs %1)">;
+
+def err_builtin_preserve_access_index_invalid_arg : Error<
+  "__builtin_preserve_access_index argument must a pointer type instead of %0">;
 } // end of sema component.
Index: clang/include/clang/Basic/Builtins.def
===
--- clang/include/clang/Basic/Builtins.def
+++ clang/include/clang/Basic/Builtins.def
@@ -1470,7 +1470,7 @@
 BUILTIN(__builtin_operator_delete, "vv*", "tn")
 BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
 BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
-BUILTIN(__builtin_preserve_access_index, "vC*vC*", "nU")
+BUILTIN(__builtin_preserve_access_index, "v.", "t")
 
 // Safestack builtins
 BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -2353,12 +2353,14 @@
 array subscript access and structure/union member access are relocatable
 under bpf compile-once run-everywhere framework. Debuginfo (typically
 with ``-g``) is needed, otherwise, the compiler will exit with an error.
+The return type for the intrinsic is the same as the type of the
+argument, and must be a pointer type.
 
 **Syntax**:
 
 .. code-block:: c
 
-  const void * __builtin_preserve_access_index(const void * ptr)
+  Po

[PATCH] D67883: [CLANG][BPF] permit any argument type for __builtin_preserve_access_index()

2019-09-21 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added a reviewer: ast.
Herald added subscribers: cfe-commits, arphaman.
Herald added a project: clang.

Commit c15aa241f821 
 
("[CLANG][BPF] change __builtin_preserve_access_index()
signature") changed the builtin function signature to

  PointerT __builtin_preserve_access_index(PointerT ptr)

with a pointer type as the argument/return type, where argument and
return types must be the same.

There is really no reason for this constraint. The builtin just
presented a code region so that IR builtins

  __builtin_{array, struct, union}_preserve_access_index

can be applied.

This patch removed the pointer type restriction to permit any
argument type as long as it is permitted by the compiler.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67883

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtin-preserve-access-index-nonptr.c
  clang/test/Sema/builtin-preserve-access-index.c

Index: clang/test/Sema/builtin-preserve-access-index.c
===
--- clang/test/Sema/builtin-preserve-access-index.c
+++ clang/test/Sema/builtin-preserve-access-index.c
@@ -4,8 +4,8 @@
   return __builtin_preserve_access_index(&arg[1], 1); // expected-error {{too many arguments to function call, expected 1, have 2}}
 }
 
-const void *invalid2(const int *arg) {
-  return __builtin_preserve_access_index(1); // expected-error {{__builtin_preserve_access_index argument must a pointer type instead of 'int'}}
+int valid2(void) {
+  return __builtin_preserve_access_index(1);
 }
 
 void *invalid3(const int *arg) {
@@ -29,3 +29,11 @@
 int valid7(struct s *arg) {
   return *__builtin_preserve_access_index(&arg->b);
 }
+
+int valid8(struct s *arg) {
+  return __builtin_preserve_access_index(arg->a + arg->b);
+}
+
+int valid9(struct s *arg) {
+  return __builtin_preserve_access_index(({arg->a = 2; arg->b = 3; }));
+}
Index: clang/test/CodeGen/builtin-preserve-access-index-nonptr.c
===
--- /dev/null
+++ clang/test/CodeGen/builtin-preserve-access-index-nonptr.c
@@ -0,0 +1,18 @@
+// RUN: %clang -target x86_64 -emit-llvm -S -g %s -o - | FileCheck %s
+
+#define _(x) (__builtin_preserve_access_index(x))
+
+struct s1 {
+  char a;
+  int b[4];
+};
+
+int unit1(struct s1 *arg) {
+  return _(arg->b[2]);
+}
+// CHECK: define dso_local i32 @unit1
+// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]]
+// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ARRAY:[0-9]+]]
+//
+// CHECK: ![[ARRAY]] = !DICompositeType(tag: DW_TAG_array_type
+// CHECK: ![[STRUCT_S1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1"
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -191,22 +191,12 @@
   return false;
 }
 
-/// Check the number of arguments and arg type, and set the result type to
+/// Check the number of arguments and set the result type to
 /// the argument type.
 static bool SemaBuiltinPreserveAI(Sema &S, CallExpr *TheCall) {
   if (checkArgCount(S, TheCall, 1))
 return true;
 
-  // The argument type must be a pointer
-  ExprResult Arg = TheCall->getArg(0);
-  QualType Ty = Arg.get()->getType();
-  if (!Ty->isPointerType()) {
-S.Diag(Arg.get()->getBeginLoc(),
-   diag::err_builtin_preserve_access_index_invalid_arg)
-<< Ty << Arg.get()->getSourceRange();
-return true;
-  }
-
   TheCall->setType(TheCall->getArg(0)->getType());
   return false;
 }
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9916,7 +9916,4 @@
   "__builtin_bit_cast %select{source|destination}0 type must be trivially copyable">;
 def err_bit_cast_type_size_mismatch : Error<
   "__builtin_bit_cast source size does not equal destination size (%0 vs %1)">;
-
-def err_builtin_preserve_access_index_invalid_arg : Error<
-  "__builtin_preserve_access_index argument must a pointer type instead of %0">;
 } // end of sema component.
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -2354,13 +2354,13 @@
 under bpf compile-once run-everywhere framework. Debuginfo (typically
 with ``-g``) is needed, otherwise, the co

[PATCH] D67940: [BPF] Preserve and make bitfield access relocatable

2019-09-23 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added reviewers: ast, eli.friedman.
Herald added subscribers: llvm-commits, cfe-commits, jdoerfert, hiraditya.
Herald added projects: clang, LLVM.

Previous work for BPF CO-RE (compile once, run everywhere)
tries to record structure, union and array accesses
in order to make addresses relocatable. Bitfield is
not handled as you cannot really take an address of
a bitfield.

Internally, for any bitfield access, llvm will generate
a GEP to the first bitfield for a contiguous run of
bitfields, and then perform proper load and bit 
manipulation from that address.

In this patch, a clang intrinsic is introduced:

  void * __builtin_preserve_bitfield_info(expr, unsigned *buf)

Given a bitfield access, the builtin will return the 
address of the first bitfield for the contiguous run 
of bitfields. The "buf" will have

  . the signness of the bitfield
  . the size of bitfield
  . the offset within the contiguous run of bitfields

These information will be sufficient for bpf program
to retrieve or assign the bitfield values.

The BPF backend will generate an offset relocation
for the leading bitfield and also record all bitfield
accesses happening in this group. So if structure changed
outside the bitfield group, relocation will handle it. 
If the structure changes inside the bitfield group,
the bpf loader may reject the program if it deems previous
bitfield extraction might get the wrong result.

For the case of bitfield access without
__builtin_preserve_bitfield_info() to get an address,
__builtin_preserve_access_index() can be used to enclose
the code. The same offset relocation will be generated.

Please see added tests on how to use the new intrinsic and 
what the new offset relocation looks like.

TODO: due to IR intrinsic __builtin_preserve_struct_access_index()
signature change, most existing CORE tests failed. Will fix it later.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67940

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGBuilder.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtin-preserve-bitfield-info-2.c
  clang/test/CodeGen/builtin-preserve-bitfield-info.c
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/IRBuilder.h
  llvm/include/llvm/IR/Intrinsics.td
  llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
  llvm/lib/Target/BPF/BPFCORE.h
  llvm/lib/Target/BPF/BTF.h
  llvm/lib/Target/BPF/BTFDebug.cpp
  llvm/lib/Target/BPF/BTFDebug.h
  llvm/test/CodeGen/BPF/CORE/intrinsic-bitfield.ll
  llvm/test/CodeGen/BPF/CORE/intrinsic-struct.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-bitfield.ll

Index: llvm/test/CodeGen/BPF/CORE/offset-reloc-bitfield.ll
===
--- /dev/null
+++ llvm/test/CodeGen/BPF/CORE/offset-reloc-bitfield.ll
@@ -0,0 +1,112 @@
+; 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:
+;   struct s {
+; int a;
+; int b1:8;
+; int b2:3;
+; int b3:4;
+;   };
+;
+;   #define _(x, y) __builtin_preserve_bitfield_info((x), (y))
+;   void process(void *);
+;   unsigned test(struct s *arg) {
+; unsigned info1, info2;
+; void *p1, *p2;
+;
+; p1 = _(arg->b2, &info1);
+; p2 = _(arg->b3, &info2);
+; process(p1);
+; process(p2);
+; // the last 16 bit is the offset, so
+; // return value should be 8 + 11 = 19
+; // At -O2, compiler should do this optimization.
+; return (info1 & 0x) + (info2 & 0x);
+;   }
+
+%struct.s = type { i32, i16 }
+
+; Function Attrs: nounwind
+define dso_local i32 @test(%struct.s* %arg) local_unnamed_addr #0 !dbg !7 {
+entry:
+  call void @llvm.dbg.value(metadata %struct.s* %arg, metadata !20, metadata !DIExpression()), !dbg !26
+  %0 = tail call i16* @llvm.preserve.struct.access.index.p0i16.p0s_struct.ss(%struct.s* %arg, i32 1, i32 2, i32 1), !dbg !27, !llvm.preserve.access.index !12
+  %1 = bitcast i16* %0 to i8*, !dbg !27
+  call void @llvm.dbg.value(metadata i32 -2147287032, metadata !21, metadata !DIExpression()), !dbg !26
+  call void @llvm.dbg.value(metadata i8* %1, metadata !23, metadata !DIExpression()), !dbg !26
+  %2 = tail call i16* @llvm.preserve.struct.access.index.p0i16.p0s_struct.ss(%struct.s* %arg, i32 1, i32 3, i32 1), !dbg !28, !llvm.preserve.access.index !12
+  %3 = bitcast i16* %2 to i8*, !dbg !28
+  call void @llvm.dbg.value(metadata i32 -2147221493, metadata !22, metadata !DIExpression()), !dbg !26
+  call void @llvm.dbg.value(metadata i8* %3, metadata !25, metadata !DIExpression()), !dbg !26
+  tail call void @process(i8* %1) #4, !dbg !29
+  tail call void @process(i8* %3) #4, !dbg !30
+  ret i32 19, !dbg !31
+}
+
+; CHECK-LA

[PATCH] D67940: [BPF] Preserve and make bitfield access relocatable

2019-09-23 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 221466.
yonghong-song added a comment.
Herald added a subscriber: ormris.

fix a bug like `foo(..., bar(&value), value)` where `value` is set in function 
`bar`. This is not right and depends on compiler optimization as there is not 
guarantee that arguments are evaluated from left to right. The new code looks 
like ` a = bar(&value); foo(..., a, value)` ...


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67940

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGBuilder.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtin-preserve-bitfield-info-2.c
  clang/test/CodeGen/builtin-preserve-bitfield-info.c
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/IRBuilder.h
  llvm/include/llvm/IR/Intrinsics.td
  llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
  llvm/lib/Target/BPF/BPFCORE.h
  llvm/lib/Target/BPF/BTF.h
  llvm/lib/Target/BPF/BTFDebug.cpp
  llvm/lib/Target/BPF/BTFDebug.h
  llvm/test/CodeGen/BPF/CORE/intrinsic-bitfield.ll
  llvm/test/CodeGen/BPF/CORE/intrinsic-struct.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-bitfield.ll

Index: llvm/test/CodeGen/BPF/CORE/offset-reloc-bitfield.ll
===
--- /dev/null
+++ llvm/test/CodeGen/BPF/CORE/offset-reloc-bitfield.ll
@@ -0,0 +1,112 @@
+; 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:
+;   struct s {
+; int a;
+; int b1:8;
+; int b2:3;
+; int b3:4;
+;   };
+;
+;   #define _(x, y) __builtin_preserve_bitfield_info((x), (y))
+;   void process(void *);
+;   unsigned test(struct s *arg) {
+; unsigned info1, info2;
+; void *p1, *p2;
+;
+; p1 = _(arg->b2, &info1);
+; p2 = _(arg->b3, &info2);
+; process(p1);
+; process(p2);
+; // the last 16 bit is the offset, so
+; // return value should be 8 + 11 = 19
+; // At -O2, compiler should do this optimization.
+; return (info1 & 0x) + (info2 & 0x);
+;   }
+
+%struct.s = type { i32, i16 }
+
+; Function Attrs: nounwind
+define dso_local i32 @test(%struct.s* %arg) local_unnamed_addr #0 !dbg !7 {
+entry:
+  call void @llvm.dbg.value(metadata %struct.s* %arg, metadata !20, metadata !DIExpression()), !dbg !26
+  %0 = tail call i16* @llvm.preserve.struct.access.index.p0i16.p0s_struct.ss(%struct.s* %arg, i32 1, i32 2, i32 1), !dbg !27, !llvm.preserve.access.index !12
+  %1 = bitcast i16* %0 to i8*, !dbg !27
+  call void @llvm.dbg.value(metadata i32 -2147287032, metadata !21, metadata !DIExpression()), !dbg !26
+  call void @llvm.dbg.value(metadata i8* %1, metadata !23, metadata !DIExpression()), !dbg !26
+  %2 = tail call i16* @llvm.preserve.struct.access.index.p0i16.p0s_struct.ss(%struct.s* %arg, i32 1, i32 3, i32 1), !dbg !28, !llvm.preserve.access.index !12
+  %3 = bitcast i16* %2 to i8*, !dbg !28
+  call void @llvm.dbg.value(metadata i32 -2147221493, metadata !22, metadata !DIExpression()), !dbg !26
+  call void @llvm.dbg.value(metadata i8* %3, metadata !25, metadata !DIExpression()), !dbg !26
+  tail call void @process(i8* %1) #4, !dbg !29
+  tail call void @process(i8* %3) #4, !dbg !30
+  ret i32 19, !dbg !31
+}
+
+; CHECK-LABEL:   test
+; CHECK: r1 = 4
+; CHECK: r{{[0-9]+}} += r1
+; CHECK: r0 = 19
+; CHECK: exit
+;
+; CHECK: .ascii  ".text" # string offset=40
+; CHECK: .ascii  "0:1"   # string offset=83
+; CHECK: .ascii  "2$3"   # string offset=87
+; CHECK:.long   16  # OffsetReloc
+; CHECK-NEXT:   .long   40  # Offset reloc section string offset=40
+; CHECK-NEXT:   .long   1
+; CHECK-NEXT:   .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:   .long   2
+; CHECK-NEXT:   .long   83
+; CHECK-NEXT:   .long   87
+
+; Function Attrs: nounwind readnone
+declare i16* @llvm.preserve.struct.access.index.p0i16.p0s_struct.ss(%struct.s*, i32, i32, i32) #1
+
+declare dso_local void @process(i8*) local_unnamed_addr #2
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+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 = { "correctly

[PATCH] D67980: [WIP][CLANG][BPF] implement clang __builtin_bitfield_info() intrinsic

2019-09-24 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added reviewers: ast, anakryiko.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The patch is still work in progress.

The signature:

  u64 __builtin_bitfield_info(bitfield_member_access)

return value:

  ret >> 16 : bitfield offset from the start of the struct
  (ret >> 15) & 0x1 : bitfield signness
  ret & (1 << 15 - 1) : bitfield size

The information is extracted from:

  https://clang.llvm.org/doxygen/structclang_1_1CodeGen_1_1CGBitFieldInfo.html

An example:
-bash-4.4$ cat bit.c

struct s {

  int a;
  long long p1; 
  int p2; 
  int b1:2;
  int b2:10;
  int b3:2;
  int b4:10;
  int b5:3;
  int d;

};
struct s *a; 
int main () {

  unsigned long long x = __builtin_bitfield_info(a->b3);
  printf("offset = %lld, sign = %lld, size = %lld\n",
 x >> 16, (x >> 15) & 1, x & ((1 << 15) - 1));
  return 0;

}
-bash-4.4$ clang -O2 -g bit.c
-bash-4.4$ ./a.out
offset = 172, sign = 1, size = 2 
-bash-4.4$

This builtin returns necessary information to user space
to extract values from the bitfields.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67980

Files:
  clang/include/clang/Basic/Builtins.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp


Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -1429,6 +1429,19 @@
 if (SemaBuiltinPreserveAI(*this, TheCall))
   return ExprError();
 break;
+  case Builtin::BI__builtin_bitfield_info: {
+if (checkArgCount(*this, TheCall, 1))
+  return ExprError();
+
+Expr *Arg = TheCall->getArg(0);
+if (Arg->getType()->getAsPlaceholderType())
+  return ExprError();
+if (Arg->IgnoreParens()->getObjectKind() != OK_BitField)
+  return ExprError();
+
+TheCall->setType(Context.UnsignedLongLongTy);
+break;
+  }
   case Builtin::BI__builtin_call_with_static_chain:
 if (SemaBuiltinCallWithStaticChain(*this, TheCall))
   return ExprError();
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -1882,6 +1882,13 @@
 IsInPreservedAIRegion = false;
 return RValue::get(Res);
   }
+  case Builtin::BI__builtin_bitfield_info: {
+const CGBitFieldInfo &Info = EmitLValue(E->getArg(0)).getBitFieldInfo();
+uint64_t Val = ((Info.StorageOffset.getQuantity() * 8 + Info.Offset) << 
16) |
+   (Info.IsSigned << 15) |
+   Info.Size;
+return RValue::get(ConstantInt::get(Int64Ty, Val));
+  }
 
   case Builtin::BI__builtin_cimag:
   case Builtin::BI__builtin_cimagf:
Index: clang/include/clang/Basic/Builtins.def
===
--- clang/include/clang/Basic/Builtins.def
+++ clang/include/clang/Basic/Builtins.def
@@ -1469,6 +1469,7 @@
 BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
 BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
 BUILTIN(__builtin_preserve_access_index, "v.", "t")
+BUILTIN(__builtin_bitfield_info, "LLUi.", "t")
 
 // Safestack builtins
 BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")


Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -1429,6 +1429,19 @@
 if (SemaBuiltinPreserveAI(*this, TheCall))
   return ExprError();
 break;
+  case Builtin::BI__builtin_bitfield_info: {
+if (checkArgCount(*this, TheCall, 1))
+  return ExprError();
+
+Expr *Arg = TheCall->getArg(0);
+if (Arg->getType()->getAsPlaceholderType())
+  return ExprError();
+if (Arg->IgnoreParens()->getObjectKind() != OK_BitField)
+  return ExprError();
+
+TheCall->setType(Context.UnsignedLongLongTy);
+break;
+  }
   case Builtin::BI__builtin_call_with_static_chain:
 if (SemaBuiltinCallWithStaticChain(*this, TheCall))
   return ExprError();
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -1882,6 +1882,13 @@
 IsInPreservedAIRegion = false;
 return RValue::get(Res);
   }
+  case Builtin::BI__builtin_bitfield_info: {
+const CGBitFieldInfo &Info = EmitLValue(E->getArg(0)).getBitFieldInfo();
+uint64_t Val = ((Info.StorageOffset.getQuantity() * 8 + Info.Offset) << 16) |
+   (Info.IsSigned << 15) |
+   Info.Size;
+return RValue::get(ConstantInt::get(Int64Ty, Val));
+  }
 
   case Builtin::BI__builtin_cimag:
   case Builtin::BI__builtin_cimagf:
Index: clang/include/clang/Basic/Builtins.def
===
--- clang/include/clang/Basic/Builtins.def
+++ clang/include/clang/Basic/Builtins

[PATCH] D67980: [WIP][CLANG][BPF] implement clang __builtin_bitfield_info() intrinsic

2019-09-24 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 221598.
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

builtin return u32 instead of u64.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67980

Files:
  clang/include/clang/Basic/Builtins.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp


Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -1429,6 +1429,19 @@
 if (SemaBuiltinPreserveAI(*this, TheCall))
   return ExprError();
 break;
+  case Builtin::BI__builtin_bitfield_info: {
+if (checkArgCount(*this, TheCall, 1))
+  return ExprError();
+
+Expr *Arg = TheCall->getArg(0);
+if (Arg->getType()->getAsPlaceholderType())
+  return ExprError();
+if (Arg->IgnoreParens()->getObjectKind() != OK_BitField)
+  return ExprError();
+
+TheCall->setType(Context.UnsignedIntTy);
+break;
+  }
   case Builtin::BI__builtin_call_with_static_chain:
 if (SemaBuiltinCallWithStaticChain(*this, TheCall))
   return ExprError();
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -1882,6 +1882,13 @@
 IsInPreservedAIRegion = false;
 return RValue::get(Res);
   }
+  case Builtin::BI__builtin_bitfield_info: {
+const CGBitFieldInfo &Info = EmitLValue(E->getArg(0)).getBitFieldInfo();
+uint32_t Val = ((Info.StorageOffset.getQuantity() * 8 + Info.Offset) << 8) 
|
+   (Info.IsSigned << 7) |
+   Info.Size;
+return RValue::get(ConstantInt::get(Int32Ty, Val));
+  }
 
   case Builtin::BI__builtin_cimag:
   case Builtin::BI__builtin_cimagf:
Index: clang/include/clang/Basic/Builtins.def
===
--- clang/include/clang/Basic/Builtins.def
+++ clang/include/clang/Basic/Builtins.def
@@ -1469,6 +1469,7 @@
 BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
 BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
 BUILTIN(__builtin_preserve_access_index, "v.", "t")
+BUILTIN(__builtin_bitfield_info, "Ui.", "t")
 
 // Safestack builtins
 BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")


Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -1429,6 +1429,19 @@
 if (SemaBuiltinPreserveAI(*this, TheCall))
   return ExprError();
 break;
+  case Builtin::BI__builtin_bitfield_info: {
+if (checkArgCount(*this, TheCall, 1))
+  return ExprError();
+
+Expr *Arg = TheCall->getArg(0);
+if (Arg->getType()->getAsPlaceholderType())
+  return ExprError();
+if (Arg->IgnoreParens()->getObjectKind() != OK_BitField)
+  return ExprError();
+
+TheCall->setType(Context.UnsignedIntTy);
+break;
+  }
   case Builtin::BI__builtin_call_with_static_chain:
 if (SemaBuiltinCallWithStaticChain(*this, TheCall))
   return ExprError();
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -1882,6 +1882,13 @@
 IsInPreservedAIRegion = false;
 return RValue::get(Res);
   }
+  case Builtin::BI__builtin_bitfield_info: {
+const CGBitFieldInfo &Info = EmitLValue(E->getArg(0)).getBitFieldInfo();
+uint32_t Val = ((Info.StorageOffset.getQuantity() * 8 + Info.Offset) << 8) |
+   (Info.IsSigned << 7) |
+   Info.Size;
+return RValue::get(ConstantInt::get(Int32Ty, Val));
+  }
 
   case Builtin::BI__builtin_cimag:
   case Builtin::BI__builtin_cimagf:
Index: clang/include/clang/Basic/Builtins.def
===
--- clang/include/clang/Basic/Builtins.def
+++ clang/include/clang/Basic/Builtins.def
@@ -1469,6 +1469,7 @@
 BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
 BUILTIN(__builtin_dump_struct, "ivC*v*", "tn")
 BUILTIN(__builtin_preserve_access_index, "v.", "t")
+BUILTIN(__builtin_bitfield_info, "Ui.", "t")
 
 // Safestack builtins
 BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67980: [WIP][CLANG][BPF] do compile-once run-everywhere relocation for bitfields

2019-09-26 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 221962.
yonghong-song retitled this revision from "[WIP][CLANG][BPF] implement clang 
__builtin_bitfield_info() intrinsic" to "[WIP][CLANG][BPF] do compile-once 
run-everywhere relocation for bitfields".
yonghong-song edited the summary of this revision.
yonghong-song added a comment.
Herald added subscribers: llvm-commits, jdoerfert, hiraditya.
Herald added a project: LLVM.

add BPF backend support


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67980

Files:
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Sema/SemaChecking.cpp
  llvm/include/llvm/IR/IRBuilder.h
  llvm/include/llvm/IR/Intrinsics.td
  llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
  llvm/lib/Target/BPF/BTFDebug.cpp
  llvm/lib/Target/BPF/BTFDebug.h

Index: llvm/lib/Target/BPF/BTFDebug.h
===
--- llvm/lib/Target/BPF/BTFDebug.h
+++ llvm/lib/Target/BPF/BTFDebug.h
@@ -254,7 +254,7 @@
   StringMap> FileContent;
   std::map> DataSecEntries;
   std::vector StructTypes;
-  std::map AccessOffsets;
+  std::map PatchImms;
   std::map>>
   FixupDerivedTypes;
 
Index: llvm/lib/Target/BPF/BTFDebug.cpp
===
--- llvm/lib/Target/BPF/BTFDebug.cpp
+++ llvm/lib/Target/BPF/BTFDebug.cpp
@@ -966,14 +966,14 @@
   size_t FirstDollar = AccessPattern.find_first_of('$');
   size_t FirstColon = AccessPattern.find_first_of(':');
   StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1);
-  StringRef OffsetStr = AccessPattern.substr(FirstColon + 1,
+  StringRef PatchImmStr = AccessPattern.substr(FirstColon + 1,
   FirstDollar - FirstColon);
 
   BTFOffsetReloc OffsetReloc;
   OffsetReloc.Label = ORSym;
   OffsetReloc.OffsetNameOff = addString(IndexPattern);
   OffsetReloc.TypeID = RootId;
-  AccessOffsets[AccessPattern.str()] = std::stoi(OffsetStr);
+  PatchImms[AccessPattern.str()] = std::stoull(PatchImmStr);
   OffsetRelocTable[SecNameOff].push_back(OffsetReloc);
 }
 
@@ -1157,10 +1157,13 @@
 MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index);
 DIType *Ty = dyn_cast(MDN);
 std::string TypeName = Ty->getName();
-int64_t Imm = AccessOffsets[GVar->getName().str()];
+uint64_t Imm = PatchImms[GVar->getName().str()];
 
-// Emit "mov ri, " for abstract member accesses.
-OutMI.setOpcode(BPF::MOV_ri);
+// Emit "mov/ld_imm64 ri, " for patched immediate.
+if (Imm > UINT_MAX)
+  OutMI.setOpcode(BPF::LD_imm64);
+else
+  OutMI.setOpcode(BPF::MOV_ri);
 OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
 OutMI.addOperand(MCOperand::createImm(Imm));
 return true;
Index: llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
===
--- llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
+++ llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
@@ -50,6 +50,32 @@
 //   addr = preserve_struct_access_index(base, gep_index, di_index)
 //  !llvm.preserve.access.index 
 //
+// Bitfield member access needs special attention. User cannot take the
+// address of a bitfield access. To avoid generating loads which might
+// have side effects with bpf programs, e.g., verifier may reject it,
+// a new clang intrinsic (__builtin_preserve_bitfield_info()) is added
+// to return bitfield member offset, signness and member size, given
+// a bitfield access. For example,
+//   struct s { int a; int b:3; int b2:4; } arg;
+//   uint64_t __builtin_preserve_bitfield_info(arg->b)
+// The application can then use member offset, signness and member size
+// to perform bit field extraction.
+//
+// A new IR intrinsic:
+//   uint64_t preserve_array_access_index(base)
+// is introduced.
+// The above __builtin_preserve_bitfield_info(arg->b) will generate
+// two preserve_*_access_index() calls like
+//   addr = preserve_struct_access_index(base, 1, 1) !struct s
+//   uint64_t preserve_array_access_index(addr)
+// The above two IR intrinsics will be eventually replaced with
+// a relocatable insn:
+//   bitfield_info = 8ULL << 48 /* member offset */ |
+//   1 << 7 /* signness */ |
+//   3 /* member size */
+// and bitfield_info can be changed by bpf loader based on the
+// types on the host.
+//
 //===--===//
 
 #include "BPF.h"
@@ -95,14 +121,15 @@
 BPFPreserveArrayAI = 1,
 BPFPreserveUnionAI = 2,
 BPFPreserveStructAI = 3,
+BPFPreserveBitFieldAI = 4,
   };
 
   std::map GEPGlobals;
   // A map to link preserve_*_access_index instrinsic calls.
   std::map> AIChain;
   // A 

[PATCH] D67940: [BPF] Preserve and make bitfield access relocatable

2019-10-01 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song abandoned this revision.
yonghong-song added a comment.

We will take a different approach. So abandon this revision.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67940



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67980: [WIP][CLANG][BPF] do compile-once run-everywhere relocation for bitfields

2019-10-02 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 222910.
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

use a bpf target builtin __builtin_get_field_info().


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67980

Files:
  clang/include/clang/Basic/BuiltinsBPF.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TargetBuiltins.h
  clang/include/clang/Sema/Sema.h
  clang/include/clang/module.modulemap
  clang/lib/Basic/Targets/BPF.cpp
  clang/lib/Basic/Targets/BPF.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Sema/SemaChecking.cpp
  llvm/include/llvm/IR/IntrinsicsBPF.td
  llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
  llvm/lib/Target/BPF/BPFCORE.h
  llvm/lib/Target/BPF/BTF.h
  llvm/lib/Target/BPF/BTFDebug.cpp
  llvm/lib/Target/BPF/BTFDebug.h

Index: llvm/lib/Target/BPF/BTFDebug.h
===
--- llvm/lib/Target/BPF/BTFDebug.h
+++ llvm/lib/Target/BPF/BTFDebug.h
@@ -228,6 +228,7 @@
   const MCSymbol *Label;  ///< MCSymbol identifying insn for the reloc
   uint32_t TypeID;///< Type ID
   uint32_t OffsetNameOff; ///< The string to traverse types
+  uint32_t RelocKind; ///< What to patch the instruction
 };
 
 /// Represent one extern relocation.
@@ -254,7 +255,7 @@
   StringMap> FileContent;
   std::map> DataSecEntries;
   std::vector StructTypes;
-  std::map AccessOffsets;
+  std::map PatchImms;
   std::map>>
   FixupDerivedTypes;
 
Index: llvm/lib/Target/BPF/BTFDebug.cpp
===
--- llvm/lib/Target/BPF/BTFDebug.cpp
+++ llvm/lib/Target/BPF/BTFDebug.cpp
@@ -844,6 +844,7 @@
 Asm->EmitLabelReference(OffsetRelocInfo.Label, 4);
 OS.EmitIntValue(OffsetRelocInfo.TypeID, 4);
 OS.EmitIntValue(OffsetRelocInfo.OffsetNameOff, 4);
+OS.EmitIntValue(OffsetRelocInfo.RelocKind, 4);
   }
 }
   }
@@ -965,15 +966,19 @@
   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 OffsetStr = AccessPattern.substr(FirstColon + 1,
-  FirstDollar - FirstColon);
+  StringRef RelocKindStr = AccessPattern.substr(FirstColon + 1,
+  SecondColon - FirstColon);
+  StringRef PatchImmStr = AccessPattern.substr(SecondColon + 1,
+  FirstDollar - SecondColon);
 
   BTFOffsetReloc OffsetReloc;
   OffsetReloc.Label = ORSym;
   OffsetReloc.OffsetNameOff = addString(IndexPattern);
   OffsetReloc.TypeID = RootId;
-  AccessOffsets[AccessPattern.str()] = std::stoi(OffsetStr);
+  OffsetReloc.RelocKind = std::stoull(RelocKindStr);
+  PatchImms[AccessPattern.str()] = std::stoull(PatchImmStr);
   OffsetRelocTable[SecNameOff].push_back(OffsetReloc);
 }
 
@@ -1154,8 +1159,8 @@
   const GlobalValue *GVal = MO.getGlobal();
   auto *GVar = dyn_cast(GVal);
   if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) {
-// Emit "mov ri, " for abstract member accesses.
-int64_t Imm = AccessOffsets[GVar->getName().str()];
+// Emit "mov ri, " for patched immediate.
+int64_t Imm = PatchImms[GVar->getName().str()];
 OutMI.setOpcode(BPF::MOV_ri);
 OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
 OutMI.addOperand(MCOperand::createImm(Imm));
Index: llvm/lib/Target/BPF/BTF.h
===
--- llvm/lib/Target/BPF/BTF.h
+++ llvm/lib/Target/BPF/BTF.h
@@ -76,7 +76,7 @@
   SecExternRelocSize = 8,
   BPFFuncInfoSize = 8,
   BPFLineInfoSize = 16,
-  BPFOffsetRelocSize = 12,
+  BPFOffsetRelocSize = 16,
   BPFExternRelocSize = 8,
 };
 
@@ -251,6 +251,7 @@
   uint32_t InsnOffset;///< Byte offset in this section
   uint32_t TypeID;///< TypeID for the relocation
   uint32_t OffsetNameOff; ///< The string to traverse types
+  uint32_t RelocKind; ///< What to patch the instruction
 };
 
 /// Specifying offset relocation's in one section.
Index: llvm/lib/Target/BPF/BPFCORE.h
===
--- llvm/lib/Target/BPF/BPFCORE.h
+++ llvm/lib/Target/BPF/BPFCORE.h
@@ -13,6 +13,14 @@
 
 class BPFCoreSharedInfo {
 public:
+  enum OffsetRelocKind : uint32_t {
+BTF_FIELD_ACCESS_OFFSET = 0,
+BTF_FIELD_EXISTENCE,
+BTF_FIELD_SIGNNESS,
+BTF_FIELD_BF_BYTE_OFFSET_64BIT_ALIGN,
+BTF_FIELD_BF_LSHIFT_64BIT_ALIGN,
+BTF_FIELD_BF_RSHIFT_64BIT_ALIGN,
+  };
   /// The attribute attached to globals representing a member offset
   static const std::string AmaAttr;
   /// The section name to identify a patchable external global
Index: llv

[PATCH] D67980: [WIP][CLANG][BPF] do compile-once run-everywhere relocation for bitfields

2019-10-02 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 222920.
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

return byte_size/offset/lshift/rshift based on size alignment


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67980

Files:
  clang/include/clang/Basic/BuiltinsBPF.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TargetBuiltins.h
  clang/include/clang/Sema/Sema.h
  clang/include/clang/module.modulemap
  clang/lib/Basic/Targets/BPF.cpp
  clang/lib/Basic/Targets/BPF.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Sema/SemaChecking.cpp
  llvm/include/llvm/IR/IntrinsicsBPF.td
  llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
  llvm/lib/Target/BPF/BPFCORE.h
  llvm/lib/Target/BPF/BTF.h
  llvm/lib/Target/BPF/BTFDebug.cpp
  llvm/lib/Target/BPF/BTFDebug.h

Index: llvm/lib/Target/BPF/BTFDebug.h
===
--- llvm/lib/Target/BPF/BTFDebug.h
+++ llvm/lib/Target/BPF/BTFDebug.h
@@ -228,6 +228,7 @@
   const MCSymbol *Label;  ///< MCSymbol identifying insn for the reloc
   uint32_t TypeID;///< Type ID
   uint32_t OffsetNameOff; ///< The string to traverse types
+  uint32_t RelocKind; ///< What to patch the instruction
 };
 
 /// Represent one extern relocation.
@@ -254,7 +255,7 @@
   StringMap> FileContent;
   std::map> DataSecEntries;
   std::vector StructTypes;
-  std::map AccessOffsets;
+  std::map PatchImms;
   std::map>>
   FixupDerivedTypes;
 
Index: llvm/lib/Target/BPF/BTFDebug.cpp
===
--- llvm/lib/Target/BPF/BTFDebug.cpp
+++ llvm/lib/Target/BPF/BTFDebug.cpp
@@ -844,6 +844,7 @@
 Asm->EmitLabelReference(OffsetRelocInfo.Label, 4);
 OS.EmitIntValue(OffsetRelocInfo.TypeID, 4);
 OS.EmitIntValue(OffsetRelocInfo.OffsetNameOff, 4);
+OS.EmitIntValue(OffsetRelocInfo.RelocKind, 4);
   }
 }
   }
@@ -965,15 +966,19 @@
   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 OffsetStr = AccessPattern.substr(FirstColon + 1,
-  FirstDollar - FirstColon);
+  StringRef RelocKindStr = AccessPattern.substr(FirstColon + 1,
+  SecondColon - FirstColon);
+  StringRef PatchImmStr = AccessPattern.substr(SecondColon + 1,
+  FirstDollar - SecondColon);
 
   BTFOffsetReloc OffsetReloc;
   OffsetReloc.Label = ORSym;
   OffsetReloc.OffsetNameOff = addString(IndexPattern);
   OffsetReloc.TypeID = RootId;
-  AccessOffsets[AccessPattern.str()] = std::stoi(OffsetStr);
+  OffsetReloc.RelocKind = std::stoull(RelocKindStr);
+  PatchImms[AccessPattern.str()] = std::stoull(PatchImmStr);
   OffsetRelocTable[SecNameOff].push_back(OffsetReloc);
 }
 
@@ -1154,8 +1159,8 @@
   const GlobalValue *GVal = MO.getGlobal();
   auto *GVar = dyn_cast(GVal);
   if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) {
-// Emit "mov ri, " for abstract member accesses.
-int64_t Imm = AccessOffsets[GVar->getName().str()];
+// Emit "mov ri, " for patched immediate.
+int64_t Imm = PatchImms[GVar->getName().str()];
 OutMI.setOpcode(BPF::MOV_ri);
 OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
 OutMI.addOperand(MCOperand::createImm(Imm));
Index: llvm/lib/Target/BPF/BTF.h
===
--- llvm/lib/Target/BPF/BTF.h
+++ llvm/lib/Target/BPF/BTF.h
@@ -76,7 +76,7 @@
   SecExternRelocSize = 8,
   BPFFuncInfoSize = 8,
   BPFLineInfoSize = 16,
-  BPFOffsetRelocSize = 12,
+  BPFOffsetRelocSize = 16,
   BPFExternRelocSize = 8,
 };
 
@@ -251,6 +251,7 @@
   uint32_t InsnOffset;///< Byte offset in this section
   uint32_t TypeID;///< TypeID for the relocation
   uint32_t OffsetNameOff; ///< The string to traverse types
+  uint32_t RelocKind; ///< What to patch the instruction
 };
 
 /// Specifying offset relocation's in one section.
Index: llvm/lib/Target/BPF/BPFCORE.h
===
--- llvm/lib/Target/BPF/BPFCORE.h
+++ llvm/lib/Target/BPF/BPFCORE.h
@@ -13,6 +13,18 @@
 
 class BPFCoreSharedInfo {
 public:
+  enum OffsetRelocKind : uint32_t {
+BTF_FIELD_ACCESS_OFFSET = 0,
+BTF_FIELD_EXISTENCE,
+BTF_FIELD_SIGNNESS,
+BTF_FIELD_BF_BYTE_OFFSET_64BIT_ALIGN,
+BTF_FIELD_BF_LSHIFT_64BIT_ALIGN,
+BTF_FIELD_BF_RSHIFT_64BIT_ALIGN,
+BTF_FIELD_BF_BYTE_SIZE,
+BTF_FIELD_BF_BYTE_OFFSET_SIZE_ALIGN,
+BTF_FIELD_BF_LSHIFT_SIZE_ALIGN,
+BTF_FIELD_BF_RSHIFT_SIZE_ALIGN,
+  };
   /// The attribute attach

[PATCH] D67980: [WIP][CLANG][BPF] do compile-once run-everywhere relocation for bitfields

2019-10-03 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked 9 inline comments as done.
yonghong-song added inline comments.



Comment at: clang/lib/CodeGen/CGBuiltin.cpp:9321-9322
+  if (IsError)
+return IsBitField ? EmitLValue(Arg).getBitFieldPointer()
+  : EmitLValue(Arg).getPointer();
+

anakryiko wrote:
> move this under `if (!getDebugInfo)` above and ditch IsError completely?
yes. previously I have two case of errors. Now only have one, it makes sense to 
merge them.



Comment at: llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp:235
   report_fatal_error("Missing metadata for 
llvm.preserve.array.access.index intrinsic");
-AccessIndex = cast(Call->getArgOperand(2))
-  ->getZExtValue();
+AccessIndex = getConstant(Call->getArgOperand(2));
 return true;

anakryiko wrote:
> getConstant returns u64, but AccessIndex is u32, is that a concern?
it should be okay. the call is generated by clang where the access index will 
be in the range. Also, llvm ConstantInt class can only return 64bit values.
https://llvm.org/doxygen/classllvm_1_1ConstantInt.html
We just do the cast here. should be okay.



Comment at: llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp:254
+  }
+  if (GV->getName().startswith("llvm.bpf.get.field.info")) {
+Kind = BPFGetFieldInfoAI;

anakryiko wrote:
> just curious, why did you decide to not follow llvm.preserve.xxx pattern 
> here? E.g., llvm.preserve.field.info would read just fine, I guess?
previously i am using preserve.field.info and switch to get.field.info as it is 
indeed to return certain field info to the user. maybe we should get back to 
preserve.field.info to indicate that relocation is generated. will do.



Comment at: llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp:533
+  auto *MemberTy = cast(CTy->getElements()[AccessIndex]);
+  assert(MemberTy->isBitField());
+  uint64_t OffsetInBits = MemberTy->getOffsetInBits();

anakryiko wrote:
> is it possible to allow capturing same bitfield information for non-bitfield 
> integers?
> 
> E.g, if my current vmlinux.h has some field as plain integer, but I know that 
> some older kernel (or maybe future kernels?) had this field as a bitfield, I 
> won't have to do anything nasty just to handle this generically. The less 
> artificial restrictions we have, the better, IMO.
Yes, we can remove this restriction. Let us first get bitfield interface right 
and then extend them to nonbitfield.



Comment at: llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp:536
+  uint64_t SizeInBits = MemberTy->getSizeInBits();
+  assert(SizeInBits <= 63);
+  switch (InfoKind) {

anakryiko wrote:
> I think we should be generic here and allow up to 128 bits and let libbpf 
> handle its limitations separately (e.g., if we can't support >64 bits 
> initially, libbpf will reject the program; but if we ever extend the support, 
> at least we won't have to go back to Clang and fix it up).
We can do this.



Comment at: llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp:541-548
+  case BPFCoreSharedInfo::BTF_FIELD_BF_BYTE_OFFSET_64BIT_ALIGN:
+PatchImm = (OffsetInBits & ~0x3f) >> 3;
+break;
+  case BPFCoreSharedInfo::BTF_FIELD_BF_LSHIFT_64BIT_ALIGN:
+PatchImm = OffsetInBits & 0x3f;
+break;
+  case BPFCoreSharedInfo::BTF_FIELD_BF_RSHIFT_64BIT_ALIGN:

anakryiko wrote:
> I'll need to do some drawing and math to check how this is going to be 
> handled in big-endian and little-endian, I'll get back to you later with that.
sounds great.



Comment at: llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp:600
+
+  PatchImm += FirstIndex * Ty->getSizeInBits() >> 3;
   break;

anakryiko wrote:
> nit: I can't from the top of my head figure out what takes precedence: shift 
> or multiplication, maybe add parens to make it obvious?
sure.



Comment at: llvm/lib/Target/BPF/BTFDebug.cpp:1163
+// Emit "mov ri, " for patched immediate.
+int64_t Imm = PatchImms[GVar->getName().str()];
 OutMI.setOpcode(BPF::MOV_ri);

anakryiko wrote:
> why int64?
Will change to u32.



Comment at: llvm/lib/Target/BPF/BTFDebug.h:227
 /// Represent one offset relocation.
 struct BTFOffsetReloc {
   const MCSymbol *Label;  ///< MCSymbol identifying insn for the reloc

anakryiko wrote:
> nit: this is not BTFOffsetReloc anymore, more like BTFFieldReloc
Yes, it becomes FieldReloc now.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67980



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67980: [WIP][CLANG][BPF] do compile-once run-everywhere relocation for bitfields

2019-10-04 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 223233.
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

using 64bit buf always, handling non bitfield members, etc.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67980

Files:
  clang/include/clang/Basic/BuiltinsBPF.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TargetBuiltins.h
  clang/include/clang/Sema/Sema.h
  clang/include/clang/module.modulemap
  clang/lib/Basic/Targets/BPF.cpp
  clang/lib/Basic/Targets/BPF.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Sema/SemaChecking.cpp
  llvm/include/llvm/IR/IntrinsicsBPF.td
  llvm/lib/Target/BPF/BPF.h
  llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
  llvm/lib/Target/BPF/BPFCORE.h
  llvm/lib/Target/BPF/BPFTargetMachine.cpp
  llvm/lib/Target/BPF/BTF.h
  llvm/lib/Target/BPF/BTFDebug.cpp
  llvm/lib/Target/BPF/BTFDebug.h

Index: llvm/lib/Target/BPF/BTFDebug.h
===
--- llvm/lib/Target/BPF/BTFDebug.h
+++ llvm/lib/Target/BPF/BTFDebug.h
@@ -224,10 +224,11 @@
 };
 
 /// Represent one offset relocation.
-struct BTFOffsetReloc {
+struct BTFFieldReloc {
   const MCSymbol *Label;  ///< MCSymbol identifying insn for the reloc
   uint32_t TypeID;///< Type ID
   uint32_t OffsetNameOff; ///< The string to traverse types
+  uint32_t RelocKind; ///< What to patch the instruction
 };
 
 /// Represent one extern relocation.
@@ -249,12 +250,12 @@
   std::unordered_map DIToIdMap;
   std::map> FuncInfoTable;
   std::map> LineInfoTable;
-  std::map> OffsetRelocTable;
+  std::map> FieldRelocTable;
   std::map> ExternRelocTable;
   StringMap> FileContent;
   std::map> DataSecEntries;
   std::vector StructTypes;
-  std::map AccessOffsets;
+  std::map PatchImms;
   std::map>>
   FixupDerivedTypes;
 
@@ -300,7 +301,7 @@
   void processGlobals(bool ProcessingMapDef);
 
   /// Generate one offset relocation record.
-  void generateOffsetReloc(const MachineInstr *MI, const MCSymbol *ORSym,
+  void generateFieldReloc(const MachineInstr *MI, const MCSymbol *ORSym,
DIType *RootTy, StringRef AccessPattern);
 
   /// Populating unprocessed struct type.
Index: llvm/lib/Target/BPF/BTFDebug.cpp
===
--- llvm/lib/Target/BPF/BTFDebug.cpp
+++ llvm/lib/Target/BPF/BTFDebug.cpp
@@ -754,7 +754,7 @@
 void BTFDebug::emitBTFExtSection() {
   // Do not emit section if empty FuncInfoTable and LineInfoTable.
   if (!FuncInfoTable.size() && !LineInfoTable.size() &&
-  !OffsetRelocTable.size() && !ExternRelocTable.size())
+  !FieldRelocTable.size() && !ExternRelocTable.size())
 return;
 
   MCContext &Ctx = OS.getContext();
@@ -766,8 +766,8 @@
 
   // Account for FuncInfo/LineInfo record size as well.
   uint32_t FuncLen = 4, LineLen = 4;
-  // Do not account for optional OffsetReloc/ExternReloc.
-  uint32_t OffsetRelocLen = 0, ExternRelocLen = 0;
+  // Do not account for optional FieldReloc/ExternReloc.
+  uint32_t FieldRelocLen = 0, ExternRelocLen = 0;
   for (const auto &FuncSec : FuncInfoTable) {
 FuncLen += BTF::SecFuncInfoSize;
 FuncLen += FuncSec.second.size() * BTF::BPFFuncInfoSize;
@@ -776,17 +776,17 @@
 LineLen += BTF::SecLineInfoSize;
 LineLen += LineSec.second.size() * BTF::BPFLineInfoSize;
   }
-  for (const auto &OffsetRelocSec : OffsetRelocTable) {
-OffsetRelocLen += BTF::SecOffsetRelocSize;
-OffsetRelocLen += OffsetRelocSec.second.size() * BTF::BPFOffsetRelocSize;
+  for (const auto &FieldRelocSec : FieldRelocTable) {
+FieldRelocLen += BTF::SecFieldRelocSize;
+FieldRelocLen += FieldRelocSec.second.size() * BTF::BPFFieldRelocSize;
   }
   for (const auto &ExternRelocSec : ExternRelocTable) {
 ExternRelocLen += BTF::SecExternRelocSize;
 ExternRelocLen += ExternRelocSec.second.size() * BTF::BPFExternRelocSize;
   }
 
-  if (OffsetRelocLen)
-OffsetRelocLen += 4;
+  if (FieldRelocLen)
+FieldRelocLen += 4;
   if (ExternRelocLen)
 ExternRelocLen += 4;
 
@@ -795,8 +795,8 @@
   OS.EmitIntValue(FuncLen, 4);
   OS.EmitIntValue(LineLen, 4);
   OS.EmitIntValue(FuncLen + LineLen, 4);
-  OS.EmitIntValue(OffsetRelocLen, 4);
-  OS.EmitIntValue(FuncLen + LineLen + OffsetRelocLen, 4);
+  OS.EmitIntValue(FieldRelocLen, 4);
+  OS.EmitIntValue(FuncLen + LineLen + FieldRelocLen, 4);
   OS.EmitIntValue(ExternRelocLen, 4);
 
   // Emit func_info table.
@@ -832,18 +832,19 @@
   }
 
   // Emit offset reloc table.
-  if (OffsetRelocLen) {
-OS.AddComment("OffsetReloc");
-OS.EmitIntValue(BTF::BPFOffsetRelocSize, 4);
-for (const auto &OffsetRelocSec : OffsetRelocTable) {
+  if (FieldRelocLen) {
+OS.AddComment("FieldReloc");
+OS.EmitIntValue(BTF::BPFFieldRelocSize, 4);
+for (const auto &FieldRelocSec : FieldRe

[PATCH] D67980: [WIP][CLANG][BPF] do compile-once run-everywhere relocation for bitfields

2019-10-05 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked 4 inline comments as done and an inline comment as not 
done.
yonghong-song added inline comments.



Comment at: llvm/lib/Target/BPF/BPFCORE.h:17
+  enum OffsetRelocKind : uint32_t {
+FIELD_ACCESS_OFFSET = 0,
+FIELD_EXISTENCE,

ast wrote:
> why ACCESS_OFFSET is necessary?
> Isn't it the same as BYTE_OFFSET but for non-bitfield?
> May be single kind will do?
This is the relocation type in the .BTF.ext. FIELD_ACCESS_OFFSET corresponds to 
odd offset relocation. The below newly added relocations are for field info.
I am using relocation enum except FIELD_ACCESS_OFFSET to be used for field_info 
in __builtin_preserve_field_info().



Comment at: llvm/lib/Target/BPF/BPFCORE.h:22
+FIELD_BYTE_OFFSET,
+FIELD_LSHIFT_64BIT_BUF,
+FIELD_RSHIFT_AFTER_LSHIFT_64BIT_BUF,

ast wrote:
> All these names are not added as builtin enum before compilation starts, 
> right?
> So C program cannot just use FIELD_BYTE_OFFSET and needs to define its own 
> enum first?
> How about FIELD_LSHIFT_U64 instead?
Yes, C programs should define its own enum to have corresponding values first.
Do not familiar within builtin enum's. Let me take a look.

FIELD_LSHIFT_U64 is shorter and looks good.



Comment at: llvm/lib/Target/BPF/BPFCORE.h:23
+FIELD_LSHIFT_64BIT_BUF,
+FIELD_RSHIFT_AFTER_LSHIFT_64BIT_BUF,
+

ast wrote:
> FIELD_RSHIFT_U64 ?
Yes, sounds better.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67980



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67980: [WIP][CLANG][BPF] do compile-once run-everywhere relocation for bitfields

2019-10-05 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

> All these names are not added as builtin enum before compilation starts, 
> right?

Do you prefer to have builtin enum? If we do this, we will emit this enum all 
the time,
regardless of whether people uses this builtin or not. Are you worried about API
stability?

I think defining explicitly in libbpf/btf.h probably a better choice? 
Defining commonly used macros like __bpf__ or __BPF__
makes more sense. Hidden enum's seems really rare.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67980



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67980: [WIP][CLANG][BPF] do compile-once run-everywhere relocation for bitfields

2019-10-05 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked an inline comment as done.
yonghong-song added inline comments.



Comment at: llvm/lib/Target/BPF/BPFCORE.h:17
+  enum OffsetRelocKind : uint32_t {
+FIELD_ACCESS_OFFSET = 0,
+FIELD_EXISTENCE,

yonghong-song wrote:
> ast wrote:
> > why ACCESS_OFFSET is necessary?
> > Isn't it the same as BYTE_OFFSET but for non-bitfield?
> > May be single kind will do?
> This is the relocation type in the .BTF.ext. FIELD_ACCESS_OFFSET corresponds 
> to odd offset relocation. The below newly added relocations are for field 
> info.
> I am using relocation enum except FIELD_ACCESS_OFFSET to be used for 
> field_info in __builtin_preserve_field_info().
Now I understand what you mean. Currently BYTE_OFFSET is calculated from the 
start of the last enclosing struct/union members while ACCESS_OFFSET could be 
the offset from outer struct/union like a.b.c.d.
Let me think whether we could consolidate two.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67980



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67980: [CLANG][BPF] do compile-once run-everywhere relocation for bitfields

2019-10-05 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 223405.
yonghong-song retitled this revision from "[WIP][CLANG][BPF] do compile-once 
run-everywhere relocation for bitfields" to "[CLANG][BPF] do compile-once 
run-everywhere relocation for bitfields".
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

fixed a few bugs from previous revision. Removed FIELD_ACCESS_OFFSET relocation 
which will be identical to FIELD_BYTE_OFFSET. All of these CORE related test 
cases are adjusted and passed now. Removed [WIP] prefix.
TODO: write new tests for the new functionality.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67980

Files:
  clang/include/clang/Basic/BuiltinsBPF.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TargetBuiltins.h
  clang/include/clang/Sema/Sema.h
  clang/include/clang/module.modulemap
  clang/lib/Basic/Targets/BPF.cpp
  clang/lib/Basic/Targets/BPF.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Sema/SemaChecking.cpp
  llvm/include/llvm/IR/IntrinsicsBPF.td
  llvm/lib/Target/BPF/BPF.h
  llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
  llvm/lib/Target/BPF/BPFCORE.h
  llvm/lib/Target/BPF/BPFTargetMachine.cpp
  llvm/lib/Target/BPF/BTF.h
  llvm/lib/Target/BPF/BTFDebug.cpp
  llvm/lib/Target/BPF/BTFDebug.h
  llvm/test/CodeGen/BPF/CORE/intrinsic-array.ll
  llvm/test/CodeGen/BPF/CORE/intrinsic-struct.ll
  llvm/test/CodeGen/BPF/CORE/intrinsic-union.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-access-str.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-basic.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-1.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-array-2.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-1.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-2.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-struct-3.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-1.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-cast-union-2.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-end-load.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-end-ret.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-global-1.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-global-2.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-global-3.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-ignore.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-middle-chain.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-1.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-multi-array-2.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-multilevel.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-1.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-pointer-2.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-struct.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-union.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll
  llvm/test/CodeGen/BPF/CORE/offset-reloc-union.ll

Index: llvm/test/CodeGen/BPF/CORE/offset-reloc-union.ll
===
--- llvm/test/CodeGen/BPF/CORE/offset-reloc-union.ll
+++ llvm/test/CodeGen/BPF/CORE/offset-reloc-union.ll
@@ -133,17 +133,18 @@
 ; CHECK-NEXT:.long   20
 ; CHECK-NEXT:.long   76
 ; CHECK-NEXT:.long   96
-; CHECK-NEXT:.long   24
-; CHECK-NEXT:.long   120
+; CHECK-NEXT:.long   28
+; CHECK-NEXT:.long   124
 ; CHECK-NEXT:.long   0
 ; CHECK-NEXT:.long   8   # FuncInfo
 
-; CHECK: .long   12  # OffsetReloc
-; CHECK-NEXT:.long   54  # Offset reloc section string offset=54
+; CHECK: .long   16  # FieldReloc
+; CHECK-NEXT:.long   54  # Field reloc section string offset=54
 ; CHECK-NEXT:.long   1
 ; CHECK-NEXT:.long   .Ltmp2
 ; CHECK-NEXT:.long   2
 ; CHECK-NEXT:.long   97
+; CHECK-NEXT:.long   0
 
 ; Function Attrs: argmemonly nounwind
 declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
Index: llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll
===
--- llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll
+++ llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll
@@ -45,12 +45,13 @@
 ; CHECK-NEXT:.byte   0
 ; CHECK: .ascii  "1:1:1" # string offset=[[ACCESS_STR:[0-9]+]]
 ; CHECK-NEXT:.byte   0
-; CHECK: .long   12  # OffsetReloc
-; CHECK-NEXT:.long   [[SEC_STR:[0-9]+]]  # Offset reloc section string offset=[[SEC_STR:[0-9]+]]
+; CHECK: .long   16  # FieldReloc
+; CHECK-

[PATCH] D69393: [RFC][DebugInfo] emit user specified address_space in dwarf

2019-10-24 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added reviewers: arsenm, aprantl, Anastasia, ast.
yonghong-song added a project: debug-info.
Herald added subscribers: cfe-commits, wdng.
Herald added a project: clang.

The RFC intends to kick off the discussion on how to support
user defined address_space attributes in dwarf.

The use case:
=

In linux kernel, under certain make flags, pointers may be
annotated with additional address_space information. The source
code is below:

  https://github.com/torvalds/linux/blob/master/include/linux/compiler_types.h

For example, we have

1. define __user   __attribute__((noderef, address_space(1)))
2. define __kernel __attribute__((address_space(0)))
3. define __iomem  __attribute__((noderef, address_space(2)))
4. define __percpu __attribute__((noderef, address_space(3)))
5. define __rcu__attribute__((noderef, address_space(4)))

Currently, the address_space annotation is not used when compiling
a normal (production) kernel. It is typically used during development
and used by 'sparse' tool to check proper pointer usage.

Now there is a growing need to put address_space info into debug info,
e.g., dwarf, in linux binary to help automatically differentiate
pointers accessing kernel and user memories in order to avoid
explicit user annotations like below:

  http://lkml.iu.edu/hypermail/linux/kernel/1905.1/05750.html

Other tracing tools like bpftrace, bcc would have similar issues.

The current patch
=

The proposal here is for user specified address_space, just add it
to DebugInfo and then later it will be automatically inserted into
dwarf. For example,

  -bash-4.4$ cat t.c
  #define __user __attribute__((noderef, address_space(3)))
  void __user *g;
  extern int __user *foo(int *a, int __user *b);
  int __user *foo(int *a, int __user *b) { return b; }
  -bash-4.4$ clang -O2 -g -c t.c
  -bash-4.4$ llvm-dwarfdump t.o
  ...
  0x002a:   DW_TAG_variable
DW_AT_name  ("g")
DW_AT_type  (0x0042 "*")
  0x0042:   DW_TAG_pointer_type
DW_AT_address_class (0x0003)
  0x0060: DW_TAG_formal_parameter
  DW_AT_name("a")
  DW_AT_type(0x0091 "int*")
  0x0071: DW_TAG_formal_parameter
  DW_AT_name("b")
  DW_AT_type(0x0081 "int*")
  0x0081:   DW_TAG_pointer_type
DW_AT_type  (0x008a "int")
DW_AT_address_class (0x0003)
  0x0091:   DW_TAG_pointer_type
DW_AT_type  (0x008a "int")
DW_AT_address_class (0x)

This patch mixed language address space and user defined address space
in the same debuginfo address_space and in the dwarf final encoding,
it is encoded as address_class which is more tailored into
language address_space.

Question:
=

This patch probably won't work as it mixed language address_space
and user address_space.

How we should proceed from here? Separate field in
IR DebugInfo and Dwarf for user defined address_space?


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D69393

Files:
  clang/lib/Basic/Targets/BPF.h
  clang/lib/Basic/Targets/X86.h


Index: clang/lib/Basic/Targets/X86.h
===
--- clang/lib/Basic/Targets/X86.h
+++ clang/lib/Basic/Targets/X86.h
@@ -257,6 +257,11 @@
 setFeatureEnabledImpl(Features, Name, Enabled);
   }
 
+  Optional
+  getDWARFAddressSpace(unsigned AddressSpace) const override {
+return AddressSpace;
+  }
+
   // This exists purely to cut down on the number of virtual calls in
   // initFeatureMap which calls this repeatedly.
   static void setFeatureEnabledImpl(llvm::StringMap &Features,
Index: clang/lib/Basic/Targets/BPF.h
===
--- clang/lib/Basic/Targets/BPF.h
+++ clang/lib/Basic/Targets/BPF.h
@@ -58,6 +58,11 @@
 
   ArrayRef getTargetBuiltins() const override;
 
+  Optional
+  getDWARFAddressSpace(unsigned AddressSpace) const override {
+return AddressSpace;
+  }
+
   const char *getClobbers() const override { return ""; }
 
   BuiltinVaListKind getBuiltinVaListKind() const override {


Index: clang/lib/Basic/Targets/X86.h
===
--- clang/lib/Basic/Targets/X86.h
+++ clang/lib/Basic/Targets/X86.h
@@ -257,6 +257,11 @@
 setFeatureEnabledImpl(Features, Name, Enabled);
   }
 
+  Optional
+  getDWARFAddressSpace(unsigned AddressSpace) const override {
+return AddressSpace;
+  }
+
   // This exists purely to cut down on the number of virtual calls in
   // initFeatureMap which calls this repeatedly.
   static void setFeatureEnabledImpl(llvm::StringMap &Features,
Index: clang/lib/Basic/Targets/BPF.h
===
--- clang/li

[PATCH] D69393: [RFC][DebugInfo] emit user specified address_space in dwarf

2019-10-24 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@probinson Thanks for the input! That is my concern too mixing the user defined 
and language defined may not be a good idea and may actually cause confusion. 
This is exactly this RFC for. Let us try a different dwarf encoding and then we 
can continue to discuss.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69393



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D83242: [clang][BPF] support expr with typedef/record type for FIELD_EXISTENCE reloc

2020-07-22 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

In D83242#2167721 , @anakryiko wrote:

> After thinking about this a bit more, I think adding a new TYPE_EXISTENCE 
> (instead of FIELD_EXISTENCE) relocation type is the better way to handle 
> this. It would allow Clang to be stricter as to what is passed into 
> FIELD_EXISTENCE (only fields, not types) vs TYPE_EXISTENCE(only types, no 
> fields). It will make it cleaner on libbpf side as well, because the 
> validation and relocation logic is different between handling fields and 
> types. So overall, I think it will be beneficial on every level of the stack 
> to separate them.  I hope it's not too hard to make this change?


Yes. Sounds better to separate them as they handle disjoint patterns. Will make 
the change.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D83242: [clang][BPF] support expr with typedef/record type for TYPE_EXISTENCE reloc

2020-07-22 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 280027.
yonghong-song retitled this revision from "[clang][BPF] support expr with 
typedef/record type for FIELD_EXISTENCE reloc" to "[clang][BPF] support expr 
with typedef/record type for TYPE_EXISTENCE reloc".
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

use a different reloc type TYPE_EXISTENCE (defined in 
llvm/lib/Target/BPF/BPFCORE.h) instead of old FIELD_EXISTENCE. This will 
simplify libbpf processing.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/Basic/TargetInfo.cpp
  clang/lib/Basic/Targets/BPF.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
  clang/test/Sema/builtins-bpf.c

Index: clang/test/Sema/builtins-bpf.c
===
--- clang/test/Sema/builtins-bpf.c
+++ clang/test/Sema/builtins-bpf.c
@@ -1,14 +1,27 @@
 // RUN: %clang_cc1 -x c -triple bpf-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
 
-struct s { int a; int b[4]; int c:1; };
-union u { int a; int b[4]; int c:1; };
+struct s {
+  int a;
+  int b[4];
+  int c:1;
+};
+union u {
+  int a;
+  int b[4];
+  int c:1;
+};
+typedef struct {
+  int a;
+  int b;
+} __t;
+typedef int (*__f)(void);
 
 unsigned invalid1(const int *arg) {
-  return __builtin_preserve_field_info(arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 not a field access}}
+  return __builtin_preserve_field_info(arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
 }
 
 unsigned invalid2(const int *arg) {
-  return __builtin_preserve_field_info(*arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 not a field access}}
+  return __builtin_preserve_field_info(*arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
 }
 
 void *invalid3(struct s *arg) {
@@ -46,3 +59,25 @@
 unsigned invalid11(struct s *arg, int info_kind) {
   return __builtin_preserve_field_info(arg->a, info_kind); // expected-error {{__builtin_preserve_field_info argument 2 not a constant}}
 }
+
+unsigned valid12() {
+  const struct s t = {};
+  return __builtin_preserve_field_info(t, 8);
+}
+
+unsigned valid13() {
+  return __builtin_preserve_field_info(*(struct s *)0, 8);
+}
+
+unsigned valid14() {
+  __t t = {};
+  return __builtin_preserve_field_info(t, 8);
+}
+
+unsigned valid15() {
+  return __builtin_preserve_field_info((const __f)0, 8);
+}
+
+unsigned invalid16(struct s *arg) {
+  return __builtin_preserve_field_info(arg->a + 2, 8); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
+}
Index: clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
===
--- /dev/null
+++ clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
@@ -0,0 +1,33 @@
+// REQUIRES: bpf-registered-target
+// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+
+#define _(x, y) (__builtin_preserve_field_info((x), (y)))
+
+struct s {
+  char a;
+};
+typedef struct {
+  char a;
+} __s1;
+
+typedef int (*__func)(void);
+
+unsigned unit1() {
+  const __s1 v = {};
+  return _(v, 8) + _(*(struct s *)0, 8);
+}
+
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0s_struct.__s1s(%struct.__s1* %{{[0-9a-z]+}}, i64 8), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[CONST_S1:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0s_struct.ss(%struct.s* null, i64 8), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S:[0-9]+]]
+
+unsigned unit2() {
+  __func f;
+  return _((__func)0, 8) + _(f, 8);
+}
+
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0f_i32f(i32 ()* null, i64 8), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0p0f_i32f(i32 ()** %{{[0-9a-z]+}}, i64 8), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF:[0-9]+]]
+
+// CHECK: ![[STRUCT_S]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s"
+// CHECK: ![[TYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__func"
+// CHECK: ![[CONST_S1]] = !DIDerivedType(tag: DW_TAG_const_type
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -2564,7 +2564,7 @@
CallExpr *TheCall) {
   assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
   BuiltinID == BPF::BI__builtin_btf_type_id) &&
- "unexpected ARM builtin");
+ "unexpected BPF builtin");
 
   if (checkArgCount(*this, TheCall, 2))
 return true;
@@ -2583,25 +2583,49 @@
 return false;
   }
 
-  // The first argument needs to be a

[PATCH] D83242: [clang][BPF] support expr with typedef/record type for TYPE_EXISTENCE reloc

2020-07-22 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

@anakryiko Please rebase on top of latest clang. There is a recent core change 
which touches BPF code which I am also modifying.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D83242: [clang][BPF] support type existence/size and enum value relocations

2020-07-28 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 281481.
yonghong-song retitled this revision from "[clang][BPF] support expr with 
typedef/record type for TYPE_EXISTENCE reloc" to "[clang][BPF] support type 
existence/size and enum value relocations".
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

support relocations for type_sizeof and enum_value as well.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/Basic/Targets/BPF.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins-bpf-preserve-field-info-1.c
  clang/test/CodeGen/builtins-bpf-preserve-field-info-2.c
  clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
  clang/test/Sema/builtins-bpf.c

Index: clang/test/Sema/builtins-bpf.c
===
--- clang/test/Sema/builtins-bpf.c
+++ clang/test/Sema/builtins-bpf.c
@@ -1,14 +1,36 @@
 // RUN: %clang_cc1 -x c -triple bpf-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
 
-struct s { int a; int b[4]; int c:1; };
-union u { int a; int b[4]; int c:1; };
+struct s {
+  int a;
+  int b[4];
+  int c:1;
+};
+union u {
+  int a;
+  int b[4];
+  int c:1;
+};
+typedef struct {
+  int a;
+  int b;
+} __t;
+typedef int (*__f)(void);
+enum AA {
+  VAL1 = 1,
+  VAL2 = 2,
+  VAL3 = 10,
+};
+typedef enum {
+  VAL10 = 10,
+  VAL11 = 11,
+} __BB;
 
 unsigned invalid1(const int *arg) {
-  return __builtin_preserve_field_info(arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 not a field access}}
+  return __builtin_preserve_field_info(arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
 }
 
 unsigned invalid2(const int *arg) {
-  return __builtin_preserve_field_info(*arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 not a field access}}
+  return __builtin_preserve_field_info(*arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
 }
 
 void *invalid3(struct s *arg) {
@@ -46,3 +68,38 @@
 unsigned invalid11(struct s *arg, int info_kind) {
   return __builtin_preserve_field_info(arg->a, info_kind); // expected-error {{__builtin_preserve_field_info argument 2 not a constant}}
 }
+
+unsigned valid12() {
+  const struct s t;
+  return __builtin_preserve_field_info(t, 8) +
+ __builtin_preserve_field_info(*(struct s *)0, 8);
+}
+
+unsigned valid13() {
+  __t t;
+  return __builtin_preserve_field_info(t, 8) +
+ __builtin_preserve_field_info(*(__t *)0, 8);
+}
+
+unsigned valid14() {
+  enum AA t;
+  return __builtin_preserve_field_info(t, 8) +
+ __builtin_preserve_field_info(*(enum AA *)0, 8);
+}
+
+unsigned invalid15() {
+  return __builtin_preserve_field_info(*(__BB *)2, 10); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
+}
+
+unsigned invalid16() {
+  return __builtin_preserve_field_info(*(__BB *)VAL3, 10); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
+}
+
+unsigned invalid17(struct s *arg) {
+  return __builtin_preserve_field_info(arg->a + 2, 8); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
+}
+
+unsigned invalid18() {
+  enum AA t = 1;
+  return __builtin_preserve_field_info(t, 10); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
+}
Index: clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
===
--- /dev/null
+++ clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
@@ -0,0 +1,55 @@
+// REQUIRES: bpf-registered-target
+// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+
+#define _(x, y) (__builtin_preserve_field_info((x), (y)))
+
+struct s {
+  char a;
+};
+typedef int __int;
+enum AA {
+  VAL1 = 1,
+  VAL2 = 2,
+};
+typedef enum AA __AA;
+
+unsigned unit1() {
+  struct s v = {};
+  return _(v, 8) + _(*(struct s *)0, 8);
+}
+
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0s_struct.ss(%struct.s* %{{[0-9a-z]+}}, i64 8), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0s_struct.ss(%struct.s* null, i64 8), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S]]
+
+unsigned unit2() {
+  __int n;
+  return _(n, 8) + _(*(__int *)0, 8);
+}
+
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0i32(i32* %{{[0-9a-z]+}}, i64 8), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF_INT:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0i32(i32* null, i64 8), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF_INT]]
+
+unsigned unit3() {
+  enum AA t;
+  return _(t, 8) + _(*(enum AA *)0, 8);
+}
+
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0i32(i32* %{{[0-9a-z]+}}, i64 8), !dbg !{{[0-9]+}}, !llvm.preserve.ac

[PATCH] D83242: [clang][BPF] support type existence/size and enum value relocations

2020-07-29 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

One potential missing relocation is to test whether a particular enum value 
(from an enum type) exists or not.

One way is to create a new relocation type ENUM_VALUE_EXISTENCE where 
"access_string" to encode the enum value. This is different from TYPE_EXISTENCE 
for enum type where the "access_string" is "0".

Alternatively, we could have TYPE_EXISTENCE to include enum value existence as 
well. "access_string" is say "0" for typedef/record/enum types and 
"0:" for enum value.

WDYT?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D83242: [clang][BPF] support type exist/size and enum exist/value relocations

2020-07-30 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 281933.
yonghong-song retitled this revision from "[clang][BPF] support type 
existence/size and enum value relocations" to "[clang][BPF] support type 
exist/size and enum exist/value relocations".
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

use a different __builtin function for new relocations to they are easily 
discoverable in user space and this also make implementation more structured.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242

Files:
  clang/include/clang/Basic/BuiltinsBPF.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
  clang/test/CodeGen/builtins-bpf-preserve-field-info-4.c
  clang/test/Sema/builtins-bpf.c
  llvm/include/llvm/IR/IntrinsicsBPF.td

Index: llvm/include/llvm/IR/IntrinsicsBPF.td
===
--- llvm/include/llvm/IR/IntrinsicsBPF.td
+++ llvm/include/llvm/IR/IntrinsicsBPF.td
@@ -26,4 +26,10 @@
   def int_bpf_btf_type_id : GCCBuiltin<"__builtin_bpf_btf_type_id">,
   Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_any_ty, llvm_i64_ty],
   [IntrNoMem]>;
+  def int_bpf_preserve_type_info : GCCBuiltin<"__builtin_bpf_preserve_type_info">,
+  Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_any_ty, llvm_i64_ty],
+  [IntrNoMem]>;
+  def int_bpf_preserve_enum_value : GCCBuiltin<"__builtin_bpf_preserve_enum_value">,
+  Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_any_ty, llvm_i64_ty],
+  [IntrNoMem]>;
 }
Index: clang/test/Sema/builtins-bpf.c
===
--- clang/test/Sema/builtins-bpf.c
+++ clang/test/Sema/builtins-bpf.c
@@ -1,7 +1,29 @@
 // RUN: %clang_cc1 -x c -triple bpf-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
 
-struct s { int a; int b[4]; int c:1; };
-union u { int a; int b[4]; int c:1; };
+struct s {
+  int a;
+  int b[4];
+  int c:1;
+};
+union u {
+  int a;
+  int b[4];
+  int c:1;
+};
+typedef struct {
+  int a;
+  int b;
+} __t;
+typedef int (*__f)(void);
+enum AA {
+  VAL1 = 1,
+  VAL2 = 2,
+  VAL3 = 10,
+};
+typedef enum {
+  VAL10 = 10,
+  VAL11 = 11,
+} __BB;
 
 unsigned invalid1(const int *arg) {
   return __builtin_preserve_field_info(arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 not a field access}}
@@ -46,3 +68,38 @@
 unsigned invalid11(struct s *arg, int info_kind) {
   return __builtin_preserve_field_info(arg->a, info_kind); // expected-error {{__builtin_preserve_field_info argument 2 not a constant}}
 }
+
+unsigned valid12() {
+  const struct s t;
+  return __builtin_preserve_type_info(t, 0) +
+ __builtin_preserve_type_info(*(struct s *)0, 1);
+}
+
+unsigned valid13() {
+  __t t;
+  return __builtin_preserve_type_info(t, 1) +
+ __builtin_preserve_type_info(*(__t *)0, 0);
+}
+
+unsigned valid14() {
+  enum AA t;
+  return __builtin_preserve_type_info(t, 0) +
+ __builtin_preserve_type_info(*(enum AA *)0, 1);
+}
+
+unsigned valid15() {
+  return __builtin_preserve_enum_value(*(enum AA *)VAL2, 1) +
+ __builtin_preserve_enum_value(*(__BB *)10, 0);
+}
+
+unsigned invalid16() {
+  return __builtin_preserve_enum_value(*(enum AA *)0, 1); // expected-error {{__builtin_preserve_enum_value argument 1 invalid}}
+}
+
+unsigned invalid17() {
+  return __builtin_preserve_enum_value(*(enum AA *)VAL10, 1); // expected-error {{__builtin_preserve_enum_value argument 1 invalid}}
+}
+
+unsigned invalid18(struct s *arg) {
+  return __builtin_preserve_type_info(arg->a + 2, 0); // expected-error {{__builtin_preserve_type_info argument 1 invalid}}
+}
Index: clang/test/CodeGen/builtins-bpf-preserve-field-info-4.c
===
--- /dev/null
+++ clang/test/CodeGen/builtins-bpf-preserve-field-info-4.c
@@ -0,0 +1,20 @@
+// REQUIRES: bpf-registered-target
+// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+
+#define _(x, y) (__builtin_preserve_enum_value((x), (y)))
+
+enum AA {
+  VAL1 = 1,
+  VAL2 = 2,
+};
+typedef enum AA __AA;
+
+unsigned unit1() {
+  return _(*(enum AA *)VAL2, 0) + _(*(__AA *)2, 1);
+}
+
+// CHECK: call i32 @llvm.bpf.preserve.enum.value.p0i32.i32(i32* inttoptr (i64 2 to i32*), i32 1, i64 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ENUM_AA:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.preserve.enum.value.p0i32.i32(i32* inttoptr (i64 2 to i32*), i32 1, i64 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF_ENUM:[0-9]+]]
+
+// CHECK: ![[ENUM_AA]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "AA"
+// CHECK: ![[TYPEDEF_ENUM]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__AA"
Index: clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
=

[PATCH] D81131: [DebugInfo] Fix assertion for extern void type

2020-06-03 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added a reviewer: dblaikie.
yonghong-song added a project: debug-info.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Commit d77ae1552fc2 
 
("[DebugInfo] Support to emit debugInfo
for extern variables") added support to emit debuginfo
for extern variables.

But if the extern variable has "void" type, the compilation will
fail.

  -bash-4.4$ cat t.c 
  extern void bla;
  void *test() {
void *x = &bla;
return x;
  }
  -bash-4.4$ clang -target bpf -g -O2 -S t.c 
  missing global variable type
  !1 = distinct !DIGlobalVariable(name: "bla", scope: !2, file: !3, line: 1,
  isLocal: false, isDefinition: false)
  ... 
  fatal error: error in backend: Broken module found, compilation aborted!
  PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash 
backtrace,
  preprocessed source, and associated run script.
  Stack dump:
  ... 

The IR requires a DIGlobalVariable must have a valid type and the 
"void" type does not generate any type, hence the above fatal error.

Note that if the extern variable is defined as "const void", the 
compilation will succeed.

  -bash-4.4$ cat t.c
  extern const void bla;
  const void *test() {
const void *x = &bla;
return x;
  }
  -bash-4.4$ clang -target bpf -g -O2 -S t.c
  -bash-4.4$ cat t.ll
  ...
  !1 = distinct !DIGlobalVariable(name: "bla", scope: !2, file: !3, line: 1,
  type: !6, isLocal: false, isDefinition: false)
  !6 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null)
  ...

It might be the expected behavior not to generate debuginfo for 
extern "void" variables. But the fatal error (with assert on) is not 
nice.

The patch simply skipped the debuginfo if the extern variable has 
"void" type. This might be not be the right way to do it. Maybe
we should error out during parsing or sematic analysis stage.
Or maybe we should allow DIGlobalVariable with extern void type.
Your advice/suggestion for the next step is appreciated.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D81131

Files:
  clang/lib/CodeGen/CodeGenModule.cpp


Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -4198,16 +4198,23 @@
 }
 
 void CodeGenModule::EmitExternalVarDeclaration(const VarDecl *D) {
-  if (CGDebugInfo *DI = getModuleDebugInfo())
-if (getCodeGenOpts().hasReducedDebugInfo()) {
-  QualType ASTTy = D->getType();
-  llvm::Type *Ty = getTypes().ConvertTypeForMem(D->getType());
-  llvm::PointerType *PTy =
-  llvm::PointerType::get(Ty, 
getContext().getTargetAddressSpace(ASTTy));
-  llvm::Constant *GV = GetOrCreateLLVMGlobal(D->getName(), PTy, D);
-  DI->EmitExternalVariable(
-  cast(GV->stripPointerCasts()), D);
-}
+  if (CGDebugInfo *DI = getModuleDebugInfo()) {
+if (!getCodeGenOpts().hasReducedDebugInfo())
+  return;
+
+// The DIGlobalVariable must have a type, skip the generation
+// if the underlying type is void without any qualifiers.
+QualType ASTTy = D->getType();
+if (!ASTTy.hasQualifiers() && ASTTy.getTypePtr()->isVoidType())
+  return;
+
+llvm::Type *Ty = getTypes().ConvertTypeForMem(D->getType());
+llvm::PointerType *PTy =
+llvm::PointerType::get(Ty, getContext().getTargetAddressSpace(ASTTy));
+llvm::Constant *GV = GetOrCreateLLVMGlobal(D->getName(), PTy, D);
+DI->EmitExternalVariable(
+cast(GV->stripPointerCasts()), D);
+  }
 }
 
 static bool isVarDeclStrongDefinition(const ASTContext &Context,


Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -4198,16 +4198,23 @@
 }
 
 void CodeGenModule::EmitExternalVarDeclaration(const VarDecl *D) {
-  if (CGDebugInfo *DI = getModuleDebugInfo())
-if (getCodeGenOpts().hasReducedDebugInfo()) {
-  QualType ASTTy = D->getType();
-  llvm::Type *Ty = getTypes().ConvertTypeForMem(D->getType());
-  llvm::PointerType *PTy =
-  llvm::PointerType::get(Ty, getContext().getTargetAddressSpace(ASTTy));
-  llvm::Constant *GV = GetOrCreateLLVMGlobal(D->getName(), PTy, D);
-  DI->EmitExternalVariable(
-  cast(GV->stripPointerCasts()), D);
-}
+  if (CGDebugInfo *DI = getModuleDebugInfo()) {
+if (!getCodeGenOpts().hasReducedDebugInfo())
+  return;
+
+// The DIGlobalVariable must have a type, skip the generation
+// if the underlying type is void without any qualifiers.
+QualType ASTTy = D->getType();
+if (!ASTTy.hasQualifiers() && ASTTy.getTypePtr()->isVoidType())
+  return;
+
+llvm::Type *Ty = getTypes().ConvertTypeForMem(D->getType());
+

[PATCH] D81131: [DebugInfo] Fix assertion for extern void type

2020-06-04 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

Thanks, @dblaikie

>> I think if we're going to support "const void" we should support "void" too 
>> & fix the verifier to allow this & make sure LLVM produces the correct debug 
>> info for it (which is probably a DW_TAG_variable without a DW_AT_type 
>> attribute (same as a function with a void return type has no DW_AT_type 
>> attribute) - and check that GCC does the same thing.

Your suggestion makes sense, I will try to fix the fatal error according to 
what you suggested.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81131



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D81131: [DebugInfo] Fix assertion for extern void type

2020-06-05 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 268995.
yonghong-song edited the summary of this revision.
yonghong-song added a comment.
Herald added subscribers: llvm-commits, hiraditya, aprantl.
Herald added a project: LLVM.

instead of skipping generating debuginfo for "extern void var_name", do 
generate debuginfo and skip emitting dwarf types for it.
cc @dblaikie


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81131

Files:
  llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
  llvm/lib/IR/Verifier.cpp
  llvm/test/DebugInfo/BPF/extern-void.ll
  llvm/test/DebugInfo/BPF/lit.local.cfg

Index: llvm/test/DebugInfo/BPF/lit.local.cfg
===
--- /dev/null
+++ llvm/test/DebugInfo/BPF/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'BPF' in config.root.targets:
+config.unsupported = True
Index: llvm/test/DebugInfo/BPF/extern-void.ll
===
--- /dev/null
+++ llvm/test/DebugInfo/BPF/extern-void.ll
@@ -0,0 +1,81 @@
+; 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 void bla1;
+;   void *test1() {
+; void *x = &bla1;
+; return x;
+;   }
+;
+;   extern const void bla2;
+;   const void *test2() {
+; const void *x = &bla2;
+; return x;
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm t.c
+
+@bla1 = external dso_local global i8, align 1, !dbg !0
+@bla2 = external dso_local constant i8, align 1, !dbg !6
+
+; Function Attrs: norecurse nounwind readnone
+define dso_local nonnull i8* @test1() local_unnamed_addr #0 !dbg !13 {
+entry:
+  call void @llvm.dbg.value(metadata i8* @bla1, metadata !18, metadata !DIExpression()), !dbg !19
+  ret i8* @bla1, !dbg !20
+}
+
+; Function Attrs: norecurse nounwind readnone
+define dso_local nonnull i8* @test2() local_unnamed_addr #0 !dbg !21 {
+entry:
+  call void @llvm.dbg.value(metadata i8* @bla2, metadata !26, metadata !DIExpression()), !dbg !27
+  ret i8* @bla2, !dbg !28
+}
+
+; CHECK:.quad bla1
+; CHECK-NEXT:   DW_TAG_variable
+;
+; CHECK:.quad   bla2
+; CHECK-NEXT:   DW_TAG_const_type
+; CHECK-NEXT:   DW_TAG_subprogram
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { norecurse nounwind readnone "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"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone speculatable willreturn }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!9, !10, !11}
+!llvm.ident = !{!12}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "bla1", scope: !2, file: !3, line: 1, isLocal: false, isDefinition: false)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0 (https://github.com/llvm/llvm-project.git 8a8c6913a931e8bbd119012f4badd81155a0f48a)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp3")
+!4 = !{}
+!5 = !{!0, !6}
+!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = distinct !DIGlobalVariable(name: "bla2", scope: !2, file: !3, line: 7, type: !8, isLocal: false, isDefinition: false)
+!8 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null)
+!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 11.0.0 (https://github.com/llvm/llvm-project.git 8a8c6913a931e8bbd119012f4badd81155a0f48a)"}
+!13 = distinct !DISubprogram(name: "test1", scope: !3, file: !3, line: 2, type: !14, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !17)
+!14 = !DISubroutineType(types: !15)
+!15 = !{!16}
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!17 = !{!18}
+!18 = !DILocalVariable(name: "x", scope: !13, file: !3, line: 3, type: !16)
+!19 = !DILocation(line: 0, scope: !13)
+!20 = !DILocation(line: 4, column: 3, scope: !13)
+!21 = distinct !DISubprogram(name: "test2", scope: !3, file: !3, line: 8, type: !22, scopeLine: 8, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !25)
+!22 = !DISubroutineType(types: !23)
+!23 = !{!24}
+!24 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, si

[PATCH] D81131: [DebugInfo] Fix assertion for extern void type

2020-06-08 Thread Yonghong Song via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3eb465a329e2: [DebugInfo] Fix assertion for extern void type 
(authored by yonghong-song).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81131

Files:
  llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
  llvm/lib/IR/Verifier.cpp
  llvm/test/DebugInfo/BPF/extern-void.ll
  llvm/test/DebugInfo/BPF/lit.local.cfg

Index: llvm/test/DebugInfo/BPF/lit.local.cfg
===
--- /dev/null
+++ llvm/test/DebugInfo/BPF/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'BPF' in config.root.targets:
+config.unsupported = True
Index: llvm/test/DebugInfo/BPF/extern-void.ll
===
--- /dev/null
+++ llvm/test/DebugInfo/BPF/extern-void.ll
@@ -0,0 +1,81 @@
+; 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 void bla1;
+;   void *test1() {
+; void *x = &bla1;
+; return x;
+;   }
+;
+;   extern const void bla2;
+;   const void *test2() {
+; const void *x = &bla2;
+; return x;
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm t.c
+
+@bla1 = external dso_local global i8, align 1, !dbg !0
+@bla2 = external dso_local constant i8, align 1, !dbg !6
+
+; Function Attrs: norecurse nounwind readnone
+define dso_local nonnull i8* @test1() local_unnamed_addr #0 !dbg !13 {
+entry:
+  call void @llvm.dbg.value(metadata i8* @bla1, metadata !18, metadata !DIExpression()), !dbg !19
+  ret i8* @bla1, !dbg !20
+}
+
+; Function Attrs: norecurse nounwind readnone
+define dso_local nonnull i8* @test2() local_unnamed_addr #0 !dbg !21 {
+entry:
+  call void @llvm.dbg.value(metadata i8* @bla2, metadata !26, metadata !DIExpression()), !dbg !27
+  ret i8* @bla2, !dbg !28
+}
+
+; CHECK:.quad bla1
+; CHECK-NEXT:   DW_TAG_variable
+;
+; CHECK:.quad   bla2
+; CHECK-NEXT:   DW_TAG_const_type
+; CHECK-NEXT:   DW_TAG_subprogram
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { norecurse nounwind readnone "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"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone speculatable willreturn }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!9, !10, !11}
+!llvm.ident = !{!12}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "bla1", scope: !2, file: !3, line: 1, isLocal: false, isDefinition: false)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0 (https://github.com/llvm/llvm-project.git 8a8c6913a931e8bbd119012f4badd81155a0f48a)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp3")
+!4 = !{}
+!5 = !{!0, !6}
+!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = distinct !DIGlobalVariable(name: "bla2", scope: !2, file: !3, line: 7, type: !8, isLocal: false, isDefinition: false)
+!8 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null)
+!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 11.0.0 (https://github.com/llvm/llvm-project.git 8a8c6913a931e8bbd119012f4badd81155a0f48a)"}
+!13 = distinct !DISubprogram(name: "test1", scope: !3, file: !3, line: 2, type: !14, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !17)
+!14 = !DISubroutineType(types: !15)
+!15 = !{!16}
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!17 = !{!18}
+!18 = !DILocalVariable(name: "x", scope: !13, file: !3, line: 3, type: !16)
+!19 = !DILocation(line: 0, scope: !13)
+!20 = !DILocation(line: 4, column: 3, scope: !13)
+!21 = distinct !DISubprogram(name: "test2", scope: !3, file: !3, line: 8, type: !22, scopeLine: 8, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !25)
+!22 = !DISubroutineType(types: !23)
+!23 = !{!24}
+!24 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64)
+!25 = !{!26}
+!26 = !DILocalVariable(name: "x", scope: !21, file: !3, line: 9, type: !24)
+!27 = !DILocation(line: 0, scope: !21)
+!28 = !DILocation(line: 10, column: 3, scope:

[PATCH] D81479: [BPF] introduce __builtin_load_u32_to_ptr() intrinsic

2020-06-09 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added a reviewer: ast.
Herald added projects: clang, LLVM.
Herald added a subscriber: llvm-commits.

In current linux BPF uapi

  https://github.com/torvalds/linux/blob/master/include/uapi/linux/bpf.h

`struct __sk_buff/xdp_md` have fields

  __u32 data;
  __u32 data_end;
  __u32 data_meta;

which actually represent pointers. Typically in bpf program, users
write the following:

  void *data = (void *)(long)__sk_buff->data;

The kernel verifier magically copied the address to the target
64bit register for __sk_buff->data and hope nothing is messed up
and it can survive to the variable "data".

In the past, we have seen a few issues with this. For example,
for the above C code, the IR looks like:

  i32_v = load u32
  i64_v = zext i32_v
  ...

The BPF backend has tried, through InstrInfo.td pattern matching or
optimization in MachineInstr SSA analysis and transformation,
to recognize the above pattern to remove zext so the really "addr"
is preserved. But this is still fragile and in the past, we have
to fix multiple bugs due to other changes in BPF backend. The
optimization may not cover all possible cases. Some users may even
use inline assembly to work around potentially missed compiler
zext elimination.

The patch introduced the following builtin function for bpf target:

  void *ptr = __builtin_load_u32_to_ptr(void *base, int offset);

The builtin will perform a 32bit load with address "base + offset"
and the result, with zext, will be returned. This way, user is
guaranteed a correct address.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D81479

Files:
  clang/include/clang/Basic/BuiltinsBPF.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtin-bpf-load-u32-to-ptr.c
  clang/test/Sema/builtin-bpf-load-u32-to-ptr.c
  llvm/include/llvm/IR/IntrinsicsBPF.td

Index: llvm/include/llvm/IR/IntrinsicsBPF.td
===
--- llvm/include/llvm/IR/IntrinsicsBPF.td
+++ llvm/include/llvm/IR/IntrinsicsBPF.td
@@ -26,4 +26,6 @@
   def int_bpf_btf_type_id : GCCBuiltin<"__builtin_bpf_btf_type_id">,
   Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_any_ty, llvm_i64_ty],
   [IntrNoMem]>;
+  def int_bpf_load_u32_to_ptr : GCCBuiltin<"__builtin_bpf_load_u32_to_ptr">,
+  Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>;
 }
Index: clang/test/Sema/builtin-bpf-load-u32-to-ptr.c
===
--- /dev/null
+++ clang/test/Sema/builtin-bpf-load-u32-to-ptr.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -x c -triple bpf-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
+
+struct t { int a; int b; };
+
+void *invalid1(struct t *arg) { return __builtin_load_u32_to_ptr(arg, arg->a); } // expected-error {{__builtin_load_u32_to_ptr argument 2 not a constant}}
+void *invalid2(struct t *arg) { return __builtin_load_u32_to_ptr(arg + 4); } // expected-error {{too few arguments to function call, expected 2, have 1}}
+void *invalid3(struct t *arg) { return __builtin_load_u32_to_ptr(arg, 4, 0); } // expected-error {{too many arguments to function call, expected 2, have 3}}
+unsigned invalid4(struct t *arg) { return __builtin_load_u32_to_ptr(arg, 4); } // expected-warning {{incompatible pointer to integer conversion returning 'void *' from a function with result type 'unsigned int'}}
+
+void *valid1(struct t *arg) { return __builtin_load_u32_to_ptr(arg, 4); }
Index: clang/test/CodeGen/builtin-bpf-load-u32-to-ptr.c
===
--- /dev/null
+++ clang/test/CodeGen/builtin-bpf-load-u32-to-ptr.c
@@ -0,0 +1,8 @@
+// REQUIRES: bpf-registered-target
+// RUN: %clang -target bpf -emit-llvm -S %s -o - | FileCheck %s
+
+struct t { int a; int b; };
+void *test(struct t *arg) { return __builtin_load_u32_to_ptr(arg, 4); }
+
+// CHECK: define dso_local i8* @test
+// CHECK: call i8* @llvm.bpf.load.u32.to.ptr(i8* %{{[0-9a-z.]+}}, i64 4)
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -2501,13 +2501,28 @@
 bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
   assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
-  BuiltinID == BPF::BI__builtin_btf_type_id) &&
- "unexpected ARM builtin");
+  BuiltinID == BPF::BI__builtin_btf_type_id ||
+  BuiltinID == BPF::BI__builtin_load_u32_to_ptr) &&
+ "unexpected BPF builtin");
+
+  // Generic checking has done basic checking against the
+  // signature, here only to ensure the second argument
+  // be a constant.
+  Expr *Arg;
+  if (BuiltinID == BPF::BI__builtin_load_u32_to_ptr) {
+llvm::APSInt Value;

[PATCH] D81479: [BPF] introduce __builtin_load_u32_to_ptr() intrinsic

2020-06-09 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

The corresponding llvm change: https://reviews.llvm.org/D81480


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81479



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D81479: [BPF] introduce __builtin_load_u32_to_ptr() intrinsic

2020-06-09 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song marked an inline comment as done.
yonghong-song added inline comments.



Comment at: clang/test/CodeGen/builtin-bpf-load-u32-to-ptr.c:5
+struct t { int a; int b; };
+void *test(struct t *arg) { return __builtin_load_u32_to_ptr(arg, 4); }
+

ast wrote:
> can it be expressed as:
> __builtin_load_u32_to_ptr(&arg->b) ?
Good question. If this, we will have code like
   tmp = ctx + 76
   void *ptr = *(u32 *)(tmp + 0)

IIRC, the verifier does not like this. The verifier prefers `ctx + offset`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81479



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D81479: [BPF] introduce __builtin_load_u32_to_ptr() intrinsic

2020-06-09 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

In D81479#2083510 , @anakryiko wrote:

> IntrinsicsBPF.td uses `__builtin_bpf_load_u32_to_ptr`, while everywhere it is 
> just `__builtin_load_u32_to_ptr`. I think having bpf prefix there is good, 
> given this is bpf-specific. But either way, probably should be consistent 
> everywhere?


Sounds good. This is indeed specific to bpf, adding bpf prefix to the public 
builtin name sounds reasonable.  Will make the change.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81479



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D81479: [BPF] introduce __builtin_bpf_load_u32_to_ptr() intrinsic

2020-06-09 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 269721.
yonghong-song retitled this revision from "[BPF] introduce 
__builtin_load_u32_to_ptr() intrinsic" to "[BPF] introduce 
__builtin_bpf_load_u32_to_ptr() intrinsic".
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

change builtin name from __builtin_load_u32_to_ptr to 
__builtin_bpf_load_u32_to_ptr to reflect it is bpf specific.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81479

Files:
  clang/include/clang/Basic/BuiltinsBPF.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtin-bpf-load-u32-to-ptr.c
  clang/test/Sema/builtin-bpf-load-u32-to-ptr.c
  llvm/include/llvm/IR/IntrinsicsBPF.td

Index: llvm/include/llvm/IR/IntrinsicsBPF.td
===
--- llvm/include/llvm/IR/IntrinsicsBPF.td
+++ llvm/include/llvm/IR/IntrinsicsBPF.td
@@ -26,4 +26,6 @@
   def int_bpf_btf_type_id : GCCBuiltin<"__builtin_bpf_btf_type_id">,
   Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_any_ty, llvm_i64_ty],
   [IntrNoMem]>;
+  def int_bpf_load_u32_to_ptr : GCCBuiltin<"__builtin_bpf_load_u32_to_ptr">,
+  Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>;
 }
Index: clang/test/Sema/builtin-bpf-load-u32-to-ptr.c
===
--- /dev/null
+++ clang/test/Sema/builtin-bpf-load-u32-to-ptr.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -x c -triple bpf-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
+
+struct t { int a; int b; };
+
+void *invalid1(struct t *arg) { return __builtin_bpf_load_u32_to_ptr(arg, arg->a); } // expected-error {{__builtin_bpf_load_u32_to_ptr argument 2 not a constant}}
+void *invalid2(struct t *arg) { return __builtin_bpf_load_u32_to_ptr(arg + 4); } // expected-error {{too few arguments to function call, expected 2, have 1}}
+void *invalid3(struct t *arg) { return __builtin_bpf_load_u32_to_ptr(arg, 4, 0); } // expected-error {{too many arguments to function call, expected 2, have 3}}
+unsigned invalid4(struct t *arg) { return __builtin_bpf_load_u32_to_ptr(arg, 4); } // expected-warning {{incompatible pointer to integer conversion returning 'void *' from a function with result type 'unsigned int'}}
+
+void *valid1(struct t *arg) { return __builtin_bpf_load_u32_to_ptr(arg, 4); }
Index: clang/test/CodeGen/builtin-bpf-load-u32-to-ptr.c
===
--- /dev/null
+++ clang/test/CodeGen/builtin-bpf-load-u32-to-ptr.c
@@ -0,0 +1,8 @@
+// REQUIRES: bpf-registered-target
+// RUN: %clang -target bpf -emit-llvm -S %s -o - | FileCheck %s
+
+struct t { int a; int b; };
+void *test(struct t *arg) { return __builtin_bpf_load_u32_to_ptr(arg, 4); }
+
+// CHECK: define dso_local i8* @test
+// CHECK: call i8* @llvm.bpf.load.u32.to.ptr(i8* %{{[0-9a-z.]+}}, i64 4)
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -2501,13 +2501,28 @@
 bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
   assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
-  BuiltinID == BPF::BI__builtin_btf_type_id) &&
- "unexpected ARM builtin");
+  BuiltinID == BPF::BI__builtin_btf_type_id ||
+  BuiltinID == BPF::BI__builtin_bpf_load_u32_to_ptr) &&
+ "unexpected BPF builtin");
+
+  // Generic checking has done basic checking against the
+  // signature, here only to ensure the second argument
+  // be a constant.
+  Expr *Arg;
+  if (BuiltinID == BPF::BI__builtin_bpf_load_u32_to_ptr) {
+llvm::APSInt Value;
+Arg = TheCall->getArg(1);
+if (!Arg->isIntegerConstantExpr(Value, Context)) {
+  Diag(Arg->getBeginLoc(), diag::err_bpf_load_u32_to_ptr_not_const)
+  << 2 << Arg->getSourceRange();
+  return true;
+}
+return false;
+  }
 
   if (checkArgCount(*this, TheCall, 2))
 return true;
 
-  Expr *Arg;
   if (BuiltinID == BPF::BI__builtin_btf_type_id) {
 // The second argument needs to be a constant int
 llvm::APSInt Value;
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -10685,7 +10685,8 @@
 Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
   assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
-  BuiltinID == BPF::BI__builtin_btf_type_id) &&
+  BuiltinID == BPF::BI__builtin_btf_type_id ||
+  BuiltinID == BPF::BI__builtin_bpf_load_u32_to_ptr) &&
  "unexpect

[PATCH] D81479: [BPF] introduce __builtin_bpf_load_u32_to_ptr() intrinsic

2020-06-09 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

In D81479#2083933 , @ast wrote:

> It feels that the same thing can be represented as inline asm.
>  What advantage builtin has?


Yes, this can be represented as an inline asm. I have a tendency not liking 
inline assembly codes in bpf programs.
But maybe for this one, we could hide inline asm in the header and provide the 
same signature like
__builtin_bpf_load_u32_to_ptr() to users.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81479



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D81479: [BPF] introduce __builtin_bpf_load_u32_to_ptr() intrinsic

2020-06-09 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

I guess I will go with inline asm in kernel for now as llvm seems already doing 
a pretty good job parsing/understanding inline asm to integrated into 
optimization passes. A few passes like SimplifyCFG, GVN, etc. may have some 
impact but probably does not really matter for the use case here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D81479



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D83242: [RFC][BPF] support expr with typedef type for FIELD_EXISTENCE reloc

2020-07-06 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added reviewers: anakryiko, ast.
Herald added subscribers: llvm-commits, cfe-commits, hiraditya.
Herald added projects: clang, LLVM.

[The patch needs more work e.g. to create proper test, to be agreed on 
interface, etc.]

This patch added support of expression with typedef type
for FIELD_EXISTENCE relocation. This tries to address the 
following use case:

  enum { FIELD_EXISTENCE = 2, };
  typedef unsigned long u64;
  typedef unsigned int u32;
  struct bpf_perf_event_data_kern;
  typedef u64 (*btf_bpf_read_branch_records)(struct bpf_perf_event_data_kern *, 
void *, u32, u64);
  int test() {
 btf_bpf_read_branch_records a;
 return __builtin_preserve_field_info(a, FIELD_EXISTENCE);
  }

A relocation with a type of typedef 'btf_bpf_read_branch_records' will be
recorded.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D83242

Files:
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp


Index: llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
===
--- llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
+++ llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
@@ -277,7 +277,7 @@
   }
   if (GV->getName().startswith("llvm.bpf.preserve.field.info")) {
 CInfo.Kind = BPFPreserveFieldInfoAI;
-CInfo.Metadata = nullptr;
+CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index);
 // Check validity of info_kind as clang did not check this.
 uint64_t InfoKind = getConstant(Call->getArgOperand(1));
 if (InfoKind >= BPFCoreSharedInfo::MAX_FIELD_RELOC_KIND)
@@ -742,6 +742,13 @@
   break;
 }
 
+if (CInfo.Kind == BPFPreserveFieldInfoAI) {
+  // typedef type.
+  TypeName = std::string(PossibleTypeDef->getName());
+  TypeMeta = PossibleTypeDef;
+  break;
+}
+
 assert(CInfo.Kind == BPFPreserveArrayAI);
 
 // Array entries will always be consumed for accumulative initial index.
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -2582,6 +2582,15 @@
 return false;
   }
 
+  // The second argument needs to be a constant int
+  Arg = TheCall->getArg(1);
+  llvm::APSInt Value;
+  if (!Arg->isIntegerConstantExpr(Value, Context)) {
+Diag(Arg->getBeginLoc(), diag::err_preserve_field_info_not_const)
+<< 2 << Arg->getSourceRange();
+return true;
+  }
+
   // The first argument needs to be a record field access.
   // If it is an array element access, we delay decision
   // to BPF backend to check whether the access is a
@@ -2590,21 +2599,14 @@
   if (Arg->getType()->getAsPlaceholderType() ||
   (Arg->IgnoreParens()->getObjectKind() != OK_BitField &&
!dyn_cast(Arg->IgnoreParens()) &&
-   !dyn_cast(Arg->IgnoreParens( {
+   !dyn_cast(Arg->IgnoreParens()) &&
+   // Value 2 here represents reloc kind FIELD_EXISTENCE.
+   (Value != 2 || !Arg->getType()->getAs( {
 Diag(Arg->getBeginLoc(), diag::err_preserve_field_info_not_field)
 << 1 << Arg->getSourceRange();
 return true;
   }
 
-  // The second argument needs to be a constant int
-  Arg = TheCall->getArg(1);
-  llvm::APSInt Value;
-  if (!Arg->isIntegerConstantExpr(Value, Context)) {
-Diag(Arg->getBeginLoc(), diag::err_preserve_field_info_not_const)
-<< 2 << Arg->getSourceRange();
-return true;
-  }
-
   TheCall->setType(Context.UnsignedIntTy);
   return false;
 }
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -10966,11 +10966,17 @@
 ConstantInt *C = cast(EmitScalarExpr(E->getArg(1)));
 Value *InfoKind = ConstantInt::get(Int64Ty, C->getSExtValue());
 
+llvm::DIType *DbgInfo =
+getDebugInfo()->getOrCreateStandaloneType(E->getArg(0)->getType(),
+  E->getArg(0)->getExprLoc());
+
 // Built the IR for the preserve_field_info intrinsic.
 llvm::Function *FnGetFieldInfo = llvm::Intrinsic::getDeclaration(
 &CGM.getModule(), llvm::Intrinsic::bpf_preserve_field_info,
 {FieldAddr->getType()});
-return Builder.CreateCall(FnGetFieldInfo, {FieldAddr, InfoKind});
+CallInst *Fn = Builder.CreateCall(FnGetFieldInfo, {FieldAddr, InfoKind});
+Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
+return Fn;
   }
   case BPF::BI__builtin_btf_type_id: {
 Value *FieldVal = nullptr;


Index: llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
===
--- llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
+++ llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
@@ -277,7 +277,7 @@
   }
   if (GV->getName().startswith("llvm.bpf.pre

[PATCH] D83242: [RFC][BPF] support expr with typedef type for FIELD_EXISTENCE reloc

2020-07-08 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

Sounds good. Will try to add support for union/struct type as well.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D83242: [clang][BPF] support expr with typedef/record type for FIELD_EXISTENCE reloc

2020-07-15 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 278190.
yonghong-song retitled this revision from "[RFC][BPF] support expr with typedef 
type for FIELD_EXISTENCE reloc" to "[clang][BPF] support expr with 
typedef/record type for FIELD_EXISTENCE reloc".
yonghong-song edited the summary of this revision.
yonghong-song added a comment.

clang change only and added tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/Basic/TargetInfo.cpp
  clang/lib/Basic/Targets/BPF.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
  clang/test/Sema/builtins-bpf.c

Index: clang/test/Sema/builtins-bpf.c
===
--- clang/test/Sema/builtins-bpf.c
+++ clang/test/Sema/builtins-bpf.c
@@ -2,13 +2,15 @@
 
 struct s { int a; int b[4]; int c:1; };
 union u { int a; int b[4]; int c:1; };
+typedef struct { int a; int b; } __t;
+typedef int (*__f)(void);
 
 unsigned invalid1(const int *arg) {
-  return __builtin_preserve_field_info(arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 not a field access}}
+  return __builtin_preserve_field_info(arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
 }
 
 unsigned invalid2(const int *arg) {
-  return __builtin_preserve_field_info(*arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 not a field access}}
+  return __builtin_preserve_field_info(*arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
 }
 
 void *invalid3(struct s *arg) {
@@ -46,3 +48,25 @@
 unsigned invalid11(struct s *arg, int info_kind) {
   return __builtin_preserve_field_info(arg->a, info_kind); // expected-error {{__builtin_preserve_field_info argument 2 not a constant}}
 }
+
+unsigned valid12() {
+  const struct s t = {};
+  return __builtin_preserve_field_info(t, 2);
+}
+
+unsigned valid13() {
+  return __builtin_preserve_field_info(*(struct s *)0, 2);
+}
+
+unsigned valid14() {
+  __t t = {};
+  return __builtin_preserve_field_info(t, 2);
+}
+
+unsigned valid15() {
+  return __builtin_preserve_field_info((const __f)0, 2);
+}
+
+unsigned invalid16(struct s *arg) {
+  return __builtin_preserve_field_info(arg->a + 2, 2); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
+}
Index: clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
===
--- /dev/null
+++ clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
@@ -0,0 +1,33 @@
+// REQUIRES: bpf-registered-target
+// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+
+#define _(x, y) (__builtin_preserve_field_info((x), (y)))
+
+struct s {
+  char a;
+};
+typedef struct {
+  char a;
+} __s1;
+
+typedef int (*__func)(void);
+
+unsigned unit1() {
+  const __s1 v = {};
+  return _(v, 2) + _(*(struct s *)0, 2);
+}
+
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0s_struct.__s1s(%struct.__s1* %{{[0-9a-z]+}}, i64 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[CONST_S1:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0s_struct.ss(%struct.s* null, i64 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S:[0-9]+]]
+
+unsigned unit2() {
+  __func f;
+  return _((__func)0, 2) + _(f, 2);
+}
+
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0f_i32f(i32 ()* null, i64 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0p0f_i32f(i32 ()** %{{[0-9a-z]+}}, i64 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF:[0-9]+]]
+
+// CHECK: ![[STRUCT_S]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s"
+// CHECK: ![[TYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__func"
+// CHECK: ![[CONST_S1]] = !DIDerivedType(tag: DW_TAG_const_type
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -2563,7 +2563,7 @@
CallExpr *TheCall) {
   assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
   BuiltinID == BPF::BI__builtin_btf_type_id) &&
- "unexpected ARM builtin");
+ "unexpected BPF builtin");
 
   if (checkArgCount(*this, TheCall, 2))
 return true;
@@ -2583,20 +2583,6 @@
 return false;
   }
 
-  // The first argument needs to be a record field access.
-  // If it is an array element access, we delay decision
-  // to BPF backend to check whether the access is a
-  // field access or not.
-  Arg = TheCall->getArg(0);
-  if (Arg->getType()->getAsPlaceholderType() ||
-  (Arg->IgnoreParens()->getObjectKind() != OK_BitField &&
-   !dyn_cast(Arg->IgnoreP

[PATCH] D83242: [clang][BPF] support expr with typedef/record type for FIELD_EXISTENCE reloc

2020-07-15 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

The llvm change is here: https://reviews.llvm.org/D83878


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D83242: [clang][BPF] support expr with typedef/record type for FIELD_EXISTENCE reloc

2020-07-15 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song added a comment.

In D83242#2154145 , @ast wrote:

> lgtm.
>  curious what happens when type is defined within args, like:
>  __builtin_preserve_field_info(*(struct { int a; } *)0, 2);


-bash-4.4$ clang -target bpf -O2 -g -S t1.c
t1.c:3:40: error: __builtin_preserve_field_info argument 1 invalid

  return __builtin_preserve_field_info(*(struct { int a; } *)0, 2);

it will flag out an error since an non-empty name is required
as we will need it to generate relocation.

  if (!RT || RT->getDecl()->getDeclName().isEmpty())

With an name, it works properly.

  -bash-4.4$ cat t1.c
  
  unsigned unit1() {
return __builtin_preserve_field_info(*(struct t { int a; } *)0, 2);
  }
  -bash-4.4$ clang -target bpf -O2 -g -S t1.c   
 
  -bash-4.4$




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D83242: [clang][BPF] support expr with typedef/record type for FIELD_EXISTENCE reloc

2020-07-15 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 278305.
yonghong-song added a comment.

fix clang-format warnings.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83242

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/Basic/TargetInfo.cpp
  clang/lib/Basic/Targets/BPF.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
  clang/test/Sema/builtins-bpf.c

Index: clang/test/Sema/builtins-bpf.c
===
--- clang/test/Sema/builtins-bpf.c
+++ clang/test/Sema/builtins-bpf.c
@@ -1,14 +1,27 @@
 // RUN: %clang_cc1 -x c -triple bpf-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
 
-struct s { int a; int b[4]; int c:1; };
-union u { int a; int b[4]; int c:1; };
+struct s {
+  int a;
+  int b[4];
+  int c:1;
+};
+union u {
+  int a;
+  int b[4];
+  int c:1;
+};
+typedef struct {
+  int a;
+  int b;
+} __t;
+typedef int (*__f)(void);
 
 unsigned invalid1(const int *arg) {
-  return __builtin_preserve_field_info(arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 not a field access}}
+  return __builtin_preserve_field_info(arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
 }
 
 unsigned invalid2(const int *arg) {
-  return __builtin_preserve_field_info(*arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 not a field access}}
+  return __builtin_preserve_field_info(*arg, 1); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
 }
 
 void *invalid3(struct s *arg) {
@@ -46,3 +59,25 @@
 unsigned invalid11(struct s *arg, int info_kind) {
   return __builtin_preserve_field_info(arg->a, info_kind); // expected-error {{__builtin_preserve_field_info argument 2 not a constant}}
 }
+
+unsigned valid12() {
+  const struct s t = {};
+  return __builtin_preserve_field_info(t, 2);
+}
+
+unsigned valid13() {
+  return __builtin_preserve_field_info(*(struct s *)0, 2);
+}
+
+unsigned valid14() {
+  __t t = {};
+  return __builtin_preserve_field_info(t, 2);
+}
+
+unsigned valid15() {
+  return __builtin_preserve_field_info((const __f)0, 2);
+}
+
+unsigned invalid16(struct s *arg) {
+  return __builtin_preserve_field_info(arg->a + 2, 2); // expected-error {{__builtin_preserve_field_info argument 1 invalid}}
+}
Index: clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
===
--- /dev/null
+++ clang/test/CodeGen/builtins-bpf-preserve-field-info-3.c
@@ -0,0 +1,33 @@
+// REQUIRES: bpf-registered-target
+// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+
+#define _(x, y) (__builtin_preserve_field_info((x), (y)))
+
+struct s {
+  char a;
+};
+typedef struct {
+  char a;
+} __s1;
+
+typedef int (*__func)(void);
+
+unsigned unit1() {
+  const __s1 v = {};
+  return _(v, 2) + _(*(struct s *)0, 2);
+}
+
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0s_struct.__s1s(%struct.__s1* %{{[0-9a-z]+}}, i64 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[CONST_S1:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0s_struct.ss(%struct.s* null, i64 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S:[0-9]+]]
+
+unsigned unit2() {
+  __func f;
+  return _((__func)0, 2) + _(f, 2);
+}
+
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0f_i32f(i32 ()* null, i64 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF:[0-9]+]]
+// CHECK: call i32 @llvm.bpf.preserve.field.info.p0p0f_i32f(i32 ()** %{{[0-9a-z]+}}, i64 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF:[0-9]+]]
+
+// CHECK: ![[STRUCT_S]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s"
+// CHECK: ![[TYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__func"
+// CHECK: ![[CONST_S1]] = !DIDerivedType(tag: DW_TAG_const_type
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -2563,7 +2563,7 @@
CallExpr *TheCall) {
   assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
   BuiltinID == BPF::BI__builtin_btf_type_id) &&
- "unexpected ARM builtin");
+ "unexpected BPF builtin");
 
   if (checkArgCount(*this, TheCall, 2))
 return true;
@@ -2583,20 +2583,6 @@
 return false;
   }
 
-  // The first argument needs to be a record field access.
-  // If it is an array element access, we delay decision
-  // to BPF backend to check whether the access is a
-  // field access or not.
-  Arg = TheCall->getArg(0);
-  if (Arg->getType()->getAsPlaceholderType() ||
-  (Arg->IgnoreParens()->getObjectKind() != OK_BitField &&
-   !dyn_cast(Arg->IgnoreParens()) &&
-   !dyn_cast(Arg->IgnoreParens( {

[PATCH] D82112: [RFC][BPF] Implement getUserCost() for BPFTargetTransformInfo

2020-06-18 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song created this revision.
yonghong-song added a reviewer: ast.
Herald added subscribers: llvm-commits, cfe-commits, hiraditya.
Herald added projects: clang, LLVM.

This patch tries to partially prevent speculative code motion for BPF.

First, some use cases on why we want to prevent speculative code motion.

Use case 1: bpf map value or some other data with a range.

  data = bpf_map_lookup_elem(&map, &key);
  if (!data) return 0;
  payload = data->payload;
  len = bpf_probe_read_kernel_str(payload, 16, &task->comm);
  if (len <= 16) 
payload += len;
  ... 

The compiler may generate code like:

  data = bpf_map_lookup_elem(&map, &key);
  if (!data) return 0;
  payload = data->payload;
  len = bpf_probe_read_kernel_str(payload, 16, &task->comm);
  new_payload = payload + len;
  if (len > 16) 
new_payload = payload
  ... 

The "payload + len" may cause kernel verifier failure as
the "len" can be anything at this moment.

Use case 2: CO-RE relocatons

  field_exist = ... 
  if (field_exist) {
offset = non-memory-access-builtin-expr1;
  } else {
offset = non-memory-access-builtin-expr2;
  }   
  use "offset" to read kernel memory

The compiler may generate code like:

  field_exist = ... 
  offset = non-memory-access-builtin-expr1;
  if (!field_exist)
offset = non-memory-access-builtin-expr2;
  use "offset" to read kernel memory

This may cause failures since if field_exist is false and 
libbpf is not able to perform relation
for "offset = non-memory-access-builtin-expr1".
The instruction itself will be rewritten as
an illegal instruction and this will cause
program load failures.

To address the above issues, people use

  . inline assembly
  . artificial complex control flow

to prevent the above optimizations.

This patch tries to do with a more user friendly way.
BPF backend TargetTransformInfo implements getUserCost()
to return UserCost INT_MAX for TCK_SizeAndLatency
to prevent compiler moving codes speculatively.
An option "adjustopt", false by default, is added to
enable this adjustment.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D82112

Files:
  clang/lib/Basic/Targets/BPF.h
  llvm/lib/Target/BPF/BPF.td
  llvm/lib/Target/BPF/BPFSubtarget.cpp
  llvm/lib/Target/BPF/BPFSubtarget.h
  llvm/lib/Target/BPF/BPFTargetMachine.cpp
  llvm/lib/Target/BPF/BPFTargetMachine.h
  llvm/lib/Target/BPF/BPFTargetTransformInfo.h

Index: llvm/lib/Target/BPF/BPFTargetTransformInfo.h
===
--- /dev/null
+++ llvm/lib/Target/BPF/BPFTargetTransformInfo.h
@@ -0,0 +1,51 @@
+//===-- BPFTargetTransformInfo.h - BPF specific TTI -*- C++ -*-===//
+//
+// 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
+//
+//===--===//
+//
+// This file a TargetTransformInfo::Concept conforming object specific to the
+// BPF target machine. It uses the target's detailed information to
+// provide more precise answers to certain TTI queries, while letting the
+// target independent and default TTI implementations handle the rest.
+//
+//===--===//
+
+#ifndef LLVM_LIB_TARGET_BPF_BPFTARGETTRANSFORMINFO_H
+#define LLVM_LIB_TARGET_BPF_BPFTARGETTRANSFORMINFO_H
+
+#include "BPFTargetMachine.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/BasicTTIImpl.h"
+
+namespace llvm {
+class BPFTTIImpl : public BasicTTIImplBase {
+  typedef BasicTTIImplBase BaseT;
+  typedef TargetTransformInfo TTI;
+  friend BaseT;
+
+  const BPFSubtarget *ST;
+  const BPFTargetLowering *TLI;
+
+  const BPFSubtarget *getST() const { return ST; }
+  const BPFTargetLowering *getTLI() const { return TLI; }
+
+public:
+  explicit BPFTTIImpl(const BPFTargetMachine *TM, const Function &F)
+  : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)),
+TLI(ST->getTargetLowering()) {}
+
+  unsigned getUserCost(const User *U, ArrayRef Operands,
+   TTI::TargetCostKind CostKind) {
+if (!ST->getHasAdjustOpt() || CostKind != TTI::TCK_SizeAndLatency)
+  return BaseT::getUserCost(U, Operands, CostKind);
+
+return INT_MAX;
+  }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_BPF_BPFTARGETTRANSFORMINFO_H
Index: llvm/lib/Target/BPF/BPFTargetMachine.h
===
--- llvm/lib/Target/BPF/BPFTargetMachine.h
+++ llvm/lib/Target/BPF/BPFTargetMachine.h
@@ -34,6 +34,8 @@
 
   TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
 
+  TargetTransformInfo getTargetTransformInfo(const Function &F) override;
+
   TargetLoweringObjectFile *getObjFileLowering() const override {
 return TLOF.get();
   }
Index: llvm/lib/Target/BPF/BPFTargetMachi

[PATCH] D74668: [Clang][BPF] implement __builtin_btf_type_id() builtin function

2020-04-30 Thread Yonghong Song via Phabricator via cfe-commits
yonghong-song updated this revision to Diff 261426.
yonghong-song added a comment.

rebase on top of master


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D74668

Files:
  clang/include/clang/Basic/BuiltinsBPF.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtin-bpf-btf-type-id.c
  clang/test/Sema/builtin-bpf-btf-type-id.c
  llvm/include/llvm/IR/IntrinsicsBPF.td

Index: llvm/include/llvm/IR/IntrinsicsBPF.td
===
--- llvm/include/llvm/IR/IntrinsicsBPF.td
+++ llvm/include/llvm/IR/IntrinsicsBPF.td
@@ -23,4 +23,6 @@
   def int_bpf_preserve_field_info : GCCBuiltin<"__builtin_bpf_preserve_field_info">,
   Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty, llvm_i64_ty],
   [IntrNoMem, ImmArg<1>]>;
+  def int_bpf_btf_type_id : GCCBuiltin<"__builtin_bpf_btf_type_id">,
+  Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_any_ty], [IntrNoMem]>;
 }
Index: clang/test/Sema/builtin-bpf-btf-type-id.c
===
--- /dev/null
+++ clang/test/Sema/builtin-bpf-btf-type-id.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -x c -triple bpf-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
+
+struct {
+  char f1[100];
+  int f2;
+} tmp = {};
+
+unsigned invalid1() { return __builtin_btf_type_id(1, 1); } // expected-error {{too many arguments to function call, expected 1, have 2}}
+int valid2() { return __builtin_btf_type_id(tmp); }
+int valid3() { return __builtin_btf_type_id(&tmp); }
+int valid4() { return __builtin_btf_type_id(tmp.f1[4]); }
Index: clang/test/CodeGen/builtin-bpf-btf-type-id.c
===
--- /dev/null
+++ clang/test/CodeGen/builtin-bpf-btf-type-id.c
@@ -0,0 +1,13 @@
+// REQUIRES: bpf-registered-target
+// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+
+unsigned test1(int a) { return __builtin_btf_type_id(a); }
+unsigned test2(int a) { return __builtin_btf_type_id(&a); }
+
+// CHECK: define dso_local i32 @test1
+// CHECK: call i32 @llvm.bpf.btf.type.id.p0i32.i32(i32* %{{[0-9a-z.]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[INT:[0-9]+]]
+// CHECK: define dso_local i32 @test2
+// CHECK: call i32 @llvm.bpf.btf.type.id.p0i32.i32(i32* %{{[0-9a-z.]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[INT_POINTER:[0-9]+]]
+//
+// CHECK: ![[INT]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed
+// CHECK: ![[INT_POINTER]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[INT]], size: 64
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -2484,9 +2484,17 @@
 
 bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
-  assert(BuiltinID == BPF::BI__builtin_preserve_field_info &&
+  assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
+  BuiltinID == BPF::BI__builtin_btf_type_id) &&
  "unexpected ARM builtin");
 
+  if (BuiltinID == BPF::BI__builtin_btf_type_id) {
+if (checkArgCount(*this, TheCall, 1))
+  return true;
+TheCall->setType(Context.UnsignedIntTy);
+return false;
+  }
+
   if (checkArgCount(*this, TheCall, 2))
 return true;
 
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -10459,33 +10459,99 @@
 
 Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
-  assert(BuiltinID == BPF::BI__builtin_preserve_field_info &&
- "unexpected ARM builtin");
+  assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
+  BuiltinID == BPF::BI__builtin_btf_type_id) &&
+ "unexpected BPF builtin");
 
-  const Expr *Arg = E->getArg(0);
-  bool IsBitField = Arg->IgnoreParens()->getObjectKind() == OK_BitField;
+  switch (BuiltinID) {
+  default:
+llvm_unreachable("Unexpected BPF builtin");
+  case BPF::BI__builtin_preserve_field_info: {
+const Expr *Arg = E->getArg(0);
+bool IsBitField = Arg->IgnoreParens()->getObjectKind() == OK_BitField;
 
-  if (!getDebugInfo()) {
-CGM.Error(E->getExprLoc(), "using builtin_preserve_field_info() without -g");
-return IsBitField ? EmitLValue(Arg).getBitFieldPointer()
-  : EmitLValue(Arg).getPointer(*this);
-  }
+if (!getDebugInfo()) {
+  CGM.Error(E->getExprLoc(), "using builtin_preserve_field_info() without -g");
+  return IsBitField ? EmitLValue(Arg).getBitFieldPointer()
+: EmitLValue(Arg).getPointer(*this);
+}
 
-  // Enable underlying preserve_*_access_index() generation.
-  

  1   2   3   4   5   >