Index: tests_lit/llvm2ice_tests/elf_container.ll |
diff --git a/tests_lit/llvm2ice_tests/elf_container.ll b/tests_lit/llvm2ice_tests/elf_container.ll |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3b6f700785f33f945ad3684c152da029d2e4a4be |
--- /dev/null |
+++ b/tests_lit/llvm2ice_tests/elf_container.ll |
@@ -0,0 +1,242 @@ |
+; Tests that we generate an ELF container with fields that make sense, |
+; cross-validating against llvm-mc. |
+ |
+; 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 |
+ |
+; Use intrinsics to test external calls. |
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) |
+declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1) |
+ |
+; Test some global data relocs (data, rodata, bss). |
+@bytes = internal global [7 x i8] c"abcdefg", align 1 |
+@const_bytes = internal constant [7 x i8] c"abcdefg", align 1 |
+ |
+@ptr = internal global i32 ptrtoint ([7 x i8]* @bytes to i32), align 4 |
+@const_ptr = internal constant i32 ptrtoint ([7 x i8]* @bytes to i32), align 4 |
+ |
+@ptr_to_func = internal global i32 ptrtoint (double ()* @returnDoubleConst to i32), align 4 |
+@const_ptr_to_func = internal constant i32 ptrtoint (double ()* @returnDoubleConst to i32), align 4 |
+ |
+@short_zero = internal global [2 x i8] zeroinitializer, align 2 |
+@double_zero = internal global [8 x i8] zeroinitializer, align 8 |
+@const_short_zero = internal constant [2 x i8] zeroinitializer, align 2 |
+@const_double_zero = internal constant [8 x i8] zeroinitializer, align 8 |
+ |
+ |
+@addend_ptr = internal global i32 add (i32 ptrtoint (i32* @ptr to i32), i32 128) |
+@const_addend_ptr = internal constant i32 add (i32 ptrtoint (i32* @ptr to i32), i32 64) |
+ |
+; Use float/double constants to test constant pools. |
+define internal float @returnFloatConst() { |
+entry: |
+ %f = fadd float 0x3FF3AE1480000000, 0x3FF3AE1400000000 |
+ ret float %f |
+} |
+ |
+define internal double @returnDoubleConst() { |
+entry: |
+ %d = fadd double 1.230000e+00, 3.210000e+00 |
+ ret double %d |
+} |
+ |
+define internal void @test_memcpy(i32 %iptr_dst, i32 %len) { |
+entry: |
+ %dst = inttoptr i32 %iptr_dst to i8* |
+ %src = bitcast [7 x i8]* @bytes to i8* |
+ call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, |
+ i32 %len, i32 1, i1 false) |
+ ret void |
+} |
+ |
+define internal void @test_memset(i32 %iptr_dst, i32 %wide_val, i32 %len) { |
+entry: |
+ %val = trunc i32 %wide_val to i8 |
+ %dst = inttoptr i32 %iptr_dst to i8* |
+ call void @llvm.memset.p0i8.i32(i8* %dst, i8 %val, |
+ i32 %len, i32 1, i1 false) |
+ ret void |
+} |
+ |
+; Test non-internal functions too. |
+define void @_start(i32) { |
+ %f = call float @returnFloatConst() |
+ %d = call double @returnDoubleConst() |
+ call void @test_memcpy(i32 0, i32 99) |
+ call void @test_memset(i32 0, i32 0, i32 99) |
+ ret void |
+} |
+ |
+ |
+; CHECK: ElfHeader { |
+; CHECK: Ident { |
+; CHECK: Magic: (7F 45 4C 46) |
+; CHECK: Class: 32-bit |
+; CHECK: DataEncoding: LittleEndian |
+; CHECK: OS/ABI: SystemV (0x0) |
+; CHECK: ABIVersion: 0 |
+; CHECK: Unused: (00 00 00 00 00 00 00) |
+; CHECK: } |
+; CHECK: Type: Relocatable (0x1) |
+; CHECK: Machine: EM_386 (0x3) |
+; CHECK: Version: 1 |
+; CHECK: Entry: 0x0 |
+; CHECK: ProgramHeaderOffset: 0x0 |
+; CHECK: SectionHeaderOffset: 0x{{[1-9A-F][0-9A-F]*}} |
+; CHECK: Flags [ (0x0) |
+; CHECK: ] |
+; CHECK: HeaderSize: 52 |
+; CHECK: ProgramHeaderEntrySize: 0 |
+; CHECK: ProgramHeaderCount: 0 |
+; CHECK: SectionHeaderEntrySize: 40 |
+; CHECK: SectionHeaderCount: {{[1-9][0-9]*}} |
+; CHECK: StringTableSectionIndex: {{[1-9][0-9]*}} |
+; CHECK: } |
+ |
+ |
+; CHECK: Sections [ |
+; CHECK: Section { |
+; CHECK: Index: 0 |
+; CHECK: Name: (0) |
+; CHECK: Type: SHT_NULL |
+; CHECK: Flags [ (0x0) |
+; CHECK: ] |
+; CHECK: Address: 0x0 |
+; CHECK: Offset: 0x0 |
+; CHECK: Size: 0 |
+; CHECK: Link: 0 |
+; CHECK: Info: 0 |
+; CHECK: AddressAlignment: 0 |
+; CHECK: EntrySize: 0 |
+; CHECK: SectionData ( |
+; CHECK-NEXT: ) |
+; CHECK: } |
+; 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 ( |
+; There's probably halt padding (0xF4) in there somewhere. |
+; CHECK: {{.*}}F4 |
+; CHECK: ) |
+; CHECK: } |
+; CHECK: Section { |
+; CHECK: Index: {{[1-9][0-9]*}} |
+; CHECK: Name: .shstrtab |
+; CHECK: Type: SHT_STRTAB |
+; CHECK: Flags [ (0x0) |
+; 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: 1 |
+; CHECK: EntrySize: 0 |
+; CHECK: SectionData ( |
+; CHECK: {{.*}}.text{{.*}} |
+; CHECK: ) |
+; CHECK: } |
+; CHECK: Section { |
+; CHECK: Index: {{[1-9][0-9]*}} |
+; CHECK: 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: [[STRTAB_INDEX:[1-9][0-9]*]] |
+; CHECK: Info: [[GLOBAL_START_INDEX:[1-9][0-9]*]] |
+; CHECK: AddressAlignment: 4 |
+; CHECK: EntrySize: 16 |
+; CHECK: } |
+; CHECK: Section { |
+; CHECK: Index: [[STRTAB_INDEX]] |
+; CHECK: Name: .strtab |
+; CHECK: Type: SHT_STRTAB |
+; CHECK: Flags [ (0x0) |
+; 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: 1 |
+; CHECK: EntrySize: 0 |
+; CHECK: } |
+ |
+ |
+; CHECK: Relocations [ |
+; TODO: fill it out. |
+; 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: } |
+; TODO: fill in the data symbols. |
+; CHECK: Symbol { |
+; CHECK: Name: returnDoubleConst |
+; CHECK-NEXT: Value: 0x{{[1-9A-F][0-9A-F]*}} |
+; 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: returnFloatConst |
+; This happens to be the first function, so its offset is 0 within the text. |
+; 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: test_memcpy |
+; CHECK-NEXT: Value: 0x{{[1-9A-F][0-9A-F]*}} |
+; 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: ] |