[LLVMdev] [PATCH 2/2] Allow full constants in symbol_offsets
Ben Gamari
bgamari.foss at gmail.com
Sun May 25 17:41:11 PDT 2014
From: Ben Gamari <ben at ben-server>
This generalized symbol offset support for allow constant offsets (Option 1 of
the original proposal[1]).
[1] http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061511.html
---
include/llvm/IR/Function.h | 32 +++++++++++++++----------
lib/AsmParser/LLParser.cpp | 4 ++--
lib/Bitcode/Reader/BitcodeReader.cpp | 19 +++++++++++++--
lib/Bitcode/Reader/BitcodeReader.h | 1 +
lib/Bitcode/Writer/BitcodeWriter.cpp | 3 ++-
lib/Bitcode/Writer/ValueEnumerator.cpp | 5 ++++
lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 10 ++++----
lib/IR/AsmWriter.cpp | 7 ++++--
lib/IR/Function.cpp | 43 +++++++++++++++++++++++++++-------
lib/IR/LLVMContextImpl.h | 6 +++++
lib/IR/TypeFinder.cpp | 3 +++
lib/Transforms/IPO/GlobalDCE.cpp | 3 +++
test/Feature/symbol_offset.ll | 4 ++--
13 files changed, 106 insertions(+), 34 deletions(-)
diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h
index 0332e74..ab85c0d 100644
--- a/include/llvm/IR/Function.h
+++ b/include/llvm/IR/Function.h
@@ -86,13 +86,15 @@ private:
mutable ArgumentListType ArgumentList; ///< The formal arguments
ValueSymbolTable *SymTab; ///< Symbol table of args/instructions
AttributeSet AttributeSets; ///< Parameter attributes
- signed SymbolOffset; ///< Symbol offset
- // HasLazyArguments is stored in Value::SubclassData.
- /*bool HasLazyArguments;*/
-
- // The Calling Convention is stored in Value::SubclassData.
- /*CallingConv::ID CallingConvention;*/
+ /*
+ * Value::SubclassData
+ *
+ * bit 0 : HasLazyArguments
+ * bit 1 : HasPrefixData
+ * bit 2 : HasSymbolOffset
+ * bit 3-6: CallingConvention
+ */
friend class SymbolTableListTraits<Function, Module>;
@@ -103,7 +105,7 @@ private:
/// needs it. The hasLazyArguments predicate returns true if the arg list
/// hasn't been set up yet.
bool hasLazyArguments() const {
- return getSubclassDataFromValue() & 1;
+ return getSubclassDataFromValue() & (1<<0);
}
void CheckLazyArguments() const {
if (hasLazyArguments())
@@ -160,11 +162,11 @@ public:
/// calling convention of this function. The enum values for the known
/// calling conventions are defined in CallingConv.h.
CallingConv::ID getCallingConv() const {
- return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 2);
+ return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 3);
}
void setCallingConv(CallingConv::ID CC) {
- setValueSubclassData((getSubclassDataFromValue() & 3) |
- (static_cast<unsigned>(CC) << 2));
+ setValueSubclassData((getSubclassDataFromValue() & 7) |
+ (static_cast<unsigned>(CC) << 3));
}
/// @brief Return the attribute list for this Function.
@@ -440,14 +442,18 @@ public:
bool arg_empty() const;
bool hasPrefixData() const {
- return getSubclassDataFromValue() & 2;
+ return getSubclassDataFromValue() & (1<<1);
}
Constant *getPrefixData() const;
void setPrefixData(Constant *PrefixData);
- signed getSymbolOffset() const;
- void setSymbolOffset(signed Offset);
+ bool hasSymbolOffset() const {
+ return getSubclassDataFromValue() & (1<<2);
+ }
+
+ Constant *getSymbolOffset() const;
+ void setSymbolOffset(Constant *Offset);
/// viewCFG - This function is meant for use from the debugger. You can just
/// say 'call F->viewCFG()' and a ghostview window should pop up from the
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 8988ffd..2b5c818 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -3110,7 +3110,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
bool UnnamedAddr;
LocTy UnnamedAddrLoc;
Constant *Prefix = nullptr;
- signed Offset = 0;
+ Constant *Offset = nullptr;
if (ParseArgumentList(ArgList, isVarArg) ||
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
@@ -3125,7 +3125,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
(EatIfPresent(lltok::kw_prefix) &&
ParseGlobalTypeAndValue(Prefix)) ||
(EatIfPresent(lltok::kw_symbol_offset) &&
- ParseInt32(Offset)))
+ ParseGlobalTypeAndValue(Offset)))
return true;
if (FuncAttrs.contains(Attribute::Builtin))
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 904468d..a4cb051 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1122,10 +1122,12 @@ error_code BitcodeReader::ResolveGlobalAndAliasInits() {
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
std::vector<std::pair<Function*, unsigned> > FunctionPrefixWorklist;
+ std::vector<std::pair<Function*, unsigned> > FunctionOffsetWorklist;
GlobalInitWorklist.swap(GlobalInits);
AliasInitWorklist.swap(AliasInits);
FunctionPrefixWorklist.swap(FunctionPrefixes);
+ FunctionOffsetWorklist.swap(FunctionOffsets);
while (!GlobalInitWorklist.empty()) {
unsigned ValID = GlobalInitWorklist.back().second;
@@ -1178,6 +1180,19 @@ error_code BitcodeReader::ResolveGlobalAndAliasInits() {
FunctionPrefixWorklist.pop_back();
}
+ while (!FunctionOffsetWorklist.empty()) {
+ unsigned ValID = FunctionOffsetWorklist.back().second;
+ if (ValID >= ValueList.size()) {
+ FunctionOffsets.push_back(FunctionOffsetWorklist.back());
+ } else {
+ if (Constant *C = dyn_cast_or_null<Constant>(ValueList[ValID]))
+ FunctionOffsetWorklist.back().first->setSymbolOffset(C);
+ else
+ return Error(ExpectedConstant);
+ }
+ FunctionOffsetWorklist.pop_back();
+ }
+
return error_code::success();
}
@@ -1977,8 +1992,8 @@ error_code BitcodeReader::ParseModule(bool Resume) {
Func->setUnnamedAddr(UnnamedAddr);
if (Record.size() > 10 && Record[10] != 0)
FunctionPrefixes.push_back(std::make_pair(Func, Record[10]-1));
- if (Record.size() > 11)
- Func->setSymbolOffset(Record[11]);
+ if (Record.size() > 11 && Record[11] != 0)
+ FunctionOffsets.push_back(std::make_pair(Func, Record[11]-1));
if (Record.size() > 12)
Func->setDLLStorageClass(GetDecodedDLLStorageClass(Record[12]));
diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h
index 593d8f9..d70f573 100644
--- a/lib/Bitcode/Reader/BitcodeReader.h
+++ b/lib/Bitcode/Reader/BitcodeReader.h
@@ -142,6 +142,7 @@ class BitcodeReader : public GVMaterializer {
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
std::vector<std::pair<Function*, unsigned> > FunctionPrefixes;
+ std::vector<std::pair<Function*, unsigned> > FunctionOffsets;
SmallVector<Instruction*, 64> InstsWithTBAATag;
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 151a4fa..e1d8838 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -655,7 +655,8 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
Vals.push_back(F->hasUnnamedAddr());
Vals.push_back(F->hasPrefixData() ? (VE.getValueID(F->getPrefixData()) + 1)
: 0);
- Vals.push_back(F->getSymbolOffset());
+ Vals.push_back(F->hasSymbolOffset() ? (VE.getValueID(F->getSymbolOffset()) + 1)
+ : 0);
Vals.push_back(getEncodedDLLStorageClass(F));
unsigned AbbrevToUse = 0;
diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp
index 8531e76..c851e9c 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -65,6 +65,11 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
if (I->hasPrefixData())
EnumerateValue(I->getPrefixData());
+ // Enumerate the symbol offset constants.
+ for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
+ if (I->hasSymbolOffset())
+ EnumerateValue(I->getSymbolOffset());
+
// Insert constants and metadata that are named at module level into the slot
// pool so that the module symbol table can refer to them...
EnumerateValueSymbolTable(M->getValueSymbolTable());
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index eed1b3b..99df7a0 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -63,6 +63,8 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed");
char AsmPrinter::ID = 0;
+static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP);
+
typedef DenseMap<GCStrategy*, std::unique_ptr<GCMetadataPrinter>> gcp_map_type;
static gcp_map_type &getGCMap(void *&P) {
if (!P)
@@ -561,14 +563,14 @@ void AsmPrinter::EmitFunctionEntryLabel() {
// The function label could have already been emitted if two symbols end up
// conflicting due to asm renaming. Detect this and emit an error.
if (CurrentFnSym->isUndefined()) {
- if (F->getSymbolOffset() != 0) {
+ if (F->hasSymbolOffset()) {
MCSymbol *dummySym = OutContext.CreateTempSymbol();
OutStreamer.EmitLabel(dummySym);
const MCExpr *symRefExpr = MCSymbolRefExpr::Create(dummySym, OutContext);
- const MCExpr *constExpr = MCConstantExpr::Create(F->getSymbolOffset(), OutContext);
- const MCExpr *addExpr = MCBinaryExpr::CreateAdd(symRefExpr, constExpr, OutContext);
- OutStreamer.EmitAssignment(CurrentFnSym, addExpr);
+ const MCExpr *offsetExpr = lowerConstant(F->getSymbolOffset(), *this);
+ const MCExpr *sumExpr = MCBinaryExpr::CreateAdd(symRefExpr, offsetExpr, OutContext);
+ OutStreamer.EmitAssignment(CurrentFnSym, sumExpr);
return;
} else {
return OutStreamer.EmitLabel(CurrentFnSym);
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp
index 9d39e4c..bd1631f 100644
--- a/lib/IR/AsmWriter.cpp
+++ b/lib/IR/AsmWriter.cpp
@@ -1657,8 +1657,11 @@ void AssemblyWriter::printFunction(const Function *F) {
Out << " prefix ";
writeOperand(F->getPrefixData(), true);
}
- if (F->getSymbolOffset() != 0)
- Out << " symbol_offset " << F->getSymbolOffset();
+ if (F->hasSymbolOffset()) {
+ Out << " symbol_offset ";
+ writeOperand(F->getSymbolOffset(), true);
+ }
+
if (F->isDeclaration()) {
Out << '\n';
} else {
diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp
index d158f9c..9195890 100644
--- a/lib/IR/Function.cpp
+++ b/lib/IR/Function.cpp
@@ -265,7 +265,7 @@ void Function::BuildLazyArguments() const {
// Clear the lazy arguments bit.
unsigned SDC = getSubclassDataFromValue();
- const_cast<Function*>(this)->setValueSubclassData(SDC &= ~1);
+ const_cast<Function*>(this)->setValueSubclassData(SDC &= ~(1<<0));
}
size_t Function::arg_size() const {
@@ -302,6 +302,9 @@ void Function::dropAllReferences() {
// Prefix data is stored in a side table.
setPrefixData(nullptr);
+
+ // Symbol offset is stored in a side table.
+ setSymbolOffset(nullptr);
}
void Function::addAttribute(unsigned i, Attribute::AttrKind attr) {
@@ -381,7 +384,10 @@ void Function::copyAttributesFrom(const GlobalValue *Src) {
setPrefixData(SrcF->getPrefixData());
else
setPrefixData(nullptr);
- setSymbolOffset(SrcF->getSymbolOffset());
+ if (SrcF->hasSymbolOffset())
+ setSymbolOffset(SrcF->getSymbolOffset());
+ else
+ setSymbolOffset(nullptr);
}
/// getIntrinsicID - This method returns the ID number of the specified
@@ -799,19 +805,40 @@ void Function::setPrefixData(Constant *PrefixData) {
PDHolder->setOperand(0, PrefixData);
else
PDHolder = ReturnInst::Create(getContext(), PrefixData);
- SCData |= 2;
+ SCData |= (1<<1);
} else {
delete PDHolder;
PDMap.erase(this);
- SCData &= ~2;
+ SCData &= ~(1<<1);
}
setValueSubclassData(SCData);
}
-signed Function::getSymbolOffset() const {
- return this->SymbolOffset;
+Constant *Function::getSymbolOffset() const {
+ assert(hasSymbolOffset());
+ const LLVMContextImpl::SymbolOffsetMapTy &SOMap =
+ getContext().pImpl->SymbolOffsetMap;
+ assert(SOMap.find(this) != SOMap.end());
+ return cast<Constant>(SOMap.find(this)->second->getReturnValue());
}
-void Function::setSymbolOffset(signed Offset) {
- this->SymbolOffset = Offset;
+void Function::setSymbolOffset(Constant *Offset) {
+ if (!Offset && !hasSymbolOffset())
+ return;
+
+ unsigned SCData = getSubclassDataFromValue();
+ LLVMContextImpl::SymbolOffsetMapTy &SOMap = getContext().pImpl->SymbolOffsetMap;
+ ReturnInst *&SOHolder = SOMap[this];
+ if (Offset) {
+ if (SOHolder)
+ SOHolder->setOperand(0, Offset);
+ else
+ SOHolder = ReturnInst::Create(getContext(), Offset);
+ SCData |= (1<<2);
+ } else {
+ delete SOHolder;
+ SOMap.erase(this);
+ SCData &= ~(1<<2);
+ }
+ setValueSubclassData(SCData);
}
diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h
index 808c239..ddb1f7d 100644
--- a/lib/IR/LLVMContextImpl.h
+++ b/lib/IR/LLVMContextImpl.h
@@ -374,6 +374,12 @@ public:
typedef DenseMap<const Function *, ReturnInst *> PrefixDataMapTy;
PrefixDataMapTy PrefixDataMap;
+ /// \brief Mapping from a function to its symbol offset, which is stored as
+ /// the operand of an unparented ReturnInst so that the prefix data has a
+ /// Use.
+ typedef DenseMap<const Function *, ReturnInst *> SymbolOffsetMapTy;
+ SymbolOffsetMapTy SymbolOffsetMap;
+
int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);
diff --git a/lib/IR/TypeFinder.cpp b/lib/IR/TypeFinder.cpp
index 689b903..5e63972 100644
--- a/lib/IR/TypeFinder.cpp
+++ b/lib/IR/TypeFinder.cpp
@@ -47,6 +47,9 @@ void TypeFinder::run(const Module &M, bool onlyNamed) {
if (FI->hasPrefixData())
incorporateValue(FI->getPrefixData());
+ if (FI->hasSymbolOffset())
+ incorporateValue(FI->getSymbolOffset());
+
// First incorporate the arguments.
for (Function::const_arg_iterator AI = FI->arg_begin(),
AE = FI->arg_end(); AI != AE; ++AI)
diff --git a/lib/Transforms/IPO/GlobalDCE.cpp b/lib/Transforms/IPO/GlobalDCE.cpp
index 9decddc..b1d65be 100644
--- a/lib/Transforms/IPO/GlobalDCE.cpp
+++ b/lib/Transforms/IPO/GlobalDCE.cpp
@@ -197,6 +197,9 @@ void GlobalDCE::GlobalIsNeeded(GlobalValue *G) {
if (F->hasPrefixData())
MarkUsedGlobalsAsNeeded(F->getPrefixData());
+ if (F->hasSymbolOffset())
+ MarkUsedGlobalsAsNeeded(F->getSymbolOffset());
+
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
for (User::op_iterator U = I->op_begin(), E = I->op_end(); U != E; ++U)
diff --git a/test/Feature/symbol_offset.ll b/test/Feature/symbol_offset.ll
index a9784f6..3bebc85 100644
--- a/test/Feature/symbol_offset.ll
+++ b/test/Feature/symbol_offset.ll
@@ -4,7 +4,7 @@
; RUN: diff %t1.ll %t2.ll
; RUN: opt -O3 -S < %t1.ll | FileCheck %s
-; CHECK: f(){{.*}}symbol_offset 1
-define void @f() symbol_offset 1 {
+; CHECK: f(){{.*}}symbol_offset i32 1
+define void @f() symbol_offset i32 1 {
ret void
}
--
1.9.2
More information about the llvm-dev
mailing list