[llvm-dev] [RFC PATCH 2/2] [clang] BPF: add __builtin_bpf_typeid()

Wang Nan via llvm-dev llvm-dev at lists.llvm.org
Tue Aug 18 07:53:33 PDT 2015


This patch introduces a new builtin function __builtin_bpf_typeid()
for BPF.

The newly created builtin function issue a constant int64 according
to type feed to it (by utilizing vararg type, __builtin_bpf_typeid
accepts all types of variable), and connect the number with the
specific structure type in Dwarf info by utilizing
EmitTypeAuxAttribute(). The number is computed by simplly
count the number of types which feed to this builtin.

After this patch we have a reliable way to record data and its
type in BPF program. For example, in following program, we output
2 u64 values in different condition.

 int func(void *ctx) {
   struct {
     u64 type;
     u64 cycles;
   } cycles_vals;

   struct {
     u64 type;
     u64 misses;
   } misses_vals;

   u32 key = bpf_get_smp_processor_id();

   if (key & 1) {
     cycles_vals.cycles = bpf_perf_event_read(&map_cycles, key);
     cycles_vals.type = __builtin_bpf_typeid(cycles_vals);
     bpf_output_trace_data(&cycles_vals, sizeof(cycles_vals));
   } else {
     misses_vals.misses = bpf_perf_event_read(&map_cache_misses, key);
     misses_vals.type = __builtin_bpf_typeid(misses_vals);
     bpf_output_trace_data(&misses_vals, sizeof(misses_vals));
   }
   return 0;
 }

And we will get following Dwarf information:

 <2><117>: Abbrev Number: 3 (DW_TAG_structure_type)
    <118>   DW_AT_byte_size   : 16
    ...
 <3><11b>: Abbrev Number: 4 (DW_TAG_member)
    <11c>   DW_AT_name        : (indirect string, offset: 0x163): type
    ...
    <126>   DW_AT_data_member_location: 0
 <3><127>: Abbrev Number: 4 (DW_TAG_member)
    <128>   DW_AT_name        : (indirect string, offset: 0x168): cycles
    ...
    <132>   DW_AT_data_member_location: 8
 <3><133>: Abbrev Number: 15 (DW_TAG_enumeration_type)
    <134>   DW_AT_name        : (indirect string, offset: 0x173): .llvm.aux.attr
    <138>   DW_AT_byte_size   : 0
 <4><139>: Abbrev Number: 16 (DW_TAG_enumerator)
    <13a>   DW_AT_name        : (indirect string, offset: 0x16f): .ID
    <13e>   DW_AT_const_value : 1
 <2><141>: Abbrev Number: 3 (DW_TAG_structure_type)
    <142>   DW_AT_byte_size   : 16
    ...
 <3><145>: Abbrev Number: 4 (DW_TAG_member)
    <146>   DW_AT_name        : (indirect string, offset: 0x163): type
    ...
    <150>   DW_AT_data_member_location: 0
 <3><151>: Abbrev Number: 4 (DW_TAG_member)
    <152>   DW_AT_name        : (indirect string, offset: 0x182): misses
    ...
    <15c>   DW_AT_data_member_location: 8
 <3><15d>: Abbrev Number: 15 (DW_TAG_enumeration_type)
    <15e>   DW_AT_name        : (indirect string, offset: 0x173): .llvm.aux.attr
    <162>   DW_AT_byte_size   : 0
 <4><163>: Abbrev Number: 16 (DW_TAG_enumerator)
    <164>   DW_AT_name        : (indirect string, offset: 0x16f): .ID
    <168>   DW_AT_const_value : 2

Then we can connect type id and layout of structure together.

Signed-off-by: Wang Nan <wangnan0 at huawei.com>
---
 include/clang/Basic/BuiltinsBPF.def  | 15 +++++++++++++++
 include/clang/Basic/TargetBuiltins.h |  9 +++++++++
 lib/Basic/Targets.cpp                | 14 +++++++++++++-
 lib/CodeGen/CGBuiltin.cpp            | 32 ++++++++++++++++++++++++++++++++
 lib/CodeGen/CodeGenFunction.h        |  1 +
 5 files changed, 70 insertions(+), 1 deletion(-)
 create mode 100644 include/clang/Basic/BuiltinsBPF.def

