Commit 9d98d791 by Karl Schimpf

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