summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/BPF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
commit706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch)
tree4adf86a776049cbf7f69a1929c4babcbbef925eb /llvm/lib/Target/BPF
parent7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff)
Notes
Diffstat (limited to 'llvm/lib/Target/BPF')
-rw-r--r--llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp2
-rw-r--r--llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp86
-rw-r--r--llvm/lib/Target/BPF/BPFAsmPrinter.cpp2
-rw-r--r--llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp1
-rw-r--r--llvm/lib/Target/BPF/BPFInstrInfo.cpp4
-rw-r--r--llvm/lib/Target/BPF/BPFInstrInfo.h2
-rw-r--r--llvm/lib/Target/BPF/BPFInstrInfo.td19
-rw-r--r--llvm/lib/Target/BPF/BPFMIPeephole.cpp89
-rw-r--r--llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp163
-rw-r--r--llvm/lib/Target/BPF/BPFSubtarget.cpp1
-rw-r--r--llvm/lib/Target/BPF/BPFTargetMachine.cpp2
-rw-r--r--llvm/lib/Target/BPF/BTF.h10
-rw-r--r--llvm/lib/Target/BPF/BTFDebug.cpp157
-rw-r--r--llvm/lib/Target/BPF/BTFDebug.h19
-rw-r--r--llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp4
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.cpp7
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.h6
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h2
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp2
-rw-r--r--llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp2
20 files changed, 435 insertions, 145 deletions
diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
index ce1d2ecd9d266..1f5d5025bc7bc 100644
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -493,7 +493,7 @@ bool BPFAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
bool BPFAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
-extern "C" void LLVMInitializeBPFAsmParser() {
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmParser() {
RegisterMCAsmParser<BPFAsmParser> X(getTheBPFTarget());
RegisterMCAsmParser<BPFAsmParser> Y(getTheBPFleTarget());
RegisterMCAsmParser<BPFAsmParser> Z(getTheBPFbeTarget());
diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
index 400701c4e5c22..a28816cc87b7d 100644
--- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
+++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
@@ -117,6 +117,7 @@ public:
struct CallInfo {
uint32_t Kind;
uint32_t AccessIndex;
+ uint32_t RecordAlignment;
MDNode *Metadata;
Value *Base;
};
@@ -130,6 +131,8 @@ private:
BPFPreserveFieldInfoAI = 4,
};
+ const DataLayout *DL = nullptr;
+
std::map<std::string, GlobalVariable *> GEPGlobals;
// A map to link preserve_*_access_index instrinsic calls.
std::map<CallInst *, std::pair<CallInst *, CallInfo>> AIChain;
@@ -154,11 +157,11 @@ private:
void replaceWithGEP(std::vector<CallInst *> &CallList,
uint32_t NumOfZerosIndex, uint32_t DIIndex);
bool HasPreserveFieldInfoCall(CallInfoStack &CallStack);
- void GetStorageBitRange(DICompositeType *CTy, DIDerivedType *MemberTy,
- uint32_t AccessIndex, uint32_t &StartBitOffset,
- uint32_t &EndBitOffset);
+ void GetStorageBitRange(DIDerivedType *MemberTy, uint32_t RecordAlignment,
+ uint32_t &StartBitOffset, uint32_t &EndBitOffset);
uint32_t GetFieldInfo(uint32_t InfoKind, DICompositeType *CTy,
- uint32_t AccessIndex, uint32_t PatchImm);
+ uint32_t AccessIndex, uint32_t PatchImm,
+ uint32_t RecordAlignment);
Value *computeBaseAndAccessKey(CallInst *Call, CallInfo &CInfo,
std::string &AccessKey, MDNode *&BaseMeta);
@@ -182,6 +185,7 @@ bool BPFAbstractMemberAccess::runOnModule(Module &M) {
if (M.debug_compile_units().empty())
return false;
+ DL = &M.getDataLayout();
return doTransformation(M);
}
@@ -243,6 +247,8 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
report_fatal_error("Missing metadata for llvm.preserve.array.access.index intrinsic");
CInfo.AccessIndex = getConstant(Call->getArgOperand(2));
CInfo.Base = Call->getArgOperand(0);
+ CInfo.RecordAlignment =
+ DL->getABITypeAlignment(CInfo.Base->getType()->getPointerElementType());
return true;
}
if (GV->getName().startswith("llvm.preserve.union.access.index")) {
@@ -252,6 +258,8 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
report_fatal_error("Missing metadata for llvm.preserve.union.access.index intrinsic");
CInfo.AccessIndex = getConstant(Call->getArgOperand(1));
CInfo.Base = Call->getArgOperand(0);
+ CInfo.RecordAlignment =
+ DL->getABITypeAlignment(CInfo.Base->getType()->getPointerElementType());
return true;
}
if (GV->getName().startswith("llvm.preserve.struct.access.index")) {
@@ -261,6 +269,8 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call,
report_fatal_error("Missing metadata for llvm.preserve.struct.access.index intrinsic");
CInfo.AccessIndex = getConstant(Call->getArgOperand(2));
CInfo.Base = Call->getArgOperand(0);
+ CInfo.RecordAlignment =
+ DL->getABITypeAlignment(CInfo.Base->getType()->getPointerElementType());
return true;
}
if (GV->getName().startswith("llvm.bpf.preserve.field.info")) {
@@ -509,40 +519,29 @@ uint64_t BPFAbstractMemberAccess::getConstant(const Value *IndexValue) {
}
/// Get the start and the end of storage offset for \p MemberTy.
-/// The storage bits are corresponding to the LLVM internal types,
-/// and the storage bits for the member determines what load width
-/// to use in order to extract the bitfield value.
-void BPFAbstractMemberAccess::GetStorageBitRange(DICompositeType *CTy,
- DIDerivedType *MemberTy,
- uint32_t AccessIndex,
+void BPFAbstractMemberAccess::GetStorageBitRange(DIDerivedType *MemberTy,
+ uint32_t RecordAlignment,
uint32_t &StartBitOffset,
uint32_t &EndBitOffset) {
- auto SOff = dyn_cast<ConstantInt>(MemberTy->getStorageOffsetInBits());
- assert(SOff);
- StartBitOffset = SOff->getZExtValue();
-
- EndBitOffset = CTy->getSizeInBits();
- uint32_t Index = AccessIndex + 1;
- for (; Index < CTy->getElements().size(); ++Index) {
- auto Member = cast<DIDerivedType>(CTy->getElements()[Index]);
- if (!Member->getStorageOffsetInBits()) {
- EndBitOffset = Member->getOffsetInBits();
- break;
- }
- SOff = dyn_cast<ConstantInt>(Member->getStorageOffsetInBits());
- assert(SOff);
- unsigned BitOffset = SOff->getZExtValue();
- if (BitOffset != StartBitOffset) {
- EndBitOffset = BitOffset;
- break;
- }
- }
+ uint32_t MemberBitSize = MemberTy->getSizeInBits();
+ uint32_t MemberBitOffset = MemberTy->getOffsetInBits();
+ uint32_t AlignBits = RecordAlignment * 8;
+ if (RecordAlignment > 8 || MemberBitSize > AlignBits)
+ report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, "
+ "requiring too big alignment");
+
+ StartBitOffset = MemberBitOffset & ~(AlignBits - 1);
+ if ((StartBitOffset + AlignBits) < (MemberBitOffset + MemberBitSize))
+ report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, "
+ "cross alignment boundary");
+ EndBitOffset = StartBitOffset + AlignBits;
}
uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
DICompositeType *CTy,
uint32_t AccessIndex,
- uint32_t PatchImm) {
+ uint32_t PatchImm,
+ uint32_t RecordAlignment) {
if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE)
return 1;
@@ -557,9 +556,10 @@ uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
if (!MemberTy->isBitField()) {
PatchImm += MemberTy->getOffsetInBits() >> 3;
} else {
- auto SOffset = dyn_cast<ConstantInt>(MemberTy->getStorageOffsetInBits());
- assert(SOffset);
- PatchImm += SOffset->getZExtValue() >> 3;
+ unsigned SBitOffset, NextSBitOffset;
+ GetStorageBitRange(MemberTy, RecordAlignment, SBitOffset,
+ NextSBitOffset);
+ PatchImm += SBitOffset >> 3;
}
}
return PatchImm;
@@ -576,7 +576,7 @@ uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
return SizeInBits >> 3;
unsigned SBitOffset, NextSBitOffset;
- GetStorageBitRange(CTy, MemberTy, AccessIndex, SBitOffset, NextSBitOffset);
+ GetStorageBitRange(MemberTy, RecordAlignment, SBitOffset, NextSBitOffset);
SizeInBits = NextSBitOffset - SBitOffset;
if (SizeInBits & (SizeInBits - 1))
report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info");
@@ -636,7 +636,7 @@ uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
}
unsigned SBitOffset, NextSBitOffset;
- GetStorageBitRange(CTy, MemberTy, AccessIndex, SBitOffset, NextSBitOffset);
+ GetStorageBitRange(MemberTy, RecordAlignment, SBitOffset, NextSBitOffset);
if (NextSBitOffset - SBitOffset > 64)
report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
@@ -667,7 +667,7 @@ uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind,
}
unsigned SBitOffset, NextSBitOffset;
- GetStorageBitRange(CTy, MemberTy, AccessIndex, SBitOffset, NextSBitOffset);
+ GetStorageBitRange(MemberTy, RecordAlignment, SBitOffset, NextSBitOffset);
if (NextSBitOffset - SBitOffset > 64)
report_fatal_error("too big field size for llvm.bpf.preserve.field.info");
@@ -822,14 +822,20 @@ 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);
+ PatchImm = GetFieldInfo(InfoKind, CTy, AccessIndex, PatchImm,
+ RecordAlignment);
}
- // Access key is the type name + reloc type + patched imm + access string,
+ // Access key is the
+ // "llvm." + type name + ":" + reloc type + ":" + patched imm + "$" +
+ // access string,
// uniquely identifying one relocation.
- AccessKey = TypeName + ":" + std::to_string(InfoKind) + ":" +
+ // The prefix "llvm." indicates this is a temporary global, which should
+ // not be emitted to ELF file.
+ AccessKey = "llvm." + TypeName + ":" + std::to_string(InfoKind) + ":" +
std::to_string(PatchImm) + "$" + AccessKey;
return Base;
diff --git a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
index 218b0302927c5..b81386f479d30 100644
--- a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
+++ b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
@@ -148,7 +148,7 @@ void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
// Force static initialization.
-extern "C" void LLVMInitializeBPFAsmPrinter() {
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmPrinter() {
RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget());
RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget());
RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget());
diff --git a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp
index f2be0ff070d2f..6f5f58554d09c 100644
--- a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp
+++ b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp
@@ -24,6 +24,7 @@
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/IntrinsicsBPF.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.cpp b/llvm/lib/Target/BPF/BPFInstrInfo.cpp
index 6de3a4084d3d4..626c204e99e6a 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.cpp
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.cpp
@@ -30,8 +30,8 @@ BPFInstrInfo::BPFInstrInfo()
void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
- const DebugLoc &DL, unsigned DestReg,
- unsigned SrcReg, bool KillSrc) const {
+ const DebugLoc &DL, MCRegister DestReg,
+ MCRegister SrcReg, bool KillSrc) const {
if (BPF::GPRRegClass.contains(DestReg, SrcReg))
BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.h b/llvm/lib/Target/BPF/BPFInstrInfo.h
index e4bd757da5608..22413d530e176 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.h
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.h
@@ -30,7 +30,7 @@ public:
const BPFRegisterInfo &getRegisterInfo() const { return RI; }
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
- const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
+ const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
bool KillSrc) const override;
bool expandPostRAPseudo(MachineInstr &MI) const override;
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td
index ae5a82a993033..0f39294daa2b9 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -437,6 +437,25 @@ class LOAD<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
class LOADi64<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
: LOAD<SizeOp, OpcodeStr, [(set i64:$dst, (OpNode ADDRri:$addr))]>;
+let isCodeGenOnly = 1 in {
+ def CORE_MEM : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value,
+ (outs GPR:$dst),
+ (ins u64imm:$opcode, GPR:$src, u64imm:$offset),
+ "$dst = core_mem($opcode, $src, $offset)",
+ []>;
+ def CORE_ALU32_MEM : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value,
+ (outs GPR32:$dst),
+ (ins u64imm:$opcode, GPR:$src, u64imm:$offset),
+ "$dst = core_alu32_mem($opcode, $src, $offset)",
+ []>;
+ let Constraints = "$dst = $src" in {
+ def CORE_SHIFT : ALU_RR<BPF_ALU64, BPF_LSH,
+ (outs GPR:$dst),
+ (ins u64imm:$opcode, GPR:$src, u64imm:$offset),
+ "$dst = core_shift($opcode, $src, $offset)",
+ []>;
+ }
+}
let Predicates = [BPFNoALU32] in {
def LDW : LOADi64<BPF_W, "u32", zextloadi32>;
diff --git a/llvm/lib/Target/BPF/BPFMIPeephole.cpp b/llvm/lib/Target/BPF/BPFMIPeephole.cpp
index e9eecc55c3c32..022267fbe3c21 100644
--- a/llvm/lib/Target/BPF/BPFMIPeephole.cpp
+++ b/llvm/lib/Target/BPF/BPFMIPeephole.cpp
@@ -51,9 +51,14 @@ private:
// Initialize class variables.
void initialize(MachineFunction &MFParm);
+ bool isCopyFrom32Def(MachineInstr *CopyMI);
+ bool isInsnFrom32Def(MachineInstr *DefInsn);
+ bool isPhiFrom32Def(MachineInstr *MovMI);
bool isMovFrom32Def(MachineInstr *MovMI);
bool eliminateZExtSeq(void);
+ std::set<MachineInstr *> PhiInsns;
+
public:
// Main entry point for this pass.
@@ -75,42 +80,86 @@ void BPFMIPeephole::initialize(MachineFunction &MFParm) {
LLVM_DEBUG(dbgs() << "*** BPF MachineSSA ZEXT Elim peephole pass ***\n\n");
}
-bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
+bool BPFMIPeephole::isCopyFrom32Def(MachineInstr *CopyMI)
{
- MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
+ MachineOperand &opnd = CopyMI->getOperand(1);
- LLVM_DEBUG(dbgs() << " Def of Mov Src:");
- LLVM_DEBUG(DefInsn->dump());
+ if (!opnd.isReg())
+ return false;
- if (!DefInsn)
+ // Return false if getting value from a 32bit physical register.
+ // Most likely, this physical register is aliased to
+ // function call return value or current function parameters.
+ Register Reg = opnd.getReg();
+ if (!Register::isVirtualRegister(Reg))
return false;
- if (DefInsn->isPHI()) {
- for (unsigned i = 1, e = DefInsn->getNumOperands(); i < e; i += 2) {
- MachineOperand &opnd = DefInsn->getOperand(i);
+ if (MRI->getRegClass(Reg) == &BPF::GPRRegClass)
+ return false;
- if (!opnd.isReg())
- return false;
+ MachineInstr *DefInsn = MRI->getVRegDef(Reg);
+ if (!isInsnFrom32Def(DefInsn))
+ return false;
- MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
- // quick check on PHI incoming definitions.
- if (!PhiDef || PhiDef->isPHI() || PhiDef->getOpcode() == BPF::COPY)
+ return true;
+}
+
+bool BPFMIPeephole::isPhiFrom32Def(MachineInstr *PhiMI)
+{
+ for (unsigned i = 1, e = PhiMI->getNumOperands(); i < e; i += 2) {
+ MachineOperand &opnd = PhiMI->getOperand(i);
+
+ if (!opnd.isReg())
+ return false;
+
+ MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
+ if (!PhiDef)
+ return false;
+ if (PhiDef->isPHI()) {
+ if (PhiInsns.find(PhiDef) != PhiInsns.end())
+ return false;
+ PhiInsns.insert(PhiDef);
+ if (!isPhiFrom32Def(PhiDef))
return false;
}
+ if (PhiDef->getOpcode() == BPF::COPY && !isCopyFrom32Def(PhiDef))
+ return false;
}
- if (DefInsn->getOpcode() == BPF::COPY) {
- MachineOperand &opnd = DefInsn->getOperand(1);
+ return true;
+}
- if (!opnd.isReg())
- return false;
+// The \p DefInsn instruction defines a virtual register.
+bool BPFMIPeephole::isInsnFrom32Def(MachineInstr *DefInsn)
+{
+ if (!DefInsn)
+ return false;
- Register Reg = opnd.getReg();
- if ((Register::isVirtualRegister(Reg) &&
- MRI->getRegClass(Reg) == &BPF::GPRRegClass))
+ if (DefInsn->isPHI()) {
+ if (PhiInsns.find(DefInsn) != PhiInsns.end())
+ return false;
+ PhiInsns.insert(DefInsn);
+ if (!isPhiFrom32Def(DefInsn))
+ return false;
+ } else if (DefInsn->getOpcode() == BPF::COPY) {
+ if (!isCopyFrom32Def(DefInsn))
return false;
}
+ return true;
+}
+
+bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
+{
+ MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
+
+ LLVM_DEBUG(dbgs() << " Def of Mov Src:");
+ LLVM_DEBUG(DefInsn->dump());
+
+ PhiInsns.clear();
+ if (!isInsnFrom32Def(DefInsn))
+ return false;
+
LLVM_DEBUG(dbgs() << " One ZExt elim sequence identified.\n");
return true;
diff --git a/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp b/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp
index 9c689aed64178..5310f0f07b65f 100644
--- a/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp
+++ b/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp
@@ -53,6 +53,19 @@ private:
void initialize(MachineFunction &MFParm);
bool removeLD(void);
+ void processCandidate(MachineRegisterInfo *MRI, MachineBasicBlock &MBB,
+ MachineInstr &MI, Register &SrcReg, Register &DstReg,
+ const GlobalValue *GVal);
+ void processDstReg(MachineRegisterInfo *MRI, Register &DstReg,
+ Register &SrcReg, const GlobalValue *GVal,
+ bool doSrcRegProp);
+ void processInst(MachineRegisterInfo *MRI, MachineInstr *Inst,
+ MachineOperand *RelocOp, const GlobalValue *GVal);
+ void checkADDrr(MachineRegisterInfo *MRI, MachineOperand *RelocOp,
+ const GlobalValue *GVal);
+ void checkShift(MachineRegisterInfo *MRI, MachineBasicBlock &MBB,
+ MachineOperand *RelocOp, const GlobalValue *GVal,
+ unsigned Opcode);
public:
// Main entry point for this pass.
@@ -71,6 +84,146 @@ void BPFMISimplifyPatchable::initialize(MachineFunction &MFParm) {
LLVM_DEBUG(dbgs() << "*** BPF simplify patchable insts pass ***\n\n");
}
+void BPFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
+ MachineOperand *RelocOp, const GlobalValue *GVal) {
+ const MachineInstr *Inst = RelocOp->getParent();
+ const MachineOperand *Op1 = &Inst->getOperand(1);
+ const MachineOperand *Op2 = &Inst->getOperand(2);
+ const MachineOperand *BaseOp = (RelocOp == Op1) ? Op2 : Op1;
+
+ // Go through all uses of %1 as in %1 = ADD_rr %2, %3
+ const MachineOperand Op0 = Inst->getOperand(0);
+ auto Begin = MRI->use_begin(Op0.getReg()), End = MRI->use_end();
+ decltype(End) NextI;
+ for (auto I = Begin; I != End; I = NextI) {
+ NextI = std::next(I);
+ // The candidate needs to have a unique definition.
+ if (!MRI->getUniqueVRegDef(I->getReg()))
+ continue;
+
+ MachineInstr *DefInst = I->getParent();
+ unsigned Opcode = DefInst->getOpcode();
+ unsigned COREOp;
+ if (Opcode == BPF::LDB || Opcode == BPF::LDH || Opcode == BPF::LDW ||
+ Opcode == BPF::LDD || Opcode == BPF::STB || Opcode == BPF::STH ||
+ Opcode == BPF::STW || Opcode == BPF::STD)
+ COREOp = BPF::CORE_MEM;
+ else if (Opcode == BPF::LDB32 || Opcode == BPF::LDH32 ||
+ Opcode == BPF::LDW32 || Opcode == BPF::STB32 ||
+ Opcode == BPF::STH32 || Opcode == BPF::STW32)
+ COREOp = BPF::CORE_ALU32_MEM;
+ else
+ continue;
+
+ // It must be a form of %1 = *(type *)(%2 + 0) or *(type *)(%2 + 0) = %1.
+ const MachineOperand &ImmOp = DefInst->getOperand(2);
+ if (!ImmOp.isImm() || ImmOp.getImm() != 0)
+ continue;
+
+ BuildMI(*DefInst->getParent(), *DefInst, DefInst->getDebugLoc(), TII->get(COREOp))
+ .add(DefInst->getOperand(0)).addImm(Opcode).add(*BaseOp)
+ .addGlobalAddress(GVal);
+ DefInst->eraseFromParent();
+ }
+}
+
+void BPFMISimplifyPatchable::checkShift(MachineRegisterInfo *MRI,
+ MachineBasicBlock &MBB, MachineOperand *RelocOp, const GlobalValue *GVal,
+ unsigned Opcode) {
+ // Relocation operand should be the operand #2.
+ MachineInstr *Inst = RelocOp->getParent();
+ if (RelocOp != &Inst->getOperand(2))
+ return;
+
+ BuildMI(MBB, *Inst, Inst->getDebugLoc(), TII->get(BPF::CORE_SHIFT))
+ .add(Inst->getOperand(0)).addImm(Opcode)
+ .add(Inst->getOperand(1)).addGlobalAddress(GVal);
+ Inst->eraseFromParent();
+}
+
+void BPFMISimplifyPatchable::processCandidate(MachineRegisterInfo *MRI,
+ MachineBasicBlock &MBB, MachineInstr &MI, Register &SrcReg,
+ Register &DstReg, const GlobalValue *GVal) {
+ 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);
+ }
+ }
+
+ BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::COPY), DstReg)
+ .addReg(SrcReg, 0, BPF::sub_32);
+ return;
+ }
+
+ // All uses of DstReg replaced by SrcReg
+ processDstReg(MRI, DstReg, SrcReg, GVal, true);
+}
+
+void BPFMISimplifyPatchable::processDstReg(MachineRegisterInfo *MRI,
+ Register &DstReg, Register &SrcReg, const GlobalValue *GVal,
+ bool doSrcRegProp) {
+ 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 (doSrcRegProp)
+ I->setReg(SrcReg);
+
+ // The candidate needs to have a unique definition.
+ if (MRI->getUniqueVRegDef(I->getReg()))
+ processInst(MRI, I->getParent(), &*I, GVal);
+ }
+}
+
+// Check to see whether we could do some optimization
+// to attach relocation to downstream dependent instructions.
+// Two kinds of patterns are recognized below:
+// Pattern 1:
+// %1 = LD_imm64 @"llvm.b:0:4$0:1" <== patch_imm = 4
+// %2 = LDD %1, 0 <== this insn will be removed
+// %3 = ADD_rr %0, %2
+// %4 = LDW[32] %3, 0 OR STW[32] %4, %3, 0
+// The `%4 = ...` will be transformed to
+// CORE_[ALU32_]MEM(%4, mem_opcode, %0, @"llvm.b:0:4$0:1")
+// and later on, BTF emit phase will translate to
+// %4 = LDW[32] %0, 4 STW[32] %4, %0, 4
+// and attach a relocation to it.
+// Pattern 2:
+// %15 = LD_imm64 @"llvm.t:5:63$0:2" <== relocation type 5
+// %16 = LDD %15, 0 <== this insn will be removed
+// %17 = SRA_rr %14, %16
+// The `%17 = ...` will be transformed to
+// %17 = CORE_SHIFT(SRA_ri, %14, @"llvm.t:5:63$0:2")
+// and later on, BTF emit phase will translate to
+// %r4 = SRA_ri %r4, 63
+void BPFMISimplifyPatchable::processInst(MachineRegisterInfo *MRI,
+ MachineInstr *Inst, MachineOperand *RelocOp, const GlobalValue *GVal) {
+ unsigned Opcode = Inst->getOpcode();
+ if (Opcode == BPF::ADD_rr)
+ checkADDrr(MRI, RelocOp, GVal);
+ else if (Opcode == BPF::SLL_rr)
+ checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SLL_ri);
+ else if (Opcode == BPF::SRA_rr)
+ checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SRA_ri);
+ else if (Opcode == BPF::SRL_rr)
+ checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SRL_ri);
+}
+
/// Remove unneeded Load instructions.
bool BPFMISimplifyPatchable::removeLD() {
MachineRegisterInfo *MRI = &MF->getRegInfo();
@@ -105,10 +258,11 @@ bool BPFMISimplifyPatchable::removeLD() {
continue;
bool IsCandidate = false;
+ const GlobalValue *GVal = nullptr;
if (DefInst->getOpcode() == BPF::LD_imm64) {
const MachineOperand &MO = DefInst->getOperand(1);
if (MO.isGlobal()) {
- const GlobalValue *GVal = MO.getGlobal();
+ GVal = MO.getGlobal();
auto *GVar = dyn_cast<GlobalVariable>(GVal);
if (GVar) {
// Global variables representing structure offset or
@@ -124,12 +278,7 @@ bool BPFMISimplifyPatchable::removeLD() {
if (!IsCandidate)
continue;
- 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);
- I->setReg(SrcReg);
- }
+ processCandidate(MRI, MBB, MI, SrcReg, DstReg, GVal);
ToErase = &MI;
Changed = true;
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.cpp b/llvm/lib/Target/BPF/BPFSubtarget.cpp
index ab3452501b952..f3cb03b1f1f57 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.cpp
+++ b/llvm/lib/Target/BPF/BPFSubtarget.cpp
@@ -52,6 +52,7 @@ void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
if (CPU == "v3") {
HasJmpExt = true;
HasJmp32 = true;
+ HasAlu32 = true;
return;
}
}
diff --git a/llvm/lib/Target/BPF/BPFTargetMachine.cpp b/llvm/lib/Target/BPF/BPFTargetMachine.cpp
index 0c4f2c74e7a4a..40375bc88bff2 100644
--- a/llvm/lib/Target/BPF/BPFTargetMachine.cpp
+++ b/llvm/lib/Target/BPF/BPFTargetMachine.cpp
@@ -27,7 +27,7 @@ static cl::
opt<bool> DisableMIPeephole("disable-bpf-peephole", cl::Hidden,
cl::desc("Disable machine peepholes for BPF"));
-extern "C" void LLVMInitializeBPFTarget() {
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTarget() {
// Register the target.
RegisterTargetMachine<BPFTargetMachine> X(getTheBPFleTarget());
RegisterTargetMachine<BPFTargetMachine> Y(getTheBPFbeTarget());
diff --git a/llvm/lib/Target/BPF/BTF.h b/llvm/lib/Target/BPF/BTF.h
index a13c862bf840a..ad3dcc14c38a3 100644
--- a/llvm/lib/Target/BPF/BTF.h
+++ b/llvm/lib/Target/BPF/BTF.h
@@ -176,12 +176,18 @@ struct BTFParam {
uint32_t Type;
};
+/// BTF_KIND_FUNC can be global, static or extern.
+enum : uint8_t {
+ FUNC_STATIC = 0,
+ FUNC_GLOBAL = 1,
+ FUNC_EXTERN = 2,
+};
+
/// Variable scoping information.
enum : uint8_t {
VAR_STATIC = 0, ///< Linkage: InternalLinkage
VAR_GLOBAL_ALLOCATED = 1, ///< Linkage: ExternalLinkage
- VAR_GLOBAL_TENTATIVE = 2, ///< Linkage: CommonLinkage
- VAR_GLOBAL_EXTERNAL = 3, ///< Linkage: ExternalLinkage
+ VAR_GLOBAL_EXTERNAL = 2, ///< Linkage: ExternalLinkage
};
/// BTF_KIND_DATASEC are followed by multiple "struct BTFDataSecVar".
diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp
index db551e739bd7c..a9fb04f20d1c8 100644
--- a/llvm/lib/Target/BPF/BTFDebug.cpp
+++ b/llvm/lib/Target/BPF/BTFDebug.cpp
@@ -308,10 +308,11 @@ void BTFTypeFuncProto::emitType(MCStreamer &OS) {
}
}
-BTFTypeFunc::BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId)
+BTFTypeFunc::BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId,
+ uint32_t Scope)
: Name(FuncName) {
Kind = BTF::BTF_KIND_FUNC;
- BTFType.Info = Kind << 24;
+ BTFType.Info = (Kind << 24) | Scope;
BTFType.Type = ProtoTypeId;
}
@@ -897,8 +898,9 @@ void BTFDebug::beginFunctionImpl(const MachineFunction *MF) {
visitSubroutineType(SP->getType(), true, FuncArgNames, ProtoTypeId);
// Construct subprogram func type
+ uint8_t Scope = SP->isLocalToUnit() ? BTF::FUNC_STATIC : BTF::FUNC_GLOBAL;
auto FuncTypeEntry =
- std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId);
+ std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId, Scope);
uint32_t FuncTypeId = addType(std::move(FuncTypeEntry));
for (const auto &TypeEntry : TypeEntries)
@@ -937,9 +939,8 @@ unsigned BTFDebug::populateStructType(const DIType *Ty) {
}
/// Generate a struct member field relocation.
-void BTFDebug::generateFieldReloc(const MachineInstr *MI,
- const MCSymbol *ORSym, DIType *RootTy,
- StringRef AccessPattern) {
+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(':');
@@ -959,33 +960,8 @@ void BTFDebug::generateFieldReloc(const MachineInstr *MI,
FieldRelocTable[SecNameOff].push_back(FieldReloc);
}
-void BTFDebug::processLDimm64(const MachineInstr *MI) {
- // If the insn is an LD_imm64, the following two cases
- // will generate an .BTF.ext record.
- //
- // If the insn is "r2 = LD_imm64 @__BTF_...",
- // add this insn into the .BTF.ext FieldReloc subsection.
- // Relocation looks like:
- // . SecName:
- // . InstOffset
- // . TypeID
- // . OffSetNameOff
- // 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 @VAR" and VAR is
- // a patchable external global, add this insn into the .BTF.ext
- // ExternReloc subsection.
- // Relocation looks like:
- // . SecName:
- // . InstOffset
- // . ExternNameOff
- // Later, the insn is replaced with "r2 = <value>" or
- // "LD_imm64 r2, <value>" where "<value>" = 0.
-
+void BTFDebug::processReloc(const MachineOperand &MO) {
// check whether this is a candidate or not
- const MachineOperand &MO = MI->getOperand(1);
if (MO.isGlobal()) {
const GlobalValue *GVal = MO.getGlobal();
auto *GVar = dyn_cast<GlobalVariable>(GVal);
@@ -995,7 +971,7 @@ void BTFDebug::processLDimm64(const MachineInstr *MI) {
MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index);
DIType *Ty = dyn_cast<DIType>(MDN);
- generateFieldReloc(MI, ORSym, Ty, GVar->getName());
+ generateFieldReloc(ORSym, Ty, GVar->getName());
}
}
}
@@ -1020,8 +996,31 @@ void BTFDebug::beginInstruction(const MachineInstr *MI) {
return;
}
- if (MI->getOpcode() == BPF::LD_imm64)
- processLDimm64(MI);
+ if (MI->getOpcode() == BPF::LD_imm64) {
+ // If the insn is "r2 = LD_imm64 @<an AmaAttr global>",
+ // add this insn into the .BTF.ext FieldReloc subsection.
+ // Relocation looks like:
+ // . SecName:
+ // . InstOffset
+ // . TypeID
+ // . OffSetNameOff
+ // . RelocType
+ // Later, the insn is replaced with "r2 = <offset>"
+ // where "<offset>" equals to the offset based on current
+ // type definitions.
+ processReloc(MI->getOperand(1));
+ } else if (MI->getOpcode() == BPF::CORE_MEM ||
+ MI->getOpcode() == BPF::CORE_ALU32_MEM ||
+ MI->getOpcode() == BPF::CORE_SHIFT) {
+ // relocation insn is a load, store or shift insn.
+ processReloc(MI->getOperand(3));
+ } else if (MI->getOpcode() == BPF::JAL) {
+ // check extern function references
+ const MachineOperand &MO = MI->getOperand(0);
+ if (MO.isGlobal()) {
+ processFuncPrototypes(dyn_cast<Function>(MO.getGlobal()));
+ }
+ }
// Skip this instruction if no DebugLoc or the DebugLoc
// is the same as the previous instruction.
@@ -1055,20 +1054,20 @@ void BTFDebug::processGlobals(bool ProcessingMapDef) {
// Collect all types referenced by globals.
const Module *M = MMI->getModule();
for (const GlobalVariable &Global : M->globals()) {
- // Ignore external globals for now.
- if (!Global.hasInitializer() && Global.hasExternalLinkage())
- continue;
-
// Decide the section name.
StringRef SecName;
if (Global.hasSection()) {
SecName = Global.getSection();
- } else {
+ } else if (Global.hasInitializer()) {
// data, bss, or readonly sections
if (Global.isConstant())
SecName = ".rodata";
else
SecName = Global.getInitializer()->isZeroValue() ? ".bss" : ".data";
+ } else {
+ // extern variables without explicit section,
+ // put them into ".extern" section.
+ SecName = ".extern";
}
if (ProcessingMapDef != SecName.startswith(".maps"))
@@ -1076,6 +1075,11 @@ void BTFDebug::processGlobals(bool ProcessingMapDef) {
SmallVector<DIGlobalVariableExpression *, 1> GVs;
Global.getDebugInfo(GVs);
+
+ // No type information, mostly internal, skip it.
+ if (GVs.size() == 0)
+ continue;
+
uint32_t GVTypeId = 0;
for (auto *GVE : GVs) {
if (SecName.startswith(".maps"))
@@ -1087,25 +1091,33 @@ void BTFDebug::processGlobals(bool ProcessingMapDef) {
// Only support the following globals:
// . static variables
- // . non-static global variables with section attributes
- // Essentially means:
- // . .bcc/.data/.rodata DataSec entities only contain static data
- // . Other DataSec entities contain static or initialized global data.
- // Initialized global data are mostly used for finding map key/value type
- // id's. Whether DataSec is readonly or not can be found from
- // corresponding ELF section flags.
+ // . non-static weak or non-weak global variables
+ // . weak or non-weak extern global variables
+ // Whether DataSec is readonly or not can be found from corresponding ELF
+ // section flags. Whether a BTF_KIND_VAR is a weak symbol or not
+ // can be found from the corresponding ELF symbol table.
auto Linkage = Global.getLinkage();
if (Linkage != GlobalValue::InternalLinkage &&
- (Linkage != GlobalValue::ExternalLinkage || !Global.hasSection()))
+ Linkage != GlobalValue::ExternalLinkage &&
+ Linkage != GlobalValue::WeakAnyLinkage &&
+ Linkage != GlobalValue::ExternalWeakLinkage)
continue;
- uint32_t GVarInfo = Linkage == GlobalValue::ExternalLinkage
- ? BTF::VAR_GLOBAL_ALLOCATED
- : BTF::VAR_STATIC;
+ uint32_t GVarInfo;
+ if (Linkage == GlobalValue::InternalLinkage) {
+ GVarInfo = BTF::VAR_STATIC;
+ } else if (Global.hasInitializer()) {
+ GVarInfo = BTF::VAR_GLOBAL_ALLOCATED;
+ } else {
+ GVarInfo = BTF::VAR_GLOBAL_EXTERNAL;
+ }
+
auto VarEntry =
std::make_unique<BTFKindVar>(Global.getName(), GVTypeId, GVarInfo);
uint32_t VarId = addType(std::move(VarEntry));
+ assert(!SecName.empty());
+
// Find or create a DataSec
if (DataSecEntries.find(SecName) == DataSecEntries.end()) {
DataSecEntries[SecName] = std::make_unique<BTFKindDataSec>(Asm, SecName);
@@ -1135,10 +1147,52 @@ bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) {
return true;
}
}
+ } else if (MI->getOpcode() == BPF::CORE_MEM ||
+ MI->getOpcode() == BPF::CORE_ALU32_MEM ||
+ MI->getOpcode() == BPF::CORE_SHIFT) {
+ const MachineOperand &MO = MI->getOperand(3);
+ if (MO.isGlobal()) {
+ const GlobalValue *GVal = MO.getGlobal();
+ auto *GVar = dyn_cast<GlobalVariable>(GVal);
+ if (GVar && GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) {
+ uint32_t Imm = PatchImms[GVar->getName().str()];
+ OutMI.setOpcode(MI->getOperand(1).getImm());
+ if (MI->getOperand(0).isImm())
+ OutMI.addOperand(MCOperand::createImm(MI->getOperand(0).getImm()));
+ else
+ OutMI.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
+ OutMI.addOperand(MCOperand::createReg(MI->getOperand(2).getReg()));
+ OutMI.addOperand(MCOperand::createImm(Imm));
+ return true;
+ }
+ }
}
return false;
}
+void BTFDebug::processFuncPrototypes(const Function *F) {
+ if (!F)
+ return;
+
+ const DISubprogram *SP = F->getSubprogram();
+ if (!SP || SP->isDefinition())
+ return;
+
+ // Do not emit again if already emitted.
+ if (ProtoFunctions.find(F) != ProtoFunctions.end())
+ return;
+ ProtoFunctions.insert(F);
+
+ uint32_t ProtoTypeId;
+ const std::unordered_map<uint32_t, StringRef> FuncArgNames;
+ visitSubroutineType(SP->getType(), false, FuncArgNames, ProtoTypeId);
+
+ uint8_t Scope = BTF::FUNC_EXTERN;
+ auto FuncTypeEntry =
+ std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId, Scope);
+ addType(std::move(FuncTypeEntry));
+}
+
void BTFDebug::endModule() {
// Collect MapDef globals if not collected yet.
if (MapDefNotCollected) {
@@ -1148,6 +1202,7 @@ void BTFDebug::endModule() {
// Collect global types/variables except MapDef globals.
processGlobals(false);
+
for (auto &DataSec : DataSecEntries)
addType(std::move(DataSec.second));
diff --git a/llvm/lib/Target/BPF/BTFDebug.h b/llvm/lib/Target/BPF/BTFDebug.h
index c01e0d1d16128..0812c4f7915de 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 <set>
#include <unordered_map>
#include "BTF.h"
@@ -151,7 +152,7 @@ class BTFTypeFunc : public BTFTypeBase {
StringRef Name;
public:
- BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId);
+ BTFTypeFunc(StringRef FuncName, uint32_t ProtoTypeId, uint32_t Scope);
uint32_t getSize() { return BTFTypeBase::getSize(); }
void completeType(BTFDebug &BDebug);
void emitType(MCStreamer &OS);
@@ -223,7 +224,7 @@ struct BTFLineInfo {
uint32_t ColumnNum; ///< the column number
};
-/// Represent one offset relocation.
+/// Represent one field relocation.
struct BTFFieldReloc {
const MCSymbol *Label; ///< MCSymbol identifying insn for the reloc
uint32_t TypeID; ///< Type ID
@@ -251,6 +252,7 @@ class BTFDebug : public DebugHandlerBase {
std::map<std::string, uint32_t> PatchImms;
std::map<StringRef, std::pair<bool, std::vector<BTFTypeDerived *>>>
FixupDerivedTypes;
+ std::set<const Function *>ProtoFunctions;
/// Add types to TypeEntries.
/// @{
@@ -293,15 +295,18 @@ class BTFDebug : public DebugHandlerBase {
/// Generate types and variables for globals.
void processGlobals(bool ProcessingMapDef);
- /// Generate one offset relocation record.
- void generateFieldReloc(const MachineInstr *MI, const MCSymbol *ORSym,
- DIType *RootTy, StringRef AccessPattern);
+ /// Generate types for function prototypes.
+ void processFuncPrototypes(const Function *);
+
+ /// Generate one field relocation record.
+ void generateFieldReloc(const MCSymbol *ORSym, DIType *RootTy,
+ StringRef AccessPattern);
/// Populating unprocessed struct type.
unsigned populateStructType(const DIType *Ty);
- /// Process LD_imm64 instructions.
- void processLDimm64(const MachineInstr *MI);
+ /// Process relocation instructions.
+ void processReloc(const MachineOperand &MO);
/// Emit common header of .BTF and .BTF.ext sections.
void emitCommonHeader();
diff --git a/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp b/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
index c845524ad657a..75f963b5448ac 100644
--- a/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
+++ b/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
@@ -67,7 +67,6 @@ public:
DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
ArrayRef<uint8_t> Bytes, uint64_t Address,
- raw_ostream &VStream,
raw_ostream &CStream) const override;
uint8_t getInstClass(uint64_t Inst) const { return (Inst >> 56) & 0x7; };
@@ -84,7 +83,7 @@ static MCDisassembler *createBPFDisassembler(const Target &T,
}
-extern "C" void LLVMInitializeBPFDisassembler() {
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFDisassembler() {
// Register the disassembler.
TargetRegistry::RegisterMCDisassembler(getTheBPFTarget(),
createBPFDisassembler);
@@ -162,7 +161,6 @@ static DecodeStatus readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
DecodeStatus BPFDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
ArrayRef<uint8_t> Bytes,
uint64_t Address,
- raw_ostream &VStream,
raw_ostream &CStream) const {
bool IsLittleEndian = getContext().getAsmInfo()->isLittleEndian();
uint64_t Insn, Hi;
diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.cpp
index 079202994c8d7..e0aeec989879d 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.cpp
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.cpp
@@ -24,9 +24,10 @@ using namespace llvm;
// Include the auto-generated portion of the assembly writer.
#include "BPFGenAsmWriter.inc"
-void BPFInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
- StringRef Annot, const MCSubtargetInfo &STI) {
- printInstruction(MI, O);
+void BPFInstPrinter::printInst(const MCInst *MI, uint64_t Address,
+ StringRef Annot, const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ printInstruction(MI, Address, O);
printAnnotation(O, Annot);
}
diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.h b/llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.h
index 8c9a0bc94cffb..2181bb575cdda 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.h
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.h
@@ -22,8 +22,8 @@ public:
const MCRegisterInfo &MRI)
: MCInstPrinter(MAI, MII, MRI) {}
- void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot,
- const MCSubtargetInfo &STI) override;
+ void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
+ const MCSubtargetInfo &STI, raw_ostream &O) override;
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
const char *Modifier = nullptr);
void printMemOperand(const MCInst *MI, int OpNo, raw_ostream &O,
@@ -32,7 +32,7 @@ public:
void printBrTargetOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
// Autogenerated by tblgen.
- void printInstruction(const MCInst *MI, raw_ostream &O);
+ void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
static const char *getRegisterName(unsigned RegNo);
};
}
diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h
index 04a6a87cebc9e..97f0cbd586082 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h
@@ -21,7 +21,7 @@ class Target;
class BPFMCAsmInfo : public MCAsmInfo {
public:
- explicit BPFMCAsmInfo(const Triple &TT) {
+ explicit BPFMCAsmInfo(const Triple &TT, const MCTargetOptions &Options) {
if (TT.getArch() == Triple::bpfeb)
IsLittleEndian = false;
diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
index fa27b335f3a18..58da0830d0022 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
@@ -97,7 +97,7 @@ static MCInstrAnalysis *createBPFInstrAnalysis(const MCInstrInfo *Info) {
return new BPFMCInstrAnalysis(Info);
}
-extern "C" void LLVMInitializeBPFTargetMC() {
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTargetMC() {
for (Target *T :
{&getTheBPFleTarget(), &getTheBPFbeTarget(), &getTheBPFTarget()}) {
// Register the MC asm info.
diff --git a/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp b/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
index 5dfa915034bad..49eb9ad62c562 100644
--- a/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
+++ b/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
@@ -24,7 +24,7 @@ Target &llvm::getTheBPFTarget() {
return TheBPFTarget;
}
-extern "C" void LLVMInitializeBPFTargetInfo() {
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTargetInfo() {
TargetRegistry::RegisterTarget(getTheBPFTarget(), "bpf", "BPF (host endian)",
"BPF", [](Triple::ArchType) { return false; },
true);