diff --git a/include/clang/Basic/BuiltinsBPF.def b/include/clang/Basic/BuiltinsBPF.def
new file mode 100644
index 0000000..7e07630
--- /dev/null
+++ b/include/clang/Basic/BuiltinsBPF.def
@@ -0,0 +1,15 @@
+//===--- BuiltinsBPF.def - BPF Builtin function database ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the BPF-specific builtin function database.  Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+BUILTIN(__builtin_bpf_typeid, "Wi.", "nc")
diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h
index b4740c5..550f921 100644
--- a/include/clang/Basic/TargetBuiltins.h
+++ b/include/clang/Basic/TargetBuiltins.h
@@ -93,6 +93,15 @@ namespace clang {
     };
   }
 
+  namespace BPF {
+    enum {
+        LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsBPF.def"
+        LastTSBuiltin
+    };
+  }
+
   /// \brief Flags to identify the types for overloaded Neon builtins.
   ///
   /// These must be kept in sync with the flags in utils/TableGen/NeonEmitter.h.
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index c5309c4..8d57dac 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -6147,6 +6147,7 @@ validateAsmConstraint(const char *&Name,
   };
 
 class BPFTargetInfo : public TargetInfo {
+  static const Builtin::Info BuiltinInfo[];
 public:
   BPFTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
     LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
@@ -6177,7 +6178,10 @@ public:
   }
 
   void getTargetBuiltins(const Builtin::Info *&Records,
-                         unsigned &NumRecords) const override {}
+                         unsigned &NumRecords) const override {
+    Records = BuiltinInfo;
+    NumRecords = clang::BPF::LastTSBuiltin - Builtin::FirstTSBuiltin;
+  }
   const char *getClobbers() const override {
     return "";
   }
@@ -6200,6 +6204,14 @@ public:
   }
 };
 
+const Builtin::Info BPFTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
+                                              ALL_LANGUAGES },
+#include "clang/Basic/BuiltinsBPF.def"
+};
+
+
 class MipsTargetInfoBase : public TargetInfo {
   virtual void setDataLayoutString() = 0;
 
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 394d0d1..d9f97bc 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -1882,6 +1882,9 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
   case llvm::Triple::nvptx:
   case llvm::Triple::nvptx64:
     return EmitNVPTXBuiltinExpr(BuiltinID, E);
+  case llvm::Triple::bpfel:
+  case llvm::Triple::bpfeb:
+    return EmitBPFBuiltinExpr(BuiltinID, E);
   default:
     return nullptr;
   }
@@ -7056,3 +7059,32 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
     return nullptr;
   }
 }
+
+Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,
+		                           const CallExpr *E) {
+  switch (BuiltinID) {
+  default:
+    return nullptr;
+  case BPF::BI__builtin_bpf_typeid:
+    static llvm::DenseMap<const Type*, uint64_t> TypeIDMap;
+
+    if (E->getNumArgs() != 1)
+      return nullptr;
+
+    const Expr *arg0 = E->getArg(0);
+    const Type *type = arg0->getType().getTypePtrOrNull();
+    if (!type->isStructureType())
+      return Builder.getInt64(0);
+
+    auto I = TypeIDMap.find(type);
+    if (I == TypeIDMap.end()) {
+      int id = TypeIDMap.size() + 1;
+      TypeIDMap[type] = id;
+      CGDebugInfo *DI = getDebugInfo();
+      if (DI != nullptr)
+        DI->EmitTypeAuxAttribute(type, "ID", TypeIDMap[type]);
+    }
+
+    return Builder.getInt64(TypeIDMap[type]);
+  }
+}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 95a512c..46ea1d8 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -2623,6 +2623,7 @@ public:
   llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
   llvm::Value *EmitSystemZBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
   llvm::Value *EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+  llvm::Value *EmitBPFBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
 
   llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
   llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
-- 
1.8.3.4



More information about the llvm-dev mailing list