Index: include/llvm/BinaryFormat/BTF.h =================================================================== --- /dev/null +++ include/llvm/BinaryFormat/BTF.h @@ -0,0 +1,209 @@ +//===-- llvm/BinaryFormat/BTF.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the layout of .BTF and .BTF.ext ELF sections. +/// +/// The binary layout for .BTF section: +/// struct Header +/// Type and Str subsections +/// The Type subsection is a collection of types with type id starting with 1. +/// The Str subsection is simply a collection of strings. +/// +/// The binary layout for .BTF.ext section: +/// struct ExtHeader +/// FuncInfo and LineInfo subsections +/// The FuncInfo subsection is defined as below: +/// BTFFuncInfo Size +/// struct SecFuncInfo for ELF section #1 +/// A number of struct BPFFuncInfo for ELF section #1 +/// struct SecFuncInfo for ELF section #2 +/// A number of struct BPFFuncInfo for ELF section #2 +/// ... +/// The LineInfo subsection is defined as below: +/// BPFLineInfo Size +/// struct SecLineInfo for ELF section #1 +/// A number of struct BPFLineInfo for ELF section #1 +/// struct SecLineInfo for ELF section #2 +/// A number of struct BPFLineInfo for ELF section #2 +/// ... +/// +/// The section formats are also defined at +/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/btf.h +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINARYFORMAT_BTF_H +#define LLVM_BINARYFORMAT_BTF_H + +namespace llvm { +namespace BTF { + +enum : uint32_t { MAGIC = 0xeB9F, VERSION = 1 }; + +/// Sizes in bytes of various things in the BTF format. +enum { + HeaderSize = 24, + ExtHeaderSize = 24, + CommonTypeSize = 12, + BTFArraySize = 12, + BTFEnumSize = 8, + BTFMemberSize = 12, + BTFParamSize = 8, + SecFuncInfoSize = 8, + SecLineInfoSize = 8, + BPFFuncInfoSize = 8, + BPFLineInfoSize = 16 +}; + +/// The .BTF section header definition. +struct Header { + uint16_t Magic; ///< Magic value + uint8_t Version; ///< Version number + uint8_t Flags; ///< Extra flags + uint32_t HdrLen; ///< Length of this header + + /// All offsets are in bytes relative to the end of this header. + uint32_t TypeOff; ///< Offset of type section + uint32_t TypeLen; ///< Length of type section + uint32_t StrOff; ///< Offset of string section + uint32_t StrLen; ///< Length of string section +}; + +enum : uint32_t { + MAX_VLEN = 0xffff ///< Max # of struct/union/enum members or func args +}; + +enum TypeKinds : uint8_t { +#define HANDLE_BTF_KIND(ID, NAME) BTF_KIND_##NAME = ID, +#include "llvm/BinaryFormat/BTF.def" +}; + +/// The BTF common type definition. Different kinds may have +/// additional information after this structure data. +struct CommonType { + /// Type name offset in the string table. + uint32_t NameOff; + + /// "Info" bits arrangement: + /// Bits 0-15: vlen (e.g. # of struct's members) + /// Bits 16-23: unused + /// Bits 24-27: kind (e.g. int, ptr, array...etc) + /// Bits 28-30: unused + /// Bit 31: kind_flag, currently used by + /// struct, union and fwd + uint32_t Info; + + /// "Size" is used by INT, ENUM, STRUCT and UNION. + /// "Size" tells the size of the type it is describing. + /// + /// "Type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, + /// FUNC and FUNC_PROTO. + /// "Type" is a type_id referring to another type. + union { + uint32_t Size; + uint32_t Type; + }; +}; + +// For some specific BTF_KIND, "struct CommonType" is immediately +// followed by extra data. + +// BTF_KIND_INT is followed by a u32 and the following +// is the 32 bits arrangement: +// BTF_INT_ENCODING(VAL) : (((VAL) & 0x0f000000) >> 24) +// BTF_INT_OFFSET(VAL) : (((VAL & 0x00ff0000)) >> 16) +// BTF_INT_BITS(VAL) : ((VAL) & 0x000000ff) + +/// Attributes stored in the INT_ENCODING. +enum : uint8_t { INT_SIGNED = (1 << 0), INT_CHAR = (1 << 1), INT_BOOL = (1 << 2) }; + +/// BTF_KIND_ENUM is followed by multiple "struct BTFEnum". +/// The exact number of btf_enum is stored in the vlen (of the +/// info in "struct CommonType"). +struct BTFEnum { + uint32_t NameOff; ///< Enum name offset in the string table + int32_t Val; ///< Enum member value +}; + +/// BTF_KIND_ARRAY is followed by one "struct BTFArray". +struct BTFArray { + uint32_t ElemType; ///< Element type + uint32_t IndexType; ///< Index type + uint32_t Nelems; ///< Number of elements for this array +}; + +/// BTF_KIND_STRUCT and BTF_KIND_UNION are followed +/// by multiple "struct BTFMember". The exact number +/// of BTFMember is stored in the vlen (of the info in +/// "struct CommonType"). +/// +/// If the struct/union contains any bitfield member, +/// the Offset below represents BitOffset (bits 0 - 23) +/// and BitFieldSize(bits 24 - 31) with BitFieldSize = 0 +/// for non bitfield members. Otherwise, the Offset +/// represents the BitOffset. +struct BTFMember { + uint32_t NameOff; ///< Member name offset in the string table + uint32_t Type; ///< Member type + uint32_t Offset; ///< BitOffset or BitFieldSize+BitOffset +}; + +/// BTF_KIND_FUNC_PROTO are followed by multiple "struct BTFParam". +/// The exist number of BTFParam is stored in the vlen (of the info +/// in "struct CommonType"). +struct BTFParam { + uint32_t NameOff; + uint32_t Type; +}; + +/// The .BTF.ext section header definition. +struct ExtHeader { + uint16_t Magic; + uint8_t Version; + uint8_t Flags; + uint32_t HdrLen; + + uint32_t FuncInfoOff; ///< Offset of func info section + uint32_t FuncInfoLen; ///< Length of func info section + uint32_t LineInfoOff; ///< Offset of line info section + uint32_t LineInfoLen; ///< Length of line info section +}; + +/// Specifying one function info. +struct BPFFuncInfo { + uint32_t InsnOffset; ///< Byte offset in the section + uint32_t TypeId; ///< Type id referring to .BTF type section +}; + +/// Specifying function info's in one section. +struct SecFuncInfo { + uint32_t SecNameOff; ///< Section name index in the .BTF string table + uint32_t NumFuncInfo; ///< Number of func info's in this section +}; + +/// Specifying one line info. +struct BPFLineInfo { + uint32_t InsnOffset; ///< Byte offset in this section + uint32_t FileNameOff; ///< File name index in the .BTF string table + uint32_t LineOff; ///< Line index in the .BTF string table + uint32_t LineCol; ///< Line num: line_col >> 10, + /// col num: line_col & 0x3ff +}; + +/// Specifying line info's in one section. +struct SecLineInfo { + uint32_t SecNameOff; ///< Section name index in the .BTF string tble + uint32_t NumLineInfo; ///< Number of line info's in this section +}; + +} // End namespace BTF. +} // End namespace llvm. + +#endif Index: include/llvm/BinaryFormat/BTF.def =================================================================== --- /dev/null +++ include/llvm/BinaryFormat/BTF.def @@ -0,0 +1,33 @@ +//===- llvm/BinaryFormat/BTF.def - BTF definitions --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for BTF. +// +//===----------------------------------------------------------------------===// + +#if !defined(HANDLE_BTF_KIND) +#error "Missing macro definition of HANDLE_BTF_*" +#endif + +HANDLE_BTF_KIND(0, UNKN) +HANDLE_BTF_KIND(1, INT) +HANDLE_BTF_KIND(2, PTR) +HANDLE_BTF_KIND(3, ARRAY) +HANDLE_BTF_KIND(4, STRUCT) +HANDLE_BTF_KIND(5, UNION) +HANDLE_BTF_KIND(6, ENUM) +HANDLE_BTF_KIND(7, FWD) +HANDLE_BTF_KIND(8, TYPEDEF) +HANDLE_BTF_KIND(9, VOLATILE) +HANDLE_BTF_KIND(10, CONST) +HANDLE_BTF_KIND(11, RESTRICT) +HANDLE_BTF_KIND(12, FUNC) +HANDLE_BTF_KIND(13, FUNC_PROTO) + +#undef HANDLE_BTF_KIND Index: include/llvm/CodeGen/AsmPrinter.h =================================================================== --- include/llvm/CodeGen/AsmPrinter.h +++ include/llvm/CodeGen/AsmPrinter.h @@ -138,6 +138,8 @@ static char ID; +protected: + struct HandlerInfo { AsmPrinterHandler *Handler; const char *TimerName; @@ -429,6 +431,10 @@ /// instructions in verbose mode. virtual void emitImplicitDef(const MachineInstr *MI) const; + /// Targets can override this to emit target specific sections. + virtual void EmitTargetSections(const char *DbgTimerName, + const char *DbgTimerDescription) {}; + //===------------------------------------------------------------------===// // Symbol Lowering Routines. //===------------------------------------------------------------------===// Index: include/llvm/CodeGen/DebugHandlerBase.h =================================================================== --- include/llvm/CodeGen/DebugHandlerBase.h +++ include/llvm/CodeGen/DebugHandlerBase.h @@ -8,16 +8,16 @@ //===----------------------------------------------------------------------===// // // Common functionality for different debug information format backends. -// LLVM currently supports DWARF and CodeView. +// LLVM currently supports DWARF, CodeView and BTF. // //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGHANDLERBASE_H #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGHANDLERBASE_H -#include "AsmPrinterHandler.h" -#include "DbgEntityHistoryCalculator.h" #include "llvm/ADT/Optional.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" +#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" #include "llvm/CodeGen/LexicalScopes.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/IR/DebugInfoMetadata.h" Index: include/llvm/MC/MCObjectFileInfo.h =================================================================== --- include/llvm/MC/MCObjectFileInfo.h +++ include/llvm/MC/MCObjectFileInfo.h @@ -210,6 +210,14 @@ MCSection *SXDataSection; MCSection *GFIDsSection; + /// BTF-specific sections. BTF stands for BPF Type Format which is + /// designed for BPF target and consumed by BPF loader and + /// the kernel. + /// @{ + MCSection *BTFSection; + MCSection *BTFExtSection; + /// @} + public: void InitMCObjectFileInfo(const Triple &TT, bool PIC, MCContext &ctx, bool LargeCodeModel = false); @@ -381,6 +389,12 @@ return EHFrameSection; } + // BTF specific sections. + /// @{ + MCSection *getBTFSection() const { return BTFSection; } + MCSection *getBTFExtSection() const { return BTFExtSection; } + /// @} + enum Environment { IsMachO, IsELF, IsCOFF, IsWasm }; Environment getObjectFileType() const { return Env; } Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/AsmPrinter.h" -#include "AsmPrinterHandler.h" #include "CodeViewDebug.h" #include "DwarfDebug.h" #include "DwarfException.h" @@ -36,6 +35,7 @@ #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/GCStrategy.h" @@ -311,6 +311,8 @@ Handlers.push_back(HandlerInfo(DD, DbgTimerName, DbgTimerDescription, DWARFGroupName, DWARFGroupDescription)); } + + EmitTargetSections(DbgTimerName, DbgTimerDescription); } switch (MAI->getExceptionHandlingType()) { Index: lib/CodeGen/AsmPrinter/CodeViewDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -14,14 +14,14 @@ #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H #define LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H -#include "DbgEntityHistoryCalculator.h" -#include "DebugHandlerBase.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" +#include "llvm/CodeGen/DebugHandlerBase.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" Index: lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp +++ lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "DbgEntityHistoryCalculator.h" +#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" Index: lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -8,11 +8,11 @@ //===----------------------------------------------------------------------===// // // Common functionality for different debug information format backends. -// LLVM currently supports DWARF and CodeView. +// LLVM currently supports DWARF, CodeView and BTF. // //===----------------------------------------------------------------------===// -#include "DebugHandlerBase.h" +#include "llvm/CodeGen/DebugHandlerBase.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -14,7 +14,6 @@ #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H -#include "DbgEntityHistoryCalculator.h" #include "DwarfDebug.h" #include "DwarfUnit.h" #include "llvm/ADT/ArrayRef.h" @@ -23,6 +22,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" #include "llvm/CodeGen/DIE.h" #include "llvm/CodeGen/LexicalScopes.h" #include "llvm/IR/DebugInfoMetadata.h" Index: lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.h +++ lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -15,8 +15,6 @@ #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H #include "AddressPool.h" -#include "DbgEntityHistoryCalculator.h" -#include "DebugHandlerBase.h" #include "DebugLocStream.h" #include "DwarfFile.h" #include "llvm/ADT/ArrayRef.h" @@ -31,6 +29,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/AccelTable.h" +#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" +#include "llvm/CodeGen/DebugHandlerBase.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" Index: lib/CodeGen/AsmPrinter/EHStreamer.h =================================================================== --- lib/CodeGen/AsmPrinter/EHStreamer.h +++ lib/CodeGen/AsmPrinter/EHStreamer.h @@ -14,8 +14,8 @@ #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H #define LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H -#include "AsmPrinterHandler.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/Support/Compiler.h" namespace llvm { Index: lib/CodeGen/AsmPrinter/WinCFGuard.h =================================================================== --- lib/CodeGen/AsmPrinter/WinCFGuard.h +++ lib/CodeGen/AsmPrinter/WinCFGuard.h @@ -14,7 +14,7 @@ #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WINCFGUARD_H #define LLVM_LIB_CODEGEN_ASMPRINTER_WINCFGUARD_H -#include "AsmPrinterHandler.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/Support/Compiler.h" namespace llvm { Index: lib/MC/MCObjectFileInfo.cpp =================================================================== --- lib/MC/MCObjectFileInfo.cpp +++ lib/MC/MCObjectFileInfo.cpp @@ -476,6 +476,9 @@ Ctx->getELFSection(".eh_frame", EHSectionType, EHSectionFlags); StackSizesSection = Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, 0); + + BTFSection = Ctx->getELFSection(".BTF", ELF::SHT_PROGBITS, 0); + BTFExtSection = Ctx->getELFSection(".BTF.ext", ELF::SHT_PROGBITS, 0); } void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { Index: lib/Target/BPF/BPFAsmPrinter.cpp =================================================================== --- lib/Target/BPF/BPFAsmPrinter.cpp +++ lib/Target/BPF/BPFAsmPrinter.cpp @@ -16,6 +16,7 @@ #include "BPFInstrInfo.h" #include "BPFMCInstLower.h" #include "BPFTargetMachine.h" +#include "BTFDebug.h" #include "InstPrinter/BPFInstPrinter.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" @@ -49,6 +50,8 @@ raw_ostream &O) override; void EmitInstruction(const MachineInstr *MI) override; + void EmitTargetSections(const char *DbgTimerName, + const char *DbgTimerDescription) override; }; } // namespace @@ -131,6 +134,13 @@ EmitToStreamer(*OutStreamer, TmpInst); } +void BPFAsmPrinter::EmitTargetSections(const char *DbgTimerName, + const char *DbgTimerDescription) { + Handlers.push_back(HandlerInfo(new BTFDebug(this), + DbgTimerName, DbgTimerDescription, + "BTF", "BTF Emission")); +} + // Force static initialization. extern "C" void LLVMInitializeBPFAsmPrinter() { RegisterAsmPrinter X(getTheBPFleTarget()); Index: lib/Target/BPF/BTFDebug.h =================================================================== --- /dev/null +++ lib/Target/BPF/BTFDebug.h @@ -0,0 +1,285 @@ +//===- llvm/lib/CodeGen/AsmPrinter/BTFDebug.h -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains support for writing BTF debug info. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_BTFDEBUG_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_BTFDEBUG_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/BinaryFormat/BTF.h" +#include "llvm/CodeGen/DebugHandlerBase.h" +#include + +namespace llvm { + +class AsmPrinter; +class BTFDebug; +class DIType; +class MCStreamer; +class MCSymbol; +class MachineFunction; + +/// The base class for BTF type generation. +class BTFTypeBase { +protected: + uint8_t Kind; + uint32_t Id; + struct BTF::CommonType BTFType; + +public: + virtual ~BTFTypeBase() = default; + void setId(uint32_t Id) { this->Id = Id; } + uint32_t getId() { return Id; } + uint32_t roundupToBytes(uint32_t NumBits) { return (NumBits + 7) >> 3; } + /// Get the size of this BTF type entry. + virtual uint32_t getSize() { return BTF::CommonTypeSize; } + /// Complete BTF type generation after all related DebugInfo types + /// have been visited so their BTF type id's are available + /// for cross referece. + virtual void completeType(BTFDebug &BDebug) {} + /// Emit types for this BTF type entry. + virtual void emitType(MCStreamer &OS); +}; + +/// Handle several derived types include pointer, const, +/// volatile, typedef and restrict. +class BTFTypeDerived : public BTFTypeBase { + const DIDerivedType *DTy; + +public: + BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag); + void completeType(BTFDebug &BDebug); + void emitType(MCStreamer &OS); +}; + +/// Handle struct or union forward declaration. +class BTFTypeFwd : public BTFTypeBase { + StringRef Name; + +public: + BTFTypeFwd(StringRef Name, bool IsUnion); + void completeType(BTFDebug &BDebug); + void emitType(MCStreamer &OS); +}; + +/// Handle int type. +class BTFTypeInt : public BTFTypeBase { + StringRef Name; + uint32_t IntVal; ///< Encoding, offset, bits + +public: + BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, uint32_t OffsetInBits, + StringRef TypeName); + uint32_t getSize() { return BTFTypeBase::getSize() + sizeof(uint32_t); } + void completeType(BTFDebug &BDebug); + void emitType(MCStreamer &OS); +}; + +/// Handle enumerate type. +class BTFTypeEnum : public BTFTypeBase { + const DICompositeType *ETy; + std::vector EnumValues; + +public: + BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues); + uint32_t getSize() { + return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnumSize; + } + void completeType(BTFDebug &BDebug); + void emitType(MCStreamer &OS); +}; + +/// Handle array type. +class BTFTypeArray : public BTFTypeBase { + const DICompositeType *ATy; + struct BTF::BTFArray ArrayInfo; + +public: + BTFTypeArray(const DICompositeType *ATy); + uint32_t getSize() { return BTFTypeBase::getSize() + BTF::BTFArraySize; } + void completeType(BTFDebug &BDebug); + void emitType(MCStreamer &OS); +}; + +/// Handle struct/union type. +class BTFTypeStruct : public BTFTypeBase { + const DICompositeType *STy; + bool HasBitField; + std::vector Members; + +public: + BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField, + uint32_t NumMembers); + uint32_t getSize() { + return BTFTypeBase::getSize() + Members.size() * BTF::BTFMemberSize; + } + void completeType(BTFDebug &BDebug); + void emitType(MCStreamer &OS); +}; + +/// Handle function pointer. +class BTFTypeFuncProto : public BTFTypeBase { + const DISubroutineType *STy; + std::unordered_map FuncArgNames; + std::vector Parameters; + +public: + BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams, + const std::unordered_map &FuncArgNames); + uint32_t getSize() { + return BTFTypeBase::getSize() + Parameters.size() * BTF::BTFParamSize; + } + void completeType(BTFDebug &BDebug); + void emitType(MCStreamer &OS); +}; + +/// Handle subprogram +class BTFTypeFunc : public BTFTypeBase { + StringRef Name; + +public: + BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId); + uint32_t getSize() { return BTFTypeBase::getSize(); } + void completeType(BTFDebug &BDebug); + void emitType(MCStreamer &OS); +}; + +/// String table. +class BTFStringTable { + /// String table size in bytes. + uint32_t Size; + /// A mapping from string table offset to the index + /// of the Table. It is used to avoid putting + /// duplicated strings in the table. + std::unordered_map OffsetToIdMap; + /// A vector of strings to represent the string table. + std::vector Table; + +public: + BTFStringTable() : Size(0) {} + uint32_t getSize() { return Size; } + std::vector &getTable() { return Table; } + /// Add a string to the string table and returns its offset + /// in the table. + uint32_t addString(StringRef S); +}; + +/// Represent one func and its type id. +struct BTFFuncInfo { + const MCSymbol *Label; ///< Func MCSymbol + uint32_t TypeId; ///< Type id referring to .BTF type section +}; + +/// Represent one line info. +struct BTFLineInfo { + MCSymbol *Label; ///< MCSymbol identifying insn for the lineinfo + uint32_t FileNameOff; ///< file name offset in the .BTF string table + uint32_t LineOff; ///< line offset in the .BTF string table + uint32_t LineNum; ///< the line number + uint32_t ColumnNum; ///< the column number +}; + +/// Collect and emit BTF information. +class BTFDebug : public DebugHandlerBase { + MCStreamer &OS; + bool SkipInstruction; + bool LineInfoGenerated; + uint32_t SecNameOff; + uint32_t ArrayIndexTypeId; + BTFStringTable StringTable; + std::vector> TypeEntries; + std::unordered_map DIToIdMap; + std::unordered_map> FuncInfoTable; + std::unordered_map> LineInfoTable; + StringMap> FileContent; + + /// Add types to TypeEntries. + /// @{ + /// Add types to TypeEntries and DIToIdMap. + void addType(std::unique_ptr TypeEntry, const DIType *Ty); + /// Add types to TypeEntries only and return type id. + uint32_t addType(std::unique_ptr TypeEntry); + /// @} + + /// IR type visiting functions. + /// @{ + void visitTypeEntry(const DIType *Ty); + void visitBasicType(const DIBasicType *BTy); + void visitSubroutineType( + const DISubroutineType *STy, bool ForSubprog, + const std::unordered_map &FuncArgNames, + uint32_t &TypeId); + void visitFwdDeclType(const DICompositeType *CTy, bool IsUnion); + void visitCompositeType(const DICompositeType *CTy); + void visitStructType(const DICompositeType *STy, bool IsStruct); + void visitArrayType(const DICompositeType *ATy); + void visitEnumType(const DICompositeType *ETy); + void visitDerivedType(const DIDerivedType *DTy); + /// @} + + /// Get the file content for the subprogram. Certain lines of the file + /// later may be put into string table and referenced by line info. + std::string populateFileContent(const DISubprogram *SP); + + /// Construct a line info. + void constructLineInfo(const DISubprogram *SP, MCSymbol *Label, uint32_t Line, + uint32_t Column); + + /// Emit common header of .BTF and .BTF.ext sections. + void emitCommonHeader(); + + /// Emit the .BTF section. + void emitBTFSection(); + + /// Emit the .BTF.ext section. + void emitBTFExtSection(); + +protected: + /// Gather pre-function debug information. + void beginFunctionImpl(const MachineFunction *MF) override; + + /// Post process after all instructions in this function are processed. + void endFunctionImpl(const MachineFunction *MF) override; + +public: + BTFDebug(AsmPrinter *AP); + + /// Get the special array index type id. + uint32_t getArrayIndexTypeId() { + assert(ArrayIndexTypeId); + return ArrayIndexTypeId; + } + + /// Add string to the string table. + size_t addString(StringRef S) { return StringTable.addString(S); } + + /// Get the type id for a particular DIType. + uint32_t getTypeId(const DIType *Ty) { + assert(Ty && "Invalid null Type"); + assert(DIToIdMap.find(Ty) != DIToIdMap.end() && + "DIType not added in the BDIToIdMap"); + return DIToIdMap[Ty]; + } + + void setSymbolSize(const MCSymbol *Symbol, uint64_t Size) override {} + + /// Process beginning of an instruction. + void beginInstruction(const MachineInstr *MI) override; + + /// Complete all the types and emit the BTF sections. + void endModule() override; +}; + +} // end namespace llvm + +#endif // LLVM_LIB_CODEGEN_ASMPRINTER_BTFDEBUG_H Index: lib/Target/BPF/BTFDebug.cpp =================================================================== --- /dev/null +++ lib/Target/BPF/BTFDebug.cpp @@ -0,0 +1,758 @@ +//===- llvm/lib/CodeGen/AsmPrinter/BTFDebug.cpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing BTF debug info. +// +//===----------------------------------------------------------------------===// + +#include "BTFDebug.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCStreamer.h" +#include +#include + +using namespace llvm; + +static const char *BTFKindStr[] = { +#define HANDLE_BTF_KIND(ID, NAME) "BTF_KIND_" #NAME, +#include "llvm/BinaryFormat/BTF.def" +}; + +/// Emit a BTF common type. +void BTFTypeBase::emitType(MCStreamer &OS) { + OS.AddComment(std::string(BTFKindStr[Kind]) + "(id = " + std::to_string(Id) + + ")"); + OS.EmitIntValue(BTFType.NameOff, 4); + OS.AddComment("0x" + Twine::utohexstr(BTFType.Info)); + OS.EmitIntValue(BTFType.Info, 4); + OS.EmitIntValue(BTFType.Size, 4); +} + +BTFTypeDerived::BTFTypeDerived(const DIDerivedType *DTy, unsigned Tag) + : DTy(DTy) { + switch (Tag) { + case dwarf::DW_TAG_pointer_type: + Kind = BTF::BTF_KIND_PTR; + break; + case dwarf::DW_TAG_const_type: + Kind = BTF::BTF_KIND_CONST; + break; + case dwarf::DW_TAG_volatile_type: + Kind = BTF::BTF_KIND_VOLATILE; + break; + case dwarf::DW_TAG_typedef: + Kind = BTF::BTF_KIND_TYPEDEF; + break; + case dwarf::DW_TAG_restrict_type: + Kind = BTF::BTF_KIND_RESTRICT; + break; + default: + llvm_unreachable("Unknown DIDerivedType Tag"); + } + BTFType.Info = Kind << 24; +} + +void BTFTypeDerived::completeType(BTFDebug &BDebug) { + BTFType.NameOff = BDebug.addString(DTy->getName()); + + // The base type for PTR/CONST/VOLATILE could be void. + const DIType *ResolvedType = DTy->getBaseType().resolve(); + if (!ResolvedType) { + assert((Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST || + Kind == BTF::BTF_KIND_VOLATILE) && + "Invalid null basetype"); + BTFType.Type = 0; + } else { + BTFType.Type = BDebug.getTypeId(ResolvedType); + } +} + +void BTFTypeDerived::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); } + +/// Represent a struct/union forward declaration. +BTFTypeFwd::BTFTypeFwd(StringRef Name, bool IsUnion) : Name(Name) { + Kind = BTF::BTF_KIND_FWD; + BTFType.Info = IsUnion << 31 | Kind << 24; + BTFType.Type = 0; +} + +void BTFTypeFwd::completeType(BTFDebug &BDebug) { + BTFType.NameOff = BDebug.addString(Name); +} + +void BTFTypeFwd::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); } + +BTFTypeInt::BTFTypeInt(uint32_t Encoding, uint32_t SizeInBits, + uint32_t OffsetInBits, StringRef TypeName) + : Name(TypeName) { + // Translate IR int encoding to BTF int encoding. + uint8_t BTFEncoding; + switch (Encoding) { + case dwarf::DW_ATE_boolean: + BTFEncoding = BTF::INT_BOOL; + break; + case dwarf::DW_ATE_signed: + case dwarf::DW_ATE_signed_char: + BTFEncoding = BTF::INT_SIGNED; + break; + case dwarf::DW_ATE_unsigned: + case dwarf::DW_ATE_unsigned_char: + BTFEncoding = 0; + break; + default: + llvm_unreachable("Unknown BTFTypeInt Encoding"); + } + + Kind = BTF::BTF_KIND_INT; + BTFType.Info = Kind << 24; + BTFType.Size = roundupToBytes(SizeInBits); + IntVal = (BTFEncoding << 24) | OffsetInBits << 16 | SizeInBits; +} + +void BTFTypeInt::completeType(BTFDebug &BDebug) { + BTFType.NameOff = BDebug.addString(Name); +} + +void BTFTypeInt::emitType(MCStreamer &OS) { + BTFTypeBase::emitType(OS); + OS.AddComment("0x" + Twine::utohexstr(IntVal)); + OS.EmitIntValue(IntVal, 4); +} + +BTFTypeEnum::BTFTypeEnum(const DICompositeType *ETy, uint32_t VLen) : ETy(ETy) { + Kind = BTF::BTF_KIND_ENUM; + BTFType.Info = Kind << 24 | VLen; + BTFType.Size = roundupToBytes(ETy->getSizeInBits()); +} + +void BTFTypeEnum::completeType(BTFDebug &BDebug) { + BTFType.NameOff = BDebug.addString(ETy->getName()); + + DINodeArray Elements = ETy->getElements(); + for (const auto Element : Elements) { + const auto *Enum = cast(Element); + + struct BTF::BTFEnum BTFEnum; + BTFEnum.NameOff = BDebug.addString(Enum->getName()); + // BTF enum value is 32bit, enforce it. + BTFEnum.Val = static_cast(Enum->getValue()); + EnumValues.push_back(BTFEnum); + } +} + +void BTFTypeEnum::emitType(MCStreamer &OS) { + BTFTypeBase::emitType(OS); + for (const auto &Enum : EnumValues) { + OS.EmitIntValue(Enum.NameOff, 4); + OS.EmitIntValue(Enum.Val, 4); + } +} + +BTFTypeArray::BTFTypeArray(const DICompositeType *ATy) : ATy(ATy) { + Kind = BTF::BTF_KIND_ARRAY; + BTFType.Info = Kind << 24; +} + +/// Represent a BTF array. BTF does not record array dimensions, +/// so conceptually a BTF array is a one-dimensional array. +void BTFTypeArray::completeType(BTFDebug &BDebug) { + BTFType.NameOff = BDebug.addString(ATy->getName()); + BTFType.Size = 0; + + auto *BaseType = ATy->getBaseType().resolve(); + ArrayInfo.ElemType = BDebug.getTypeId(BaseType); + + // The IR does not really have a type for the index. + // A special type for array index should have been + // created during initial type traversal. Just + // retrieve that type id. + ArrayInfo.IndexType = BDebug.getArrayIndexTypeId(); + + // Get the number of array elements. + // If the array size is 0, set the number of elements as 0. + // Otherwise, recursively traverse the base types to + // find the element size. The number of elements is + // the totoal array size in bits divided by + // element size in bits. + uint64_t ArraySizeInBits = ATy->getSizeInBits(); + if (!ArraySizeInBits) { + ArrayInfo.Nelems = 0; + } else { + uint32_t BaseTypeSize = BaseType->getSizeInBits(); + while (!BaseTypeSize) { + const auto *DDTy = cast(BaseType); + BaseType = DDTy->getBaseType().resolve(); + assert(BaseType); + BaseTypeSize = BaseType->getSizeInBits(); + } + ArrayInfo.Nelems = ATy->getSizeInBits() / BaseTypeSize; + } +} + +void BTFTypeArray::emitType(MCStreamer &OS) { + BTFTypeBase::emitType(OS); + OS.EmitIntValue(ArrayInfo.ElemType, 4); + OS.EmitIntValue(ArrayInfo.IndexType, 4); + OS.EmitIntValue(ArrayInfo.Nelems, 4); +} + +/// Represent either a struct or a union. +BTFTypeStruct::BTFTypeStruct(const DICompositeType *STy, bool IsStruct, + bool HasBitField, uint32_t Vlen) + : STy(STy), HasBitField(HasBitField) { + Kind = IsStruct ? BTF::BTF_KIND_STRUCT : BTF::BTF_KIND_UNION; + BTFType.Size = roundupToBytes(STy->getSizeInBits()); + BTFType.Info = (HasBitField << 31) | (Kind << 24) | Vlen; +} + +void BTFTypeStruct::completeType(BTFDebug &BDebug) { + BTFType.NameOff = BDebug.addString(STy->getName()); + + // Add struct/union members. + const DINodeArray Elements = STy->getElements(); + for (const auto *Element : Elements) { + struct BTF::BTFMember BTFMember; + const auto *DDTy = cast(Element); + + BTFMember.NameOff = BDebug.addString(DDTy->getName()); + if (HasBitField) { + uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0; + BTFMember.Offset = BitFieldSize << 24 | DDTy->getOffsetInBits(); + } else { + BTFMember.Offset = DDTy->getOffsetInBits(); + } + BTFMember.Type = BDebug.getTypeId(DDTy->getBaseType().resolve()); + Members.push_back(BTFMember); + } +} + +void BTFTypeStruct::emitType(MCStreamer &OS) { + BTFTypeBase::emitType(OS); + for (const auto &Member : Members) { + OS.EmitIntValue(Member.NameOff, 4); + OS.EmitIntValue(Member.Type, 4); + OS.AddComment("0x" + Twine::utohexstr(Member.Offset)); + OS.EmitIntValue(Member.Offset, 4); + } +} + +/// The Func kind represents both subprogram and pointee of function +/// pointers. If the FuncName is empty, it represents a pointee of function +/// pointer. Otherwise, it represents a subprogram. The func arg names +/// are empty for pointee of function pointer case, and are valid names +/// for subprogram. +BTFTypeFuncProto::BTFTypeFuncProto( + const DISubroutineType *STy, uint32_t VLen, + const std::unordered_map &FuncArgNames) + : STy(STy), FuncArgNames(FuncArgNames) { + Kind = BTF::BTF_KIND_FUNC_PROTO; + BTFType.Info = (Kind << 24) | VLen; +} + +void BTFTypeFuncProto::completeType(BTFDebug &BDebug) { + DITypeRefArray Elements = STy->getTypeArray(); + auto RetType = Elements[0].resolve(); + BTFType.Type = RetType ? BDebug.getTypeId(RetType) : 0; + BTFType.NameOff = 0; + + // For null parameter which is typically the last one + // to represent the vararg, encode the NameOff/Type to be 0. + for (unsigned I = 1, N = Elements.size(); I < N; ++I) { + struct BTF::BTFParam Param; + auto Element = Elements[I].resolve(); + if (Element) { + Param.NameOff = BDebug.addString(FuncArgNames[I]); + Param.Type = BDebug.getTypeId(Element); + } else { + Param.NameOff = 0; + Param.Type = 0; + } + Parameters.push_back(Param); + } +} + +void BTFTypeFuncProto::emitType(MCStreamer &OS) { + BTFTypeBase::emitType(OS); + for (const auto &Param : Parameters) { + OS.EmitIntValue(Param.NameOff, 4); + OS.EmitIntValue(Param.Type, 4); + } +} + +BTFTypeFunc::BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId) + : Name(FuncName) { + Kind = BTF::BTF_KIND_FUNC; + BTFType.Info = Kind << 24; + BTFType.Type = ProtoTypeId; +} + +void BTFTypeFunc::completeType(BTFDebug &BDebug) { + BTFType.NameOff = BDebug.addString(Name); +} + +void BTFTypeFunc::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); } + +uint32_t BTFStringTable::addString(StringRef S) { + // Check whether the string already exists. + for (auto &OffsetM : OffsetToIdMap) { + if (Table[OffsetM.second] == S) + return OffsetM.first; + } + // Not find, add to the string table. + uint32_t Offset = Size; + OffsetToIdMap[Offset] = Table.size(); + Table.push_back(S); + Size += S.size() + 1; + return Offset; +} + +BTFDebug::BTFDebug(AsmPrinter *AP) + : DebugHandlerBase(AP), OS(*Asm->OutStreamer), SkipInstruction(false), + LineInfoGenerated(false), SecNameOff(0), ArrayIndexTypeId(0) { + addString("\0"); +} + +void BTFDebug::addType(std::unique_ptr TypeEntry, + const DIType *Ty) { + TypeEntry->setId(TypeEntries.size() + 1); + DIToIdMap[Ty] = TypeEntry->getId(); + TypeEntries.push_back(std::move(TypeEntry)); +} + +uint32_t BTFDebug::addType(std::unique_ptr TypeEntry) { + TypeEntry->setId(TypeEntries.size() + 1); + uint32_t Id = TypeEntry->getId(); + TypeEntries.push_back(std::move(TypeEntry)); + return Id; +} + +void BTFDebug::visitBasicType(const DIBasicType *BTy) { + // Only int types are supported in BTF. + uint32_t Encoding = BTy->getEncoding(); + if (Encoding != dwarf::DW_ATE_boolean && Encoding != dwarf::DW_ATE_signed && + Encoding != dwarf::DW_ATE_signed_char && + Encoding != dwarf::DW_ATE_unsigned && + Encoding != dwarf::DW_ATE_unsigned_char) + return; + + // Create a BTF type instance for this DIBasicType and put it into + // DIToIdMap for cross-type reference check. + auto TypeEntry = llvm::make_unique( + Encoding, BTy->getSizeInBits(), BTy->getOffsetInBits(), BTy->getName()); + addType(std::move(TypeEntry), BTy); +} + +/// Handle subprogram or subroutine types. +void BTFDebug::visitSubroutineType( + const DISubroutineType *STy, bool ForSubprog, + const std::unordered_map &FuncArgNames, + uint32_t &TypeId) { + DITypeRefArray Elements = STy->getTypeArray(); + uint32_t VLen = Elements.size() - 1; + if (VLen > BTF::MAX_VLEN) + return; + + // Subprogram has a valid non-zero-length name, and the pointee of + // a function pointer has an empty name. The subprogram type will + // not be added to DIToIdMap as it should not be referenced by + // any other types. + auto TypeEntry = llvm::make_unique(STy, VLen, FuncArgNames); + if (ForSubprog) + TypeId = addType(std::move(TypeEntry)); // For subprogram + else + addType(std::move(TypeEntry), STy); // For func ptr + + // Visit return type and func arg types. + for (const auto Element : Elements) { + visitTypeEntry(Element.resolve()); + } +} + +/// Handle structure/union types. +void BTFDebug::visitStructType(const DICompositeType *CTy, bool IsStruct) { + const DINodeArray Elements = CTy->getElements(); + uint32_t VLen = Elements.size(); + if (VLen > BTF::MAX_VLEN) + return; + + // Check whether we have any bitfield members or not + bool HasBitField = false; + for (const auto *Element : Elements) { + auto E = cast(Element); + if (E->isBitField()) { + HasBitField = true; + break; + } + } + + auto TypeEntry = + llvm::make_unique(CTy, IsStruct, HasBitField, VLen); + addType(std::move(TypeEntry), CTy); + + // Visit all struct members. + for (const auto *Element : Elements) + visitTypeEntry(cast(Element)); +} + +void BTFDebug::visitArrayType(const DICompositeType *CTy) { + auto TypeEntry = llvm::make_unique(CTy); + addType(std::move(TypeEntry), CTy); + + // The IR does not have a type for array index while BTF wants one. + // So create an array index type if there is none. + if (!ArrayIndexTypeId) { + auto TypeEntry = llvm::make_unique(dwarf::DW_ATE_unsigned, 32, + 0, "__ARRAY_SIZE_TYPE__"); + ArrayIndexTypeId = addType(std::move(TypeEntry)); + } + + // Visit array element type. + visitTypeEntry(CTy->getBaseType().resolve()); +} + +void BTFDebug::visitEnumType(const DICompositeType *CTy) { + DINodeArray Elements = CTy->getElements(); + uint32_t VLen = Elements.size(); + if (VLen > BTF::MAX_VLEN) + return; + + auto TypeEntry = llvm::make_unique(CTy, VLen); + addType(std::move(TypeEntry), CTy); + // No need to visit base type as BTF does not encode it. +} + +/// Handle structure/union forward declarations. +void BTFDebug::visitFwdDeclType(const DICompositeType *CTy, bool IsUnion) { + auto TypeEntry = llvm::make_unique(CTy->getName(), IsUnion); + addType(std::move(TypeEntry), CTy); +} + +/// Handle structure, union, array and enumeration types. +void BTFDebug::visitCompositeType(const DICompositeType *CTy) { + auto Tag = CTy->getTag(); + if (Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { + // Handle forward declaration differently as it does not have members. + if (CTy->isForwardDecl()) + visitFwdDeclType(CTy, Tag == dwarf::DW_TAG_union_type); + else + visitStructType(CTy, Tag == dwarf::DW_TAG_structure_type); + } else if (Tag == dwarf::DW_TAG_array_type) + visitArrayType(CTy); + else if (Tag == dwarf::DW_TAG_enumeration_type) + visitEnumType(CTy); +} + +/// Handle pointer, typedef, const, volatile, restrict and member types. +void BTFDebug::visitDerivedType(const DIDerivedType *DTy) { + unsigned Tag = DTy->getTag(); + + if (Tag == dwarf::DW_TAG_pointer_type || Tag == dwarf::DW_TAG_typedef || + Tag == dwarf::DW_TAG_const_type || Tag == dwarf::DW_TAG_volatile_type || + Tag == dwarf::DW_TAG_restrict_type) { + auto TypeEntry = llvm::make_unique(DTy, Tag); + addType(std::move(TypeEntry), DTy); + } else if (Tag != dwarf::DW_TAG_member) { + return; + } + + // Visit base type of pointer, typedef, const, volatile, restrict or + // struct/union member. + visitTypeEntry(DTy->getBaseType().resolve()); +} + +void BTFDebug::visitTypeEntry(const DIType *Ty) { + if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) + return; + + uint32_t TypeId; + if (const auto *BTy = dyn_cast(Ty)) + visitBasicType(BTy); + else if (const auto *STy = dyn_cast(Ty)) + visitSubroutineType(STy, false, std::unordered_map(), + TypeId); + else if (const auto *CTy = dyn_cast(Ty)) + visitCompositeType(CTy); + else if (const auto *DTy = dyn_cast(Ty)) + visitDerivedType(DTy); + else + llvm_unreachable("Unknown DIType"); +} + +/// Read file contents from the actual file or from the source +std::string BTFDebug::populateFileContent(const DISubprogram *SP) { + auto File = SP->getFile(); + std::string FileName; + + if (File->getDirectory().size()) + FileName = File->getDirectory().str() + "/" + File->getFilename().str(); + else + FileName = File->getFilename(); + + // No need to populate the contends if it has been populated! + if (FileContent.find(FileName) != FileContent.end()) + return FileName; + + std::vector Content; + std::string Line; + Content.push_back(Line); // Line 0 for empty string + + auto Source = File->getSource(); + if (Source) { + std::istringstream InputString(Source.getValue()); + while (std::getline(InputString, Line)) + Content.push_back(Line); + } else { + std::ifstream InputFile(FileName); + while (std::getline(InputFile, Line)) + Content.push_back(Line); + } + + FileContent[FileName] = Content; + return FileName; +} + +void BTFDebug::constructLineInfo(const DISubprogram *SP, MCSymbol *Label, + uint32_t Line, uint32_t Column) { + std::string FileName = populateFileContent(SP); + BTFLineInfo LineInfo; + + LineInfo.Label = Label; + LineInfo.FileNameOff = addString(FileName); + // If file content is not available, let LineOff = 0. + if (Line < FileContent[FileName].size()) + LineInfo.LineOff = addString(FileContent[FileName][Line]); + else + LineInfo.LineOff = 0; + LineInfo.LineNum = Line; + LineInfo.ColumnNum = Column; + LineInfoTable[SecNameOff].push_back(LineInfo); +} + +void BTFDebug::emitCommonHeader() { + OS.AddComment("0x" + Twine::utohexstr(BTF::MAGIC)); + OS.EmitIntValue(BTF::MAGIC, 2); + OS.EmitIntValue(BTF::VERSION, 1); + OS.EmitIntValue(0, 1); +} + +void BTFDebug::emitBTFSection() { + MCContext &context = OS.getContext(); + OS.SwitchSection(context.getObjectFileInfo()->getBTFSection()); + + // Emit header. + emitCommonHeader(); + OS.EmitIntValue(BTF::HeaderSize, 4); + + uint32_t TypeLen = 0, StrLen; + for (const auto &TypeEntry : TypeEntries) + TypeLen += TypeEntry->getSize(); + StrLen = StringTable.getSize(); + + OS.EmitIntValue(0, 4); + OS.EmitIntValue(TypeLen, 4); + OS.EmitIntValue(TypeLen, 4); + OS.EmitIntValue(StrLen, 4); + + // Emit type table. + for (const auto &TypeEntry : TypeEntries) + TypeEntry->emitType(OS); + + // Emit string table. + uint32_t StringOffset = 0; + for (const auto &S : StringTable.getTable()) { + OS.AddComment("string offset=" + std::to_string(StringOffset)); + OS.EmitBytes(S); + OS.EmitBytes(StringRef("\0", 1)); + StringOffset += S.size() + 1; + } +} + +void BTFDebug::emitBTFExtSection() { + MCContext &context = OS.getContext(); + OS.SwitchSection(context.getObjectFileInfo()->getBTFExtSection()); + + // Emit header. + emitCommonHeader(); + OS.EmitIntValue(BTF::ExtHeaderSize, 4); + + // Account for FuncInfo/LineInfo record size as well. + uint32_t FuncLen = 4, LineLen = 4; + for (const auto &FuncSec : FuncInfoTable) { + FuncLen += BTF::SecFuncInfoSize; + FuncLen += FuncSec.second.size() * BTF::BPFFuncInfoSize; + } + for (const auto &LineSec : LineInfoTable) { + LineLen += BTF::SecLineInfoSize; + LineLen += LineSec.second.size() * BTF::BPFLineInfoSize; + } + + OS.EmitIntValue(0, 4); + OS.EmitIntValue(FuncLen, 4); + OS.EmitIntValue(FuncLen, 4); + OS.EmitIntValue(LineLen, 4); + + // Emit func_info table. + OS.AddComment("FuncInfo"); + OS.EmitIntValue(BTF::BPFFuncInfoSize, 4); + for (const auto &FuncSec : FuncInfoTable) { + OS.AddComment("FuncInfo section string offset=" + + std::to_string(FuncSec.first)); + OS.EmitIntValue(FuncSec.first, 4); + OS.EmitIntValue(FuncSec.second.size(), 4); + for (const auto &FuncInfo : FuncSec.second) { + Asm->EmitLabelReference(FuncInfo.Label, 4); + OS.EmitIntValue(FuncInfo.TypeId, 4); + } + } + + // Emit line_info table. + OS.AddComment("LineInfo"); + OS.EmitIntValue(BTF::BPFLineInfoSize, 4); + for (const auto &LineSec : LineInfoTable) { + OS.AddComment("LineInfo section string offset=" + + std::to_string(LineSec.first)); + OS.EmitIntValue(LineSec.first, 4); + OS.EmitIntValue(LineSec.second.size(), 4); + for (const auto &LineInfo : LineSec.second) { + Asm->EmitLabelReference(LineInfo.Label, 4); + OS.EmitIntValue(LineInfo.FileNameOff, 4); + OS.EmitIntValue(LineInfo.LineOff, 4); + OS.AddComment("Line " + std::to_string(LineInfo.LineNum) + " Col " + + std::to_string(LineInfo.ColumnNum)); + OS.EmitIntValue(LineInfo.LineNum << 10 | LineInfo.ColumnNum, 4); + } + } +} + +void BTFDebug::beginFunctionImpl(const MachineFunction *MF) { + auto *SP = MF->getFunction().getSubprogram(); + auto *Unit = SP->getUnit(); + + if (Unit->getEmissionKind() == DICompileUnit::NoDebug) { + SkipInstruction = true; + return; + } + SkipInstruction = false; + + // Collect all types locally referenced in this function. + // Use RetainedNodes so we can collect all argument names + // even if the argument is not used. + std::unordered_map FuncArgNames; + for (const DINode *DN : SP->getRetainedNodes()) { + if (const auto *DV = dyn_cast(DN)) { + visitTypeEntry(DV->getType().resolve()); + + // Collect function arguments for subprogram func type. + uint32_t Arg = DV->getArg(); + if (Arg) + FuncArgNames[Arg] = DV->getName(); + } + } + + // Construct subprogram func proto type. + uint32_t ProtoTypeId; + visitSubroutineType(SP->getType(), true, FuncArgNames, ProtoTypeId); + + // Construct subprogram func type + auto FuncTypeEntry = + llvm::make_unique(SP->getName(), ProtoTypeId); + uint32_t FuncTypeId = addType(std::move(FuncTypeEntry)); + + // Construct funcinfo and the first lineinfo for the function. + MCSymbol *FuncLabel = Asm->getFunctionBegin(); + BTFFuncInfo FuncInfo; + FuncInfo.Label = FuncLabel; + FuncInfo.TypeId = FuncTypeId; + if (FuncLabel->isInSection()) { + MCSection &Section = FuncLabel->getSection(); + const MCSectionELF *SectionELF = dyn_cast(&Section); + assert(SectionELF && "Null section for Function Label"); + SecNameOff = addString(SectionELF->getSectionName()); + } else { + SecNameOff = addString(".text"); + } + FuncInfoTable[SecNameOff].push_back(FuncInfo); +} + +void BTFDebug::endFunctionImpl(const MachineFunction *MF) { + SkipInstruction = false; + LineInfoGenerated = false; + SecNameOff = 0; +} + +void BTFDebug::beginInstruction(const MachineInstr *MI) { + DebugHandlerBase::beginInstruction(MI); + + if (SkipInstruction || MI->isMetaInstruction() || + MI->getFlag(MachineInstr::FrameSetup)) + return; + + if (MI->isInlineAsm()) { + // Count the number of register definitions to find the asm string. + unsigned NumDefs = 0; + for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); + ++NumDefs) + ; + + // Skip this inline asm instruction if the asmstr is empty. + const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); + if (AsmStr[0] == 0) + return; + } + + // Skip this instruction if no DebugLoc or the DebugLoc + // is the same as the previous instruction. + const DebugLoc &DL = MI->getDebugLoc(); + if (!DL || PrevInstLoc == DL) { + // This instruction will be skipped, no LineInfo has + // been generated, construct one based on function signature. + if (LineInfoGenerated == false) { + auto *S = MI->getMF()->getFunction().getSubprogram(); + MCSymbol *FuncLabel = Asm->getFunctionBegin(); + constructLineInfo(S, FuncLabel, S->getLine(), 0); + LineInfoGenerated = true; + } + + return; + } + + // Create a temporary label to remember the insn for lineinfo. + MCSymbol *LineSym = OS.getContext().createTempSymbol(); + OS.EmitLabel(LineSym); + + // Construct the lineinfo. + auto SP = DL.get()->getScope()->getSubprogram(); + constructLineInfo(SP, LineSym, DL.getLine(), DL.getCol()); + + LineInfoGenerated = true; + PrevInstLoc = DL; +} + +void BTFDebug::endModule() { + // Collect all types referenced by globals. + const Module *M = MMI->getModule(); + for (const DICompileUnit *CUNode : M->debug_compile_units()) { + for (const auto *GVE : CUNode->getGlobalVariables()) { + DIGlobalVariable *GV = GVE->getVariable(); + visitTypeEntry(GV->getType().resolve()); + } + } + + // Complete BTF type cross refereences. + for (const auto &TypeEntry : TypeEntries) + TypeEntry->completeType(*this); + + // Emit BTF sections. + emitBTFSection(); + emitBTFExtSection(); +} Index: lib/Target/BPF/CMakeLists.txt =================================================================== --- lib/Target/BPF/CMakeLists.txt +++ lib/Target/BPF/CMakeLists.txt @@ -25,6 +25,7 @@ BPFTargetMachine.cpp BPFMIPeephole.cpp BPFMIChecking.cpp + BTFDebug.cpp ) add_subdirectory(AsmParser) Index: test/CodeGen/BPF/BTF/array-1d-char.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/array-1d-char.ll @@ -0,0 +1,68 @@ +; 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: +; char a[10]; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global [10 x i8] zeroinitializer, align 1, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12} +!llvm.ident = !{!13} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 56 +; CHECK-NEXT: .long 56 +; CHECK-NEXT: .long 26 +; CHECK-NEXT: .long 0 # BTF_KIND_ARRAY(id = 1) +; CHECK-NEXT: .long 50331648 # 0x3000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 10 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 32 # 0x20 +; CHECK-NEXT: .long 21 # BTF_KIND_INT(id = 3) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "__ARRAY_SIZE_TYPE__" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=21 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 80, elements: !8) +!7 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!8 = !{!9} +!9 = !DISubrange(count: 10) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} Index: test/CodeGen/BPF/BTF/array-1d-int.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/array-1d-int.ll @@ -0,0 +1,68 @@ +; 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: +; int a[10]; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global [10 x i32] zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12} +!llvm.ident = !{!13} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 56 +; CHECK-NEXT: .long 56 +; CHECK-NEXT: .long 25 +; CHECK-NEXT: .long 0 # BTF_KIND_ARRAY(id = 1) +; CHECK-NEXT: .long 50331648 # 0x3000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 10 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 32 # 0x20 +; CHECK-NEXT: .long 21 # BTF_KIND_INT(id = 3) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "__ARRAY_SIZE_TYPE__" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=21 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 320, elements: !8) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{!9} +!9 = !DISubrange(count: 10) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} Index: test/CodeGen/BPF/BTF/array-2d-int.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/array-2d-int.ll @@ -0,0 +1,68 @@ +; 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: +; int a[10][10]; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global [10 x [10 x i32]] zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12} +!llvm.ident = !{!13} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 56 +; CHECK-NEXT: .long 56 +; CHECK-NEXT: .long 25 +; CHECK-NEXT: .long 0 # BTF_KIND_ARRAY(id = 1) +; CHECK-NEXT: .long 50331648 # 0x3000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 100 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 32 # 0x20 +; CHECK-NEXT: .long 21 # BTF_KIND_INT(id = 3) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "__ARRAY_SIZE_TYPE__" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=21 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 3200, elements: !8) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{!9, !9} +!9 = !DISubrange(count: 10) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} Index: test/CodeGen/BPF/BTF/array-size-0.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/array-size-0.ll @@ -0,0 +1,70 @@ +; 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 t {}; +; struct t a[10]; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +%struct.t = type {} + +@a = common dso_local local_unnamed_addr global [10 x %struct.t] zeroinitializer, align 1, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12} +!llvm.ident = !{!13} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 52 +; CHECK-NEXT: .long 52 +; CHECK-NEXT: .long 23 +; CHECK-NEXT: .long 0 # BTF_KIND_ARRAY(id = 1) +; CHECK-NEXT: .long 50331648 # 0x3000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 32 # 0x20 +; CHECK-NEXT: .long 21 # BTF_KIND_STRUCT(id = 3) +; CHECK-NEXT: .long 67108864 # 0x4000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "__ARRAY_SIZE_TYPE__" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 116 # string offset=21 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, elements: !8) +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: !3, line: 1, elements: !4) +!8 = !{!9} +!9 = !DISubrange(count: 10) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} Index: test/CodeGen/BPF/BTF/array-typedef.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/array-typedef.ll @@ -0,0 +1,82 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s + +; Source code: +; typedef unsigned _int; +; typedef _int __int; +; __int a[10]; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global [10 x i32] zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!12, !13, !14} +!llvm.ident = !{!15} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 80 +; CHECK-NEXT: .long 80 +; CHECK-NEXT: .long 45 +; CHECK-NEXT: .long 0 # BTF_KIND_ARRAY(id = 1) +; CHECK-NEXT: .long 50331648 # 0x3000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 10 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 32 # 0x20 +; CHECK-NEXT: .long 21 # BTF_KIND_TYPEDEF(id = 3) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 27 # BTF_KIND_TYPEDEF(id = 4) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 32 # BTF_KIND_INT(id = 5) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 32 # 0x20 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "__ARRAY_SIZE_TYPE__" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "__int" # string offset=21 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "_int" # string offset=27 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "unsigned int" # string offset=32 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 3, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 320, elements: !10) +!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !3, line: 2, baseType: !8) +!8 = !DIDerivedType(tag: DW_TAG_typedef, name: "_int", file: !3, line: 1, baseType: !9) +!9 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!10 = !{!11} +!11 = !DISubrange(count: 10) +!12 = !{i32 2, !"Dwarf Version", i32 4} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 4} +!15 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} Index: test/CodeGen/BPF/BTF/binary-format.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/binary-format.ll @@ -0,0 +1,68 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; int f(int a) { return a; } +; Compilation flag: +; clang -target bpf -O2 -g -gdwarf-5 -gembed-source -S -emit-llvm t.c + +; Function Attrs: nounwind readnone +define dso_local i32 @f(i32 returned %a) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata i32 %a, metadata !12, metadata !DIExpression()), !dbg !13 + ret i32 %a, !dbg !14 +} + +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 30000000 +; CHECK-EL: 0x00000010 30000000 33000000 2b000000 00000001 +; CHECK-EL: 0x00000020 04000000 20000001 00000000 0100000d +; CHECK-EL: 0x00000030 01000000 2f000000 01000000 31000000 +; CHECK-EL: 0x00000040 0000000c 02000000 002e7465 7874002f +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000030 +; CHECK-EB: 0x00000010 00000030 00000033 0000002b 01000000 +; CHECK-EB: 0x00000020 00000004 01000020 00000000 0d000001 +; CHECK-EB: 0x00000030 00000001 0000002f 00000001 00000031 +; CHECK-EB: 0x00000040 0c000000 00000002 002e7465 7874002f +; CHECK: 0x00000050 746d702f 742e6300 696e7420 6628696e +; CHECK: 0x00000060 74206129 207b2072 65747572 6e20613b +; CHECK: 0x00000070 207d0069 6e740061 006600 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 14000000 +; CHECK-EL: 0x00000010 14000000 2c000000 08000000 01000000 +; CHECK-EL: 0x00000020 01000000 00000000 03000000 10000000 +; CHECK-EL: 0x00000030 01000000 02000000 00000000 07000000 +; CHECK-EL: 0x00000040 10000000 00040000 08000000 07000000 +; CHECK-EL: 0x00000050 10000000 10040000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000014 +; CHECK-EB: 0x00000010 00000014 0000002c 00000008 00000001 +; CHECK-EB: 0x00000020 00000001 00000000 00000003 00000010 +; CHECK-EB: 0x00000030 00000001 00000002 00000000 00000007 +; CHECK-EB: 0x00000040 00000010 00000400 00000008 00000007 +; CHECK-EB: 0x00000050 00000010 00000410 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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 speculatable } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/tmp", checksumkind: CSK_MD5, checksum: "1924f0d78deb326ceb76cd8e9f450775", source: "int f(int a) { return a; }\0A") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 1, type: !10) +!13 = !DILocation(line: 1, column: 11, scope: !7) +!14 = !DILocation(line: 1, column: 16, scope: !7) Index: test/CodeGen/BPF/BTF/char.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/char.ll @@ -0,0 +1,53 @@ +; 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: +; char a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i8 0, align 1, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "char" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/enum-basic.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/enum-basic.ll @@ -0,0 +1,62 @@ +; 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: +; enum { A = -1, B = 2 } a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12, !13} +!llvm.ident = !{!14} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 28 +; CHECK-NEXT: .long 28 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 0 # BTF_KIND_ENUM(id = 1) +; CHECK-NEXT: .long 100663298 # 0x6000002 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long -1 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .byte 65 # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 66 # string offset=3 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !10, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{!5} +!5 = !DICompositeType(tag: DW_TAG_enumeration_type, file: !3, line: 1, baseType: !6, size: 32, elements: !7) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !{!8, !9} +!8 = !DIEnumerator(name: "A", value: -1) +!9 = !DIEnumerator(name: "B", value: 2) +!10 = !{!0} +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 1, !"wchar_size", i32 4} +!14 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/func-func-ptr.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/func-func-ptr.ll @@ -0,0 +1,128 @@ +; 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: +; void (*a1)(int p1); +; struct t1 { void (*a1)(int p1); } b1; +; void f1(int p2) { } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +%struct.t1 = type { void (i32)* } + +@a1 = common dso_local local_unnamed_addr global void (i32)* null, align 8, !dbg !0 +@b1 = common dso_local local_unnamed_addr global %struct.t1 zeroinitializer, align 8, !dbg !6 + +; Function Attrs: nounwind readnone +define dso_local void @f1(i32 %p2) local_unnamed_addr #0 !dbg !19 { +entry: + call void @llvm.dbg.value(metadata i32 %p2, metadata !21, metadata !DIExpression()), !dbg !22 + ret void, !dbg !23 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 104 +; CHECK-NEXT: .long 104 +; CHECK-NEXT: .long 32 +; CHECK-NEXT: .long 16 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 2) +; CHECK-NEXT: .long 218103809 # 0xd000001 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 23 # BTF_KIND_FUNC(id = 3) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 4) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 5) +; CHECK-NEXT: .long 218103809 # 0xd000001 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 26 # BTF_KIND_STRUCT(id = 6) +; CHECK-NEXT: .long 67108865 # 0x4000001 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 29 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii ".text" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/t.c" # string offset=7 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "p2" # string offset=20 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "f1" # string offset=23 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "t1" # string offset=26 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "a1" # string offset=29 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 28 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 1 # FuncInfo section string offset=1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long .Lfunc_begin0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 16 # LineInfo +; CHECK-NEXT: .long 1 # LineInfo section string offset=1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3091 # Line 3 Col 19 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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 speculatable } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!15, !16, !17} +!llvm.ident = !{!18} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a1", scope: !2, file: !3, line: 1, type: !11, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/tmp") +!4 = !{} +!5 = !{!0, !6} +!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!7 = distinct !DIGlobalVariable(name: "b1", scope: !2, file: !3, line: 2, type: !8, isLocal: false, isDefinition: true) +!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", file: !3, line: 2, size: 64, elements: !9) +!9 = !{!10} +!10 = !DIDerivedType(tag: DW_TAG_member, name: "a1", scope: !8, file: !3, line: 2, baseType: !11, size: 64) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DISubroutineType(types: !13) +!13 = !{null, !14} +!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!15 = !{i32 2, !"Dwarf Version", i32 4} +!16 = !{i32 2, !"Debug Info Version", i32 3} +!17 = !{i32 1, !"wchar_size", i32 4} +!18 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} +!19 = distinct !DISubprogram(name: "f1", scope: !3, file: !3, line: 3, type: !12, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !20) +!20 = !{!21} +!21 = !DILocalVariable(name: "p2", arg: 1, scope: !19, file: !3, line: 3, type: !14) +!22 = !DILocation(line: 3, column: 13, scope: !19) +!23 = !DILocation(line: 3, column: 19, scope: !19) Index: test/CodeGen/BPF/BTF/func-non-void.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/func-non-void.ll @@ -0,0 +1,97 @@ +; 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: +; int f1(int a1) { return a1; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +; Function Attrs: nounwind readnone +define dso_local i32 @f1(i32 returned) local_unnamed_addr #0 !dbg !7 { + call void @llvm.dbg.value(metadata i32 %0, metadata !12, metadata !DIExpression()), !dbg !13 + ret i32 %0, !dbg !14 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 48 +; CHECK-NEXT: .long 48 +; CHECK-NEXT: .long 26 +; CHECK-NEXT: .long 16 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 2) +; CHECK-NEXT: .long 218103809 # 0xd000001 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 23 # BTF_KIND_FUNC(id = 3) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii ".text" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/t.c" # string offset=7 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "a1" # string offset=20 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "f1" # string offset=23 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 44 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 1 # FuncInfo section string offset=1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long .Lfunc_begin0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 16 # LineInfo +; CHECK-NEXT: .long 1 # LineInfo section string offset=1 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long .Lfunc_begin0 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 1024 # Line 1 Col 0 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 1042 # Line 1 Col 18 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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 speculatable } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 345562) (llvm/trunk 345560)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 345562) (llvm/trunk 345560)"} +!7 = distinct !DISubprogram(name: "f1", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12} +!12 = !DILocalVariable(name: "a1", arg: 1, scope: !7, file: !1, line: 1, type: !10) +!13 = !DILocation(line: 1, column: 12, scope: !7) +!14 = !DILocation(line: 1, column: 18, scope: !7) Index: test/CodeGen/BPF/BTF/func-source.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/func-source.ll @@ -0,0 +1,80 @@ +; 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: +; void f(void) { } +; Compilation flag: +; clang -target bpf -O2 -g -gdwarf-5 -gembed-source -S -emit-llvm t.c +; +; This test embeds the source code in the IR, so the line info should have +; correct reference to the lines in the string table. + +; Function Attrs: norecurse nounwind readnone +define dso_local void @f() local_unnamed_addr #0 !dbg !7 { +entry: + ret void, !dbg !10 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 35 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) +; CHECK-NEXT: .long 218103808 # 0xd000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 33 # BTF_KIND_FUNC(id = 2) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii ".text" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/t.c" # string offset=7 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "void f(void) { }" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 102 # string offset=33 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 28 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 1 # FuncInfo section string offset=1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long .Lfunc_begin0 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 16 # LineInfo +; CHECK-NEXT: .long 1 # LineInfo section string offset=1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 1040 # Line 1 Col 16 + +attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/tmp", checksumkind: CSK_MD5, checksum: "978599fafe3a080b456e3d95a3710359", source: "void f(void) { }\0A") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null} +!10 = !DILocation(line: 1, column: 16, scope: !7) Index: test/CodeGen/BPF/BTF/func-typedef.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/func-typedef.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: +; typedef int _int; +; typedef _int __int; +; __int f(__int a) { return a; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +; Function Attrs: nounwind readnone +define dso_local i32 @f(i32 returned %a) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata i32 %a, metadata !14, metadata !DIExpression()), !dbg !15 + ret i32 %a, !dbg !16 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 72 +; CHECK-NEXT: .long 72 +; CHECK-NEXT: .long 35 +; CHECK-NEXT: .long 16 # BTF_KIND_TYPEDEF(id = 1) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 22 # BTF_KIND_TYPEDEF(id = 2) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 27 # BTF_KIND_INT(id = 3) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 4) +; CHECK-NEXT: .long 218103809 # 0xd000001 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 31 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 33 # BTF_KIND_FUNC(id = 5) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii ".text" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/t.c" # string offset=7 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "__int" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "_int" # string offset=22 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=27 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 97 # string offset=31 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 102 # string offset=33 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 44 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 1 # FuncInfo section string offset=1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long .Lfunc_begin0 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 16 # LineInfo +; CHECK-NEXT: .long 1 # LineInfo section string offset=1 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long .Lfunc_begin0 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3072 # Line 3 Col 0 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3092 # Line 3 Col 20 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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 speculatable } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !13) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 2, baseType: !11) +!11 = !DIDerivedType(tag: DW_TAG_typedef, name: "_int", file: !1, line: 1, baseType: !12) +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !{!14} +!14 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 3, type: !10) +!15 = !DILocation(line: 3, column: 15, scope: !7) +!16 = !DILocation(line: 3, column: 20, scope: !7) Index: test/CodeGen/BPF/BTF/func-unused-arg.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/func-unused-arg.ll @@ -0,0 +1,93 @@ +; 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: +; int f1(int a1) { return 0; } +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +; Function Attrs: nounwind readnone +define dso_local i32 @f1(i32) local_unnamed_addr #0 !dbg !7 { + call void @llvm.dbg.value(metadata i32 %0, metadata !12, metadata !DIExpression()), !dbg !13 + ret i32 0, !dbg !14 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 48 +; CHECK-NEXT: .long 48 +; CHECK-NEXT: .long 26 +; CHECK-NEXT: .long 16 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 2) +; CHECK-NEXT: .long 218103809 # 0xd000001 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 23 # BTF_KIND_FUNC(id = 3) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii ".text" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/t.c" # string offset=7 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "a1" # string offset=20 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "f1" # string offset=23 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 28 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 1 # FuncInfo section string offset=1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long .Lfunc_begin0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 16 # LineInfo +; CHECK-NEXT: .long 1 # LineInfo section string offset=1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 1042 # Line 1 Col 18 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "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 speculatable } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 345562) (llvm/trunk 345560)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 345562) (llvm/trunk 345560)"} +!7 = distinct !DISubprogram(name: "f1", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12} +!12 = !DILocalVariable(name: "a1", arg: 1, scope: !7, file: !1, line: 1, type: !10) +!13 = !DILocation(line: 1, column: 12, scope: !7) +!14 = !DILocation(line: 1, column: 18, scope: !7) Index: test/CodeGen/BPF/BTF/func-void.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/func-void.ll @@ -0,0 +1,74 @@ +; 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: +; void f1(void) {} +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +; Function Attrs: norecurse nounwind readnone +define dso_local void @f1() local_unnamed_addr #0 !dbg !7 { + ret void, !dbg !10 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 19 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) +; CHECK-NEXT: .long 218103808 # 0xd000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 16 # BTF_KIND_FUNC(id = 2) +; CHECK-NEXT: .long 201326592 # 0xc000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii ".text" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "/tmp/t.c" # string offset=7 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "f1" # string offset=16 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 20 +; CHECK-NEXT: .long 28 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 1 # FuncInfo section string offset=1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long .Lfunc_begin0 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 16 # LineInfo +; CHECK-NEXT: .long 1 # LineInfo section string offset=1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 1040 # Line 1 Col 16 + +attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 345562) (llvm/trunk 345560)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 345562) (llvm/trunk 345560)"} +!7 = distinct !DISubprogram(name: "f1", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null} +!10 = !DILocation(line: 1, column: 16, scope: !7) Index: test/CodeGen/BPF/BTF/fwd-no-define.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/fwd-no-define.ll @@ -0,0 +1,73 @@ +; 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 t1; +; struct t2 {struct t1 *p;} a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +%struct.t2 = type { %struct.t1* } +%struct.t1 = type opaque + +@a = common dso_local local_unnamed_addr global %struct.t2 zeroinitializer, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12, !13} +!llvm.ident = !{!14} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 48 +; CHECK-NEXT: .long 48 +; CHECK-NEXT: .long 9 +; CHECK-NEXT: .long 1 # BTF_KIND_STRUCT(id = 1) +; CHECK-NEXT: .long 67108865 # 0x4000001 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 2) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 6 # BTF_KIND_FWD(id = 3) +; CHECK-NEXT: .long 117440512 # 0x7000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "t2" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 112 # string offset=4 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "t1" # string offset=6 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t2", file: !3, line: 2, size: 64, elements: !7) +!7 = !{!8} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "p", scope: !6, file: !3, line: 2, baseType: !9, size: 64) +!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) +!10 = !DICompositeType(tag: DW_TAG_structure_type, name: "t1", file: !3, line: 1, flags: DIFlagFwdDecl) +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 1, !"wchar_size", i32 4} +!14 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/fwd-with-define.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/fwd-with-define.ll @@ -0,0 +1,66 @@ +; 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 t1; +; struct t1 {struct t1 *p;} a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +%struct.t1 = type { %struct.t1* } + +@a = common dso_local local_unnamed_addr global %struct.t1 zeroinitializer, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12} +!llvm.ident = !{!13} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 36 +; CHECK-NEXT: .long 36 +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long 1 # BTF_KIND_STRUCT(id = 1) +; CHECK-NEXT: .long 67108865 # 0x4000001 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 2) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "t1" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 112 # string offset=4 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", file: !3, line: 2, size: 64, elements: !7) +!7 = !{!8} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "p", scope: !6, file: !3, line: 2, baseType: !9, size: 64) +!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/int.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/int.ll @@ -0,0 +1,53 @@ +; 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: +; int a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/longlong.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/longlong.ll @@ -0,0 +1,53 @@ +; 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: +; long long a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i64 0, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 15 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 16777280 # 0x1000040 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "long long int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/ptr-const-void.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/ptr-const-void.ll @@ -0,0 +1,54 @@ +; 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: +; const void *a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@p = common dso_local local_unnamed_addr global i8* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10} +!llvm.ident = !{!11} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 1) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # BTF_KIND_CONST(id = 2) +; CHECK-NEXT: .long 167772160 # 0xa000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "p", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/ptr-func-1.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/ptr-func-1.ll @@ -0,0 +1,55 @@ +; 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: +; void (*a)(void); +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global void ()* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!9, !10, !11} +!llvm.ident = !{!12} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 1) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 2) +; CHECK-NEXT: .long 218103808 # 0xd000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DISubroutineType(types: !8) +!8 = !{null} +!9 = !{i32 2, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/ptr-func-2.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/ptr-func-2.ll @@ -0,0 +1,73 @@ +; 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: +; int (*a)(int a, char b); +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i32 (i32, i8)* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12, !13} +!llvm.ident = !{!14} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 72 +; CHECK-NEXT: .long 72 +; CHECK-NEXT: .long 10 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 1) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 2) +; CHECK-NEXT: .long 218103810 # 0xd000002 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 3) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 5 # BTF_KIND_INT(id = 4) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DISubroutineType(types: !8) +!8 = !{!9, !9, !10} +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 1, !"wchar_size", i32 4} +!14 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/ptr-func-3.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/ptr-func-3.ll @@ -0,0 +1,73 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s + +; Source code: +; typedef int __int; +; __int (*a)(__int a, __int b); +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i32 (i32, i32)* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12, !13} +!llvm.ident = !{!14} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 68 +; CHECK-NEXT: .long 68 +; CHECK-NEXT: .long 11 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 1) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # BTF_KIND_FUNC_PROTO(id = 2) +; CHECK-NEXT: .long 218103810 # 0xd000002 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 1 # BTF_KIND_TYPEDEF(id = 3) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 7 # BTF_KIND_INT(id = 4) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "__int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=7 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DISubroutineType(types: !8) +!8 = !{!9, !9, !9} +!9 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !3, line: 1, baseType: !10) +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 1, !"wchar_size", i32 4} +!14 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/ptr-int.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/ptr-int.ll @@ -0,0 +1,58 @@ +; 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: +; int *a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i32* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10} +!llvm.ident = !{!11} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 28 +; CHECK-NEXT: .long 28 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 1) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/ptr-void.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/ptr-void.ll @@ -0,0 +1,50 @@ +; 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: +; void *a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i8* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 12 +; CHECK-NEXT: .long 12 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 1) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} Index: test/CodeGen/BPF/BTF/ptr-volatile-const-void.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/ptr-volatile-const-void.ll @@ -0,0 +1,58 @@ +; 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: +; volatile const void *p; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@p = common dso_local local_unnamed_addr global i8* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!9, !10, !11} +!llvm.ident = !{!12} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 36 +; CHECK-NEXT: .long 36 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 1) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # BTF_KIND_CONST(id = 2) +; CHECK-NEXT: .long 167772160 # 0xa000000 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 0 # BTF_KIND_VOLATILE(id = 3) +; CHECK-NEXT: .long 150994944 # 0x9000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "p", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !8) +!8 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: null) +!9 = !{i32 2, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/ptr-volatile-void.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/ptr-volatile-void.ll @@ -0,0 +1,54 @@ +; 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: +; volatile void *a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@p = common dso_local local_unnamed_addr global i8* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10} +!llvm.ident = !{!11} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 1) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # BTF_KIND_VOLATILE(id = 2) +; CHECK-NEXT: .long 150994944 # 0x9000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "p", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: null) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/restrict-ptr.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/restrict-ptr.ll @@ -0,0 +1,61 @@ +; 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: +; int * restrict p; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@p = common dso_local local_unnamed_addr global i32* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!9, !10, !11} +!llvm.ident = !{!12} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 40 +; CHECK-NEXT: .long 40 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 0 # BTF_KIND_RESTRICT(id = 1) +; CHECK-NEXT: .long 184549376 # 0xb000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 2) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 3) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "p", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !7) +!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) +!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!9 = !{i32 2, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/short.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/short.ll @@ -0,0 +1,54 @@ +; 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: +; short a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + + +@a = common dso_local local_unnamed_addr global i16 0, align 2, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 16777232 # 0x1000010 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "short" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/struct-anon.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/struct-anon.ll @@ -0,0 +1,76 @@ +; 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 { struct {int m;}; } a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +%struct.anon = type { %struct.anon.0 } +%struct.anon.0 = type { i32 } + +@a = common dso_local local_unnamed_addr global %struct.anon zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!13, !14, !15} +!llvm.ident = !{!16} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 64 +; CHECK-NEXT: .long 64 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 0 # BTF_KIND_STRUCT(id = 1) +; CHECK-NEXT: .long 67108865 # 0x4000001 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 0 # BTF_KIND_STRUCT(id = 2) +; CHECK-NEXT: .long 67108865 # 0x4000001 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 3 # BTF_KIND_INT(id = 3) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .byte 109 # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=3 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3, line: 1, size: 32, elements: !7) +!7 = !{!8} +!8 = !DIDerivedType(tag: DW_TAG_member, scope: !6, file: !3, line: 1, baseType: !9, size: 32) +!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !6, file: !3, line: 1, size: 32, elements: !10) +!10 = !{!11} +!11 = !DIDerivedType(tag: DW_TAG_member, name: "m", scope: !9, file: !3, line: 1, baseType: !12, size: 32) +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !{i32 2, !"Dwarf Version", i32 4} +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = !{i32 1, !"wchar_size", i32 4} +!16 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/struct-basic.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/struct-basic.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: +; struct t1 {char m1; int n1;} a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +%struct.t1 = type { i8, i32 } + +@a = common dso_local local_unnamed_addr global %struct.t1 zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!12, !13, !14} +!llvm.ident = !{!15} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 68 +; CHECK-NEXT: .long 68 +; CHECK-NEXT: .long 19 +; CHECK-NEXT: .long 1 # BTF_KIND_STRUCT(id = 1) +; CHECK-NEXT: .long 67108866 # 0x4000002 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 32 +; CHECK-NEXT: .long 10 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .long 15 # BTF_KIND_INT(id = 3) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "t1" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "m1" # string offset=4 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "n1" # string offset=7 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=10 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=15 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", file: !3, line: 1, size: 64, elements: !7) +!7 = !{!8, !10} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "m1", scope: !6, file: !3, line: 1, baseType: !9, size: 8) +!9 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!10 = !DIDerivedType(tag: DW_TAG_member, name: "n1", scope: !6, file: !3, line: 1, baseType: !11, size: 32, offset: 32) +!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!12 = !{i32 2, !"Dwarf Version", i32 4} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 4} +!15 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} Index: test/CodeGen/BPF/BTF/struct-bitfield-typedef.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/struct-bitfield-typedef.ll @@ -0,0 +1,99 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s + +; Source code: +; typedef int _int; +; typedef _int __int; +; struct {char m:2; __int n:3; char p;} a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +%struct.anon = type { i8, i8, [2 x i8] } + +@a = common dso_local local_unnamed_addr global %struct.anon zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!15, !16, !17} +!llvm.ident = !{!18} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 104 +; CHECK-NEXT: .long 104 +; CHECK-NEXT: .long 27 +; CHECK-NEXT: .long 0 # BTF_KIND_STRUCT(id = 1) +; CHECK-NEXT: .long 2214592515 # 0x84000003 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 50331650 # 0x3000002 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 8 # 0x8 +; CHECK-NEXT: .long 7 # BTF_KIND_INT(id = 2) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .long 12 # BTF_KIND_TYPEDEF(id = 3) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 18 # BTF_KIND_TYPEDEF(id = 4) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 23 # BTF_KIND_INT(id = 5) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .byte 109 # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 110 # string offset=3 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 112 # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=7 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "__int" # string offset=12 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "_int" # string offset=18 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=23 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 3, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3, line: 3, size: 32, elements: !7) +!7 = !{!8, !10, !14} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "m", scope: !6, file: !3, line: 3, baseType: !9, size: 2, flags: DIFlagBitField, extraData: i64 0) +!9 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!10 = !DIDerivedType(tag: DW_TAG_member, name: "n", scope: !6, file: !3, line: 3, baseType: !11, size: 3, offset: 2, flags: DIFlagBitField, extraData: i64 0) +!11 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !3, line: 2, baseType: !12) +!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "_int", file: !3, line: 1, baseType: !13) +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !DIDerivedType(tag: DW_TAG_member, name: "p", scope: !6, file: !3, line: 3, baseType: !9, size: 8, offset: 8) +!15 = !{i32 2, !"Dwarf Version", i32 4} +!16 = !{i32 2, !"Debug Info Version", i32 3} +!17 = !{i32 1, !"wchar_size", i32 4} +!18 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} Index: test/CodeGen/BPF/BTF/struct-enum.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/struct-enum.ll @@ -0,0 +1,86 @@ +; 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: +; enum t1 { A , B }; +; struct t2 { enum t1 m:2; enum t1 n; } a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +%struct.t2 = type { i8, i32 } + +@a = common dso_local local_unnamed_addr global %struct.t2 zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!15, !16, !17} +!llvm.ident = !{!18} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 64 +; CHECK-NEXT: .long 64 +; CHECK-NEXT: .long 15 +; CHECK-NEXT: .long 1 # BTF_KIND_STRUCT(id = 1) +; CHECK-NEXT: .long 2214592514 # 0x84000002 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 32 # 0x20 +; CHECK-NEXT: .long 8 # BTF_KIND_ENUM(id = 2) +; CHECK-NEXT: .long 100663298 # 0x6000002 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 11 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 13 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "t2" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 109 # string offset=4 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 110 # string offset=6 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "t1" # string offset=8 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 65 # string offset=11 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 66 # string offset=13 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 2, type: !11, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !10, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{!5} +!5 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "t1", file: !3, line: 1, baseType: !6, size: 32, elements: !7) +!6 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!7 = !{!8, !9} +!8 = !DIEnumerator(name: "A", value: 0, isUnsigned: true) +!9 = !DIEnumerator(name: "B", value: 1, isUnsigned: true) +!10 = !{!0} +!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t2", file: !3, line: 2, size: 64, elements: !12) +!12 = !{!13, !14} +!13 = !DIDerivedType(tag: DW_TAG_member, name: "m", scope: !11, file: !3, line: 2, baseType: !5, size: 2, flags: DIFlagBitField, extraData: i64 0) +!14 = !DIDerivedType(tag: DW_TAG_member, name: "n", scope: !11, file: !3, line: 2, baseType: !5, size: 32, offset: 32) +!15 = !{i32 2, !"Dwarf Version", i32 4} +!16 = !{i32 2, !"Debug Info Version", i32 3} +!17 = !{i32 1, !"wchar_size", i32 4} +!18 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/uchar.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/uchar.ll @@ -0,0 +1,53 @@ +; 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: +; unsigned char a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i8 0, align 1, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 15 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 8 # 0x8 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "unsigned char" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} Index: test/CodeGen/BPF/BTF/uint.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/uint.ll @@ -0,0 +1,53 @@ +; 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: +; unsigned a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 14 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 32 # 0x20 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "unsigned int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/ulonglong.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/ulonglong.ll @@ -0,0 +1,53 @@ +; 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: +; unsigned long long a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i64 0, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 64 # 0x40 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "long long unsigned int" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"} Index: test/CodeGen/BPF/BTF/union-array-typedef.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/union-array-typedef.ll @@ -0,0 +1,103 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s + +; Source code: +; typedef int _int; +; union t {char m[4]; _int n;} a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +%union.t = type { i32 } + +@a = common dso_local local_unnamed_addr global %union.t zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!16, !17, !18} +!llvm.ident = !{!19} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 120 +; CHECK-NEXT: .long 120 +; CHECK-NEXT: .long 41 +; CHECK-NEXT: .long 1 # BTF_KIND_UNION(id = 1) +; CHECK-NEXT: .long 83886082 # 0x5000002 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 0 # BTF_KIND_ARRAY(id = 2) +; CHECK-NEXT: .long 50331648 # 0x3000000 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 7 # BTF_KIND_INT(id = 3) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 32 # 0x20 +; CHECK-NEXT: .long 27 # BTF_KIND_INT(id = 4) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 16777224 # 0x1000008 +; CHECK-NEXT: .long 32 # BTF_KIND_TYPEDEF(id = 5) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long 37 # BTF_KIND_INT(id = 6) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .byte 116 # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 109 # string offset=3 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 110 # string offset=5 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "__ARRAY_SIZE_TYPE__" # string offset=7 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "char" # string offset=27 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "_int" # string offset=32 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .ascii "int" # string offset=37 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "t", file: !3, line: 2, size: 32, elements: !7) +!7 = !{!8, !13} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "m", scope: !6, file: !3, line: 2, baseType: !9, size: 32) +!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, elements: !11) +!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!11 = !{!12} +!12 = !DISubrange(count: 4) +!13 = !DIDerivedType(tag: DW_TAG_member, name: "n", scope: !6, file: !3, line: 2, baseType: !14, size: 32) +!14 = !DIDerivedType(tag: DW_TAG_typedef, name: "_int", file: !3, line: 1, baseType: !15) +!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!16 = !{i32 2, !"Dwarf Version", i32 4} +!17 = !{i32 2, !"Debug Info Version", i32 3} +!18 = !{i32 1, !"wchar_size", i32 4} +!19 = !{!"clang version 8.0.0 (trunk 345296) (llvm/trunk 345297)"} Index: test/CodeGen/BPF/BTF/ushort.ll =================================================================== --- /dev/null +++ test/CodeGen/BPF/BTF/ushort.ll @@ -0,0 +1,53 @@ +; 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: +; unsigned short a; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t.c + +@a = common dso_local local_unnamed_addr global i16 0, align 2, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +; CHECK: .section .BTF,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 16 # 0x10 +; CHECK-NEXT: .byte 0 # string offset=0 +; CHECK-NEXT: .ascii "unsigned short" # string offset=1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .section .BTF.ext,"",@progbits +; CHECK-NEXT: .short 60319 # 0xeb9f +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .long 24 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 8 # FuncInfo +; CHECK-NEXT: .long 16 # LineInfo + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344789) (llvm/trunk 344782)"}