Wang Nan via llvm-dev
2015-Aug-18 14:53 UTC
[llvm-dev] [RFC PATCH 1/2] [clang]: Add AuxAttr support
This patch adds EmitTypeAuxAttribute() function to CGDebugInfo, which allows other parts of clang issue auxiliary information through an enumeration type in Dwarf information. For example, by calling DI->EmitTypeAuxAttribute(type, "ID", 1234); We can get following information in dwarf: <1><3f>: Abbrev Number: 3 (DW_TAG_structure_type) <40> DW_AT_name : (indirect string, offset: 0xeb): my_str ... <2><47>: Abbrev Number: 4 (DW_TAG_member) <48> DW_AT_name : (indirect string, offset: 0xe3): x <4c> DW_AT_type : <0x6d> ... ... <2><5f>: Abbrev Number: 5 (DW_TAG_enumeration_type) <60> DW_AT_name : (indirect string, offset: 0x140): .llvm.aux.attr <64> DW_AT_byte_size : 0 <3><65>: Abbrev Number: 6 (DW_TAG_enumerator) <66> DW_AT_name : (indirect string, offset: 0x13c): .ID <6a> DW_AT_const_value : 1234 By DW_TAG_enumeration_type '.llvm.aux.attr', we can connect an attribute named ".ID" to this structure type, whose value should be 1234. Note that enumeration types and enumerators generated by EmitTypeAuxAttribute() are all leaded with a '.', which would be never issued by normal C programs. Signed-off-by: Wang Nan <wangnan0 at huawei.com> --- lib/CodeGen/CGDebugInfo.cpp | 31 +++++++++++++++++++++++++++++++ lib/CodeGen/CGDebugInfo.h | 5 +++++ 2 files changed, 36 insertions(+) diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index eaa1e25..99d4230 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -3363,6 +3363,31 @@ void CGDebugInfo::finalize() { RE = RetainedTypes.end(); RI != RE; ++RI) DBuilder.retainType(cast<llvm::DIType>(TypeCache[*RI])); + + if (AuxAttrs.size() > 0) { + for (const auto &p_type : AuxAttrs) { + SmallVector<llvm::Metadata *, 16> Enumerators; + const Type *type = p_type.first; + + for (const auto &p_attr : p_type.second) { + std::string key("." + p_attr.first); + std::replace(key.begin(), key.end(), ' ', '.'); + + Enumerators.push_back(DBuilder.createEnumerator(StringRef(key), + p_attr.second)); + } + + llvm::DINodeArray EltArray = DBuilder.getOrCreateArray(Enumerators); + + llvm::DIFile *file = getOrCreateFile(SourceLocation()); + + DBuilder.createEnumerationType( + type == nullptr ? file : getContextDescriptor(type->getAsTagDecl()), + ".llvm.aux.attr", file, 0, 0, 0, + EltArray, nullptr, SmallString<256>()); + } + } + DBuilder.finalize(); } @@ -3374,3 +3399,9 @@ void CGDebugInfo::EmitExplicitCastType(QualType Ty) { // Don't ignore in case of explicit cast where it is referenced indirectly. DBuilder.retainType(DieTy); } + +void CGDebugInfo::EmitTypeAuxAttribute(const Type *Ty, std::string key, + uint64_t val) +{ + AuxAttrs[Ty].push_back(std::make_pair(key, val)); +} diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 9c62f6c..94abd3b 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -121,6 +121,9 @@ class CGDebugInfo { llvm::DenseMap<const Decl *, llvm::TypedTrackingMDRef<llvm::DIDerivedType>> StaticDataMemberCache; + llvm::DenseMap<const Type *, std::vector<std::pair<std::string, uint64_t> > > + AuxAttrs; + /// Helper functions for getOrCreateType. /// @{ /// Currently the checksum of an interface includes the number of @@ -337,6 +340,8 @@ public: /// Emit C++ namespace alias. llvm::DIImportedEntity *EmitNamespaceAlias(const NamespaceAliasDecl &NA); + void EmitTypeAuxAttribute(const Type *Ty, std::string key, uint64_t val); + /// Emit record type's standalone debug info. llvm::DIType *getOrCreateRecordType(QualType Ty, SourceLocation L); -- 1.8.3.4
Wang Nan via llvm-dev
2015-Aug-18 14:53 UTC
[llvm-dev] [RFC PATCH 2/2] [clang] BPF: add __builtin_bpf_typeid()
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
Adrian Prantl via llvm-dev
2018-Feb-23 00:37 UTC
[llvm-dev] [RFC PATCH 1/2] [clang]: Add AuxAttr support
> On Aug 18, 2015, at 7:53 AM, Wang Nan via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > This patch adds EmitTypeAuxAttribute() function to CGDebugInfo, which > allows other parts of clang issue auxiliary information through an > enumeration type in Dwarf information.That's a rather unusual mechanism. Can you elaborate what the use-case for this would be and why this should be part of mainline clang? -- adrian