Commit 77973ccd by Jan Voung

Track protos + globals w/out initializers as undef too (not just helper funcs)

Also handle empty global variable lists -- and initialize ShAddralign to 1 instead of 0, just in case. Previously it would try to align by 0 when the variable list was empty. This should help the crosstests pass with --elf. BUG=none R=kschimpf@google.com, stichnot@chromium.org Review URL: https://codereview.chromium.org/899483002
parent 3ce1a991
...@@ -121,9 +121,20 @@ public: ...@@ -121,9 +121,20 @@ public:
Ice::Constant *convertConstant(const Constant *Const) { Ice::Constant *convertConstant(const Constant *Const) {
if (const auto GV = dyn_cast<GlobalValue>(Const)) { if (const auto GV = dyn_cast<GlobalValue>(Const)) {
Ice::GlobalDeclaration *Decl = getConverter().getGlobalDeclaration(GV); Ice::GlobalDeclaration *Decl = getConverter().getGlobalDeclaration(GV);
const Ice::RelocOffsetT Offset = 0; bool IsUndefined = false;
return Ctx->getConstantSym(Offset, Decl->getName(), if (const auto *Func = llvm::dyn_cast<Ice::FunctionDeclaration>(Decl))
Decl->getSuppressMangling()); IsUndefined = Func->isProto();
else if (const auto *Var = llvm::dyn_cast<Ice::VariableDeclaration>(Decl))
IsUndefined = !Var->hasInitializer();
else
report_fatal_error("Unhandled GlobalDeclaration type");
if (IsUndefined)
return Ctx->getConstantExternSym(Decl->getName());
else {
const Ice::RelocOffsetT Offset = 0;
return Ctx->getConstantSym(Offset, Decl->getName(),
Decl->getSuppressMangling());
}
} else if (const auto CI = dyn_cast<ConstantInt>(Const)) { } else if (const auto CI = dyn_cast<ConstantInt>(Const)) {
Ice::Type Ty = convertToIceType(CI->getType()); Ice::Type Ty = convertToIceType(CI->getType());
return Ctx->getConstantInt(Ty, CI->getSExtValue()); return Ctx->getConstantInt(Ty, CI->getSExtValue());
......
...@@ -308,11 +308,13 @@ void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars, ...@@ -308,11 +308,13 @@ void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars,
void ELFObjectWriter::writeDataOfType(SectionType ST, void ELFObjectWriter::writeDataOfType(SectionType ST,
const VariableDeclarationList &Vars, const VariableDeclarationList &Vars,
FixupKind RelocationKind, bool IsELF64) { FixupKind RelocationKind, bool IsELF64) {
if (Vars.empty())
return;
ELFDataSection *Section; ELFDataSection *Section;
ELFRelocationSection *RelSection; ELFRelocationSection *RelSection;
// TODO(jvoung): Handle fdata-sections. // TODO(jvoung): Handle fdata-sections.
IceString SectionName; IceString SectionName;
Elf64_Xword ShAddralign = 0; Elf64_Xword ShAddralign = 1;
for (VariableDeclaration *Var : Vars) { for (VariableDeclaration *Var : Vars) {
Elf64_Xword Align = Var->getAlignment(); Elf64_Xword Align = Var->getAlignment();
ShAddralign = std::max(ShAddralign, Align); ShAddralign = std::max(ShAddralign, Align);
...@@ -362,6 +364,10 @@ void ELFObjectWriter::writeDataOfType(SectionType ST, ...@@ -362,6 +364,10 @@ void ELFObjectWriter::writeDataOfType(SectionType ST,
const uint8_t SymbolType = STT_OBJECT; const uint8_t SymbolType = STT_OBJECT;
for (VariableDeclaration *Var : Vars) { for (VariableDeclaration *Var : Vars) {
// If the variable declaration does not have an initializer, its symtab
// entry will be created separately.
if (!Var->hasInitializer())
continue;
Elf64_Xword Align = Var->getAlignment(); Elf64_Xword Align = Var->getAlignment();
Section->padToAlignment(Str, Align); Section->padToAlignment(Str, Align);
SizeT SymbolSize = Var->getNumBytes(); SizeT SymbolSize = Var->getNumBytes();
......
...@@ -284,10 +284,15 @@ public: ...@@ -284,10 +284,15 @@ public:
// TODO(kschimpf) Don't get addresses of intrinsic function declarations. // TODO(kschimpf) Don't get addresses of intrinsic function declarations.
Ice::GlobalDeclaration *Decl = nullptr; Ice::GlobalDeclaration *Decl = nullptr;
unsigned FcnIDSize = FunctionDeclarationList.size(); unsigned FcnIDSize = FunctionDeclarationList.size();
bool IsUndefined = false;
if (ID < FcnIDSize) { if (ID < FcnIDSize) {
Decl = FunctionDeclarationList[ID]; Decl = FunctionDeclarationList[ID];
const auto Func = llvm::cast<Ice::FunctionDeclaration>(Decl);
IsUndefined = Func->isProto();
} else if ((ID - FcnIDSize) < VariableDeclarations.size()) { } else if ((ID - FcnIDSize) < VariableDeclarations.size()) {
Decl = VariableDeclarations[ID - FcnIDSize]; Decl = VariableDeclarations[ID - FcnIDSize];
const auto Var = llvm::cast<Ice::VariableDeclaration>(Decl);
IsUndefined = !Var->hasInitializer();
} }
std::string Name; std::string Name;
bool SuppressMangling; bool SuppressMangling;
...@@ -303,9 +308,13 @@ public: ...@@ -303,9 +308,13 @@ public:
Name = "??"; Name = "??";
SuppressMangling = false; SuppressMangling = false;
} }
const Ice::RelocOffsetT Offset = 0; if (IsUndefined)
C = getTranslator().getContext()->getConstantSym(Offset, Name, C = getTranslator().getContext()->getConstantExternSym(Name);
SuppressMangling); else {
const Ice::RelocOffsetT Offset = 0;
C = getTranslator().getContext()->getConstantSym(Offset, Name,
SuppressMangling);
}
ValueIDConstants[ID] = C; ValueIDConstants[ID] = C;
return C; return C;
} }
......
...@@ -21,6 +21,11 @@ ...@@ -21,6 +21,11 @@
declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1) declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1)
; Try other external functions (for cross tests).
; Not testing external global variables since the NaCl bitcode writer
; refuses to freeze such IR.
declare void @external_foo(i32)
; Test some global data relocs (data, rodata, bss). ; Test some global data relocs (data, rodata, bss).
@bytes = internal global [7 x i8] c"ab\03\FF\F6fg", align 1 @bytes = internal global [7 x i8] c"ab\03\FF\F6fg", align 1
@bytes_const = internal constant [7 x i8] c"ab\03\FF\F6fg", align 1 @bytes_const = internal constant [7 x i8] c"ab\03\FF\F6fg", align 1
...@@ -97,6 +102,12 @@ define internal float @test_call_internal() { ...@@ -97,6 +102,12 @@ define internal float @test_call_internal() {
ret float %f ret float %f
} }
; Test calling an external function.
define internal void @test_call_external() {
call void @external_foo(i32 42)
ret void
}
; Test copying a function pointer, or a global data pointer. ; Test copying a function pointer, or a global data pointer.
define internal i32 @test_ret_fp() { define internal i32 @test_ret_fp() {
%r = ptrtoint float ()* @returnFloatConst to i32 %r = ptrtoint float ()* @returnFloatConst to i32
...@@ -387,6 +398,7 @@ define void @_start(i32) { ...@@ -387,6 +398,7 @@ define void @_start(i32) {
; CHECK: 0x34 R_386_32 .L$double$2 0x0 ; CHECK: 0x34 R_386_32 .L$double$2 0x0
; CHECK: 0x{{.*}} R_386_PC32 memcpy ; CHECK: 0x{{.*}} R_386_PC32 memcpy
; CHECK: 0x{{.*}} R_386_PC32 memset ; CHECK: 0x{{.*}} R_386_PC32 memset
; CHECK: 0x{{.*}} R_386_PC32 external_foo
; CHECK: } ; CHECK: }
; CHECK: Section ({{[0-9]+}}) .rel.data { ; CHECK: Section ({{[0-9]+}}) .rel.data {
; The set of relocations between llvm-mc and the integrated elf-writer ; The set of relocations between llvm-mc and the integrated elf-writer
...@@ -614,6 +626,15 @@ define void @_start(i32) { ...@@ -614,6 +626,15 @@ define void @_start(i32) {
; CHECK-NEXT: Section: .text ; CHECK-NEXT: Section: .text
; CHECK-NEXT: } ; CHECK-NEXT: }
; CHECK: Symbol { ; CHECK: Symbol {
; CHECK: Name: external_foo
; CHECK-NEXT: Value: 0x0
; CHECK-NEXT: Size: 0
; CHECK-NEXT: Binding: Global
; CHECK-NEXT: Type: None
; CHECK-NEXT: Other: 0
; CHECK-NEXT: Section: Undefined
; CHECK-NEXT: }
; CHECK: Symbol {
; CHECK: Name: memcpy ; CHECK: Name: memcpy
; CHECK-NEXT: Value: 0x0 ; CHECK-NEXT: Value: 0x0
; CHECK-NEXT: Size: 0 ; CHECK-NEXT: Size: 0
......
; Tests that we generate an ELF container correctly when there
; is no data section.
; For the integrated ELF writer, we can't pipe the output because we need
; to seek backward and patch up the file headers. So, use a temporary file.
; RUN: %p2i -i %s --args -O2 --verbose none -elf-writer -o %t \
; RUN: && llvm-readobj -file-headers -sections -section-data \
; RUN: -relocations -symbols %t | FileCheck %s
; RUN: %p2i -i %s --args -O2 --verbose none \
; RUN: | llvm-mc -triple=i686-none-nacl -filetype=obj -o - \
; RUN: | llvm-readobj -file-headers -sections -section-data \
; RUN: -relocations -symbols - | FileCheck %s
declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
define internal i32 @foo(i32 %x, i32 %len) {
%y = add i32 %x, %x
%dst = inttoptr i32 %y to i8*
%src = inttoptr i32 %x to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src,
i32 %len, i32 1, i1 false)
ret i32 %y
}
; Test defining a non-internal function.
define void @_start(i32 %x) {
%ignored = call i32 @foo(i32 %x, i32 4)
ret void
}
; CHECK: Section {
; CHECK: Index: {{[1-9][0-9]*}}
; CHECK: Name: .text
; CHECK: Type: SHT_PROGBITS
; CHECK: Flags [ (0x6)
; CHECK: SHF_ALLOC
; CHECK: SHF_EXECINSTR
; CHECK: ]
; CHECK: Address: 0x0
; CHECK: Offset: 0x{{[1-9A-F][0-9A-F]*}}
; CHECK: Size: {{[1-9][0-9]*}}
; CHECK: Link: 0
; CHECK: Info: 0
; CHECK: AddressAlignment: 32
; CHECK: EntrySize: 0
; CHECK: SectionData (
; CHECK: )
; CHECK: }
; CHECK: Section {
; CHECK: Index: {{[1-9][0-9]*}}
; CHECK: Name: .rel.text
; CHECK: Type: SHT_REL
; CHECK: Flags [ (0x0)
; CHECK: ]
; CHECK: Address: 0x0
; CHECK: Offset: 0x{{[1-9A-F][0-9A-F]*}}
; CHECK: Size: {{[1-9][0-9]*}}
; CHECK: Link: [[SYMTAB_INDEX:[1-9][0-9]*]]
; CHECK: Info: {{[1-9][0-9]*}}
; CHECK: AddressAlignment: 4
; CHECK: EntrySize: 8
; CHECK: SectionData (
; CHECK: )
; CHECK: }
; CHECK: Section {
; CHECK: Index: [[SYMTAB_INDEX]]
; CHECK-NEXT: Name: .symtab
; CHECK: Type: SHT_SYMTAB
; CHECK: Flags [ (0x0)
; CHECK: ]
; CHECK: Address: 0x0
; CHECK: Offset: 0x{{[1-9A-F][0-9A-F]*}}
; CHECK: Size: {{[1-9][0-9]*}}
; CHECK: Link: {{[1-9][0-9]*}}
; CHECK: Info: {{[1-9][0-9]*}}
; CHECK: AddressAlignment: 4
; CHECK: EntrySize: 16
; CHECK: }
; CHECK: Relocations [
; CHECK: Section ({{[0-9]+}}) .rel.text {
; CHECK: 0x21 R_386_PC32 memcpy 0x0
; CHECK: }
; CHECK: ]
; CHECK: Symbols [
; CHECK-NEXT: Symbol {
; CHECK-NEXT: Name: (0)
; CHECK-NEXT: Value: 0x0
; CHECK-NEXT: Size: 0
; CHECK-NEXT: Binding: Local
; CHECK-NEXT: Type: None
; CHECK-NEXT: Other: 0
; CHECK-NEXT: Section: Undefined (0x0)
; CHECK-NEXT: }
; CHECK: Symbol {
; CHECK: Name: foo
; CHECK-NEXT: Value: 0x0
; CHECK-NEXT: Size: 0
; CHECK-NEXT: Binding: Local
; CHECK-NEXT: Type: None
; CHECK-NEXT: Other: 0
; CHECK-NEXT: Section: .text
; CHECK-NEXT: }
; CHECK: Symbol {
; CHECK: Name: _start
; CHECK-NEXT: Value: 0x{{[1-9A-F][0-9A-F]*}}
; CHECK-NEXT: Size: 0
; CHECK-NEXT: Binding: Global
; CHECK-NEXT: Type: Function
; CHECK-NEXT: Other: 0
; CHECK-NEXT: Section: .text
; CHECK-NEXT: }
; CHECK: Symbol {
; CHECK: Name: memcpy
; CHECK-NEXT: Value: 0x0
; CHECK-NEXT: Size: 0
; CHECK-NEXT: Binding: Global
; CHECK-NEXT: Type: None
; CHECK-NEXT: Other: 0
; CHECK-NEXT: Section: Undefined
; CHECK-NEXT: }
; CHECK: ]
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