Introduce the notion of function addresses in Subzero.
Introduces the notion of a function address, to replace using LLVM
IR's Function class. Modifies Ice converter, and Subzero's bitcode
reader, to build function addresses.
BUG=None
R=jvoung@chromium.org, stichnot@chromium.org
Review URL: https://codereview.chromium.org/641193002
diff --git a/src/IceConverter.cpp b/src/IceConverter.cpp
index 380f1a0..a97cb68 100644
--- a/src/IceConverter.cpp
+++ b/src/IceConverter.cpp
@@ -34,6 +34,7 @@
#include "IceTypes.h"
#include "IceTypeConverter.h"
+// TODO(kschimpf): Remove two namespaces being visible at once.
using namespace llvm;
namespace {
@@ -52,11 +53,14 @@
LLVM2ICEConverter &operator=(const LLVM2ICEConverter &) = delete;
public:
- LLVM2ICEConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext)
- : Ctx(Ctx), TypeConverter(LLVMContext) {}
+ LLVM2ICEConverter(Ice::Converter &Converter)
+ : Converter(Converter), Ctx(Converter.getContext()),
+ TypeConverter(Converter.getModule()->getContext()) {}
+
+ Ice::Converter &getConverter() const { return Converter; }
protected:
- // Data
+ Ice::Converter &Converter;
Ice::GlobalContext *Ctx;
const Ice::TypeConverter TypeConverter;
};
@@ -72,8 +76,8 @@
operator=(const LLVM2ICEFunctionConverter &) = delete;
public:
- LLVM2ICEFunctionConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext)
- : LLVM2ICEConverter(Ctx, LLVMContext), Func(NULL) {}
+ LLVM2ICEFunctionConverter(Ice::Converter &Converter)
+ : LLVM2ICEConverter(Converter), Func(nullptr) {}
// Caller is expected to delete the returned Ice::Cfg object.
Ice::Cfg *convertFunction(const Function *F) {
@@ -126,12 +130,12 @@
else if (Type == Ice::IceType_f64)
return Ctx->getConstantDouble(CFP->getValueAPF().convertToDouble());
llvm_unreachable("Unexpected floating point type");
- return NULL;
+ return nullptr;
} else if (const auto CU = dyn_cast<UndefValue>(Const)) {
return Ctx->getConstantUndef(convertToIceType(CU->getType()));
} else {
llvm_unreachable("Unhandled constant type");
- return NULL;
+ return nullptr;
}
}
@@ -141,7 +145,7 @@
// and a version that just uses convertToIceType on V.
Ice::Variable *mapValueToIceVar(const Value *V, Ice::Type IceTy) {
if (IceTy == Ice::IceType_void)
- return NULL;
+ return nullptr;
if (VarMap.find(V) == VarMap.end()) {
VarMap[V] = Func->makeVariable(IceTy, V->getName());
}
@@ -169,10 +173,10 @@
// Given an LLVM instruction and an operand number, produce the
// Ice::Operand this refers to. If there's no such operand, return
- // NULL.
+ // nullptr.
Ice::Operand *convertOperand(const Instruction *Inst, unsigned OpNum) {
if (OpNum >= Inst->getNumOperands()) {
- return NULL;
+ return nullptr;
}
const Value *Op = Inst->getOperand(OpNum);
return convertValue(Op);
@@ -292,7 +296,7 @@
}
llvm_unreachable("convertInstruction");
- return NULL;
+ return nullptr;
}
Ice::Inst *convertLoadInstruction(const LoadInst *Inst) {
@@ -524,8 +528,8 @@
unsigned NumArgs = Inst->getNumArgOperands();
// Note: Subzero doesn't (yet) do anything special with the Tail
// flag in the bitcode, i.e. CallInst::isTailCall().
- Ice::InstCall *NewInst = NULL;
- const Ice::Intrinsics::FullIntrinsicInfo *Info = NULL;
+ Ice::InstCall *NewInst = nullptr;
+ const Ice::Intrinsics::FullIntrinsicInfo *Info = nullptr;
if (const auto Target = dyn_cast<Ice::ConstantRelocatable>(CallTarget)) {
// Check if this direct call is to an Intrinsic (starts with "llvm.")
@@ -545,7 +549,7 @@
}
// Not an intrinsic call.
- if (NewInst == NULL) {
+ if (NewInst == nullptr) {
NewInst = Ice::InstCall::create(Func, NumArgs, Dest, CallTarget,
Inst->isTailCall());
}
@@ -636,48 +640,37 @@
operator-(const LLVM2ICEGlobalsConverter &) = delete;
public:
- LLVM2ICEGlobalsConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext)
- : LLVM2ICEConverter(Ctx, LLVMContext) {}
+ LLVM2ICEGlobalsConverter(Ice::Converter &Converter)
+ : LLVM2ICEConverter(Converter) {}
- ~LLVM2ICEGlobalsConverter() { DeleteContainerSeconds(GlobalVarAddressMap); }
-
- /// Converts global variables, and their initializers into ICE global
- /// addresses, for module Mod. Puts corresponding converted global
- /// addresses into GlobalAddresses.
- void convertGlobalsToIce(Module *Mod,
- Ice::Translator::GlobalAddressList &GlobalAddresses);
+ /// Converts global variables, and their initializers into ICE
+ /// global variable declarations, for module Mod. Puts corresponding
+ /// converted declarations into VariableDeclarations.
+ void convertGlobalsToIce(
+ Module *Mod,
+ Ice::Translator::VariableDeclarationListType &VariableDeclarations);
private:
- typedef std::map<const GlobalVariable *, Ice::GlobalAddress *>
- GlobalVarAddressMapType;
- // Map from global variables to their corresponding global address.
- GlobalVarAddressMapType GlobalVarAddressMap;
-
- // Adds the Initializer to the list of initializers for Global address.
- void addGlobalInitializer(Ice::GlobalAddress &Global,
+ // Adds the Initializer to the list of initializers for the Global
+ // variable declaraation.
+ void addGlobalInitializer(Ice::VariableDeclaration &Global,
const Constant *Initializer) {
const bool HasOffset = false;
- const Ice::GlobalAddress::RelocOffsetType Offset = 0;
+ const Ice::VariableDeclaration::RelocOffsetType Offset = 0;
addGlobalInitializer(Global, Initializer, HasOffset, Offset);
}
- // Adds Initializer to the list of initializers for Global
- // address. HasOffset is true only if Initializer is a relocation
- // initializer and Offset should be added to the relocation.
- void addGlobalInitializer(Ice::GlobalAddress &Global,
+ // Adds Initializer to the list of initializers for Global variable
+ // declaration. HasOffset is true only if Initializer is a
+ // relocation initializer and Offset should be added to the
+ // relocation.
+ void addGlobalInitializer(Ice::VariableDeclaration &Global,
const Constant *Initializer, bool HasOffset,
- Ice::GlobalAddress::RelocOffsetType Offset);
-
- // Returns the global address associated with global variable GV.
- Ice::GlobalAddress *getGlobalVarAddress(const GlobalVariable *GV) {
- if (GlobalVarAddressMap.find(GV) == GlobalVarAddressMap.end())
- GlobalVarAddressMap[GV] = new Ice::GlobalAddress();
- return GlobalVarAddressMap[GV];
- }
+ Ice::VariableDeclaration::RelocOffsetType Offset);
// Converts the given constant C to the corresponding integer
// literal it contains.
- Ice::GlobalAddress::RelocOffsetType
+ Ice::VariableDeclaration::RelocOffsetType
getIntegerLiteralConstant(const Value *C) {
const auto CI = dyn_cast<ConstantInt>(C);
if (CI && CI->getType()->isIntegerTy(32))
@@ -692,30 +685,26 @@
};
void LLVM2ICEGlobalsConverter::convertGlobalsToIce(
- Module *Mod, Ice::Translator::GlobalAddressList &GlobalAddresses) {
+ Module *Mod,
+ Ice::Translator::VariableDeclarationListType &VariableDeclarations) {
for (Module::const_global_iterator I = Mod->global_begin(),
E = Mod->global_end();
I != E; ++I) {
if (!I->hasInitializer() && Ctx->getFlags().AllowUninitializedGlobals)
continue;
- const auto GV = dyn_cast<GlobalVariable>(I);
- assert(GV);
+ const GlobalVariable *GV = I;
Ice::IceString Name = GV->getName();
if (!GV->hasInternalLinkage()) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
- StrBuf << "Can't define external global address: " << Name;
+ StrBuf << "Can't define external global declaration: " << Name;
report_fatal_error(StrBuf.str());
}
- Ice::GlobalAddress *Addr = getGlobalVarAddress(GV);
- GlobalAddresses.push_back(Addr);
- Addr->setAlignment(GV->getAlignment());
- Addr->setIsConstant(GV->isConstant());
- // Note: We allow external for cross tests.
- Addr->setIsInternal(!GV->isExternallyInitialized());
- Addr->setName(Name);
+ Ice::GlobalDeclaration *Var = getConverter().getGlobalDeclaration(GV);
+ Ice::VariableDeclaration* VarDecl = cast<Ice::VariableDeclaration>(Var);
+ VariableDeclarations.push_back(VarDecl);
const Constant *Initializer = GV->getInitializer();
if (const auto CompoundInit = dyn_cast<ConstantStruct>(Initializer)) {
@@ -723,24 +712,25 @@
E = CompoundInit->op_end();
I != E; ++I) {
if (const auto Init = dyn_cast<Constant>(I)) {
- addGlobalInitializer(*Addr, Init);
+ addGlobalInitializer(*VarDecl, Init);
}
}
} else {
- addGlobalInitializer(*Addr, Initializer);
+ addGlobalInitializer(*VarDecl, Initializer);
}
}
}
void LLVM2ICEGlobalsConverter::addGlobalInitializer(
- Ice::GlobalAddress &Global, const Constant *Initializer, bool HasOffset,
- Ice::GlobalAddress::RelocOffsetType Offset) {
+ Ice::VariableDeclaration &Global, const Constant *Initializer,
+ bool HasOffset, Ice::VariableDeclaration::RelocOffsetType Offset) {
+ (void)HasOffset;
assert(HasOffset || Offset == 0);
if (const auto CDA = dyn_cast<ConstantDataArray>(Initializer)) {
assert(!HasOffset && isa<IntegerType>(CDA->getElementType()) &&
(cast<IntegerType>(CDA->getElementType())->getBitWidth() == 8));
- Global.addInitializer(new Ice::GlobalAddress::DataInitializer(
+ Global.addInitializer(new Ice::VariableDeclaration::DataInitializer(
CDA->getRawDataValues().data(), CDA->getNumElements()));
return;
}
@@ -750,7 +740,7 @@
assert(!HasOffset && isa<IntegerType>(AT->getElementType()) &&
(cast<IntegerType>(AT->getElementType())->getBitWidth() == 8));
Global.addInitializer(
- new Ice::GlobalAddress::ZeroInitializer(AT->getNumElements()));
+ new Ice::VariableDeclaration::ZeroInitializer(AT->getNumElements()));
} else {
llvm_unreachable("Unhandled constant aggregate zero type");
}
@@ -769,18 +759,11 @@
TypeConverter.getIcePointerType());
const auto GV = dyn_cast<GlobalValue>(Exp->getOperand(0));
assert(GV);
- if (const auto Fcn = dyn_cast<Function>(GV)) {
- Ice::GlobalAddress::RelocationAddress Addr(Fcn);
- Global.addInitializer(
- new Ice::GlobalAddress::RelocInitializer(Addr, Offset));
- return;
- } else if (const auto Var = dyn_cast<GlobalVariable>(GV)) {
- Ice::GlobalAddress::RelocationAddress Addr(getGlobalVarAddress(Var));
- Global.addInitializer(
- new Ice::GlobalAddress::RelocInitializer(Addr, Offset));
- return;
- }
- break;
+ const Ice::GlobalDeclaration *Addr =
+ getConverter().getGlobalDeclaration(GV);
+ Global.addInitializer(
+ new Ice::VariableDeclaration::RelocInitializer(Addr, Offset));
+ return;
}
default:
break;
@@ -797,19 +780,96 @@
namespace Ice {
+void Converter::nameUnnamedGlobalVariables(Module *Mod) {
+ const IceString &GlobalPrefix = Flags.DefaultGlobalPrefix;
+ if (GlobalPrefix.empty())
+ return;
+ uint32_t NameIndex = 0;
+ Ostream &errs = Ctx->getStrDump();
+ for (auto V = Mod->global_begin(), E = Mod->global_end(); V != E; ++V) {
+ if (!V->hasName()) {
+ V->setName(createUnnamedName(GlobalPrefix, NameIndex));
+ ++NameIndex;
+ } else {
+ checkIfUnnamedNameSafe(V->getName(), "global", GlobalPrefix, errs);
+ }
+ }
+}
+
+void Converter::nameUnnamedFunctions(Module *Mod) {
+ const IceString &FunctionPrefix = Flags.DefaultFunctionPrefix;
+ if (FunctionPrefix.empty())
+ return;
+ uint32_t NameIndex = 0;
+ Ostream &errs = Ctx->getStrDump();
+ for (Function &F : *Mod) {
+ if (!F.hasName()) {
+ F.setName(createUnnamedName(FunctionPrefix, NameIndex));
+ ++NameIndex;
+ } else {
+ checkIfUnnamedNameSafe(F.getName(), "function", FunctionPrefix, errs);
+ }
+ }
+}
+
void Converter::convertToIce() {
TimerMarker T(TimerStack::TT_convertToIce, Ctx);
- nameUnnamedGlobalAddresses(Mod);
+ nameUnnamedGlobalVariables(Mod);
nameUnnamedFunctions(Mod);
+ installGlobalDeclarations(Mod);
convertGlobals(Mod);
convertFunctions();
}
+GlobalDeclaration *Converter::getGlobalDeclaration(const GlobalValue *V) {
+ GlobalDeclarationMapType::const_iterator Pos = GlobalDeclarationMap.find(V);
+ if (Pos == GlobalDeclarationMap.end()) {
+ std::string Buffer;
+ raw_string_ostream StrBuf(Buffer);
+ StrBuf << "Can't find global declaration for: " << V->getName();
+ report_fatal_error(StrBuf.str());
+ }
+ return Pos->second;
+}
+
+void Converter::installGlobalDeclarations(Module *Mod) {
+ const TypeConverter Converter(Mod->getContext());
+ // Install function declarations.
+ for (const Function &Func : *Mod) {
+ FuncSigType Signature;
+ FunctionType *FuncType = Func.getFunctionType();
+ Signature.setReturnType(
+ Converter.convertToIceType(FuncType->getReturnType()));
+ for (size_t I = 0; I < FuncType->getNumParams(); ++I) {
+ Signature.appendArgType(
+ Converter.convertToIceType(FuncType->getParamType(I)));
+ }
+ FunctionDeclaration *IceFunc = FunctionDeclaration::create(
+ Ctx, Signature, Func.getCallingConv(), Func.getLinkage(), Func.empty());
+ IceFunc->setName(Func.getName());
+ GlobalDeclarationMap[&Func] = IceFunc;
+ }
+ // Install global variable declarations.
+ for (Module::const_global_iterator I = Mod->global_begin(),
+ E = Mod->global_end();
+ I != E; ++I) {
+ const GlobalVariable *GV = I;
+ VariableDeclaration *Var = VariableDeclaration::create(Ctx);
+ 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());
+ GlobalDeclarationMap[GV] = Var;
+ }
+}
+
void Converter::convertGlobals(Module *Mod) {
- LLVM2ICEGlobalsConverter GlobalsConverter(Ctx, Mod->getContext());
- Translator::GlobalAddressList GlobalAddresses;
- GlobalsConverter.convertGlobalsToIce(Mod, GlobalAddresses);
- lowerGlobals(GlobalAddresses);
+ LLVM2ICEGlobalsConverter GlobalsConverter(*this);
+ Translator::VariableDeclarationListType VariableDeclarations;
+ GlobalsConverter.convertGlobalsToIce(Mod, VariableDeclarations);
+ lowerGlobals(VariableDeclarations);
}
void Converter::convertFunctions() {
@@ -823,7 +883,7 @@
TimerID = Ctx->getTimerID(StackID, I.getName());
Ctx->pushTimer(TimerID, StackID);
}
- LLVM2ICEFunctionConverter FunctionConverter(Ctx, Mod->getContext());
+ LLVM2ICEFunctionConverter FunctionConverter(*this);
Cfg *Fcn = FunctionConverter.convertFunction(&I);
translateFcn(Fcn);
diff --git a/src/IceConverter.h b/src/IceConverter.h
index 763dcae..d26c34c 100644
--- a/src/IceConverter.h
+++ b/src/IceConverter.h
@@ -14,9 +14,11 @@
#ifndef SUBZERO_SRC_ICECONVERTER_H
#define SUBZERO_SRC_ICECONVERTER_H
+#include "IceDefs.h"
#include "IceTranslator.h"
namespace llvm {
+class GlobalValue;
class Module;
}
@@ -27,18 +29,42 @@
Converter(llvm::Module *Mod, GlobalContext *Ctx, const Ice::ClFlags &Flags)
: Translator(Ctx, Flags), Mod(Mod) {}
+ ~Converter() {}
+
/// Converts the LLVM Module to ICE. Sets exit status to false if successful,
/// true otherwise.
void convertToIce();
+ llvm::Module *getModule() const { return Mod; }
+
+ // Returns the global declaration associated with the corresponding
+ // global value V. If no such global address, generates fatal error.
+ GlobalDeclaration *getGlobalDeclaration(const llvm::GlobalValue *V);
+
private:
llvm::Module *Mod;
+ typedef std::map<const llvm::GlobalValue *, GlobalDeclaration *>
+ GlobalDeclarationMapType;
+ GlobalDeclarationMapType GlobalDeclarationMap;
+
+ // Walks module and generates names for unnamed globals using prefix
+ // getFlags().DefaultGlobalPrefix, if the prefix is non-empty.
+ void nameUnnamedGlobalVariables(llvm::Module *Mod);
+
+ // Walks module and generates names for unnamed functions using
+ // prefix getFlags().DefaultFunctionPrefix, if the prefix is
+ // non-empty.
+ void nameUnnamedFunctions(llvm::Module *Mod);
+
// Converts functions to ICE, and then machine code.
void convertFunctions();
// Converts globals to ICE, and then machine code.
void convertGlobals(llvm::Module *Mod);
+ // Installs global declarations into GlobalDeclarationMap.
+ void installGlobalDeclarations(llvm::Module *Mod);
+
Converter(const Converter &) = delete;
Converter &operator=(const Converter &) = delete;
};
diff --git a/src/IceDefs.h b/src/IceDefs.h
index 29ed5d8..62665e7 100644
--- a/src/IceDefs.h
+++ b/src/IceDefs.h
@@ -26,7 +26,6 @@
#include <set>
#include <string>
#include <vector>
-
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallBitVector.h"
@@ -39,7 +38,9 @@
class Cfg;
class CfgNode;
class Constant;
+class FunctionDeclaration;
class GlobalContext;
+class GlobalDeclaration;
class Inst;
class InstPhi;
class InstTarget;
@@ -48,6 +49,7 @@
class Operand;
class TargetLowering;
class Variable;
+class VariableDeclaration;
class VariablesMetadata;
// TODO: Switch over to LLVM's ADT container classes.
diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp
index c8b429f..b724433 100644
--- a/src/IceGlobalContext.cpp
+++ b/src/IceGlobalContext.cpp
@@ -19,6 +19,7 @@
#include "IceClFlags.h"
#include "IceDefs.h"
#include "IceGlobalContext.h"
+#include "IceGlobalInits.h"
#include "IceOperand.h"
#include "IceTargetLowering.h"
#include "IceTimerTree.h"
@@ -289,7 +290,9 @@
return getTestPrefix() + Name;
}
-GlobalContext::~GlobalContext() {}
+GlobalContext::~GlobalContext() {
+ llvm::DeleteContainerPointers(GlobalDeclarations);
+}
Constant *GlobalContext::getConstantInt64(Type Ty, uint64_t ConstantInt64) {
assert(Ty == IceType_i64);
@@ -385,6 +388,23 @@
llvm_unreachable("Unknown type");
}
+FunctionDeclaration *
+GlobalContext::newFunctionDeclaration(const FuncSigType *Signature,
+ unsigned CallingConv, unsigned Linkage,
+ bool IsProto) {
+ FunctionDeclaration *Func = new FunctionDeclaration(
+ *Signature, static_cast<llvm::CallingConv::ID>(CallingConv),
+ static_cast<llvm::GlobalValue::LinkageTypes>(Linkage), IsProto);
+ GlobalDeclarations.push_back(Func);
+ return Func;
+}
+
+VariableDeclaration *GlobalContext::newVariableDeclaration() {
+ VariableDeclaration *Var = new VariableDeclaration();
+ GlobalDeclarations.push_back(Var);
+ return Var;
+}
+
TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
const IceString &Name) {
assert(StackID < Timers.size());
diff --git a/src/IceGlobalContext.h b/src/IceGlobalContext.h
index cc5da58..026cb7f 100644
--- a/src/IceGlobalContext.h
+++ b/src/IceGlobalContext.h
@@ -21,6 +21,7 @@
#include "llvm/Support/raw_ostream.h"
#include "IceDefs.h"
+#include "IceClFlags.h"
#include "IceIntrinsics.h"
#include "IceRNG.h"
#include "IceTimerTree.h"
@@ -29,6 +30,7 @@
namespace Ice {
class ClFlags;
+class FuncSigType;
// This class collects rudimentary statistics during translation.
class CodeStats {
@@ -117,6 +119,17 @@
// getConstantPool() returns a copy of the constant pool for
// constants of a given type.
ConstantList getConstantPool(Type Ty) const;
+ // Returns a new function declaration, allocated in an internal
+ // memory pool. Ownership of the function is maintained by this
+ // class instance.
+ FunctionDeclaration *newFunctionDeclaration(const FuncSigType *Signature,
+ unsigned CallingConv,
+ unsigned Linkage, bool IsProto);
+
+ // Returns a new global variable declaration, allocated in an
+ // internal memory pool. Ownership of the function is maintained by
+ // this class instance.
+ VariableDeclaration *newVariableDeclaration();
const ClFlags &getFlags() const { return Flags; }
@@ -186,6 +199,7 @@
CodeStats StatsFunction;
CodeStats StatsCumulative;
std::vector<TimerStack> Timers;
+ std::vector<GlobalDeclaration *> GlobalDeclarations;
GlobalContext(const GlobalContext &) = delete;
GlobalContext &operator=(const GlobalContext &) = delete;
diff --git a/src/IceGlobalInits.cpp b/src/IceGlobalInits.cpp
index 4d9dadb..d9cea26 100644
--- a/src/IceGlobalInits.cpp
+++ b/src/IceGlobalInits.cpp
@@ -1,4 +1,4 @@
-//===- subzero/src/IceGlobalInits.cpp - Global initializers ---------------===//
+//===- subzero/src/IceGlobalInits.cpp - Global declarations ---------------===//
//
// The Subzero Code Generator
//
@@ -7,8 +7,9 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the notion of global addresses and
-// initializers in Subzero.
+// This file implements the notion of function declarations, global
+// variable declarations, and the corresponding variable initializers
+// in Subzero.
//
//===----------------------------------------------------------------------===//
@@ -17,18 +18,82 @@
#include "llvm/IR/Value.h"
#include "IceDefs.h"
+#include "IceGlobalContext.h"
#include "IceGlobalInits.h"
#include "IceTypes.h"
namespace {
char hexdigit(unsigned X) { return X < 10 ? '0' + X : 'A' + X - 10; }
+
+void dumpLinkage(Ice::Ostream &Stream,
+ llvm::GlobalValue::LinkageTypes Linkage) {
+ switch (Linkage) {
+ case llvm::GlobalValue::ExternalLinkage:
+ Stream << "external";
+ return;
+ case llvm::GlobalValue::InternalLinkage:
+ Stream << "internal";
+ return;
+ default:
+ break;
+ }
+ std::string Buffer;
+ llvm::raw_string_ostream StrBuf(Buffer);
+ StrBuf << "Unknown linkage value: " << Linkage;
+ llvm::report_fatal_error(StrBuf.str());
}
+void dumpCallingConv(Ice::Ostream &, llvm::CallingConv::ID CallingConv) {
+ if (CallingConv == llvm::CallingConv::C)
+ return;
+ std::string Buffer;
+ llvm::raw_string_ostream StrBuf(Buffer);
+ StrBuf << "Unknown calling convention: " << CallingConv;
+ llvm::report_fatal_error(StrBuf.str());
+}
+
+} // end of anonymous namespace
+
namespace Ice {
-GlobalAddress::~GlobalAddress() { llvm::DeleteContainerPointers(Initializers); }
+FunctionDeclaration *
+FunctionDeclaration::create(GlobalContext *Ctx, const FuncSigType &Signature,
+ llvm::CallingConv::ID CallingConv,
+ llvm::GlobalValue::LinkageTypes Linkage,
+ bool IsProto) {
+ return Ctx->newFunctionDeclaration(&Signature, CallingConv, Linkage, IsProto);
+}
-void GlobalAddress::dumpType(Ostream &Stream) const {
+void FunctionDeclaration::dumpType(Ostream &Stream) const {
+ Stream << Signature;
+}
+
+void FunctionDeclaration::dump(Ostream &Stream) const {
+ if (IsProto)
+ Stream << "declare ";
+ ::dumpLinkage(Stream, Linkage);
+ ::dumpCallingConv(Stream, CallingConv);
+ Stream << Signature.getReturnType() << " @" << Name << "(";
+ bool IsFirst = true;
+ for (Type ArgTy : Signature.getArgList()) {
+ if (IsFirst)
+ IsFirst = false;
+ else
+ Stream << ", ";
+ Stream << ArgTy;
+ }
+ Stream << ")";
+}
+
+VariableDeclaration *VariableDeclaration::create(GlobalContext *Ctx) {
+ return Ctx->newVariableDeclaration();
+}
+
+VariableDeclaration::~VariableDeclaration() {
+ llvm::DeleteContainerPointers(Initializers);
+}
+
+void VariableDeclaration::dumpType(Ostream &Stream) const {
if (Initializers.size() == 1) {
Initializers.front()->dumpType(Stream);
} else {
@@ -46,8 +111,8 @@
}
}
-void GlobalAddress::dump(Ostream &Stream) const {
- Stream << "@" << getName() << " = internal "
+void VariableDeclaration::dump(Ostream &Stream) const {
+ Stream << "@" << Name << " = internal "
<< (IsConstant ? "constant" : "global") << " ";
// Add initializer.
@@ -74,11 +139,11 @@
Stream << "\n";
}
-void GlobalAddress::Initializer::dumpType(Ostream &Stream) const {
+void VariableDeclaration::Initializer::dumpType(Ostream &Stream) const {
Stream << "[" << getNumBytes() << " x " << Ice::IceType_i8 << "]";
}
-void GlobalAddress::DataInitializer::dump(Ostream &Stream) const {
+void VariableDeclaration::DataInitializer::dump(Ostream &Stream) const {
dumpType(Stream);
Stream << " c\"";
// Code taken from PrintEscapedString() in AsmWriter.cpp. Keep
@@ -93,41 +158,24 @@
Stream << "\"";
}
-void GlobalAddress::ZeroInitializer::dump(Ostream &Stream) const {
+void VariableDeclaration::ZeroInitializer::dump(Ostream &Stream) const {
dumpType(Stream);
Stream << " zeroinitializer";
}
-IceString GlobalAddress::RelocInitializer::getName() const {
- switch (Address.getKind()) {
- case FunctionRelocation:
- return Address.getFunction()->getName();
- case GlobalAddressRelocation:
- return Address.getGlobalAddr()->getName();
- default:
- llvm::report_fatal_error("Malformed relocation address!");
- }
-}
-
-void GlobalAddress::RelocInitializer::dumpType(Ostream &Stream) const {
+void VariableDeclaration::RelocInitializer::dumpType(Ostream &Stream) const {
Stream << Ice::IceType_i32;
}
-void GlobalAddress::RelocInitializer::dump(Ostream &Stream) const {
+void VariableDeclaration::RelocInitializer::dump(Ostream &Stream) const {
if (Offset != 0) {
dumpType(Stream);
Stream << " add (";
}
dumpType(Stream);
Stream << " ptrtoint (";
- if (Address.getKind() == FunctionRelocation) {
- Stream << *Address.getFunction()->getType() << " @"
- << Address.getFunction()->getName();
- } else {
- Address.getGlobalAddr()->dumpType(Stream);
- Stream << "* @" << Address.getGlobalAddr()->getName();
- }
- Stream << " to ";
+ Declaration->dumpType(Stream);
+ Stream << "* @" << Declaration->getName() << " to ";
dumpType(Stream);
Stream << ")";
if (Offset != 0) {
@@ -136,4 +184,5 @@
Stream << " " << Offset << ")";
}
}
-}
+
+} // end of namespace Ice
diff --git a/src/IceGlobalInits.h b/src/IceGlobalInits.h
index 09e5574..0f6565c 100644
--- a/src/IceGlobalInits.h
+++ b/src/IceGlobalInits.h
@@ -1,4 +1,4 @@
-//===- subzero/src/IceGlobalInits.h - Global initializers -------*- C++ -*-===//
+//===- subzero/src/IceGlobalInits.h - Global declarations -------*- C++ -*-===//
//
// The Subzero Code Generator
//
@@ -7,30 +7,118 @@
//
//===----------------------------------------------------------------------===//
//
-// This file declares the representation of global addresses and
-// initializers in Subzero. Global initializers are represented as a
-// sequence of simple initializers.
+// This file declares the representation of function declarations,
+// global variable declarations, and the corresponding variable
+// initializers in Subzero. Global variable initializers are
+// represented as a sequence of simple initializers.
//
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEGLOBALINITS_H
#define SUBZERO_SRC_ICEGLOBALINITS_H
-#include "IceDefs.h"
+#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes
-namespace llvm {
-// TODO(kschimpf): Remove this dependency on LLVM IR.
-class Value;
-}
+#include "IceDefs.h"
+#include "IceTypes.h"
+
+// TODO(kschimpf): Remove ourselves from using LLVM representation for calling
+// conventions and linkage types.
namespace Ice {
-/// Models a global address, and its initializers.
-class GlobalAddress {
- GlobalAddress(const GlobalAddress &) = delete;
- GlobalAddress &operator=(const GlobalAddress &) = delete;
+/// Base class for global variable and function declarations.
+class GlobalDeclaration {
+ GlobalDeclaration(const GlobalDeclaration &) = delete;
+ GlobalDeclaration &operator=(const GlobalDeclaration &) = delete;
public:
+ /// Discriminator for LLVM-style RTTI.
+ enum GlobalDeclarationKind {
+ FunctionDeclarationKind,
+ VariableDeclarationKind
+ };
+ GlobalDeclarationKind getKind() const { return Kind; }
+ const IceString &getName() const { return Name; }
+ void setName(const IceString &NewName) { Name = NewName; }
+ bool hasName() const { return !Name.empty(); }
+ 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;
+
+ // 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;
+
+protected:
+ GlobalDeclaration(GlobalDeclarationKind Kind) : Kind(Kind) {}
+
+ const GlobalDeclarationKind Kind;
+ IceString Name;
+};
+
+// Models a function declaration. This includes the type signature of
+// the function, its calling conventions, and its linkage.
+class FunctionDeclaration : public GlobalDeclaration {
+ FunctionDeclaration(const FunctionDeclaration &) = delete;
+ FunctionDeclaration &operator=(const FunctionDeclaration &) = delete;
+ friend class GlobalContext;
+
+public:
+ static FunctionDeclaration *create(GlobalContext *Ctx,
+ const FuncSigType &Signature,
+ llvm::CallingConv::ID CallingConv,
+ llvm::GlobalValue::LinkageTypes Linkage,
+ bool IsProto);
+ ~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);
+ }
+
+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) {}
+};
+
+/// Models a global variable declaration, and its initializers.
+class VariableDeclaration : public GlobalDeclaration {
+ VariableDeclaration(const VariableDeclaration &) = delete;
+ VariableDeclaration &operator=(const VariableDeclaration &) = delete;
+ friend class GlobalContext;
+ // TODO(kschimpf) Factor out allocation of initializers into the
+ // global context, so that memory allocation/collection can be
+ // optimized.
+public:
/// Base class for a global variable initializer.
class Initializer {
Initializer(const Initializer &) = delete;
@@ -81,8 +169,8 @@
}
~DataInitializer() override {}
const DataVecType &getContents() const { return Contents; }
- SizeT getNumBytes() const override { return Contents.size(); }
- void dump(Ostream &Stream) const override;
+ SizeT getNumBytes() const final { return Contents.size(); }
+ void dump(Ostream &Stream) const final;
static bool classof(const Initializer *D) {
return D->getKind() == DataInitializerKind;
}
@@ -101,8 +189,8 @@
explicit ZeroInitializer(SizeT Size)
: Initializer(ZeroInitializerKind), Size(Size) {}
~ZeroInitializer() override {}
- SizeT getNumBytes() const override { return Size; }
- void dump(Ostream &Stream) const override;
+ SizeT getNumBytes() const final { return Size; }
+ void dump(Ostream &Stream) const final;
static bool classof(const Initializer *Z) {
return Z->getKind() == ZeroInitializerKind;
}
@@ -112,76 +200,33 @@
SizeT Size;
};
- /// Defines the kind of relocation addresses allowed.
- enum RelocationKind { FunctionRelocation, GlobalAddressRelocation };
-
- /// Defines a relocation address (i.e. reference to a function
- /// or global variable address).
- class RelocationAddress {
- RelocationAddress &operator=(const RelocationAddress &) = delete;
-
- public:
- explicit RelocationAddress(const RelocationAddress &Addr)
- : Kind(Addr.Kind) {
- switch (Kind) {
- case FunctionRelocation:
- Address.Function = Addr.Address.Function;
- break;
- case GlobalAddressRelocation:
- Address.GlobalAddr = Addr.Address.GlobalAddr;
- }
- }
- explicit RelocationAddress(llvm::Value *Function)
- : Kind(FunctionRelocation) {
- Address.Function = Function;
- }
- explicit RelocationAddress(GlobalAddress *GlobalAddr)
- : Kind(GlobalAddressRelocation) {
- Address.GlobalAddr = GlobalAddr;
- }
- RelocationKind getKind() const { return Kind; }
- llvm::Value *getFunction() const {
- assert(Kind == FunctionRelocation);
- return Address.Function;
- }
- GlobalAddress *getGlobalAddr() const {
- assert(Kind == GlobalAddressRelocation);
- return Address.GlobalAddr;
- }
- private:
- const RelocationKind Kind;
- union {
- // TODO(kschimpf) Integrate Functions into ICE model.
- llvm::Value *Function;
- GlobalAddress *GlobalAddr;
- } Address;
- };
-
// Relocation address offsets must be 32 bit values.
typedef int32_t RelocOffsetType;
static const SizeT RelocAddrSize = 4;
- /// Defines the relocation value of another address.
+ /// Defines the relocation value of another global declaration.
class RelocInitializer : public Initializer {
RelocInitializer(const RelocInitializer &) = delete;
RelocInitializer &operator=(const RelocInitializer &) = delete;
public:
- RelocInitializer(const RelocationAddress &Address, RelocOffsetType Offset)
- : Initializer(RelocInitializerKind), Address(Address), Offset(Offset) {}
+ RelocInitializer(const GlobalDeclaration *Declaration,
+ RelocOffsetType Offset)
+ : Initializer(RelocInitializerKind), Declaration(Declaration),
+ Offset(Offset) {}
~RelocInitializer() override {}
RelocOffsetType getOffset() const { return Offset; }
- IceString getName() const;
- SizeT getNumBytes() const override { return RelocAddrSize; }
- void dump(Ostream &Stream) const override;
- virtual void dumpType(Ostream &Stream) const;
+ const GlobalDeclaration *getDeclaration() const { return Declaration; }
+ SizeT getNumBytes() const final { return RelocAddrSize; }
+ void dump(Ostream &Stream) const final;
+ void dumpType(Ostream &Stream) const final;
static bool classof(const Initializer *R) {
return R->getKind() == RelocInitializerKind;
}
private:
- // The global address used in the relocation.
- const RelocationAddress Address;
+ // The global declaration used in the relocation.
+ const GlobalDeclaration *Declaration;
// The offset to add to the relocation.
const RelocOffsetType Offset;
};
@@ -189,19 +234,21 @@
/// Models the list of initializers.
typedef std::vector<Initializer *> InitializerListType;
- GlobalAddress() : Alignment(0), IsConstant(false), IsInternal(true) {}
- ~GlobalAddress();
+ static VariableDeclaration *create(GlobalContext *Ctx);
+ ~VariableDeclaration() final;
const InitializerListType &getInitializers() const { return Initializers; }
- bool hasName() const { return !Name.empty(); }
- const IceString &getName() const { return Name; }
- void setName(const IceString &NewName) { Name = NewName; }
bool getIsConstant() const { return IsConstant; }
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 {
+ return !(Initializers.size() == 1 &&
+ llvm::isa<ZeroInitializer>(Initializers[0]));
+ }
/// Returns the number of bytes for the initializer of the global
/// address.
@@ -219,36 +266,49 @@
Initializers.push_back(Initializer);
}
- /// Prints out type for initializer associated with the global address
+ /// Prints out type for initializer associated with the declaration
/// to Stream.
- void dumpType(Ostream &Stream) const;
+ void dumpType(Ostream &Stream) const final;
- /// Prints out the definition of the global address (including
- /// initialization).
- void dump(Ostream &Stream) const;
+ /// Prints out the definition of the global variable declaration
+ /// (including initialization).
+ void dump(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);
+ }
+
private:
- // list of initializers associated with the global address.
+ // list of initializers for the declared variable.
InitializerListType Initializers;
- // The name for the global.
- IceString Name;
- // The alignment of the initializer.
+ // The alignment of the declared variable.
uint32_t Alignment;
- // True if a constant initializer.
+ // True if a declared (global) constant.
bool IsConstant;
- // True if the address is internal.
+ // True if the declaration is internal.
bool IsInternal;
+
+ VariableDeclaration()
+ : GlobalDeclaration(VariableDeclarationKind), Alignment(0),
+ IsConstant(false), IsInternal(true) {}
};
template <class StreamType>
inline StreamType &operator<<(StreamType &Stream,
- const GlobalAddress::Initializer &Init) {
+ const VariableDeclaration::Initializer &Init) {
Init.dump(Stream);
return Stream;
}
template <class StreamType>
-inline StreamType &operator<<(StreamType &Stream, const GlobalAddress &Addr) {
+inline StreamType &operator<<(StreamType &Stream,
+ const GlobalDeclaration &Addr) {
Addr.dump(Stream);
return Stream;
}
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index f116cf3..bbda1f8 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -27,7 +27,6 @@
typedef uint8_t AsmCodeByte;
class Assembler;
-class GlobalAddress;
// LoweringContext makes it easy to iterate through non-deleted
// instructions in a node, and insert new (lowered) instructions at
@@ -249,7 +248,7 @@
GlobalContext *Ctx);
virtual ~TargetGlobalInitLowering();
- virtual void lower(const GlobalAddress &Addr, bool DisableTranslation) = 0;
+ virtual void lower(const VariableDeclaration &Var) = 0;
protected:
TargetGlobalInitLowering(GlobalContext *Ctx) : Ctx(Ctx) {}
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index eb41b84..4e04186 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -4427,32 +4427,19 @@
TargetGlobalInitX8632::TargetGlobalInitX8632(GlobalContext *Ctx)
: TargetGlobalInitLowering(Ctx) {}
-void TargetGlobalInitX8632::lower(const GlobalAddress &Global,
- bool DisableTranslation) {
- if (Ctx->isVerbose()) {
- Global.dump(Ctx->getStrDump());
- }
-
- if (DisableTranslation)
- return;
+void TargetGlobalInitX8632::lower(const VariableDeclaration &Var) {
Ostream &Str = Ctx->getStrEmit();
- // TODO(kschimpf): Don't mangle name if external and uninitialized. This
- // will allow us to cross test relocations for references to external
- // global variables.
-
- const GlobalAddress::InitializerListType &Initializers =
- Global.getInitializers();
+ const VariableDeclaration::InitializerListType &Initializers =
+ Var.getInitializers();
assert(Initializers.size());
- bool HasInitializer =
- !(Initializers.size() == 1 &&
- llvm::isa<GlobalAddress::ZeroInitializer>(Initializers[0]));
- bool IsConstant = Global.getIsConstant();
- bool IsExternal = !Global.getIsInternal();
- uint32_t Align = Global.getAlignment();
- SizeT Size = Global.getNumBytes();
- IceString MangledName = Ctx->mangleName(Global.getName());
+ bool HasInitializer = Var.hasInitializer();
+ bool IsConstant = Var.getIsConstant();
+ bool IsExternal = Var.getIsExternal();
+ uint32_t Align = Var.getAlignment();
+ SizeT Size = Var.getNumBytes();
+ IceString MangledName = Var.mangleName(Ctx);
IceString SectionSuffix = "";
if (Ctx->getFlags().DataSections)
SectionSuffix = "." + MangledName;
@@ -4483,30 +4470,29 @@
Str << "\t.comm\t" << MangledName << "," << Size << "," << Align << "\n";
if (HasInitializer) {
- for (GlobalAddress::Initializer *Init : Initializers) {
+ for (VariableDeclaration::Initializer *Init : Initializers) {
switch (Init->getKind()) {
- case GlobalAddress::Initializer::DataInitializerKind: {
- const auto Data =
- llvm::cast<GlobalAddress::DataInitializer>(Init)->getContents();
+ case VariableDeclaration::Initializer::DataInitializerKind: {
+ const auto Data = llvm::cast<VariableDeclaration::DataInitializer>(Init)
+ ->getContents();
for (SizeT i = 0; i < Init->getNumBytes(); ++i) {
Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n";
}
break;
}
- case GlobalAddress::Initializer::ZeroInitializerKind:
+ case VariableDeclaration::Initializer::ZeroInitializerKind:
Str << "\t.zero\t" << Init->getNumBytes() << "\n";
break;
- case GlobalAddress::Initializer::RelocInitializerKind: {
- const auto Reloc = llvm::cast<GlobalAddress::RelocInitializer>(Init);
+ case VariableDeclaration::Initializer::RelocInitializerKind: {
+ const auto Reloc =
+ llvm::cast<VariableDeclaration::RelocInitializer>(Init);
Str << "\t.long\t";
- // TODO(kschimpf): Once the representation of a relocation has
- // been modified to reference the corresponding global
- // address, modify to not mangle the name if the global is
- // external and uninitialized. This will allow us to better
- // test cross test relocations.
- Str << Ctx->mangleName(Reloc->getName());
- if (GlobalAddress::RelocOffsetType Offset = Reloc->getOffset()) {
- Str << " + " << Offset;
+ Str << Reloc->getDeclaration()->mangleName(Ctx);
+ if (VariableDeclaration::RelocOffsetType Offset = Reloc->getOffset()) {
+ if (Offset >= 0 || (Offset == INT32_MIN))
+ Str << " + " << Offset;
+ else
+ Str << " - " << -Offset;
}
Str << "\n";
break;
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index 82a8208..bb57740 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -482,8 +482,7 @@
return new TargetGlobalInitX8632(Ctx);
}
- virtual void lower(const GlobalAddress &Addr,
- bool DisableTranslation) override;
+ virtual void lower(const VariableDeclaration &Var) final;
protected:
TargetGlobalInitX8632(GlobalContext *Ctx);
diff --git a/src/IceTranslator.cpp b/src/IceTranslator.cpp
index e86d60a..6d4af11 100644
--- a/src/IceTranslator.cpp
+++ b/src/IceTranslator.cpp
@@ -22,6 +22,7 @@
#include "IceCfg.h"
#include "IceClFlags.h"
#include "IceDefs.h"
+#include "IceGlobalInits.h"
#include "IceTargetLowering.h"
#include "IceTranslator.h"
@@ -54,38 +55,6 @@
return false;
}
-void Translator::nameUnnamedGlobalAddresses(llvm::Module *Mod) {
- const IceString &GlobalPrefix = Flags.DefaultGlobalPrefix;
- if (GlobalPrefix.empty())
- return;
- uint32_t NameIndex = 0;
- Ostream &errs = Ctx->getStrDump();
- for (auto V = Mod->global_begin(), E = Mod->global_end(); V != E; ++V) {
- if (!V->hasName()) {
- V->setName(createUnnamedName(GlobalPrefix, NameIndex));
- ++NameIndex;
- } else {
- checkIfUnnamedNameSafe(V->getName(), "global", GlobalPrefix, errs);
- }
- }
-}
-
-void Translator::nameUnnamedFunctions(llvm::Module *Mod) {
- const IceString &FunctionPrefix = Flags.DefaultFunctionPrefix;
- if (FunctionPrefix.empty())
- return;
- uint32_t NameIndex = 0;
- Ostream &errs = Ctx->getStrDump();
- for (llvm::Function &F : *Mod) {
- if (!F.hasName()) {
- F.setName(createUnnamedName(FunctionPrefix, NameIndex));
- ++NameIndex;
- } else {
- checkIfUnnamedNameSafe(F.getName(), "function", FunctionPrefix, errs);
- }
- }
-}
-
void Translator::translateFcn(Cfg *Fcn) {
Ctx->resetStats();
Func.reset(Fcn);
@@ -110,12 +79,18 @@
Func->getTarget()->emitConstants();
}
-void Translator::lowerGlobals(const GlobalAddressList &GlobalAddresses) {
- llvm::OwningPtr<Ice::TargetGlobalInitLowering> GlobalLowering(
- Ice::TargetGlobalInitLowering::createLowering(Ctx->getTargetArch(), Ctx));
+void Translator::lowerGlobals(
+ const VariableDeclarationListType &VariableDeclarations) {
+ llvm::OwningPtr<TargetGlobalInitLowering> GlobalLowering(
+ TargetGlobalInitLowering::createLowering(Ctx->getTargetArch(), Ctx));
bool DisableTranslation = Ctx->getFlags().DisableTranslation;
- for (const Ice::GlobalAddress *Addr : GlobalAddresses) {
- GlobalLowering->lower(*Addr, DisableTranslation);
+ bool DumpGlobalVariables = Ctx->isVerbose();
+ Ostream &Stream = Ctx->getStrDump();
+ for (const Ice::VariableDeclaration *Global : VariableDeclarations) {
+ if (DumpGlobalVariables)
+ Global->dump(Stream);
+ if(!DisableTranslation)
+ GlobalLowering->lower(*Global);
}
GlobalLowering.reset();
}
diff --git a/src/IceTranslator.h b/src/IceTranslator.h
index 8aeda94..8134697 100644
--- a/src/IceTranslator.h
+++ b/src/IceTranslator.h
@@ -25,16 +25,15 @@
class ClFlags;
class Cfg;
-class GlobalAddress;
+class VariableDeclaration;
class GlobalContext;
-// Base class for translating ICE to machine code.
-// Derived classes convert other intermediate representations down to ICE,
-// and then call the appropriate (inherited) methods to convert ICE into
-// machine instructions.
+// Base class for translating ICE to machine code. Derived classes convert
+// other intermediate representations down to ICE, and then call the appropriate
+// (inherited) methods to convert ICE into machine instructions.
class Translator {
public:
- typedef std::vector<Ice::GlobalAddress *> GlobalAddressList;
+ typedef std::vector<VariableDeclaration *> VariableDeclarationListType;
Translator(GlobalContext *Ctx, const ClFlags &Flags)
: Ctx(Ctx), Flags(Flags), ErrorStatus(0) {}
@@ -54,8 +53,9 @@
/// Emits the constant pool.
void emitConstants();
- /// Lowers the given list of global addresses to target.
- void lowerGlobals(const GlobalAddressList &GlobalAddresses);
+ /// Lowers the given list of global addresses to target. Generates
+ /// list of corresponding variable declarations.
+ void lowerGlobals(const VariableDeclarationListType &VariableDeclarations);
/// Creates a name using the given prefix and corresponding index.
std::string createUnnamedName(const IceString &Prefix, SizeT Index);
@@ -66,15 +66,6 @@
bool checkIfUnnamedNameSafe(const IceString &Name, const char *Kind,
const IceString &Prefix, Ostream &Stream);
- // Walks module and generates names for unnamed globals using prefix
- // getFlags().DefaultGlobalPrefix, if the prefix is non-empty.
- void nameUnnamedGlobalAddresses(llvm::Module *Mod);
-
- // Walks module and generates names for unnamed functions using
- // prefix getFlags().DefaultFunctionPrefix, if the prefix is
- // non-empty.
- void nameUnnamedFunctions(llvm::Module *Mod);
-
protected:
GlobalContext *Ctx;
const ClFlags &Flags;
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index 6642ba9..4f7a745 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -24,7 +24,6 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/ValueHandle.h"
#include "IceCfg.h"
#include "IceCfgNode.h"
@@ -36,9 +35,8 @@
#include "IceTypeConverter.h"
#include "PNaClTranslator.h"
-using namespace llvm;
-
namespace {
+using namespace llvm;
// TODO(kschimpf) Remove error recovery once implementation complete.
static cl::opt<bool> AllowErrorRecovery(
@@ -160,19 +158,21 @@
TopLevelParser &operator=(const TopLevelParser &) = delete;
public:
+ typedef std::vector<Ice::FunctionDeclaration *> FunctionDeclarationListType;
+
TopLevelParser(Ice::Translator &Translator, const std::string &InputName,
NaClBitcodeHeader &Header, NaClBitstreamCursor &Cursor,
bool &ErrorStatus)
: NaClBitcodeParser(Cursor), Translator(Translator),
Mod(new Module(InputName, getGlobalContext())), DL(PNaClDataLayout),
- Header(Header), TypeConverter(getLLVMContext()),
+ Header(Header), TypeConverter(Mod->getContext()),
ErrorStatus(ErrorStatus), NumErrors(0), NumFunctionIds(0),
NumFunctionBlocks(0) {
Mod->setDataLayout(PNaClDataLayout);
setErrStream(Translator.getContext()->getStrDump());
}
- ~TopLevelParser() override { DeleteContainerPointers(GlobalIDAddresses); }
+ ~TopLevelParser() override {}
Ice::Translator &getTranslator() { return Translator; }
@@ -198,9 +198,6 @@
/// Returns the number of bytes in the bitcode header.
size_t getHeaderSize() const { return Header.getHeaderSize(); }
- /// Returns the llvm context to use.
- LLVMContext &getLLVMContext() const { return Mod->getContext(); }
-
/// Changes the size of the type list to the given size.
void resizeTypeIDValues(unsigned NewSize) { TypeIDValues.resize(NewSize); }
@@ -236,36 +233,40 @@
}
/// Sets the next function ID to the given LLVM function.
- void setNextFunctionID(Function *Fcn) {
+ void setNextFunctionID(Ice::FunctionDeclaration *Fcn) {
++NumFunctionIds;
- FunctionIDValues.push_back(Fcn);
+ FunctionDeclarationList.push_back(Fcn);
}
/// Defines the next function ID as one that has an implementation
/// (i.e a corresponding function block in the bitcode).
void setNextValueIDAsImplementedFunction() {
- DefiningFunctionsList.push_back(FunctionIDValues.size());
+ DefiningFunctionDeclarationsList.push_back(FunctionDeclarationList.size());
}
/// Returns the value id that should be associated with the the
/// current function block. Increments internal counters during call
/// so that it will be in correct position for next function block.
unsigned getNextFunctionBlockValueID() {
- if (NumFunctionBlocks >= DefiningFunctionsList.size())
+ if (NumFunctionBlocks >= DefiningFunctionDeclarationsList.size())
report_fatal_error(
"More function blocks than defined function addresses");
- return DefiningFunctionsList[NumFunctionBlocks++];
+ return DefiningFunctionDeclarationsList[NumFunctionBlocks++];
}
- /// Returns the LLVM Function address associated with ID.
- Function *getFunctionByID(unsigned ID) const {
- if (ID >= FunctionIDValues.size())
- return nullptr;
- Value *V = FunctionIDValues[ID];
- return cast<Function>(V);
+ /// Returns the function associated with ID.
+ Ice::FunctionDeclaration *getFunctionByID(unsigned ID) {
+ if (ID < FunctionDeclarationList.size())
+ return FunctionDeclarationList[ID];
+ return reportGetFunctionByIDError(ID);
}
- /// Returns the corresponding constant associated with a global value
+ /// Returns the list of function declarations.
+ const FunctionDeclarationListType &getFunctionDeclarationList() const {
+ return FunctionDeclarationList;
+ }
+
+ /// Returns the corresponding constant associated with a global declaration.
/// (i.e. relocatable).
Ice::Constant *getOrCreateGlobalConstantByID(unsigned ID) {
// TODO(kschimpf): Can this be built when creating global initializers?
@@ -273,7 +274,7 @@
if (ID >= ValueIDConstants.size()) {
C = nullptr;
unsigned ExpectedSize =
- FunctionIDValues.size() + GlobalIDAddresses.size();
+ FunctionDeclarationList.size() + VariableDeclarations.size();
if (ID >= ExpectedSize)
ExpectedSize = ID;
ValueIDConstants.resize(ExpectedSize);
@@ -284,12 +285,13 @@
return C;
// If reached, no such constant exists, create one.
+ // TODO(kschimpf) Don't get addresses of intrinsic function declarations.
std::string Name;
- unsigned FcnIDSize = FunctionIDValues.size();
+ unsigned FcnIDSize = FunctionDeclarationList.size();
if (ID < FcnIDSize) {
- Name = FunctionIDValues[ID]->getName();
- } else if ((ID - FcnIDSize) < GlobalIDAddresses.size()) {
- Name = GlobalIDAddresses[ID - FcnIDSize]->getName();
+ Name = FunctionDeclarationList[ID]->getName();
+ } else if ((ID - FcnIDSize) < VariableDeclarations.size()) {
+ Name = VariableDeclarations[ID - FcnIDSize]->getName();
} else {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
@@ -304,47 +306,49 @@
return C;
}
- /// Returns the number of function addresses (i.e. ID's) defined in
- /// the bitcode file.
+ /// Returns the number of function declarations in the bitcode file.
unsigned getNumFunctionIDs() const { return NumFunctionIds; }
- /// Returns the number of global IDs (function and global addresses)
- /// defined in the bitcode file.
+ /// Returns the number of global declarations (i.e. IDs) defined in
+ /// the bitcode file.
unsigned getNumGlobalIDs() const {
- return FunctionIDValues.size() + GlobalIDAddresses.size();
+ return FunctionDeclarationList.size() + VariableDeclarations.size();
}
- /// Creates Count global addresses.
- void CreateGlobalAddresses(size_t Count) {
- assert(GlobalIDAddresses.empty());
+ /// Creates Count global variable declarations.
+ void CreateGlobalVariables(size_t Count) {
+ assert(VariableDeclarations.empty());
+ Ice::GlobalContext *Context = getTranslator().getContext();
for (size_t i = 0; i < Count; ++i) {
- GlobalIDAddresses.push_back(new Ice::GlobalAddress());
+ VariableDeclarations.push_back(Ice::VariableDeclaration::create(Context));
}
}
- /// Returns the number of global addresses (i.e. ID's) defined in
- /// the bitcode file.
- Ice::SizeT getNumGlobalAddresses() const { return GlobalIDAddresses.size(); }
-
- /// Returns the global address with the given index.
- Ice::GlobalAddress *getGlobalAddress(size_t Index) {
- if (Index < GlobalIDAddresses.size())
- return GlobalIDAddresses[Index];
- std::string Buffer;
- raw_string_ostream StrBuf(Buffer);
- StrBuf << "Global index " << Index
- << " not allowed. Out of range. Must be less than "
- << GlobalIDAddresses.size();
- Error(StrBuf.str());
- // TODO(kschimpf) Remove error recovery once implementation complete.
- if (!GlobalIDAddresses.empty())
- return GlobalIDAddresses[0];
- report_fatal_error("Unable to continue");
+ /// Returns the number of global variable declarations in the
+ /// bitcode file.
+ Ice::SizeT getNumGlobalVariables() const {
+ return VariableDeclarations.size();
}
- /// Returns the list of read global addresses.
- const Ice::Translator::GlobalAddressList &getGlobalIDAddresses() {
- return GlobalIDAddresses;
+ /// Returns the global variable declaration with the given index.
+ Ice::VariableDeclaration *getGlobalVariableByID(unsigned Index) {
+ if (Index < VariableDeclarations.size())
+ return VariableDeclarations[Index];
+ return reportGetGlobalVariableByIDError(Index);
+ }
+
+ /// Returns the global declaration (variable or function) with the
+ /// given Index.
+ Ice::GlobalDeclaration *getGlobalDeclarationByID(size_t Index) {
+ if (Index < NumFunctionIds)
+ return getFunctionByID(Index);
+ else
+ return getGlobalVariableByID(Index - NumFunctionIds);
+ }
+
+ /// Returns the list of parsed global variable declarations.
+ const Ice::Translator::VariableDeclarationListType &getGlobalVariables() {
+ return VariableDeclarations;
}
/// Returns the corresponding ICE type for LLVMTy.
@@ -383,20 +387,21 @@
unsigned NumErrors;
// The types associated with each type ID.
std::vector<ExtendedType> TypeIDValues;
- // The set of function value IDs.
- std::vector<WeakVH> FunctionIDValues;
- // The set of global addresses IDs.
- Ice::Translator::GlobalAddressList GlobalIDAddresses;
- // Relocatable constants associated with FunctionIDValues and
- // GlobalIDAddresses.
+ // The set of functions.
+ FunctionDeclarationListType FunctionDeclarationList;
+ // The set of global variables.
+ Ice::Translator::VariableDeclarationListType VariableDeclarations;
+ // Relocatable constants associated with global declarations.
std::vector<Ice::Constant *> ValueIDConstants;
- // The number of function IDs.
+ // The number of function declarations (i.e. IDs).
unsigned NumFunctionIds;
// The number of function blocks (processed so far).
unsigned NumFunctionBlocks;
- // The list of value IDs (in the order found) of defining function
- // addresses.
- std::vector<unsigned> DefiningFunctionsList;
+ // The list of function declaration IDs (in the order found) that
+ // aren't just proto declarations.
+ // TODO(kschimpf): Instead of using this list, just use
+ // FunctionDeclarationList, and the isProto member function.
+ std::vector<unsigned> DefiningFunctionDeclarationsList;
// Error recovery value to use when getFuncSigTypeByID fails.
Ice::FuncSigType UndefinedFuncSigType;
@@ -423,6 +428,14 @@
void reportBadTypeIDAs(unsigned ID, const ExtendedType *Ty,
ExtendedType::TypeKind WantedType);
+ // Reports that there is no function declaration for ID. Returns an
+ // error recovery value to use.
+ Ice::FunctionDeclaration *reportGetFunctionByIDError(unsigned ID);
+
+ // Reports that there is not global variable declaration for
+ // ID. Returns an error recovery value to use.
+ Ice::VariableDeclaration *reportGetGlobalVariableByIDError(unsigned Index);
+
// Reports that there is no corresponding ICE type for LLVMTy, and
// returns ICE::IceType_void.
Ice::Type convertToIceTypeError(Type *LLVMTy);
@@ -440,6 +453,34 @@
Error(StrBuf.str());
}
+Ice::FunctionDeclaration *
+TopLevelParser::reportGetFunctionByIDError(unsigned ID) {
+ std::string Buffer;
+ raw_string_ostream StrBuf(Buffer);
+ StrBuf << "Function index " << ID
+ << " not allowed. Out of range. Must be less than "
+ << FunctionDeclarationList.size();
+ Error(StrBuf.str());
+ // TODO(kschimpf) Remove error recovery once implementation complete.
+ if (!FunctionDeclarationList.empty())
+ return FunctionDeclarationList[0];
+ report_fatal_error("Unable to continue");
+}
+
+Ice::VariableDeclaration *
+TopLevelParser::reportGetGlobalVariableByIDError(unsigned Index) {
+ std::string Buffer;
+ raw_string_ostream StrBuf(Buffer);
+ StrBuf << "Global index " << Index
+ << " not allowed. Out of range. Must be less than "
+ << VariableDeclarations.size();
+ Error(StrBuf.str());
+ // TODO(kschimpf) Remove error recovery once implementation complete.
+ if (!VariableDeclarations.empty())
+ return VariableDeclarations[0];
+ report_fatal_error("Unable to continue");
+}
+
Ice::Type TopLevelParser::convertToIceTypeError(Type *LLVMTy) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
@@ -747,38 +788,40 @@
llvm_unreachable("Unknown type block record not processed!");
}
-/// Parses the globals block (i.e. global variables).
+/// Parses the globals block (i.e. global variable declarations and
+/// corresponding initializers).
class GlobalsParser : public BlockParserBaseClass {
public:
GlobalsParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
: BlockParserBaseClass(BlockID, EnclosingParser), InitializersNeeded(0),
- NextGlobalID(0), CurrentAddress(&DummyAddress) {}
-
- ~GlobalsParser() override {}
+ NextGlobalID(0), DummyGlobalVar(Ice::VariableDeclaration::create(
+ getTranslator().getContext())),
+ CurGlobalVar(DummyGlobalVar) {}
private:
// Keeps track of how many initializers are expected for the global variable
- // being built.
+ // declaration being built.
unsigned InitializersNeeded;
- // The index of the next global variable.
+ // The index of the next global variable declaration.
unsigned NextGlobalID;
- // Holds the current global address whose initializer is being defined.
- Ice::GlobalAddress *CurrentAddress;
+ // Dummy global variable declaration to guarantee CurGlobalVar is
+ // always defined (allowing code to not need to check if
+ // CurGlobalVar is nullptr).
+ Ice::VariableDeclaration *DummyGlobalVar;
- // Dummy global address to guarantee CurrentAddress is always defined
- // (allowing code to not need to check if CurrentAddress is nullptr).
- Ice::GlobalAddress DummyAddress;
+ // Holds the current global variable declaration being built.
+ Ice::VariableDeclaration *CurGlobalVar;
void ExitBlock() override {
verifyNoMissingInitializers();
- unsigned NumIDs = Context->getNumGlobalAddresses();
+ unsigned NumIDs = Context->getNumGlobalVariables();
if (NextGlobalID < NumIDs) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Globals block expects " << NumIDs
- << " global definitions. Found: " << NextGlobalID;
+ << " global variable declarations. Found: " << NextGlobalID;
Error(StrBuf.str());
}
BlockParserBaseClass::ExitBlock();
@@ -786,12 +829,12 @@
void ProcessRecord() override;
- // Checks if the number of initializers for the CurrentAddress is the same as
+ // Checks if the number of initializers for the CurGlobalVar is the same as
// the number found in the bitcode file. If different, and error message is
// generated, and the internal state of the parser is fixed so this condition
// is no longer violated.
void verifyNoMissingInitializers() {
- size_t NumInits = CurrentAddress->getInitializers().size();
+ size_t NumInits = CurGlobalVar->getInitializers().size();
if (InitializersNeeded != NumInits) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
@@ -801,6 +844,7 @@
StrBuf << "s";
StrBuf << ". Found: " << NumInits;
Error(StrBuf.str());
+ InitializersNeeded = NumInits;
}
}
};
@@ -812,11 +856,11 @@
// COUNT: [n]
if (!isValidRecordSize(1, "Globals count"))
return;
- if (NextGlobalID != Context->getNumGlobalAddresses()) {
+ if (NextGlobalID != Context->getNumGlobalVariables()) {
Error("Globals count record not first in block.");
return;
}
- Context->CreateGlobalAddresses(Values[0]);
+ Context->CreateGlobalVariables(Values[0]);
return;
case naclbitc::GLOBALVAR_VAR: {
// VAR: [align, isconst]
@@ -824,9 +868,9 @@
return;
verifyNoMissingInitializers();
InitializersNeeded = 1;
- CurrentAddress = Context->getGlobalAddress(NextGlobalID);
- CurrentAddress->setAlignment((1 << Values[0]) >> 1);
- CurrentAddress->setIsConstant(Values[1] != 0);
+ CurGlobalVar = Context->getGlobalVariableByID(NextGlobalID);
+ CurGlobalVar->setAlignment((1 << Values[0]) >> 1);
+ CurGlobalVar->setIsConstant(Values[1] != 0);
++NextGlobalID;
return;
}
@@ -834,7 +878,7 @@
// COMPOUND: [size]
if (!isValidRecordSize(1, "globals compound"))
return;
- if (!CurrentAddress->getInitializers().empty()) {
+ if (!CurGlobalVar->getInitializers().empty()) {
Error("Globals compound record not first initializer");
return;
}
@@ -851,17 +895,17 @@
// ZEROFILL: [size]
if (!isValidRecordSize(1, "Globals zerofill"))
return;
- CurrentAddress->addInitializer(
- new Ice::GlobalAddress::ZeroInitializer(Values[0]));
- break;
+ CurGlobalVar->addInitializer(
+ new Ice::VariableDeclaration::ZeroInitializer(Values[0]));
+ return;
}
case naclbitc::GLOBALVAR_DATA: {
// DATA: [b0, b1, ...]
if (!isValidRecordSizeAtLeast(1, "Globals data"))
return;
- CurrentAddress->addInitializer(
- new Ice::GlobalAddress::DataInitializer(Values));
- break;
+ CurGlobalVar->addInitializer(
+ new Ice::VariableDeclaration::DataInitializer(Values));
+ return;
}
case naclbitc::GLOBALVAR_RELOC: {
// RELOC: [val, [addend]]
@@ -871,19 +915,9 @@
Ice::SizeT Offset = 0;
if (Values.size() == 2)
Offset = Values[1];
- unsigned NumFunctions = Context->getNumFunctionIDs();
- if (Index < NumFunctions) {
- llvm::Function *Fcn = Context->getFunctionByID(Index);
- Ice::GlobalAddress::RelocationAddress Addr(Fcn);
- CurrentAddress->addInitializer(
- new Ice::GlobalAddress::RelocInitializer(Addr, Offset));
- } else {
- Ice::GlobalAddress::RelocationAddress Addr(
- Context->getGlobalAddress(Index - NumFunctions));
- CurrentAddress->addInitializer(
- new Ice::GlobalAddress::RelocInitializer(Addr, Offset));
- }
- break;
+ CurGlobalVar->addInitializer(new Ice::VariableDeclaration::RelocInitializer(
+ Context->getGlobalDeclarationByID(Index), Offset));
+ return;
}
default:
BlockParserBaseClass::ProcessRecord();
@@ -964,23 +998,25 @@
: BlockParserBaseClass(BlockID, EnclosingParser),
Func(new Ice::Cfg(getTranslator().getContext())), CurrentBbIndex(0),
FcnId(Context->getNextFunctionBlockValueID()),
- LLVMFunc(Context->getFunctionByID(FcnId)),
+ FuncDecl(Context->getFunctionByID(FcnId)),
CachedNumGlobalValueIDs(Context->getNumGlobalIDs()),
NextLocalInstIndex(Context->getNumGlobalIDs()),
InstIsTerminating(false) {
- Func->setFunctionName(LLVMFunc->getName());
+ Func->setFunctionName(FuncDecl->getName());
if (getFlags().TimeEachFunction)
getTranslator().getContext()->pushTimer(
getTranslator().getContext()->getTimerID(
Ice::GlobalContext::TSK_Funcs, Func->getFunctionName()),
Ice::GlobalContext::TSK_Funcs);
- Func->setReturnType(Context->convertToIceType(LLVMFunc->getReturnType()));
- Func->setInternal(LLVMFunc->hasInternalLinkage());
+ // TODO(kschimpf) Clean up API to add a function signature to
+ // a CFG.
+ const Ice::FuncSigType &Signature = FuncDecl->getSignature();
+ Func->setReturnType(Signature.getReturnType());
+ Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage);
CurrentNode = InstallNextBasicBlock();
Func->setEntryNode(CurrentNode);
- for (auto ArgI = LLVMFunc->arg_begin(), ArgE = LLVMFunc->arg_end();
- ArgI != ArgE; ++ArgI) {
- Func->addArg(getNextInstVar(Context->convertToIceType(ArgI->getType())));
+ for (Ice::Type ArgType : Signature.getArgList()) {
+ Func->addArg(getNextInstVar(ArgType));
}
}
@@ -1000,8 +1036,8 @@
Ice::CfgNode *CurrentNode;
// The ID for the function.
unsigned FcnId;
- // The corresponding LLVM function.
- Function *LLVMFunc;
+ // The corresponding function declaration.
+ Ice::FunctionDeclaration *FuncDecl;
// Holds the dividing point between local and global absolute value indices.
uint32_t CachedNumGlobalValueIDs;
// Holds operands local to the function block, based on indices
@@ -1999,12 +2035,12 @@
// CALL_INDIRECT: [cc, fn, returnty, args...]
//
// Note: The difference between CALL and CALL_INDIRECT is that
- // CALL has an explicit function address, while the CALL_INDIRECT
- // is just an address. For CALL, we can infer the return type by
- // looking up the type signature associated with the function
- // address. For CALL_INDIRECT we can only infer the type signature
- // via argument types, and the corresponding return type stored in
- // CALL_INDIRECT record.
+ // CALL has a reference to an explicit function declaration, while
+ // the CALL_INDIRECT is just an address. For CALL, we can infer
+ // the return type by looking up the type signature associated
+ // with the function declaration. For CALL_INDIRECT we can only
+ // infer the type signature via argument types, and the
+ // corresponding return type stored in CALL_INDIRECT record.
Ice::SizeT ParamsStartIndex = 2;
if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL) {
if (!isValidRecordSizeAtLeast(2, "function block call"))
@@ -2034,17 +2070,9 @@
Ice::Type ReturnType = Ice::IceType_void;
const Ice::Intrinsics::FullIntrinsicInfo *IntrinsicInfo = nullptr;
if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL) {
- Function *Fcn = Context->getFunctionByID(CalleeIndex);
- if (Fcn == nullptr) {
- std::string Buffer;
- raw_string_ostream StrBuf(Buffer);
- StrBuf << "Function call to non-function: " << *Callee;
- Error(StrBuf.str());
- return;
- }
-
- FunctionType *FcnTy = Fcn->getFunctionType();
- ReturnType = Context->convertToIceType(FcnTy->getReturnType());
+ Ice::FunctionDeclaration *Fcn = Context->getFunctionByID(CalleeIndex);
+ const Ice::FuncSigType &Signature = Fcn->getSignature();
+ ReturnType = Signature.getReturnType();
// Check if this direct call is to an Intrinsic (starts with "llvm.")
static Ice::IceString LLVMPrefix("llvm.");
@@ -2339,45 +2367,60 @@
public:
ModuleParser(unsigned BlockID, TopLevelParser *Context)
: BlockParserBaseClass(BlockID, Context),
- GlobalAddressNamesAndInitializersInstalled(false) {}
+ GlobalDeclarationNamesAndInitializersInstalled(false) {}
~ModuleParser() override {}
private:
- // True if we have already instaledl names for unnamed global addresses,
- // and generated global constant initializers.
- bool GlobalAddressNamesAndInitializersInstalled;
+ // True if we have already installed names for unnamed global declarations,
+ // and have generated global constant initializers.
+ bool GlobalDeclarationNamesAndInitializersInstalled;
- // Generates names for unnamed global addresses, and lowers global
- // constant initializers to the target. May be called multiple
- // times. Only the first call will do the installation.
- void InstallGlobalAddressNamesAndInitializers() {
- if (!GlobalAddressNamesAndInitializersInstalled) {
+ // Generates names for unnamed global addresses (i.e. functions and
+ // global variables). Then lowers global variable declaration
+ // initializers to the target. May be called multiple times. Only
+ // the first call will do the installation.
+ void InstallGlobalNamesAndGlobalVarInitializers() {
+ if (!GlobalDeclarationNamesAndInitializersInstalled) {
Ice::Translator &Trans = getTranslator();
const Ice::IceString &GlobalPrefix = getFlags().DefaultGlobalPrefix;
if (!GlobalPrefix.empty()) {
uint32_t NameIndex = 0;
- for (Ice::GlobalAddress *Address : Context->getGlobalIDAddresses()) {
- if (!Address->hasName()) {
- Address->setName(Trans.createUnnamedName(GlobalPrefix, NameIndex));
- ++NameIndex;
- } else {
- Trans.checkIfUnnamedNameSafe(Address->getName(), "global",
- GlobalPrefix,
- Trans.getContext()->getStrDump());
- }
+ for (Ice::VariableDeclaration *Var : Context->getGlobalVariables()) {
+ installDeclarationName(Trans, Var, GlobalPrefix, "global", NameIndex);
}
}
- Trans.nameUnnamedFunctions(Context->getModule());
- getTranslator().lowerGlobals(Context->getGlobalIDAddresses());
- GlobalAddressNamesAndInitializersInstalled = true;
+ const Ice::IceString &FunctionPrefix = getFlags().DefaultFunctionPrefix;
+ if (!FunctionPrefix.empty()) {
+ uint32_t NameIndex = 0;
+ for (Ice::FunctionDeclaration *Func :
+ Context->getFunctionDeclarationList()) {
+ installDeclarationName(Trans, Func, FunctionPrefix, "function",
+ NameIndex);
+ }
+ }
+ getTranslator().lowerGlobals(Context->getGlobalVariables());
+ GlobalDeclarationNamesAndInitializersInstalled = true;
+ }
+ }
+
+ void installDeclarationName(Ice::Translator &Trans,
+ Ice::GlobalDeclaration *Decl,
+ const Ice::IceString &Prefix, const char *Context,
+ uint32_t &NameIndex) {
+ if (!Decl->hasName()) {
+ Decl->setName(Trans.createUnnamedName(Prefix, NameIndex));
+ ++NameIndex;
+ } else {
+ Trans.checkIfUnnamedNameSafe(Decl->getName(), Context, Prefix,
+ Trans.getContext()->getStrDump());
}
}
bool ParseBlock(unsigned BlockID) override;
void ExitBlock() override {
- InstallGlobalAddressNamesAndInitializers();
+ InstallGlobalNamesAndGlobalVarInitializers();
getTranslator().emitConstants();
}
@@ -2400,26 +2443,8 @@
};
void ModuleValuesymtabParser::setValueName(uint64_t Index, StringType &Name) {
- if (Index < Context->getNumFunctionIDs()) {
- Function *Fcn = Context->getFunctionByID(Index);
- if (Fcn != nullptr) {
- Fcn->setName(StringRef(Name.data(), Name.size()));
- return;
- }
- } else {
- unsigned NumFunctions = Context->getNumFunctionIDs();
- if (Index >= NumFunctions) {
- Context->getGlobalAddress(Index - NumFunctions)
- ->setName(StringRef(Name.data(), Name.size()));
- }
- return;
- }
-
- std::string Buffer;
- raw_string_ostream StrBuf(Buffer);
- StrBuf << "Invalid global address ID in valuesymtab: " << Index;
- Error(StrBuf.str());
- return;
+ Context->getGlobalDeclarationByID(Index)
+ ->setName(StringRef(Name.data(), Name.size()));
}
void ModuleValuesymtabParser::setBbName(uint64_t Index, StringType &Name) {
@@ -2447,7 +2472,7 @@
return Parser.ParseThisBlock();
}
case naclbitc::FUNCTION_BLOCK_ID: {
- InstallGlobalAddressNamesAndInitializers();
+ InstallGlobalNamesAndGlobalVarInitializers();
FunctionParser Parser(BlockID, this);
return Parser.ParseThisBlock();
}
@@ -2476,7 +2501,7 @@
// FUNCTION: [type, callingconv, isproto, linkage]
if (!isValidRecordSize(4, "Function heading"))
return;
- const Ice::FuncSigType &Ty = Context->getFuncSigTypeByID(Values[0]);
+ const Ice::FuncSigType &Signature = Context->getFuncSigTypeByID(Values[0]);
CallingConv::ID CallingConv;
if (!naclbitc::DecodeCallingConv(Values[1], CallingConv)) {
std::string Buffer;
@@ -2494,19 +2519,12 @@
Error(StrBuf.str());
return;
}
- SmallVector<Type *, 8> ArgTys;
- for (Ice::Type ArgType : Ty.getArgList()) {
- ArgTys.push_back(Context->convertToLLVMType(ArgType));
- }
- Function *Func = Function::Create(
- FunctionType::get(Context->convertToLLVMType(Ty.getReturnType()),
- ArgTys, false),
- Linkage, "", Context->getModule());
- Func->setCallingConv(CallingConv);
+ Ice::FunctionDeclaration *Func = Ice::FunctionDeclaration::create(
+ getTranslator().getContext(), Signature, CallingConv, Linkage,
+ Values[2] == 0);
if (Values[2] == 0)
Context->setNextValueIDAsImplementedFunction();
Context->setNextFunctionID(Func);
- // TODO(kschimpf) verify if Func matches PNaCl ABI.
return;
}
default: