Commit df6f9d18 by Karl Schimpf

Fix handling of relocation names, so that prefix mangling works.

Fixes bug in the representation of relocation names (in either global initializers or as constant expressions in code) so that they understand when the name is externally defined. This allows us to test this property using command line arguments, and fixes relocation tests in cross compilations (where externnally referenced names shouldn't be name mangled). BUG= R=jvoung@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/667763002
parent f76fd377
......@@ -45,9 +45,9 @@ namespace Subzero_ {
// functions receive arguments from the caller in the same way. The
// caller is compiled by llc.
size_t ArgNum, Subzero_ArgNum;
CalleePtrTy Callee, Subzero_Callee;
char *Buf, *Subzero_Buf;
size_t ArgNum;
CalleePtrTy Callee;
char *Buf;
const static size_t BUF_SIZE = 16;
......@@ -83,13 +83,13 @@ void testCaller(size_t &TotalTests, size_t &Passes, size_t &Failures) {
for (size_t f = 0; f < NumFuncs; ++f) {
char BufLlc[BUF_SIZE], BufSz[BUF_SIZE];
Callee = Subzero_Callee = Funcs[f].Callee;
Callee = Funcs[f].Callee;
for (size_t i = 0; i < Funcs[f].Args; ++i) {
memset(BufLlc, 0xff, sizeof(BufLlc));
memset(BufSz, 0xff, sizeof(BufSz));
ArgNum = Subzero_ArgNum = i;
ArgNum = i;
Buf = BufLlc;
Funcs[f].Caller();
......@@ -133,18 +133,18 @@ void testCallee(size_t &TotalTests, size_t &Passes, size_t &Failures) {
for (size_t f = 0; f < NumFuncs; ++f) {
char BufLlc[BUF_SIZE], BufSz[BUF_SIZE];
Buf = BufLlc;
Subzero_Buf = BufSz;
for (size_t i = 0; i < Funcs[f].Args; ++i) {
memset(BufLlc, 0xff, sizeof(BufLlc));
memset(BufSz, 0xff, sizeof(BufSz));
ArgNum = Subzero_ArgNum = i;
ArgNum = i;
Buf = BufLlc;
Callee = Funcs[f].Callee;
Funcs[f].Caller();
Buf = BufSz;
Callee = Funcs[f].Subzero_Callee;
Funcs[f].Caller();
......
......@@ -31,12 +31,6 @@ int ArrayInitFull[] = {10, 20, 30, 40, 50};
const int ArrayConst[] = {-10, -20, -30};
static double ArrayDouble[10] = { 0.5, 1.5, 2.5, 3.5 };
#if 0
// TODO(kschimpf) Add this example once we know how to not mangle
// uninitialized, external globals (so that we can compare that
// the same, unmangled relocations are used). See comment in
// TargetGlobalInitX8632::lower in IceTargetLoweringX8632.cpp for
// details.
static struct {
int Array1[5];
uint8_t *Pointer1;
......@@ -56,7 +50,6 @@ static struct {
{ ExternName3, {1000, 1010, 1020}, ExternName2 },
ExternName5,
};
#endif
#define ARRAY(a) \
{ (uint8_t *)(a), sizeof(a) }
......@@ -74,7 +67,7 @@ struct {
ARRAY(ArrayDouble),
{(uint8_t *)(ArrayInitPartial + 2),
sizeof(ArrayInitPartial) - 2 * sizeof(int)},
// { (uint8_t*)(&StructEx), sizeof(StructEx) },
{ (uint8_t*)(&StructEx), sizeof(StructEx) },
};
size_t NumArraysElements = sizeof(Arrays) / sizeof(*Arrays);
......
......@@ -349,7 +349,7 @@ void Cfg::dump(const IceString &Message) {
Str << "define ";
if (getInternal())
Str << "internal ";
Str << ReturnType << " @" << getFunctionName() << "(";
Str << ReturnType << " @" << Ctx->mangleName(getFunctionName()) << "(";
for (SizeT i = 0; i < Args.size(); ++i) {
if (i > 0)
Str << ", ";
......
......@@ -114,8 +114,11 @@ public:
// global initializers.
Ice::Constant *convertConstant(const Constant *Const) {
if (const auto GV = dyn_cast<GlobalValue>(Const)) {
return Ctx->getConstantSym(convertToIceType(GV->getType()), 0,
GV->getName());
Ice::GlobalDeclaration *Decl = getConverter().getGlobalDeclaration(GV);
const Ice::RelocOffsetT Offset = 0;
return Ctx->getConstantSym(TypeConverter.getIcePointerType(),
Offset, Decl->getName(),
Decl->getSuppressMangling());
} else if (const auto CI = dyn_cast<ConstantInt>(Const)) {
Ice::Type Ty = convertToIceType(CI->getType());
if (Ty == Ice::IceType_i64) {
......@@ -690,21 +693,30 @@ void LLVM2ICEGlobalsConverter::convertGlobalsToIce(
for (Module::const_global_iterator I = Mod->global_begin(),
E = Mod->global_end();
I != E; ++I) {
if (!I->hasInitializer() && Ctx->getFlags().AllowUninitializedGlobals)
continue;
const GlobalVariable *GV = I;
Ice::IceString Name = GV->getName();
if (!GV->hasInternalLinkage()) {
Ice::GlobalDeclaration *Var = getConverter().getGlobalDeclaration(GV);
Ice::VariableDeclaration* VarDecl = cast<Ice::VariableDeclaration>(Var);
VariableDeclarations.push_back(VarDecl);
if (!GV->hasInternalLinkage() && GV->hasInitializer()) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Can't define external global declaration: " << Name;
StrBuf << "Can't define external global declaration: " << GV->getName();
report_fatal_error(StrBuf.str());
}
Ice::GlobalDeclaration *Var = getConverter().getGlobalDeclaration(GV);
Ice::VariableDeclaration* VarDecl = cast<Ice::VariableDeclaration>(Var);
VariableDeclarations.push_back(VarDecl);
if (!GV->hasInitializer()) {
if (Ctx->getFlags().AllowUninitializedGlobals)
continue;
else {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Global declaration missing initializer: " << GV->getName();
report_fatal_error(StrBuf.str());
}
}
const Constant *Initializer = GV->getInitializer();
if (const auto CompoundInit = dyn_cast<ConstantStruct>(Initializer)) {
......@@ -858,9 +870,7 @@ void Converter::installGlobalDeclarations(Module *Mod) {
Var->setName(GV->getName());
Var->setAlignment(GV->getAlignment());
Var->setIsConstant(GV->isConstant());
// Note: We allow external for cross tests.
// TODO(kschimpf) Put behind flag AllowUninitializedGlobals.
Var->setIsInternal(!GV->isExternallyInitialized());
Var->setLinkage(GV->getLinkage());
GlobalDeclarationMap[GV] = Var;
}
}
......
......@@ -68,12 +68,13 @@ void FunctionDeclaration::dumpType(Ostream &Stream) const {
Stream << Signature;
}
void FunctionDeclaration::dump(Ostream &Stream) const {
void FunctionDeclaration::dump(GlobalContext *Ctx, Ostream &Stream) const {
if (IsProto)
Stream << "declare ";
::dumpLinkage(Stream, Linkage);
::dumpCallingConv(Stream, CallingConv);
Stream << Signature.getReturnType() << " @" << Name << "(";
Stream << Signature.getReturnType() << " @"
<< (Ctx ? Ctx->mangleName(Name) : Name) << "(";
bool IsFirst = true;
for (Type ArgTy : Signature.getArgList()) {
if (IsFirst)
......@@ -111,9 +112,11 @@ void VariableDeclaration::dumpType(Ostream &Stream) const {
}
}
void VariableDeclaration::dump(Ostream &Stream) const {
Stream << "@" << Name << " = internal "
<< (IsConstant ? "constant" : "global") << " ";
void VariableDeclaration::dump(GlobalContext *Ctx, Ostream &Stream) const {
Stream << "@" << ((Ctx && !getSuppressMangling())
? Ctx->mangleName(Name) : Name) << " = ";
::dumpLinkage(Stream, Linkage);
Stream << " " << (IsConstant ? "constant" : "global") << " ";
// Add initializer.
if (Initializers.size() == 1) {
......@@ -128,7 +131,7 @@ void VariableDeclaration::dump(Ostream &Stream) const {
} else {
Stream << ", ";
}
Init->dump(Stream);
Init->dump(Ctx, Stream);
}
Stream << " }>";
}
......@@ -143,7 +146,8 @@ void VariableDeclaration::Initializer::dumpType(Ostream &Stream) const {
Stream << "[" << getNumBytes() << " x " << Ice::IceType_i8 << "]";
}
void VariableDeclaration::DataInitializer::dump(Ostream &Stream) const {
void VariableDeclaration::DataInitializer::dump(
GlobalContext *, Ostream &Stream) const {
dumpType(Stream);
Stream << " c\"";
// Code taken from PrintEscapedString() in AsmWriter.cpp. Keep
......@@ -158,7 +162,8 @@ void VariableDeclaration::DataInitializer::dump(Ostream &Stream) const {
Stream << "\"";
}
void VariableDeclaration::ZeroInitializer::dump(Ostream &Stream) const {
void VariableDeclaration::ZeroInitializer::dump(
GlobalContext *, Ostream &Stream) const {
dumpType(Stream);
Stream << " zeroinitializer";
}
......@@ -167,7 +172,8 @@ void VariableDeclaration::RelocInitializer::dumpType(Ostream &Stream) const {
Stream << Ice::IceType_i32;
}
void VariableDeclaration::RelocInitializer::dump(Ostream &Stream) const {
void VariableDeclaration::RelocInitializer::dump(
GlobalContext *Ctx, Ostream &Stream) const {
if (Offset != 0) {
dumpType(Stream);
Stream << " add (";
......@@ -175,7 +181,12 @@ void VariableDeclaration::RelocInitializer::dump(Ostream &Stream) const {
dumpType(Stream);
Stream << " ptrtoint (";
Declaration->dumpType(Stream);
Stream << "* @" << Declaration->getName() << " to ";
Stream << "* @";
if (Ctx)
Stream << Ctx->mangleName(Declaration->getName());
else
Stream << Declaration->getName();
Stream << " to ";
dumpType(Stream);
Stream << ")";
if (Offset != 0) {
......
......@@ -43,26 +43,45 @@ public:
const IceString &getName() const { return Name; }
void setName(const IceString &NewName) { Name = NewName; }
bool hasName() const { return !Name.empty(); }
bool isInternal() const {
return Linkage == llvm::GlobalValue::InternalLinkage;
}
llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; }
bool isExternal() const {
return Linkage == llvm::GlobalValue::ExternalLinkage;
}
void setLinkage(llvm::GlobalValue::LinkageTypes NewLinkage) {
Linkage = NewLinkage;
}
virtual ~GlobalDeclaration() {}
/// Returns true if the declaration is external.
virtual bool getIsExternal() const = 0;
/// Prints out type of the global declaration.
virtual void dumpType(Ostream &Stream) const = 0;
/// Prints out the global declaration.
virtual void dump(Ostream &Stream) const = 0;
virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0;
void dump(Ostream &Stream) const {
GlobalContext *const Ctx = nullptr;
dump(Ctx, Stream);
}
/// Returns true if when emitting names, we should suppress mangling.
virtual bool getSuppressMangling() const = 0;
// Mangles name for cross tests, unless external and not defined locally
// (so that relocations accross llvm2ice and pnacl-llc will work).
virtual IceString mangleName(GlobalContext *Ctx) const = 0;
virtual IceString mangleName(GlobalContext *Ctx) const {
return getSuppressMangling() ? Name : Ctx->mangleName(Name);
}
protected:
GlobalDeclaration(GlobalDeclarationKind Kind) : Kind(Kind) {}
GlobalDeclaration(GlobalDeclarationKind Kind,
llvm::GlobalValue::LinkageTypes Linkage)
: Kind(Kind), Linkage(Linkage) {}
const GlobalDeclarationKind Kind;
IceString Name;
llvm::GlobalValue::LinkageTypes Linkage;
};
// Models a function declaration. This includes the type signature of
......@@ -81,33 +100,27 @@ public:
~FunctionDeclaration() final {}
const FuncSigType &getSignature() const { return Signature; }
llvm::CallingConv::ID getCallingConv() const { return CallingConv; }
llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; }
// isProto implies that there isn't a (local) definition for the function.
bool isProto() const { return IsProto; }
static bool classof(const GlobalDeclaration *Addr) {
return Addr->getKind() == FunctionDeclarationKind;
}
void dumpType(Ostream &Stream) const final;
void dump(Ostream &Stream) const final;
bool getIsExternal() const final {
return Linkage == llvm::GlobalValue::ExternalLinkage;
}
virtual IceString mangleName(GlobalContext *Ctx) const final {
return (getIsExternal() && IsProto) ? Name : Ctx->mangleName(Name);
void dump(GlobalContext *Ctx, Ostream &Stream) const final;
bool getSuppressMangling() const final {
return isExternal() && IsProto;
}
private:
const Ice::FuncSigType Signature;
llvm::CallingConv::ID CallingConv;
llvm::GlobalValue::LinkageTypes Linkage;
bool IsProto;
FunctionDeclaration(const FuncSigType &Signature,
llvm::CallingConv::ID CallingConv,
llvm::GlobalValue::LinkageTypes Linkage, bool IsProto)
: GlobalDeclaration(FunctionDeclarationKind), Signature(Signature),
CallingConv(CallingConv), Linkage(Linkage), IsProto(IsProto) {}
: GlobalDeclaration(FunctionDeclarationKind, Linkage),
Signature(Signature), CallingConv(CallingConv), IsProto(IsProto) {}
};
/// Models a global variable declaration, and its initializers.
......@@ -134,7 +147,10 @@ public:
InitializerKind getKind() const { return Kind; }
virtual ~Initializer() {}
virtual SizeT getNumBytes() const = 0;
virtual void dump(Ostream &Stream) const = 0;
virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0;
void dump(Ostream &Stream) const {
dump(nullptr, Stream);
}
virtual void dumpType(Ostream &Stream) const;
protected:
......@@ -170,7 +186,7 @@ public:
~DataInitializer() override {}
const DataVecType &getContents() const { return Contents; }
SizeT getNumBytes() const final { return Contents.size(); }
void dump(Ostream &Stream) const final;
void dump(GlobalContext *Ctx, Ostream &Stream) const final;
static bool classof(const Initializer *D) {
return D->getKind() == DataInitializerKind;
}
......@@ -190,7 +206,7 @@ public:
: Initializer(ZeroInitializerKind), Size(Size) {}
~ZeroInitializer() override {}
SizeT getNumBytes() const final { return Size; }
void dump(Ostream &Stream) const final;
void dump(GlobalContext *Ctx, Ostream &Stream) const final;
static bool classof(const Initializer *Z) {
return Z->getKind() == ZeroInitializerKind;
}
......@@ -218,7 +234,7 @@ public:
RelocOffsetType getOffset() const { return Offset; }
const GlobalDeclaration *getDeclaration() const { return Declaration; }
SizeT getNumBytes() const final { return RelocAddrSize; }
void dump(Ostream &Stream) const final;
void dump(GlobalContext *Ctx, Ostream &Stream) const final;
void dumpType(Ostream &Stream) const final;
static bool classof(const Initializer *R) {
return R->getKind() == RelocInitializerKind;
......@@ -242,10 +258,8 @@ public:
void setIsConstant(bool NewValue) { IsConstant = NewValue; }
uint32_t getAlignment() const { return Alignment; }
void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; }
bool getIsInternal() const { return IsInternal; }
void setIsInternal(bool NewValue) { IsInternal = NewValue; }
bool getIsExternal() const final { return !getIsInternal(); }
bool hasInitializer() const {
bool hasInitializer() const { return !Initializers.empty(); }
bool hasNonzeroInitializer() const {
return !(Initializers.size() == 1 &&
llvm::isa<ZeroInitializer>(Initializers[0]));
}
......@@ -272,18 +286,16 @@ public:
/// Prints out the definition of the global variable declaration
/// (including initialization).
void dump(Ostream &Stream) const final;
void dump(GlobalContext *Ctx, Ostream &Stream) const final;
static bool classof(const GlobalDeclaration *Addr) {
return Addr->getKind() == VariableDeclarationKind;
}
IceString mangleName(GlobalContext *Ctx) const final {
return (getIsExternal() && !hasInitializer())
? Name : Ctx->mangleName(Name);
bool getSuppressMangling() const final {
return isExternal() && !hasInitializer();
}
private:
// list of initializers for the declared variable.
InitializerListType Initializers;
......@@ -291,12 +303,11 @@ private:
uint32_t Alignment;
// True if a declared (global) constant.
bool IsConstant;
// True if the declaration is internal.
bool IsInternal;
VariableDeclaration()
: GlobalDeclaration(VariableDeclarationKind), Alignment(0),
IsConstant(false), IsInternal(true) {}
: GlobalDeclaration(VariableDeclarationKind,
llvm::GlobalValue::InternalLinkage),
Alignment(0), IsConstant(false) {}
};
template <class StreamType>
......
......@@ -460,8 +460,13 @@ void ConstantRelocatable::emit(GlobalContext *Ctx) const {
}
}
void ConstantRelocatable::dump(const Cfg *, Ostream &Str) const {
Str << "@" << Name;
void ConstantRelocatable::dump(const Cfg *Func, Ostream &Str) const {
Str << "@";
if (Func && !SuppressMangling) {
Str << Func->getContext()->mangleName(Name);
} else {
Str << Name;
}
if (Offset)
Str << "+" << Offset;
}
......
......@@ -4448,10 +4448,14 @@ void TargetGlobalInitX8632::lower(const VariableDeclaration &Var) {
const VariableDeclaration::InitializerListType &Initializers =
Var.getInitializers();
assert(Initializers.size());
bool HasInitializer = Var.hasInitializer();
// If external and not initialized, this must be a cross test.
// Don't generate a declaration for such cases.
bool IsExternal = Var.isExternal();
if (IsExternal && !Var.hasInitializer()) return;
bool HasNonzeroInitializer = Var.hasNonzeroInitializer();
bool IsConstant = Var.getIsConstant();
bool IsExternal = Var.getIsExternal();
uint32_t Align = Var.getAlignment();
SizeT Size = Var.getNumBytes();
IceString MangledName = Var.mangleName(Ctx);
......@@ -4463,7 +4467,7 @@ void TargetGlobalInitX8632::lower(const VariableDeclaration &Var) {
if (IsConstant)
Str << "\t.section\t.rodata" << SectionSuffix << ",\"a\",@progbits\n";
else if (HasInitializer)
else if (HasNonzeroInitializer)
Str << "\t.section\t.data" << SectionSuffix << ",\"aw\",@progbits\n";
else if (IsExternal)
Str << "\t.section\t.bss" << SectionSuffix << ",\"aw\",@nobits\n";
......@@ -4471,20 +4475,20 @@ void TargetGlobalInitX8632::lower(const VariableDeclaration &Var) {
if (IsExternal)
Str << "\t.globl\t" << MangledName << "\n";
else if (!IsConstant && !HasInitializer)
else if (!IsConstant && !HasNonzeroInitializer)
Str << "\t.local\t" << MangledName << "\n";
// Internal symbols only get .local when using .comm.
if ((IsConstant || HasInitializer || IsExternal) && Align > 1)
if ((IsConstant || HasNonzeroInitializer || IsExternal) && Align > 1)
Str << "\t.align\t" << Align << "\n";
// Alignment is part of .comm.
if (IsConstant || HasInitializer || IsExternal)
if (IsConstant || HasNonzeroInitializer || IsExternal)
Str << MangledName << ":\n";
else
Str << "\t.comm\t" << MangledName << "," << Size << "," << Align << "\n";
if (HasInitializer) {
if (HasNonzeroInitializer) {
for (VariableDeclaration::Initializer *Init : Initializers) {
switch (Init->getKind()) {
case VariableDeclaration::Initializer::DataInitializerKind: {
......@@ -4526,7 +4530,7 @@ void TargetGlobalInitX8632::lower(const VariableDeclaration &Var) {
Str << "\t.zero\t" << Size << "\n";
// Size is part of .comm.
if (IsConstant || HasInitializer || IsExternal)
if (IsConstant || HasNonzeroInitializer || IsExternal)
Str << "\t.size\t" << MangledName << ", " << Size << "\n";
// Size is part of .comm.
}
......
......@@ -88,7 +88,7 @@ void Translator::lowerGlobals(
Ostream &Stream = Ctx->getStrDump();
for (const Ice::VariableDeclaration *Global : VariableDeclarations) {
if (DumpGlobalVariables)
Global->dump(Stream);
Global->dump(getContext(), Stream);
if(!DisableTranslation)
GlobalLowering->lower(*Global);
}
......
......@@ -286,22 +286,30 @@ public:
// If reached, no such constant exists, create one.
// TODO(kschimpf) Don't get addresses of intrinsic function declarations.
std::string Name;
Ice::GlobalDeclaration *Decl = nullptr;
unsigned FcnIDSize = FunctionDeclarationList.size();
if (ID < FcnIDSize) {
Name = FunctionDeclarationList[ID]->getName();
Decl = FunctionDeclarationList[ID];
} else if ((ID - FcnIDSize) < VariableDeclarations.size()) {
Name = VariableDeclarations[ID - FcnIDSize]->getName();
Decl = VariableDeclarations[ID - FcnIDSize];
}
std::string Name;
bool SuppressMangling;
if (Decl) {
Name = Decl->getName();
SuppressMangling = Decl->getSuppressMangling();
} else {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Reference to global not defined: " << ID;
Error(StrBuf.str());
// TODO(kschimpf) Remove error recovery once implementation complete.
Name = "??";
SuppressMangling = false;
}
const Ice::RelocOffsetT Offset = 0;
C = getTranslator().getContext()->getConstantSym(
getIcePointerType(), Offset, Name);
getIcePointerType(), Offset, Name, SuppressMangling);
ValueIDConstants[ID] = C;
return C;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment