summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/BPF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/Target/BPF
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'llvm/lib/Target/BPF')
-rw-r--r--llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp16
-rw-r--r--llvm/lib/Target/BPF/BPF.h2
-rw-r--r--llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp63
-rw-r--r--llvm/lib/Target/BPF/BPFAsmPrinter.cpp4
-rw-r--r--llvm/lib/Target/BPF/BPFCORE.h18
-rw-r--r--llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp2
-rw-r--r--llvm/lib/Target/BPF/BPFISelLowering.cpp40
-rw-r--r--llvm/lib/Target/BPF/BPFISelLowering.h28
-rw-r--r--llvm/lib/Target/BPF/BPFInstrInfo.cpp4
-rw-r--r--llvm/lib/Target/BPF/BPFInstrInfo.h4
-rw-r--r--llvm/lib/Target/BPF/BPFInstrInfo.td5
-rw-r--r--llvm/lib/Target/BPF/BPFMCInstLower.h2
-rw-r--r--llvm/lib/Target/BPF/BPFMIPeephole.cpp69
-rw-r--r--llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp107
-rw-r--r--llvm/lib/Target/BPF/BPFPreserveDIType.cpp131
-rw-r--r--llvm/lib/Target/BPF/BPFSelectionDAGInfo.cpp6
-rw-r--r--llvm/lib/Target/BPF/BPFSelectionDAGInfo.h4
-rw-r--r--llvm/lib/Target/BPF/BPFTargetMachine.cpp8
-rw-r--r--llvm/lib/Target/BPF/BTFDebug.cpp282
-rw-r--r--llvm/lib/Target/BPF/BTFDebug.h68
-rw-r--r--llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp3
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp3
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h3
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h4
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,