diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/Target/BPF | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'llvm/lib/Target/BPF')
24 files changed, 611 insertions, 265 deletions
diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp index 1f5d5025bc7bc..57488bc28f982 100644 --- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp +++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp @@ -39,6 +39,8 @@ class BPFAsmParser : public MCTargetAsmParser { bool MatchingInlineAsm) override; bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; @@ -295,7 +297,7 @@ bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, break; case Match_Success: Inst.setLoc(IDLoc); - Out.EmitInstruction(Inst, getSTI()); + Out.emitInstruction(Inst, getSTI()); return false; case Match_MissingFeature: return Error(IDLoc, "instruction use requires an option to be enabled"); @@ -322,6 +324,14 @@ bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, bool BPFAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success) + return Error(StartLoc, "invalid register name"); + return false; +} + +OperandMatchResultTy BPFAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { const AsmToken &Tok = getParser().getTok(); StartLoc = Tok.getLoc(); EndLoc = Tok.getEndLoc(); @@ -330,10 +340,10 @@ bool BPFAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, if (!MatchRegisterName(Name)) { getParser().Lex(); // Eat identifier token. - return false; + return MatchOperand_Success; } - return Error(StartLoc, "invalid register name"); + return MatchOperand_NoMatch; } OperandMatchResultTy diff --git a/llvm/lib/Target/BPF/BPF.h b/llvm/lib/Target/BPF/BPF.h index 6e4f35f4c5d72..4a46b11e5e08a 100644 --- a/llvm/lib/Target/BPF/BPF.h +++ b/llvm/lib/Target/BPF/BPF.h @@ -16,6 +16,7 @@ namespace llvm { class BPFTargetMachine; ModulePass *createBPFAbstractMemberAccess(BPFTargetMachine *TM); +ModulePass *createBPFPreserveDIType(); FunctionPass *createBPFISelDag(BPFTargetMachine &TM); FunctionPass *createBPFMISimplifyPatchablePass(); @@ -25,6 +26,7 @@ FunctionPass *createBPFMIPreEmitPeepholePass(); FunctionPass *createBPFMIPreEmitCheckingPass(); void initializeBPFAbstractMemberAccessPass(PassRegistry&); +void initializeBPFPreserveDITypePass(PassRegistry&); void initializeBPFMISimplifyPatchablePass(PassRegistry&); void initializeBPFMIPeepholePass(PassRegistry&); void initializeBPFMIPeepholeTruncElimPass(PassRegistry&); diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp index a28816cc87b7d..16708c4d1ce6f 100644 --- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp +++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp @@ -92,7 +92,7 @@ #define DEBUG_TYPE "bpf-abstract-member-access" namespace llvm { -const std::string BPFCoreSharedInfo::AmaAttr = "btf_ama"; +constexpr StringRef BPFCoreSharedInfo::AmaAttr; } // namespace llvm using namespace llvm; @@ -117,7 +117,7 @@ public: struct CallInfo { uint32_t Kind; uint32_t AccessIndex; - uint32_t RecordAlignment; + Align RecordAlignment; MDNode *Metadata; Value *Base; }; @@ -157,11 +157,11 @@ private: void replaceWithGEP(std::vector<CallInst *> &CallList, uint32_t NumOfZerosIndex, uint32_t DIIndex); bool HasPreserveFieldInfoCall(CallInfoStack &CallStack); - void GetStorageBitRange(DIDerivedType *MemberTy, uint32_t RecordAlignment, + void GetStorageBitRange(DIDerivedType *MemberTy, Align RecordAlignment, uint32_t &StartBitOffset, uint32_t &EndBitOffset); uint32_t GetFieldInfo(uint32_t InfoKind, DICompositeType *CTy, uint32_t AccessIndex, uint32_t PatchImm, - uint32_t RecordAlignment); + Align RecordAlignment); Value *computeBaseAndAccessKey(CallInst *Call, CallInfo &CInfo, std::string &AccessKey, MDNode *&BaseMeta); @@ -189,18 +189,20 @@ bool BPFAbstractMemberAccess::runOnModule(Module &M) { return doTransformation(M); } -static bool SkipDIDerivedTag(unsigned Tag) { +static bool SkipDIDerivedTag(unsigned Tag, bool skipTypedef) { if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_member) - return false; + return false; + if (Tag == dwarf::DW_TAG_typedef && !skipTypedef) + return false; return true; } -static DIType * stripQualifiers(DIType *Ty) { +static DIType * stripQualifiers(DIType *Ty, bool skipTypedef = true) { while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { - if (!SkipDIDerivedTag(DTy->getTag())) + if (!SkipDIDerivedTag(DTy->getTag(), skipTypedef)) break; Ty = DTy->getBaseType(); } @@ -209,7 +211,7 @@ static DIType * stripQualifiers(DIType *Ty) { static const DIType * stripQualifiers(const DIType *Ty) { while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { - if (!SkipDIDerivedTag(DTy->getTag())) + if (!SkipDIDerivedTag(DTy->getTag(), true)) break; Ty = DTy->getBaseType(); } @@ -237,7 +239,7 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call, if (!Call) return false; - const auto *GV = dyn_cast<GlobalValue>(Call->getCalledValue()); + const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand()); if (!GV) return false; if (GV->getName().startswith("llvm.preserve.array.access.index")) { @@ -248,7 +250,7 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call, CInfo.AccessIndex = getConstant(Call->getArgOperand(2)); CInfo.Base = Call->getArgOperand(0); CInfo.RecordAlignment = - DL->getABITypeAlignment(CInfo.Base->getType()->getPointerElementType()); + DL->getABITypeAlign(CInfo.Base->getType()->getPointerElementType()); return true; } if (GV->getName().startswith("llvm.preserve.union.access.index")) { @@ -259,7 +261,7 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call, CInfo.AccessIndex = getConstant(Call->getArgOperand(1)); CInfo.Base = Call->getArgOperand(0); CInfo.RecordAlignment = - DL->getABITypeAlignment(CInfo.Base->getType()->getPointerElementType()); + DL->getABITypeAlign(CInfo.Base->getType()->getPointerElementType()); return true; } if (GV->getName().startswith("llvm.preserve.struct.access.index")) { @@ -270,7 +272,7 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call, CInfo.AccessIndex = getConstant(Call->getArgOperand(2)); CInfo.Base = Call->getArgOperand(0); CInfo.RecordAlignment = - DL->getABITypeAlignment(CInfo.Base->getType()->getPointerElementType()); + DL->getABITypeAlign(CInfo.Base->getType()->getPointerElementType()); return true; } if (GV->getName().startswith("llvm.bpf.preserve.field.info")) { @@ -520,12 +522,12 @@ uint64_t BPFAbstractMemberAccess::getConstant(const Value *IndexValue) { /// Get the start and the end of storage offset for \p MemberTy. void BPFAbstractMemberAccess::GetStorageBitRange(DIDerivedType *MemberTy, - uint32_t RecordAlignment, + Align RecordAlignment, uint32_t &StartBitOffset, uint32_t &EndBitOffset) { uint32_t MemberBitSize = MemberTy->getSizeInBits(); uint32_t MemberBitOffset = MemberTy->getOffsetInBits(); - uint32_t AlignBits = RecordAlignment * 8; + uint32_t AlignBits = RecordAlignment.value() * 8; if (RecordAlignment > 8 || MemberBitSize > AlignBits) report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, " "requiring too big alignment"); @@ -541,7 +543,7 @@ uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind, DICompositeType *CTy, uint32_t AccessIndex, uint32_t PatchImm, - uint32_t RecordAlignment) { + Align RecordAlignment) { if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE) return 1; @@ -710,7 +712,7 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call, // calculated here as all debuginfo types are available. // Get type name and calculate the first index. - // We only want to get type name from structure or union. + // We only want to get type name from typedef, structure or union. // If user wants a relocation like // int *p; ... __builtin_preserve_access_index(&p[4]) ... // or @@ -727,12 +729,15 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call, if (!Base) Base = CInfo.Base; - DIType *Ty = stripQualifiers(cast<DIType>(CInfo.Metadata)); + DIType *PossibleTypeDef = stripQualifiers(cast<DIType>(CInfo.Metadata), + false); + DIType *Ty = stripQualifiers(PossibleTypeDef); if (CInfo.Kind == BPFPreserveUnionAI || CInfo.Kind == BPFPreserveStructAI) { - // struct or union type - TypeName = Ty->getName(); - TypeMeta = Ty; + // struct or union type. If the typedef is in the metadata, always + // use the typedef. + TypeName = std::string(PossibleTypeDef->getName()); + TypeMeta = PossibleTypeDef; PatchImm += FirstIndex * (Ty->getSizeInBits() >> 3); break; } @@ -782,7 +787,7 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call, unsigned CTag = CTy->getTag(); if (CTag == dwarf::DW_TAG_structure_type || CTag == dwarf::DW_TAG_union_type) { - TypeName = CTy->getName(); + TypeName = std::string(CTy->getName()); } else { if (HasPreserveFieldInfoCall(CallStack)) report_fatal_error("Invalid field access for llvm.preserve.field.info intrinsic"); @@ -803,8 +808,10 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call, CInfo = StackElem.second; CallStack.pop(); - if (CInfo.Kind == BPFPreserveFieldInfoAI) + if (CInfo.Kind == BPFPreserveFieldInfoAI) { + InfoKind = CInfo.AccessIndex; break; + } // If the next Call (the top of the stack) is a BPFPreserveFieldInfoAI, // the action will be extracting field info. @@ -822,11 +829,10 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call, AccessKey += ":" + std::to_string(AccessIndex); MDNode *MDN = CInfo.Metadata; - uint32_t RecordAlignment = CInfo.RecordAlignment; // At this stage, it cannot be pointer type. auto *CTy = cast<DICompositeType>(stripQualifiers(cast<DIType>(MDN))); PatchImm = GetFieldInfo(InfoKind, CTy, AccessIndex, PatchImm, - RecordAlignment); + CInfo.RecordAlignment); } // Access key is the @@ -873,8 +879,8 @@ bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call, if (CInfo.Kind == BPFPreserveFieldInfoAI) { // Load the global variable which represents the returned field info. - auto *LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV); - BB->getInstList().insert(Call->getIterator(), LDInst); + auto *LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "", + Call); Call->replaceAllUsesWith(LDInst); Call->eraseFromParent(); return true; @@ -891,8 +897,7 @@ bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call, // The original Call inst is removed. // Load the global variable. - auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV); - BB->getInstList().insert(Call->getIterator(), LDInst); + auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call); // Generate a BitCast auto *BCInst = new BitCastInst(Base, Type::getInt8PtrTy(BB->getContext())); diff --git a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp index b81386f479d30..37950e105bdc1 100644 --- a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp +++ b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp @@ -48,7 +48,7 @@ public: bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override; - void EmitInstruction(const MachineInstr *MI) override; + void emitInstruction(const MachineInstr *MI) override; private: BTFDebug *BTF; @@ -137,7 +137,7 @@ bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, return false; } -void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) { +void BPFAsmPrinter::emitInstruction(const MachineInstr *MI) { MCInst TmpInst; if (!BTF || !BTF->InstLower(MI, TmpInst)) { diff --git a/llvm/lib/Target/BPF/BPFCORE.h b/llvm/lib/Target/BPF/BPFCORE.h index ed4778353e529..af6425b16fa01 100644 --- a/llvm/lib/Target/BPF/BPFCORE.h +++ b/llvm/lib/Target/BPF/BPFCORE.h @@ -9,22 +9,36 @@ #ifndef LLVM_LIB_TARGET_BPF_BPFCORE_H #define LLVM_LIB_TARGET_BPF_BPFCORE_H +#include "llvm/ADT/StringRef.h" + namespace llvm { class BPFCoreSharedInfo { public: - enum OffsetRelocKind : uint32_t { + enum PatchableRelocKind : uint32_t { FIELD_BYTE_OFFSET = 0, FIELD_BYTE_SIZE, FIELD_EXISTENCE, FIELD_SIGNEDNESS, FIELD_LSHIFT_U64, FIELD_RSHIFT_U64, + BTF_TYPE_ID_LOCAL, + BTF_TYPE_ID_REMOTE, MAX_FIELD_RELOC_KIND, }; + + enum BTFTypeIdFlag : uint32_t { + BTF_TYPE_ID_LOCAL_RELOC = 0, + BTF_TYPE_ID_REMOTE_RELOC, + + MAX_BTF_TYPE_ID_FLAG, + }; + /// The attribute attached to globals representing a field access - static const std::string AmaAttr; + static constexpr StringRef AmaAttr = "btf_ama"; + /// The attribute attached to globals representing a type id + static constexpr StringRef TypeIdAttr = "btf_type_id"; }; } // namespace llvm diff --git a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp index 6f5f58554d09c..d407edfbd9660 100644 --- a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp +++ b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp @@ -304,7 +304,7 @@ void BPFDAGToDAGISel::PreprocessLoad(SDNode *Node, LLVM_DEBUG(dbgs() << "Replacing load of size " << size << " with constant " << val << '\n'); - SDValue NVal = CurDAG->getConstant(val, DL, MVT::i64); + SDValue NVal = CurDAG->getConstant(val, DL, LD->getValueType(0)); // After replacement, the current node is dead, we need to // go backward one step to make iterator still work diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp index 56e0288f26c9f..a02556a399098 100644 --- a/llvm/lib/Target/BPF/BPFISelLowering.cpp +++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp @@ -171,6 +171,38 @@ bool BPFTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) cons return false; } +bool BPFTargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const { + if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy()) + return false; + unsigned NumBits1 = Ty1->getPrimitiveSizeInBits(); + unsigned NumBits2 = Ty2->getPrimitiveSizeInBits(); + return NumBits1 > NumBits2; +} + +bool BPFTargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { + if (!VT1.isInteger() || !VT2.isInteger()) + return false; + unsigned NumBits1 = VT1.getSizeInBits(); + unsigned NumBits2 = VT2.getSizeInBits(); + return NumBits1 > NumBits2; +} + +bool BPFTargetLowering::isZExtFree(Type *Ty1, Type *Ty2) const { + if (!getHasAlu32() || !Ty1->isIntegerTy() || !Ty2->isIntegerTy()) + return false; + unsigned NumBits1 = Ty1->getPrimitiveSizeInBits(); + unsigned NumBits2 = Ty2->getPrimitiveSizeInBits(); + return NumBits1 == 32 && NumBits2 == 64; +} + +bool BPFTargetLowering::isZExtFree(EVT VT1, EVT VT2) const { + if (!getHasAlu32() || !VT1.isInteger() || !VT2.isInteger()) + return false; + unsigned NumBits1 = VT1.getSizeInBits(); + unsigned NumBits2 = VT2.getSizeInBits(); + return NumBits1 == 32 && NumBits2 == 64; +} + std::pair<unsigned, const TargetRegisterClass *> BPFTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, @@ -195,6 +227,8 @@ SDValue BPFTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { return LowerGlobalAddress(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); + case ISD::DYNAMIC_STACKALLOC: + report_fatal_error("Unsupported dynamic stack allocation"); default: llvm_unreachable("unimplemented operand"); } @@ -570,6 +604,12 @@ BPFTargetLowering::EmitSubregExt(MachineInstr &MI, MachineBasicBlock *BB, DebugLoc DL = MI.getDebugLoc(); MachineRegisterInfo &RegInfo = F->getRegInfo(); + + if (!isSigned) { + Register PromotedReg0 = RegInfo.createVirtualRegister(RC); + BuildMI(BB, DL, TII.get(BPF::MOV_32_64), PromotedReg0).addReg(Reg); + return PromotedReg0; + } Register PromotedReg0 = RegInfo.createVirtualRegister(RC); Register PromotedReg1 = RegInfo.createVirtualRegister(RC); Register PromotedReg2 = RegInfo.createVirtualRegister(RC); diff --git a/llvm/lib/Target/BPF/BPFISelLowering.h b/llvm/lib/Target/BPF/BPFISelLowering.h index b81bf4e1320dc..cc752dda87b02 100644 --- a/llvm/lib/Target/BPF/BPFISelLowering.h +++ b/llvm/lib/Target/BPF/BPFISelLowering.h @@ -99,10 +99,9 @@ private: const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override; - EVT getOptimalMemOpType(uint64_t Size, unsigned DstAlign, unsigned SrcAlign, - bool IsMemset, bool ZeroMemset, bool MemcpyStrSrc, + EVT getOptimalMemOpType(const MemOp &Op, const AttributeList &FuncAttributes) const override { - return Size >= 8 ? MVT::i64 : MVT::i32; + return Op.size() >= 8 ? MVT::i64 : MVT::i32; } bool shouldConvertConstantLoadToIntImm(const APInt &Imm, @@ -110,6 +109,29 @@ private: return true; } + // Prevent reducing load width during SelectionDag phase. + // Otherwise, we may transform the following + // ctx = ctx + reloc_offset + // ... (*(u32 *)ctx) & 0x8000... + // to + // ctx = ctx + reloc_offset + // ... (*(u8 *)(ctx + 1)) & 0x80 ... + // which will be rejected by the verifier. + bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, + EVT NewVT) const override { + return false; + } + + // isTruncateFree - Return true if it's free to truncate a value of + // type Ty1 to type Ty2. e.g. On BPF at alu32 mode, it's free to truncate + // a i64 value in register R1 to i32 by referencing its sub-register W1. + bool isTruncateFree(Type *Ty1, Type *Ty2) const override; + bool isTruncateFree(EVT VT1, EVT VT2) const override; + + // For 32bit ALU result zext to 64bit is free. + bool isZExtFree(Type *Ty1, Type *Ty2) const override; + bool isZExtFree(EVT VT1, EVT VT2) const override; + unsigned EmitSubregExt(MachineInstr &MI, MachineBasicBlock *BB, unsigned Reg, bool isSigned) const; diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.cpp b/llvm/lib/Target/BPF/BPFInstrInfo.cpp index 626c204e99e6a..54360a89782bd 100644 --- a/llvm/lib/Target/BPF/BPFInstrInfo.cpp +++ b/llvm/lib/Target/BPF/BPFInstrInfo.cpp @@ -123,7 +123,7 @@ bool BPFInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned SrcReg, bool IsKill, int FI, + Register SrcReg, bool IsKill, int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const { DebugLoc DL; @@ -146,7 +146,7 @@ void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned DestReg, int FI, + Register DestReg, int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const { DebugLoc DL; diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.h b/llvm/lib/Target/BPF/BPFInstrInfo.h index 22413d530e176..e797363ead8f2 100644 --- a/llvm/lib/Target/BPF/BPFInstrInfo.h +++ b/llvm/lib/Target/BPF/BPFInstrInfo.h @@ -36,13 +36,13 @@ public: bool expandPostRAPseudo(MachineInstr &MI) const override; void storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, unsigned SrcReg, + MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override; void loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, unsigned DestReg, + MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override; bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td index 0f39294daa2b9..4298e2eaec046 100644 --- a/llvm/lib/Target/BPF/BPFInstrInfo.td +++ b/llvm/lib/Target/BPF/BPFInstrInfo.td @@ -526,7 +526,7 @@ class NOP_I<string OpcodeStr> let BPFClass = BPF_ALU64; } -let hasSideEffects = 0 in +let hasSideEffects = 0, isCodeGenOnly = 1 in def NOP : NOP_I<"nop">; class RET<string OpcodeStr> @@ -732,8 +732,7 @@ let isCodeGenOnly = 1 in { def : Pat<(i64 (sext GPR32:$src)), (SRA_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>; -def : Pat<(i64 (zext GPR32:$src)), - (SRL_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>; +def : Pat<(i64 (zext GPR32:$src)), (MOV_32_64 GPR32:$src)>; // For i64 -> i32 truncation, use the 32-bit subregister directly. def : Pat<(i32 (trunc GPR:$src)), diff --git a/llvm/lib/Target/BPF/BPFMCInstLower.h b/llvm/lib/Target/BPF/BPFMCInstLower.h index 0622d20814d31..4bd0f1f0bf1cf 100644 --- a/llvm/lib/Target/BPF/BPFMCInstLower.h +++ b/llvm/lib/Target/BPF/BPFMCInstLower.h @@ -18,9 +18,7 @@ class MCInst; class MCOperand; class MCSymbol; class MachineInstr; -class MachineModuleInfoMachO; class MachineOperand; -class Mangler; // BPFMCInstLower - This class is used to lower an MachineInstr into an MCInst. class LLVM_LIBRARY_VISIBILITY BPFMCInstLower { diff --git a/llvm/lib/Target/BPF/BPFMIPeephole.cpp b/llvm/lib/Target/BPF/BPFMIPeephole.cpp index 022267fbe3c21..df870314fffe3 100644 --- a/llvm/lib/Target/BPF/BPFMIPeephole.cpp +++ b/llvm/lib/Target/BPF/BPFMIPeephole.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/Debug.h" +#include <set> using namespace llvm; @@ -56,6 +57,7 @@ private: bool isPhiFrom32Def(MachineInstr *MovMI); bool isMovFrom32Def(MachineInstr *MovMI); bool eliminateZExtSeq(void); + bool eliminateZExt(void); std::set<MachineInstr *> PhiInsns; @@ -68,7 +70,12 @@ public: initialize(MF); - return eliminateZExtSeq(); + // First try to eliminate (zext, lshift, rshift) and then + // try to eliminate zext. + bool ZExtSeqExist, ZExtExist; + ZExtSeqExist = eliminateZExtSeq(); + ZExtExist = eliminateZExt(); + return ZExtSeqExist || ZExtExist; } }; @@ -233,6 +240,51 @@ bool BPFMIPeephole::eliminateZExtSeq(void) { return Eliminated; } +bool BPFMIPeephole::eliminateZExt(void) { + MachineInstr* ToErase = nullptr; + bool Eliminated = false; + + for (MachineBasicBlock &MBB : *MF) { + for (MachineInstr &MI : MBB) { + // If the previous instruction was marked for elimination, remove it now. + if (ToErase) { + ToErase->eraseFromParent(); + ToErase = nullptr; + } + + if (MI.getOpcode() != BPF::MOV_32_64) + continue; + + // Eliminate MOV_32_64 if possible. + // MOV_32_64 rA, wB + // + // If wB has been zero extended, replace it with a SUBREG_TO_REG. + // This is to workaround BPF programs where pkt->{data, data_end} + // is encoded as u32, but actually the verifier populates them + // as 64bit pointer. The MOV_32_64 will zero out the top 32 bits. + LLVM_DEBUG(dbgs() << "Candidate MOV_32_64 instruction:"); + LLVM_DEBUG(MI.dump()); + + if (!isMovFrom32Def(&MI)) + continue; + + LLVM_DEBUG(dbgs() << "Removing the MOV_32_64 instruction\n"); + + Register dst = MI.getOperand(0).getReg(); + Register src = MI.getOperand(1).getReg(); + + // Build a SUBREG_TO_REG instruction. + BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), dst) + .addImm(0).addReg(src).addImm(BPF::sub_32); + + ToErase = &MI; + Eliminated = true; + } + } + + return Eliminated; +} + } // end default namespace INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE, @@ -300,19 +352,16 @@ bool BPFMIPreEmitPeephole::eliminateRedundantMov(void) { // // MOV rA, rA // - // This is particularly possible to happen when sub-register support - // enabled. The special type cast insn MOV_32_64 involves different - // register class on src (i32) and dst (i64), RA could generate useless - // instruction due to this. + // Note that we cannot remove + // MOV_32_64 rA, wA + // MOV_rr_32 wA, wA + // as these two instructions having side effects, zeroing out + // top 32 bits of rA. unsigned Opcode = MI.getOpcode(); - if (Opcode == BPF::MOV_32_64 || - Opcode == BPF::MOV_rr || Opcode == BPF::MOV_rr_32) { + if (Opcode == BPF::MOV_rr) { Register dst = MI.getOperand(0).getReg(); Register src = MI.getOperand(1).getReg(); - if (Opcode == BPF::MOV_32_64) - dst = TRI->getSubReg(dst, BPF::sub_32); - if (dst != src) continue; diff --git a/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp b/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp index 5310f0f07b65f..ae1f5ea21c127 100644 --- a/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp +++ b/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp @@ -22,6 +22,9 @@ // r1 = <calculated field_info> // add r3, struct_base_reg, r1 // +// This pass also removes the intermediate load generated in IR pass for +// __builtin_btf_type_id() intrinsic. +// //===----------------------------------------------------------------------===// #include "BPF.h" @@ -55,10 +58,10 @@ private: bool removeLD(void); void processCandidate(MachineRegisterInfo *MRI, MachineBasicBlock &MBB, MachineInstr &MI, Register &SrcReg, Register &DstReg, - const GlobalValue *GVal); + const GlobalValue *GVal, bool IsAma); void processDstReg(MachineRegisterInfo *MRI, Register &DstReg, Register &SrcReg, const GlobalValue *GVal, - bool doSrcRegProp); + bool doSrcRegProp, bool IsAma); void processInst(MachineRegisterInfo *MRI, MachineInstr *Inst, MachineOperand *RelocOp, const GlobalValue *GVal); void checkADDrr(MachineRegisterInfo *MRI, MachineOperand *RelocOp, @@ -70,9 +73,10 @@ private: public: // Main entry point for this pass. bool runOnMachineFunction(MachineFunction &MF) override { - if (!skipFunction(MF.getFunction())) { - initialize(MF); - } + if (skipFunction(MF.getFunction())) + return false; + + initialize(MF); return removeLD(); } }; @@ -115,11 +119,22 @@ void BPFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI, else continue; - // It must be a form of %1 = *(type *)(%2 + 0) or *(type *)(%2 + 0) = %1. + // It must be a form of %2 = *(type *)(%1 + 0) or *(type *)(%1 + 0) = %2. const MachineOperand &ImmOp = DefInst->getOperand(2); if (!ImmOp.isImm() || ImmOp.getImm() != 0) continue; + // Reject the form: + // %1 = ADD_rr %2, %3 + // *(type *)(%2 + 0) = %1 + if (Opcode == BPF::STB || Opcode == BPF::STH || Opcode == BPF::STW || + Opcode == BPF::STD || Opcode == BPF::STB32 || Opcode == BPF::STH32 || + Opcode == BPF::STW32) { + const MachineOperand &Opnd = DefInst->getOperand(0); + if (Opnd.isReg() && Opnd.getReg() == I->getReg()) + continue; + } + BuildMI(*DefInst->getParent(), *DefInst, DefInst->getDebugLoc(), TII->get(COREOp)) .add(DefInst->getOperand(0)).addImm(Opcode).add(*BaseOp) .addGlobalAddress(GVal); @@ -143,25 +158,27 @@ void BPFMISimplifyPatchable::checkShift(MachineRegisterInfo *MRI, void BPFMISimplifyPatchable::processCandidate(MachineRegisterInfo *MRI, MachineBasicBlock &MBB, MachineInstr &MI, Register &SrcReg, - Register &DstReg, const GlobalValue *GVal) { + Register &DstReg, const GlobalValue *GVal, bool IsAma) { if (MRI->getRegClass(DstReg) == &BPF::GPR32RegClass) { - // We can optimize such a pattern: - // %1:gpr = LD_imm64 @"llvm.s:0:4$0:2" - // %2:gpr32 = LDW32 %1:gpr, 0 - // %3:gpr = SUBREG_TO_REG 0, %2:gpr32, %subreg.sub_32 - // %4:gpr = ADD_rr %0:gpr, %3:gpr - // or similar patterns below for non-alu32 case. - auto Begin = MRI->use_begin(DstReg), End = MRI->use_end(); - decltype(End) NextI; - for (auto I = Begin; I != End; I = NextI) { - NextI = std::next(I); - if (!MRI->getUniqueVRegDef(I->getReg())) - continue; - - unsigned Opcode = I->getParent()->getOpcode(); - if (Opcode == BPF::SUBREG_TO_REG) { - Register TmpReg = I->getParent()->getOperand(0).getReg(); - processDstReg(MRI, TmpReg, DstReg, GVal, false); + if (IsAma) { + // We can optimize such a pattern: + // %1:gpr = LD_imm64 @"llvm.s:0:4$0:2" + // %2:gpr32 = LDW32 %1:gpr, 0 + // %3:gpr = SUBREG_TO_REG 0, %2:gpr32, %subreg.sub_32 + // %4:gpr = ADD_rr %0:gpr, %3:gpr + // or similar patterns below for non-alu32 case. + auto Begin = MRI->use_begin(DstReg), End = MRI->use_end(); + decltype(End) NextI; + for (auto I = Begin; I != End; I = NextI) { + NextI = std::next(I); + if (!MRI->getUniqueVRegDef(I->getReg())) + continue; + + unsigned Opcode = I->getParent()->getOpcode(); + if (Opcode == BPF::SUBREG_TO_REG) { + Register TmpReg = I->getParent()->getOperand(0).getReg(); + processDstReg(MRI, TmpReg, DstReg, GVal, false, IsAma); + } } } @@ -171,12 +188,12 @@ void BPFMISimplifyPatchable::processCandidate(MachineRegisterInfo *MRI, } // All uses of DstReg replaced by SrcReg - processDstReg(MRI, DstReg, SrcReg, GVal, true); + processDstReg(MRI, DstReg, SrcReg, GVal, true, IsAma); } void BPFMISimplifyPatchable::processDstReg(MachineRegisterInfo *MRI, Register &DstReg, Register &SrcReg, const GlobalValue *GVal, - bool doSrcRegProp) { + bool doSrcRegProp, bool IsAma) { auto Begin = MRI->use_begin(DstReg), End = MRI->use_end(); decltype(End) NextI; for (auto I = Begin; I != End; I = NextI) { @@ -185,7 +202,7 @@ void BPFMISimplifyPatchable::processDstReg(MachineRegisterInfo *MRI, I->setReg(SrcReg); // The candidate needs to have a unique definition. - if (MRI->getUniqueVRegDef(I->getReg())) + if (IsAma && MRI->getUniqueVRegDef(I->getReg())) processInst(MRI, I->getParent(), &*I, GVal); } } @@ -257,28 +274,26 @@ bool BPFMISimplifyPatchable::removeLD() { if (!DefInst) continue; - bool IsCandidate = false; - const GlobalValue *GVal = nullptr; - if (DefInst->getOpcode() == BPF::LD_imm64) { - const MachineOperand &MO = DefInst->getOperand(1); - if (MO.isGlobal()) { - GVal = MO.getGlobal(); - auto *GVar = dyn_cast<GlobalVariable>(GVal); - if (GVar) { - // Global variables representing structure offset or - // patchable extern globals. - if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) { - assert(MI.getOperand(2).getImm() == 0); - IsCandidate = true; - } - } - } - } + if (DefInst->getOpcode() != BPF::LD_imm64) + continue; + + const MachineOperand &MO = DefInst->getOperand(1); + if (!MO.isGlobal()) + continue; + + const GlobalValue *GVal = MO.getGlobal(); + auto *GVar = dyn_cast<GlobalVariable>(GVal); + if (!GVar) + continue; - if (!IsCandidate) + // Global variables representing structure offset or type id. + bool IsAma = false; + if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) + IsAma = true; + else if (!GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) continue; - processCandidate(MRI, MBB, MI, SrcReg, DstReg, GVal); + processCandidate(MRI, MBB, MI, SrcReg, DstReg, GVal, IsAma); ToErase = &MI; Changed = true; diff --git a/llvm/lib/Target/BPF/BPFPreserveDIType.cpp b/llvm/lib/Target/BPF/BPFPreserveDIType.cpp new file mode 100644 index 0000000000000..c3cb7647aa794 --- /dev/null +++ b/llvm/lib/Target/BPF/BPFPreserveDIType.cpp @@ -0,0 +1,131 @@ +//===----------- BPFPreserveDIType.cpp - Preserve DebugInfo Types ---------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Preserve Debuginfo types encoded in __builtin_btf_type_id() metadata. +// +//===----------------------------------------------------------------------===// + +#include "BPF.h" +#include "BPFCORE.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/User.h" +#include "llvm/IR/Value.h" +#include "llvm/Pass.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" + +#define DEBUG_TYPE "bpf-preserve-di-type" + +namespace llvm { +constexpr StringRef BPFCoreSharedInfo::TypeIdAttr; +} // namespace llvm + +using namespace llvm; + +namespace { + +class BPFPreserveDIType final : public ModulePass { + StringRef getPassName() const override { + return "BPF Preserve DebugInfo Type"; + } + + bool runOnModule(Module &M) override; + +public: + static char ID; + BPFPreserveDIType() : ModulePass(ID) {} + +private: + bool doTransformation(Module &M); +}; +} // End anonymous namespace + +char BPFPreserveDIType::ID = 0; +INITIALIZE_PASS(BPFPreserveDIType, DEBUG_TYPE, "preserve debuginfo type", false, + false) + +ModulePass *llvm::createBPFPreserveDIType() { return new BPFPreserveDIType(); } + +bool BPFPreserveDIType::runOnModule(Module &M) { + LLVM_DEBUG(dbgs() << "********** preserve debuginfo type **********\n"); + + // Bail out if no debug info. + if (M.debug_compile_units().empty()) + return false; + + return doTransformation(M); +} + +bool BPFPreserveDIType::doTransformation(Module &M) { + std::vector<CallInst *> PreserveDITypeCalls; + + for (auto &F : M) { + for (auto &BB : F) { + for (auto &I : BB) { + auto *Call = dyn_cast<CallInst>(&I); + if (!Call) + continue; + + const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand()); + if (!GV) + continue; + + if (GV->getName().startswith("llvm.bpf.btf.type.id")) { + if (!Call->getMetadata(LLVMContext::MD_preserve_access_index)) + report_fatal_error( + "Missing metadata for llvm.bpf.btf.type.id intrinsic"); + PreserveDITypeCalls.push_back(Call); + } + } + } + } + + if (PreserveDITypeCalls.empty()) + return false; + + std::string BaseName = "llvm.btf_type_id."; + int Count = 0; + for (auto Call : PreserveDITypeCalls) { + const ConstantInt *Flag = dyn_cast<ConstantInt>(Call->getArgOperand(2)); + assert(Flag); + uint64_t FlagValue = Flag->getValue().getZExtValue(); + + if (FlagValue >= BPFCoreSharedInfo::MAX_BTF_TYPE_ID_FLAG) + report_fatal_error("Incorrect flag for llvm.bpf.btf.type.id intrinsic"); + + uint32_t Reloc; + if (FlagValue == BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL_RELOC) + Reloc = BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL; + else + Reloc = BPFCoreSharedInfo::BTF_TYPE_ID_REMOTE; + + BasicBlock *BB = Call->getParent(); + IntegerType *VarType = Type::getInt32Ty(BB->getContext()); + std::string GVName = BaseName + std::to_string(Count) + "$" + + std::to_string(Reloc); + GlobalVariable *GV = + new GlobalVariable(M, VarType, false, GlobalVariable::ExternalLinkage, + NULL, GVName); + GV->addAttribute(BPFCoreSharedInfo::TypeIdAttr); + MDNode *MD = Call->getMetadata(LLVMContext::MD_preserve_access_index); + GV->setMetadata(LLVMContext::MD_preserve_access_index, MD); + + // Load the global variable which represents the type info. + auto *LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "", + Call); + Call->replaceAllUsesWith(LDInst); + Call->eraseFromParent(); + Count++; + } + + return true; +} diff --git a/llvm/lib/Target/BPF/BPFSelectionDAGInfo.cpp b/llvm/lib/Target/BPF/BPFSelectionDAGInfo.cpp index a711294048ba3..4c36c0edcef6f 100644 --- a/llvm/lib/Target/BPF/BPFSelectionDAGInfo.cpp +++ b/llvm/lib/Target/BPF/BPFSelectionDAGInfo.cpp @@ -19,7 +19,7 @@ using namespace llvm; SDValue BPFSelectionDAGInfo::EmitTargetCodeForMemcpy( SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, - SDValue Size, unsigned Align, bool isVolatile, bool AlwaysInline, + SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const { // Requires the copy size to be a constant. ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); @@ -27,7 +27,7 @@ SDValue BPFSelectionDAGInfo::EmitTargetCodeForMemcpy( return SDValue(); unsigned CopyLen = ConstantSize->getZExtValue(); - unsigned StoresNumEstimate = alignTo(CopyLen, Align) >> Log2_32(Align); + unsigned StoresNumEstimate = alignTo(CopyLen, Alignment) >> Log2(Alignment); // Impose the same copy length limit as MaxStoresPerMemcpy. if (StoresNumEstimate > getCommonMaxStoresPerMemFunc()) return SDValue(); @@ -36,7 +36,7 @@ SDValue BPFSelectionDAGInfo::EmitTargetCodeForMemcpy( Dst = DAG.getNode(BPFISD::MEMCPY, dl, VTs, Chain, Dst, Src, DAG.getConstant(CopyLen, dl, MVT::i64), - DAG.getConstant(Align, dl, MVT::i64)); + DAG.getConstant(Alignment.value(), dl, MVT::i64)); return Dst.getValue(0); } diff --git a/llvm/lib/Target/BPF/BPFSelectionDAGInfo.h b/llvm/lib/Target/BPF/BPFSelectionDAGInfo.h index fb88c32ceb0cf..79f05e57bb5cd 100644 --- a/llvm/lib/Target/BPF/BPFSelectionDAGInfo.h +++ b/llvm/lib/Target/BPF/BPFSelectionDAGInfo.h @@ -21,8 +21,8 @@ class BPFSelectionDAGInfo : public SelectionDAGTargetInfo { public: SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, - SDValue Size, unsigned Align, bool isVolatile, - bool AlwaysInline, + SDValue Size, Align Alignment, + bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const override; diff --git a/llvm/lib/Target/BPF/BPFTargetMachine.cpp b/llvm/lib/Target/BPF/BPFTargetMachine.cpp index 40375bc88bff2..54204ee197ec0 100644 --- a/llvm/lib/Target/BPF/BPFTargetMachine.cpp +++ b/llvm/lib/Target/BPF/BPFTargetMachine.cpp @@ -35,6 +35,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTarget() { PassRegistry &PR = *PassRegistry::getPassRegistry(); initializeBPFAbstractMemberAccessPass(PR); + initializeBPFPreserveDITypePass(PR); initializeBPFMIPeepholePass(PR); initializeBPFMIPeepholeTruncElimPass(PR); } @@ -42,9 +43,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTarget() { // DataLayout: little or big endian static std::string computeDataLayout(const Triple &TT) { if (TT.getArch() == Triple::bpfeb) - return "E-m:e-p:64:64-i64:64-n32:64-S128"; + return "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128"; else - return "e-m:e-p:64:64-i64:64-n32:64-S128"; + return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"; } static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) { @@ -63,7 +64,7 @@ BPFTargetMachine::BPFTargetMachine(const Target &T, const Triple &TT, getEffectiveRelocModel(RM), getEffectiveCodeModel(CM, CodeModel::Small), OL), TLOF(std::make_unique<TargetLoweringObjectFileELF>()), - Subtarget(TT, CPU, FS, *this) { + Subtarget(TT, std::string(CPU), std::string(FS), *this) { initAsmInfo(); BPFMCAsmInfo *MAI = @@ -96,6 +97,7 @@ TargetPassConfig *BPFTargetMachine::createPassConfig(PassManagerBase &PM) { void BPFPassConfig::addIRPasses() { addPass(createBPFAbstractMemberAccess(&getBPFTargetMachine())); + addPass(createBPFPreserveDIType()); TargetPassConfig::addIRPasses(); } diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp index a9fb04f20d1c8..4510e93574892 100644 --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -34,10 +34,10 @@ static const char *BTFKindStr[] = { void BTFTypeBase::emitType(MCStreamer &OS) { OS.AddComment(std::string(BTFKindStr[Kind]) + "(id = " + std::to_string(Id) + ")"); - OS.EmitIntValue(BTFType.NameOff, 4); + OS.emitInt32(BTFType.NameOff); OS.AddComment("0x" + Twine::utohexstr(BTFType.Info)); - OS.EmitIntValue(BTFType.Info, 4); - OS.EmitIntValue(BTFType.Size, 4); + OS.emitInt32(BTFType.Info); + OS.emitInt32(BTFType.Size); } BTFTypeDerived::BTFTypeDerived(const DIDerivedType *DTy, unsigned Tag, @@ -148,7 +148,7 @@ void BTFTypeInt::completeType(BTFDebug &BDebug) { void BTFTypeInt::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); OS.AddComment("0x" + Twine::utohexstr(IntVal)); - OS.EmitIntValue(IntVal, 4); + OS.emitInt32(IntVal); } BTFTypeEnum::BTFTypeEnum(const DICompositeType *ETy, uint32_t VLen) : ETy(ETy) { @@ -171,7 +171,12 @@ void BTFTypeEnum::completeType(BTFDebug &BDebug) { struct BTF::BTFEnum BTFEnum; BTFEnum.NameOff = BDebug.addString(Enum->getName()); // BTF enum value is 32bit, enforce it. - BTFEnum.Val = static_cast<uint32_t>(Enum->getValue()); + uint32_t Value; + if (Enum->isUnsigned()) + Value = static_cast<uint32_t>(Enum->getValue().getZExtValue()); + else + Value = static_cast<uint32_t>(Enum->getValue().getSExtValue()); + BTFEnum.Val = Value; EnumValues.push_back(BTFEnum); } } @@ -179,8 +184,8 @@ void BTFTypeEnum::completeType(BTFDebug &BDebug) { void BTFTypeEnum::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); for (const auto &Enum : EnumValues) { - OS.EmitIntValue(Enum.NameOff, 4); - OS.EmitIntValue(Enum.Val, 4); + OS.emitInt32(Enum.NameOff); + OS.emitInt32(Enum.Val); } } @@ -209,9 +214,9 @@ void BTFTypeArray::completeType(BTFDebug &BDebug) { void BTFTypeArray::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); - OS.EmitIntValue(ArrayInfo.ElemType, 4); - OS.EmitIntValue(ArrayInfo.IndexType, 4); - OS.EmitIntValue(ArrayInfo.Nelems, 4); + OS.emitInt32(ArrayInfo.ElemType); + OS.emitInt32(ArrayInfo.IndexType); + OS.emitInt32(ArrayInfo.Nelems); } /// Represent either a struct or a union. @@ -252,14 +257,14 @@ void BTFTypeStruct::completeType(BTFDebug &BDebug) { void BTFTypeStruct::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); for (const auto &Member : Members) { - OS.EmitIntValue(Member.NameOff, 4); - OS.EmitIntValue(Member.Type, 4); + OS.emitInt32(Member.NameOff); + OS.emitInt32(Member.Type); OS.AddComment("0x" + Twine::utohexstr(Member.Offset)); - OS.EmitIntValue(Member.Offset, 4); + OS.emitInt32(Member.Offset); } } -std::string BTFTypeStruct::getName() { return STy->getName(); } +std::string BTFTypeStruct::getName() { return std::string(STy->getName()); } /// The Func kind represents both subprogram and pointee of function /// pointers. If the FuncName is empty, it represents a pointee of function @@ -303,8 +308,8 @@ void BTFTypeFuncProto::completeType(BTFDebug &BDebug) { void BTFTypeFuncProto::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); for (const auto &Param : Parameters) { - OS.EmitIntValue(Param.NameOff, 4); - OS.EmitIntValue(Param.Type, 4); + OS.emitInt32(Param.NameOff); + OS.emitInt32(Param.Type); } } @@ -340,7 +345,7 @@ void BTFKindVar::completeType(BTFDebug &BDebug) { void BTFKindVar::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); - OS.EmitIntValue(Info, 4); + OS.emitInt32(Info); } BTFKindDataSec::BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName) @@ -359,9 +364,9 @@ void BTFKindDataSec::emitType(MCStreamer &OS) { BTFTypeBase::emitType(OS); for (const auto &V : Vars) { - OS.EmitIntValue(std::get<0>(V), 4); - Asm->EmitLabelReference(std::get<1>(V), 4); - OS.EmitIntValue(std::get<2>(V), 4); + OS.emitInt32(std::get<0>(V)); + Asm->emitLabelReference(std::get<1>(V), 4); + OS.emitInt32(std::get<2>(V)); } } @@ -374,7 +379,7 @@ uint32_t BTFStringTable::addString(StringRef S) { // Not find, add to the string table. uint32_t Offset = Size; OffsetToIdMap[Offset] = Table.size(); - Table.push_back(S); + Table.push_back(std::string(S)); Size += S.size() + 1; return Offset; } @@ -563,7 +568,7 @@ void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId, auto CTag = CTy->getTag(); if ((CTag == dwarf::DW_TAG_structure_type || CTag == dwarf::DW_TAG_union_type) && - !CTy->isForwardDecl()) { + !CTy->getName().empty() && !CTy->isForwardDecl()) { /// Find a candidate, generate a fixup. Later on the struct/union /// pointee type will be replaced with either a real type or /// a forward declaration. @@ -600,6 +605,38 @@ void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId, bool CheckPointer, bool SeenPointer) { if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) { TypeId = DIToIdMap[Ty]; + + // To handle the case like the following: + // struct t; + // typedef struct t _t; + // struct s1 { _t *c; }; + // int test1(struct s1 *arg) { ... } + // + // struct t { int a; int b; }; + // struct s2 { _t c; } + // int test2(struct s2 *arg) { ... } + // + // During traversing test1() argument, "_t" is recorded + // in DIToIdMap and a forward declaration fixup is created + // for "struct t" to avoid pointee type traversal. + // + // During traversing test2() argument, even if we see "_t" is + // already defined, we should keep moving to eventually + // bring in types for "struct t". Otherwise, the "struct s2" + // definition won't be correct. + if (Ty && (!CheckPointer || !SeenPointer)) { + if (const auto *DTy = dyn_cast<DIDerivedType>(Ty)) { + unsigned Tag = DTy->getTag(); + if (Tag == dwarf::DW_TAG_typedef || Tag == dwarf::DW_TAG_const_type || + Tag == dwarf::DW_TAG_volatile_type || + Tag == dwarf::DW_TAG_restrict_type) { + uint32_t TmpTypeId; + visitTypeEntry(DTy->getBaseType(), TmpTypeId, CheckPointer, + SeenPointer); + } + } + } + return; } @@ -627,7 +664,17 @@ void BTFDebug::visitMapDefType(const DIType *Ty, uint32_t &TypeId) { return; } - // MapDef type is a struct type + // MapDef type may be a struct type or a non-pointer derived type + const DIType *OrigTy = Ty; + while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { + auto Tag = DTy->getTag(); + if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && + Tag != dwarf::DW_TAG_volatile_type && + Tag != dwarf::DW_TAG_restrict_type) + break; + Ty = DTy->getBaseType(); + } + const auto *CTy = dyn_cast<DICompositeType>(Ty); if (!CTy) return; @@ -636,27 +683,15 @@ void BTFDebug::visitMapDefType(const DIType *Ty, uint32_t &TypeId) { if (Tag != dwarf::DW_TAG_structure_type || CTy->isForwardDecl()) return; - // Record this type + // Visit all struct members to ensure pointee type is visited const DINodeArray Elements = CTy->getElements(); - bool HasBitField = false; - for (const auto *Element : Elements) { - auto E = cast<DIDerivedType>(Element); - if (E->isBitField()) { - HasBitField = true; - break; - } - } - - auto TypeEntry = - std::make_unique<BTFTypeStruct>(CTy, true, HasBitField, Elements.size()); - StructTypes.push_back(TypeEntry.get()); - TypeId = addType(std::move(TypeEntry), CTy); - - // Visit all struct members for (const auto *Element : Elements) { const auto *MemberType = cast<DIDerivedType>(Element); visitTypeEntry(MemberType->getBaseType()); } + + // Visit this type, struct or a const/typedef/volatile/restrict type + visitTypeEntry(OrigTy, TypeId, false, false); } /// Read file contents from the actual file or from the source @@ -667,7 +702,7 @@ std::string BTFDebug::populateFileContent(const DISubprogram *SP) { if (!File->getFilename().startswith("/") && File->getDirectory().size()) FileName = File->getDirectory().str() + "/" + File->getFilename().str(); else - FileName = File->getFilename(); + FileName = std::string(File->getFilename()); // No need to populate the contends if it has been populated! if (FileContent.find(FileName) != FileContent.end()) @@ -686,7 +721,7 @@ std::string BTFDebug::populateFileContent(const DISubprogram *SP) { Buf = std::move(*BufOrErr); if (Buf) for (line_iterator I(*Buf, false), E; I != E; ++I) - Content.push_back(*I); + Content.push_back(std::string(*I)); FileContent[FileName] = Content; return FileName; @@ -711,9 +746,9 @@ void BTFDebug::constructLineInfo(const DISubprogram *SP, MCSymbol *Label, void BTFDebug::emitCommonHeader() { OS.AddComment("0x" + Twine::utohexstr(BTF::MAGIC)); - OS.EmitIntValue(BTF::MAGIC, 2); - OS.EmitIntValue(BTF::VERSION, 1); - OS.EmitIntValue(0, 1); + OS.emitIntValue(BTF::MAGIC, 2); + OS.emitInt8(BTF::VERSION); + OS.emitInt8(0); } void BTFDebug::emitBTFSection() { @@ -726,17 +761,17 @@ void BTFDebug::emitBTFSection() { // Emit header. emitCommonHeader(); - OS.EmitIntValue(BTF::HeaderSize, 4); + OS.emitInt32(BTF::HeaderSize); 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); + OS.emitInt32(0); + OS.emitInt32(TypeLen); + OS.emitInt32(TypeLen); + OS.emitInt32(StrLen); // Emit type table. for (const auto &TypeEntry : TypeEntries) @@ -746,8 +781,8 @@ void BTFDebug::emitBTFSection() { 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)); + OS.emitBytes(S); + OS.emitBytes(StringRef("\0", 1)); StringOffset += S.size() + 1; } } @@ -764,7 +799,7 @@ void BTFDebug::emitBTFExtSection() { // Emit header. emitCommonHeader(); - OS.EmitIntValue(BTF::ExtHeaderSize, 4); + OS.emitInt32(BTF::ExtHeaderSize); // Account for FuncInfo/LineInfo record size as well. uint32_t FuncLen = 4, LineLen = 4; @@ -786,59 +821,59 @@ void BTFDebug::emitBTFExtSection() { if (FieldRelocLen) FieldRelocLen += 4; - OS.EmitIntValue(0, 4); - OS.EmitIntValue(FuncLen, 4); - OS.EmitIntValue(FuncLen, 4); - OS.EmitIntValue(LineLen, 4); - OS.EmitIntValue(FuncLen + LineLen, 4); - OS.EmitIntValue(FieldRelocLen, 4); + OS.emitInt32(0); + OS.emitInt32(FuncLen); + OS.emitInt32(FuncLen); + OS.emitInt32(LineLen); + OS.emitInt32(FuncLen + LineLen); + OS.emitInt32(FieldRelocLen); // Emit func_info table. OS.AddComment("FuncInfo"); - OS.EmitIntValue(BTF::BPFFuncInfoSize, 4); + OS.emitInt32(BTF::BPFFuncInfoSize); 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); + OS.emitInt32(FuncSec.first); + OS.emitInt32(FuncSec.second.size()); for (const auto &FuncInfo : FuncSec.second) { - Asm->EmitLabelReference(FuncInfo.Label, 4); - OS.EmitIntValue(FuncInfo.TypeId, 4); + Asm->emitLabelReference(FuncInfo.Label, 4); + OS.emitInt32(FuncInfo.TypeId); } } // Emit line_info table. OS.AddComment("LineInfo"); - OS.EmitIntValue(BTF::BPFLineInfoSize, 4); + OS.emitInt32(BTF::BPFLineInfoSize); 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); + OS.emitInt32(LineSec.first); + OS.emitInt32(LineSec.second.size()); for (const auto &LineInfo : LineSec.second) { - Asm->EmitLabelReference(LineInfo.Label, 4); - OS.EmitIntValue(LineInfo.FileNameOff, 4); - OS.EmitIntValue(LineInfo.LineOff, 4); + Asm->emitLabelReference(LineInfo.Label, 4); + OS.emitInt32(LineInfo.FileNameOff); + OS.emitInt32(LineInfo.LineOff); OS.AddComment("Line " + std::to_string(LineInfo.LineNum) + " Col " + std::to_string(LineInfo.ColumnNum)); - OS.EmitIntValue(LineInfo.LineNum << 10 | LineInfo.ColumnNum, 4); + OS.emitInt32(LineInfo.LineNum << 10 | LineInfo.ColumnNum); } } // Emit field reloc table. if (FieldRelocLen) { OS.AddComment("FieldReloc"); - OS.EmitIntValue(BTF::BPFFieldRelocSize, 4); + OS.emitInt32(BTF::BPFFieldRelocSize); for (const auto &FieldRelocSec : FieldRelocTable) { OS.AddComment("Field reloc section string offset=" + std::to_string(FieldRelocSec.first)); - OS.EmitIntValue(FieldRelocSec.first, 4); - OS.EmitIntValue(FieldRelocSec.second.size(), 4); + OS.emitInt32(FieldRelocSec.first); + OS.emitInt32(FieldRelocSec.second.size()); for (const auto &FieldRelocInfo : FieldRelocSec.second) { - Asm->EmitLabelReference(FieldRelocInfo.Label, 4); - OS.EmitIntValue(FieldRelocInfo.TypeID, 4); - OS.EmitIntValue(FieldRelocInfo.OffsetNameOff, 4); - OS.EmitIntValue(FieldRelocInfo.RelocKind, 4); + Asm->emitLabelReference(FieldRelocInfo.Label, 4); + OS.emitInt32(FieldRelocInfo.TypeID); + OS.emitInt32(FieldRelocInfo.OffsetNameOff); + OS.emitInt32(FieldRelocInfo.RelocKind); } } } @@ -915,7 +950,7 @@ void BTFDebug::beginFunctionImpl(const MachineFunction *MF) { MCSection &Section = FuncLabel->getSection(); const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section); assert(SectionELF && "Null section for Function Label"); - SecNameOff = addString(SectionELF->getSectionName()); + SecNameOff = addString(SectionELF->getName()); } else { SecNameOff = addString(".text"); } @@ -928,9 +963,9 @@ void BTFDebug::endFunctionImpl(const MachineFunction *MF) { SecNameOff = 0; } -/// On-demand populate struct types as requested from abstract member -/// accessing. -unsigned BTFDebug::populateStructType(const DIType *Ty) { +/// On-demand populate types as requested from abstract member +/// accessing or preserve debuginfo type. +unsigned BTFDebug::populateType(const DIType *Ty) { unsigned Id; visitTypeEntry(Ty, Id, false, false); for (const auto &TypeEntry : TypeEntries) @@ -939,24 +974,32 @@ unsigned BTFDebug::populateStructType(const DIType *Ty) { } /// Generate a struct member field relocation. -void BTFDebug::generateFieldReloc(const MCSymbol *ORSym, DIType *RootTy, - StringRef AccessPattern) { - unsigned RootId = populateStructType(RootTy); - size_t FirstDollar = AccessPattern.find_first_of('$'); - size_t FirstColon = AccessPattern.find_first_of(':'); - size_t SecondColon = AccessPattern.find_first_of(':', FirstColon + 1); - StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1); - StringRef RelocKindStr = AccessPattern.substr(FirstColon + 1, - SecondColon - FirstColon); - StringRef PatchImmStr = AccessPattern.substr(SecondColon + 1, - FirstDollar - SecondColon); - +void BTFDebug::generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId, + const GlobalVariable *GVar, bool IsAma) { BTFFieldReloc FieldReloc; FieldReloc.Label = ORSym; - FieldReloc.OffsetNameOff = addString(IndexPattern); FieldReloc.TypeID = RootId; - FieldReloc.RelocKind = std::stoull(RelocKindStr); - PatchImms[AccessPattern.str()] = std::stoul(PatchImmStr); + + StringRef AccessPattern = GVar->getName(); + size_t FirstDollar = AccessPattern.find_first_of('$'); + if (IsAma) { + size_t FirstColon = AccessPattern.find_first_of(':'); + size_t SecondColon = AccessPattern.find_first_of(':', FirstColon + 1); + StringRef IndexPattern = AccessPattern.substr(FirstDollar + 1); + StringRef RelocKindStr = AccessPattern.substr(FirstColon + 1, + SecondColon - FirstColon); + StringRef PatchImmStr = AccessPattern.substr(SecondColon + 1, + FirstDollar - SecondColon); + + FieldReloc.OffsetNameOff = addString(IndexPattern); + FieldReloc.RelocKind = std::stoull(std::string(RelocKindStr)); + PatchImms[GVar] = std::stoul(std::string(PatchImmStr)); + } else { + StringRef RelocStr = AccessPattern.substr(FirstDollar + 1); + FieldReloc.OffsetNameOff = addString("0"); + FieldReloc.RelocKind = std::stoull(std::string(RelocStr)); + PatchImms[GVar] = RootId; + } FieldRelocTable[SecNameOff].push_back(FieldReloc); } @@ -965,14 +1008,20 @@ void BTFDebug::processReloc(const MachineOperand &MO) { if (MO.isGlobal()) { const GlobalValue *GVal = MO.getGlobal(); auto *GVar = dyn_cast<GlobalVariable>(GVal); - if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) { - MCSymbol *ORSym = OS.getContext().createTempSymbol(); - OS.EmitLabel(ORSym); + if (!GVar) + return; - MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index); - DIType *Ty = dyn_cast<DIType>(MDN); - generateFieldReloc(ORSym, Ty, GVar->getName()); - } + if (!GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) && + !GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) + return; + + MCSymbol *ORSym = OS.getContext().createTempSymbol(); + OS.emitLabel(ORSym); + + MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index); + uint32_t RootId = populateType(dyn_cast<DIType>(MDN)); + generatePatchImmReloc(ORSym, RootId, GVar, + GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)); } } @@ -1008,6 +1057,9 @@ void BTFDebug::beginInstruction(const MachineInstr *MI) { // Later, the insn is replaced with "r2 = <offset>" // where "<offset>" equals to the offset based on current // type definitions. + // + // If the insn is "r2 = LD_imm64 @<an TypeIdAttr global>", + // The LD_imm64 result will be replaced with a btf type id. processReloc(MI->getOperand(1)); } else if (MI->getOpcode() == BPF::CORE_MEM || MI->getOpcode() == BPF::CORE_ALU32_MEM || @@ -1040,7 +1092,7 @@ void BTFDebug::beginInstruction(const MachineInstr *MI) { // Create a temporary label to remember the insn for lineinfo. MCSymbol *LineSym = OS.getContext().createTempSymbol(); - OS.EmitLabel(LineSym); + OS.emitLabel(LineSym); // Construct the lineinfo. auto SP = DL.get()->getScope()->getSubprogram(); @@ -1119,15 +1171,17 @@ void BTFDebug::processGlobals(bool ProcessingMapDef) { assert(!SecName.empty()); // Find or create a DataSec - if (DataSecEntries.find(SecName) == DataSecEntries.end()) { - DataSecEntries[SecName] = std::make_unique<BTFKindDataSec>(Asm, SecName); + if (DataSecEntries.find(std::string(SecName)) == DataSecEntries.end()) { + DataSecEntries[std::string(SecName)] = + std::make_unique<BTFKindDataSec>(Asm, std::string(SecName)); } // Calculate symbol size const DataLayout &DL = Global.getParent()->getDataLayout(); uint32_t Size = DL.getTypeAllocSize(Global.getType()->getElementType()); - DataSecEntries[SecName]->addVar(VarId, Asm->getSymbol(&Global), Size); + DataSecEntries[std::string(SecName)]->addVar(VarId, Asm->getSymbol(&Global), + Size); } } @@ -1138,9 +1192,15 @@ bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) { if (MO.isGlobal()) { const GlobalValue *GVal = MO.getGlobal(); auto *GVar = dyn_cast<GlobalVariable>(GVal); - if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) { - // Emit "mov ri, <imm>" for patched immediate. - uint32_t Imm = PatchImms[GVar->getName().str()]; + if (GVar) { + // Emit "mov ri, <imm>" + uint32_t Imm; + if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) || + GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr)) + Imm = PatchImms[GVar]; + else + return false; + OutMI.setOpcode(BPF::MOV_ri); OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); OutMI.addOperand(MCOperand::createImm(Imm)); @@ -1155,7 +1215,7 @@ bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) { const GlobalValue *GVal = MO.getGlobal(); auto *GVar = dyn_cast<GlobalVariable>(GVal); if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) { - uint32_t Imm = PatchImms[GVar->getName().str()]; + uint32_t Imm = PatchImms[GVar]; OutMI.setOpcode(MI->getOperand(1).getImm()); if (MI->getOperand(0).isImm()) OutMI.addOperand(MCOperand::createImm(MI->getOperand(0).getImm())); diff --git a/llvm/lib/Target/BPF/BTFDebug.h b/llvm/lib/Target/BPF/BTFDebug.h index 0812c4f7915de..2f39f665299a5 100644 --- a/llvm/lib/Target/BPF/BTFDebug.h +++ b/llvm/lib/Target/BPF/BTFDebug.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/CodeGen/DebugHandlerBase.h" +#include "llvm/CodeGen/MachineInstr.h" #include <set> #include <unordered_map> #include "BTF.h" @@ -25,6 +26,7 @@ namespace llvm { class AsmPrinter; class BTFDebug; class DIType; +class GlobalVariable; class MCStreamer; class MCSymbol; class MachineFunction; @@ -61,8 +63,8 @@ class BTFTypeDerived : public BTFTypeBase { public: BTFTypeDerived(const DIDerivedType *Ty, unsigned Tag, bool NeedsFixup); - void completeType(BTFDebug &BDebug); - void emitType(MCStreamer &OS); + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; void setPointeeType(uint32_t PointeeType); }; @@ -72,8 +74,8 @@ class BTFTypeFwd : public BTFTypeBase { public: BTFTypeFwd(StringRef Name, bool IsUnion); - void completeType(BTFDebug &BDebug); - void emitType(MCStreamer &OS); + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; }; /// Handle int type. @@ -84,9 +86,9 @@ class BTFTypeInt : public BTFTypeBase { 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); + uint32_t getSize() override { return BTFTypeBase::getSize() + sizeof(uint32_t); } + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; }; /// Handle enumerate type. @@ -96,11 +98,11 @@ class BTFTypeEnum : public BTFTypeBase { public: BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues); - uint32_t getSize() { + uint32_t getSize() override { return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnumSize; } - void completeType(BTFDebug &BDebug); - void emitType(MCStreamer &OS); + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; }; /// Handle array type. @@ -109,9 +111,9 @@ class BTFTypeArray : public BTFTypeBase { public: BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems); - uint32_t getSize() { return BTFTypeBase::getSize() + BTF::BTFArraySize; } - void completeType(BTFDebug &BDebug); - void emitType(MCStreamer &OS); + uint32_t getSize() override { return BTFTypeBase::getSize() + BTF::BTFArraySize; } + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; }; /// Handle struct/union type. @@ -123,11 +125,11 @@ class BTFTypeStruct : public BTFTypeBase { public: BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField, uint32_t NumMembers); - uint32_t getSize() { + uint32_t getSize() override { return BTFTypeBase::getSize() + Members.size() * BTF::BTFMemberSize; } - void completeType(BTFDebug &BDebug); - void emitType(MCStreamer &OS); + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; std::string getName(); }; @@ -140,11 +142,11 @@ class BTFTypeFuncProto : public BTFTypeBase { public: BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams, const std::unordered_map<uint32_t, StringRef> &FuncArgNames); - uint32_t getSize() { + uint32_t getSize() override { return BTFTypeBase::getSize() + Parameters.size() * BTF::BTFParamSize; } - void completeType(BTFDebug &BDebug); - void emitType(MCStreamer &OS); + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; }; /// Handle subprogram @@ -153,9 +155,9 @@ class BTFTypeFunc : public BTFTypeBase { public: BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, uint32_t Scope); - uint32_t getSize() { return BTFTypeBase::getSize(); } - void completeType(BTFDebug &BDebug); - void emitType(MCStreamer &OS); + uint32_t getSize() override { return BTFTypeBase::getSize(); } + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; }; /// Handle variable instances @@ -165,9 +167,9 @@ class BTFKindVar : public BTFTypeBase { public: BTFKindVar(StringRef VarName, uint32_t TypeId, uint32_t VarInfo); - uint32_t getSize() { return BTFTypeBase::getSize() + 4; } - void completeType(BTFDebug &BDebug); - void emitType(MCStreamer &OS); + uint32_t getSize() override { return BTFTypeBase::getSize() + 4; } + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; }; /// Handle data sections @@ -178,15 +180,15 @@ class BTFKindDataSec : public BTFTypeBase { public: BTFKindDataSec(AsmPrinter *AsmPrt, std::string SecName); - uint32_t getSize() { + uint32_t getSize() override { return BTFTypeBase::getSize() + BTF::BTFDataSecVarSize * Vars.size(); } void addVar(uint32_t Id, const MCSymbol *Sym, uint32_t Size) { Vars.push_back(std::make_tuple(Id, Sym, Size)); } std::string getName() { return Name; } - void completeType(BTFDebug &BDebug); - void emitType(MCStreamer &OS); + void completeType(BTFDebug &BDebug) override; + void emitType(MCStreamer &OS) override; }; /// String table. @@ -249,7 +251,7 @@ class BTFDebug : public DebugHandlerBase { StringMap<std::vector<std::string>> FileContent; std::map<std::string, std::unique_ptr<BTFKindDataSec>> DataSecEntries; std::vector<BTFTypeStruct *> StructTypes; - std::map<std::string, uint32_t> PatchImms; + std::map<const GlobalVariable *, uint32_t> PatchImms; std::map<StringRef, std::pair<bool, std::vector<BTFTypeDerived *>>> FixupDerivedTypes; std::set<const Function *>ProtoFunctions; @@ -299,11 +301,11 @@ class BTFDebug : public DebugHandlerBase { void processFuncPrototypes(const Function *); /// Generate one field relocation record. - void generateFieldReloc(const MCSymbol *ORSym, DIType *RootTy, - StringRef AccessPattern); + void generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId, + const GlobalVariable *, bool IsAma); - /// Populating unprocessed struct type. - unsigned populateStructType(const DIType *Ty); + /// Populating unprocessed type on demand. + unsigned populateType(const DIType *Ty); /// Process relocation instructions. void processReloc(const MachineOperand &MO); diff --git a/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp b/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp index 75f963b5448ac..4d98dc7341d06 100644 --- a/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp +++ b/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp @@ -126,6 +126,9 @@ static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo, static DecodeStatus decodeMemoryOpValue(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { unsigned Register = (Insn >> 16) & 0xf; + if (Register > 11) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register])); unsigned Offset = (Insn & 0xffff); Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset))); diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp index ba35a175b9a78..9d829ac45a10b 100644 --- a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp +++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp @@ -48,9 +48,6 @@ public: return false; } - void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, - MCInst &Res) const override {} - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; }; diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h index 97f0cbd586082..3292c3e5ebb51 100644 --- a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h +++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h @@ -17,7 +17,6 @@ #include "llvm/MC/MCAsmInfo.h" namespace llvm { -class Target; class BPFMCAsmInfo : public MCAsmInfo { public: @@ -42,6 +41,8 @@ public: // section will be parsable, but with odd offsets and // line numbers, etc. CodePointerSize = 8; + + UseIntegratedAssembler = false; } void setDwarfUsesRelocationsAcrossSections(bool enable) { diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h index 1a391321f60d0..a426a132cf47d 100644 --- a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h +++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h @@ -27,11 +27,7 @@ class MCObjectTargetWriter; class MCRegisterInfo; class MCSubtargetInfo; class MCTargetOptions; -class StringRef; class Target; -class Triple; -class raw_ostream; -class raw_pwrite_stream; MCCodeEmitter *createBPFMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, |