Commit 6ff33d2f by Karl Schimpf

Test generation of global initializers in Subzero bitcode reader.

Adds workaround that uses IceConverter's convertGlobals to generate global initializers. This should complete the initial implementation of Subzero's bitcode reader. BUG= https://code.google.com/p/nativeclient/issues/detail?id=3892 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/587893003
parent 800dab29
...@@ -627,53 +627,10 @@ namespace Ice { ...@@ -627,53 +627,10 @@ namespace Ice {
void Converter::convertToIce() { void Converter::convertToIce() {
nameUnnamedGlobalAddresses(Mod); nameUnnamedGlobalAddresses(Mod);
if (!Ctx->getFlags().DisableGlobals) if (!Ctx->getFlags().DisableGlobals)
convertGlobals(); convertGlobals(Mod);
convertFunctions(); convertFunctions();
} }
void Converter::convertGlobals() {
OwningPtr<TargetGlobalInitLowering> GlobalLowering(
TargetGlobalInitLowering::createLowering(Ctx->getTargetArch(), Ctx));
for (Module::const_global_iterator I = Mod->global_begin(),
E = Mod->global_end();
I != E; ++I) {
if (!I->hasInitializer())
continue;
const llvm::Constant *Initializer = I->getInitializer();
IceString Name = I->getName();
unsigned Align = I->getAlignment();
uint64_t NumElements = 0;
const char *Data = NULL;
bool IsInternal = I->hasInternalLinkage();
bool IsConst = I->isConstant();
bool IsZeroInitializer = false;
if (const ConstantDataArray *CDA =
dyn_cast<ConstantDataArray>(Initializer)) {
NumElements = CDA->getNumElements();
assert(isa<IntegerType>(CDA->getElementType()) &&
cast<IntegerType>(CDA->getElementType())->getBitWidth() == 8);
Data = CDA->getRawDataValues().data();
} else if (isa<ConstantAggregateZero>(Initializer)) {
if (const ArrayType *AT = dyn_cast<ArrayType>(Initializer->getType())) {
assert(isa<IntegerType>(AT->getElementType()) &&
cast<IntegerType>(AT->getElementType())->getBitWidth() == 8);
NumElements = AT->getNumElements();
IsZeroInitializer = true;
} else {
llvm_unreachable("Unhandled constant aggregate zero type");
}
} else {
llvm_unreachable("Unhandled global initializer");
}
GlobalLowering->lower(Name, Align, IsInternal, IsConst, IsZeroInitializer,
NumElements, Data,
Ctx->getFlags().DisableTranslation);
}
GlobalLowering.reset();
}
void Converter::convertFunctions() { void Converter::convertFunctions() {
for (Module::const_iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { for (Module::const_iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) {
if (I->empty()) if (I->empty())
......
...@@ -32,8 +32,6 @@ public: ...@@ -32,8 +32,6 @@ public:
private: private:
llvm::Module *Mod; llvm::Module *Mod;
// Converts globals to ICE, and then machine code.
void convertGlobals();
// Converts functions to ICE, and then machine code. // Converts functions to ICE, and then machine code.
void convertFunctions(); void convertFunctions();
Converter(const Converter &) LLVM_DELETED_FUNCTION; Converter(const Converter &) LLVM_DELETED_FUNCTION;
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include "IceDefs.h" #include "IceDefs.h"
#include "IceTargetLowering.h" #include "IceTargetLowering.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include <iostream> #include <iostream>
...@@ -104,3 +106,49 @@ void Translator::emitConstants() { ...@@ -104,3 +106,49 @@ void Translator::emitConstants() {
if (!Ctx->getFlags().DisableTranslation && Func) if (!Ctx->getFlags().DisableTranslation && Func)
Func->getTarget()->emitConstants(); Func->getTarget()->emitConstants();
} }
void Translator::convertGlobals(llvm::Module *Mod) {
llvm::OwningPtr<TargetGlobalInitLowering> GlobalLowering(
TargetGlobalInitLowering::createLowering(Ctx->getTargetArch(), Ctx));
for (llvm::Module::const_global_iterator I = Mod->global_begin(),
E = Mod->global_end();
I != E; ++I) {
if (!I->hasInitializer())
continue;
const llvm::Constant *Initializer = I->getInitializer();
IceString Name = I->getName();
unsigned Align = I->getAlignment();
uint64_t NumElements = 0;
const char *Data = NULL;
bool IsInternal = I->hasInternalLinkage();
bool IsConst = I->isConstant();
bool IsZeroInitializer = false;
if (const llvm::ConstantDataArray *CDA =
llvm::dyn_cast<llvm::ConstantDataArray>(Initializer)) {
NumElements = CDA->getNumElements();
assert(llvm::isa<llvm::IntegerType>(CDA->getElementType()) &&
(llvm::cast<llvm::IntegerType>(CDA->getElementType())
->getBitWidth() == 8));
Data = CDA->getRawDataValues().data();
} else if (llvm::isa<llvm::ConstantAggregateZero>(Initializer)) {
if (const llvm::ArrayType *AT =
llvm::dyn_cast<llvm::ArrayType>(Initializer->getType())) {
assert(llvm::isa<llvm::IntegerType>(AT->getElementType()) &&
(llvm::cast<llvm::IntegerType>(AT->getElementType())
->getBitWidth() == 8));
NumElements = AT->getNumElements();
IsZeroInitializer = true;
} else {
llvm_unreachable("Unhandled constant aggregate zero type");
}
} else {
llvm_unreachable("Unhandled global initializer");
}
GlobalLowering->lower(Name, Align, IsInternal, IsConst, IsZeroInitializer,
NumElements, Data,
Ctx->getFlags().DisableTranslation);
}
GlobalLowering.reset();
}
...@@ -56,6 +56,11 @@ public: ...@@ -56,6 +56,11 @@ public:
// prefix is non-empty. // prefix is non-empty.
void nameUnnamedGlobalAddresses(llvm::Module *Mod); void nameUnnamedGlobalAddresses(llvm::Module *Mod);
// Converts globals to ICE, and then machine code.
// TODO(kschimpf) Remove this once we have ported to PNaClTranslator,
// and PNaClTranslator generates initializers while parsing.
void convertGlobals(llvm::Module *Mod);
protected: protected:
GlobalContext *Ctx; GlobalContext *Ctx;
const ClFlags &Flags; const ClFlags &Flags;
......
...@@ -351,7 +351,9 @@ protected: ...@@ -351,7 +351,9 @@ protected:
Context(EnclosingParser->Context) {} Context(EnclosingParser->Context) {}
// Gets the translator associated with the bitcode parser. // Gets the translator associated with the bitcode parser.
Ice::Translator &getTranslator() { return Context->getTranslator(); } Ice::Translator &getTranslator() const { return Context->getTranslator(); }
const Ice::ClFlags &getFlags() const { return getTranslator().getFlags(); }
// Generates an error Message with the bit address prefixed to it. // Generates an error Message with the bit address prefixed to it.
virtual bool Error(const std::string &Message) LLVM_OVERRIDE { virtual bool Error(const std::string &Message) LLVM_OVERRIDE {
...@@ -1376,7 +1378,7 @@ private: ...@@ -1376,7 +1378,7 @@ private:
}; };
FunctionParser::~FunctionParser() { FunctionParser::~FunctionParser() {
if (getTranslator().getFlags().SubzeroTimingEnabled) { if (getFlags().SubzeroTimingEnabled) {
errs() << "[Subzero timing] Convert function " << Func->getFunctionName() errs() << "[Subzero timing] Convert function " << Func->getFunctionName()
<< ": " << TConvert.getElapsedSec() << " sec\n"; << ": " << TConvert.getElapsedSec() << " sec\n";
} }
...@@ -2216,16 +2218,36 @@ bool FunctionParser::ParseBlock(unsigned BlockID) { ...@@ -2216,16 +2218,36 @@ bool FunctionParser::ParseBlock(unsigned BlockID) {
class ModuleParser : public BlockParserBaseClass { class ModuleParser : public BlockParserBaseClass {
public: public:
ModuleParser(unsigned BlockID, TopLevelParser *Context) ModuleParser(unsigned BlockID, TopLevelParser *Context)
: BlockParserBaseClass(BlockID, Context), FoundFirstFunctionBlock(false) { : BlockParserBaseClass(BlockID, Context),
} GlobalAddressNamesAndInitializersInstalled(false) {}
virtual ~ModuleParser() LLVM_OVERRIDE {} virtual ~ModuleParser() LLVM_OVERRIDE {}
private: private:
// True if we have parsed a function block. // True if we have already instaledl names for unnamed global addresses,
bool FoundFirstFunctionBlock; // and generated global constant initializers.
bool GlobalAddressNamesAndInitializersInstalled;
// Temporary hack to generate names for unnamed global addresses,
// and generate global constant initializers. May be called multiple
// times. Only the first call will do the installation.
// NOTE: Doesn't handle relocations for global constant initializers.
void InstallGlobalAddressNamesAndInitializers() {
if (!GlobalAddressNamesAndInitializersInstalled) {
getTranslator().nameUnnamedGlobalAddresses(Context->getModule());
if (!getFlags().DisableGlobals)
getTranslator().convertGlobals(Context->getModule());
GlobalAddressNamesAndInitializersInstalled = true;
}
}
virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE; virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE;
virtual void ExitBlock() LLVM_OVERRIDE {
InstallGlobalAddressNamesAndInitializers();
getTranslator().emitConstants();
}
virtual void ProcessRecord() LLVM_OVERRIDE; virtual void ProcessRecord() LLVM_OVERRIDE;
}; };
...@@ -2282,10 +2304,7 @@ bool ModuleParser::ParseBlock(unsigned BlockID) LLVM_OVERRIDE { ...@@ -2282,10 +2304,7 @@ bool ModuleParser::ParseBlock(unsigned BlockID) LLVM_OVERRIDE {
return Parser.ParseThisBlock(); return Parser.ParseThisBlock();
} }
case naclbitc::FUNCTION_BLOCK_ID: { case naclbitc::FUNCTION_BLOCK_ID: {
if (!FoundFirstFunctionBlock) { InstallGlobalAddressNamesAndInitializers();
getTranslator().nameUnnamedGlobalAddresses(Context->getModule());
FoundFirstFunctionBlock = true;
}
FunctionParser Parser(BlockID, this); FunctionParser Parser(BlockID, this);
return Parser.ParseThisBlock(); return Parser.ParseThisBlock();
} }
......
; Test of global initializers.
; Check that we generate proper global initializers.
; RUN: llvm-as < %s | pnacl-freeze -allow-local-symbol-tables \
; RUN: | %llvm2ice -verbose inst -build-on-read \
; RUN: -allow-local-symbol-tables \
; RUN: | FileCheck %s
; Check that what we generate is valid assembly
; RUN: llvm-as < %s | pnacl-freeze -allow-local-symbol-tables \
; RUN: | %llvm2ice -verbose none -build-on-read \
; RUN: -allow-local-symbol-tables \
; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj
; Check that we don't generate errors
; RUN: llvm-as < %s | pnacl-freeze -allow-local-symbol-tables \
; RUN: | %llvm2ice -verbose none -build-on-read \
; RUN: -allow-local-symbol-tables \
; RUN: | FileCheck --check-prefix=ERRORS %s
@PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4
; CHECK: .data
; CHECK-NEXT: .local
; 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
; CHECK: .section .rodata,"a",@progbits
; CHECK-NEXT: .local
; 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
; CHECK: .data
; CHECK-NEXT: .local
; 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
; CHECK: .data
; CHECK-NEXT: .local
; CHECK-NEXT: .align 4
; CHECK-NEXT: ArrayInitPartial:
; CHECK-NEXT: .byte
; CHECK: .size ArrayInitPartial, 40
@PrimitiveInitStatic = internal global [4 x i8] zeroinitializer, align 4
; CHECK: .data
; CHECK-NEXT: .local PrimitiveInitStatic
; CHECK-NEXT: .comm PrimitiveInitStatic, 4, 4
@PrimitiveUninit = internal global [4 x i8] zeroinitializer, align 4
; CHECK: .data
; CHECK-NEXT: .local PrimitiveUninit
; CHECK-NEXT: .comm PrimitiveUninit, 4, 4
@ArrayUninit = internal global [20 x i8] zeroinitializer, align 4
; CHECK: .data
; CHECK-NEXT: .local ArrayUninit
; CHECK-NEXT: .comm ArrayUninit, 20, 4
@ArrayUninitConstDouble = internal constant [200 x i8] zeroinitializer, align 8
; CHECK: .section .rodata,"a",@progbits
; CHECK-NEXT: .local
; 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
; CHECK: .section .rodata,"a",@progbits
; CHECK-NEXT: .local
; 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
@__fini_array_start = internal constant [0 x i8] zeroinitializer, align 4
@__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
define internal i32 @main(i32 %argc, i32 %argv) {
entry:
%expanded1 = ptrtoint [4 x i8]* @PrimitiveInit to i32
call void @use(i32 %expanded1)
%expanded3 = ptrtoint [4 x i8]* @PrimitiveInitConst to i32
call void @use(i32 %expanded3)
%expanded5 = ptrtoint [4 x i8]* @PrimitiveInitStatic to i32
call void @use(i32 %expanded5)
%expanded7 = ptrtoint [4 x i8]* @PrimitiveUninit to i32
call void @use(i32 %expanded7)
%expanded9 = ptrtoint [20 x i8]* @ArrayInit to i32
call void @use(i32 %expanded9)
%expanded11 = ptrtoint [40 x i8]* @ArrayInitPartial to i32
call void @use(i32 %expanded11)
%expanded13 = ptrtoint [20 x i8]* @ArrayUninit to i32
call void @use(i32 %expanded13)
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)
define internal i32 @nacl_tp_tdb_offset(i32 %__0) {
entry:
ret i32 0
}
define internal i32 @nacl_tp_tls_offset(i32 %size) {
entry:
%result = sub i32 0, %size
ret i32 %result
}
; ERRORS-NOT: ICE translation error
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