diff options
| author | Mark Seaborn <mseaborn@chromium.org> | 2013-04-23 14:49:45 -0700 |
|---|---|---|
| committer | Mark Seaborn <mseaborn@chromium.org> | 2013-04-23 14:49:45 -0700 |
| commit | e0e366e55459a2b934253ac1ada762bdade64571 (patch) | |
| tree | 8d75f1e95c84511fc9d265341d2d0c688f51a20d /test/Transforms | |
| parent | 744ccd6c8bd149a17575b9d768b9a90ce06bf122 (diff) | |
PNaCl: Add FlattenGlobals pass for simplifying global variable initializers
This pass converts initializers for global variables into a flattened
normal form which removes nested struct types and simplifies
ConstantExprs.
In the future, we might change the bitcode format to use the flattened
bytes+relocs representation for global initializers. In that case, we
will be able to reuse the FlattenedConstant class in the bitcode
reader/writer for converting to and from this form.
BUG=https://code.google.com/p/nativeclient/issues/detail?id=3113
TEST=test/Transforms/NaCl/flatten-globals.ll
Review URL: https://codereview.chromium.org/14017011
Diffstat (limited to 'test/Transforms')
| -rw-r--r-- | test/Transforms/NaCl/flatten-globals.ll | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/test/Transforms/NaCl/flatten-globals.ll b/test/Transforms/NaCl/flatten-globals.ll new file mode 100644 index 0000000000..4ac96d6a7c --- /dev/null +++ b/test/Transforms/NaCl/flatten-globals.ll @@ -0,0 +1,180 @@ +; RUN: opt -flatten-globals %s -S | FileCheck %s +; RUN: opt -flatten-globals %s -S | FileCheck %s -check-prefix=CLEANED + +target datalayout = "p:32:32:32" + + +; Check simple cases + +@var_i32 = global i32 258 +; CHECK: @var_i32 = global [4 x i8] c"\02\01\00\00" +; CHECK-CLEANED-NOT: global i32 258 + +@external_var = external global i32 +; CHECK: @external_var = external global [4 x i8] + +@zero_init = global i32 0 +; CHECK: @zero_init = global [4 x i8] zeroinitializer + +@big_zero_init = global [2000 x i8] zeroinitializer +; CHECK: @big_zero_init = global [2000 x i8] zeroinitializer + +@null_ptr = global i32* null +; CHECK: @null_ptr = global [4 x i8] zeroinitializer + +@undef_value = global i32 undef +; CHECK: @undef_value = global [4 x i8] zeroinitializer + + +; Check various data types + +@var_i1 = global i8 1 +; CHECK: @var_i1 = global [1 x i8] c"\01" + +@var_i8 = global i8 65 +; CHECK: @var_i8 = global [1 x i8] c"A" + +@var_i16 = global i16 258 +; CHECK: @var_i16 = global [2 x i8] c"\02\01" + +@var_i64 = global i64 72623859790382856 +; CHECK: @var_i64 = global [8 x i8] c"\08\07\06\05\04\03\02\01" + +@var_i128 = global i128 1339673755198158349044581307228491536 +; CHECK: @var_i128 = global [16 x i8] c"\10\0F\0E\0D\0C\0B\0A\09\08\07\06\05\04\03\02\01" + +; Check that padding bits come out as zero. +@var_i121 = global i121 1339673755198158349044581307228491536 +; CHECK: @var_i121 = global [16 x i8] c"\10\0F\0E\0D\0C\0B\0A\09\08\07\06\05\04\03\02\01" + +@var_double = global double 123.456 +; CHECK: @var_double = global [8 x i8] c"w\BE\9F\1A/\DD^@" + +@var_float = global float 123.0 +; CHECK: @var_float = global [4 x i8] c"\00\00\F6B" + + +; Check aggregates + +@padded_struct = global { i8, i8, i32 } { i8 65, i8 66, i32 258 } +; CHECK: @padded_struct = global [8 x i8] c"AB\00\00\02\01\00\00" + +@packed_struct = global <{ i8, i8, i32 }> <{ i8 67, i8 68, i32 258 }> +; CHECK: @packed_struct = global [6 x i8] c"CD\02\01\00\00" + +@i8_array = global [6 x i8] c"Hello\00" +; CHECK: @i8_array = global [6 x i8] c"Hello\00" + +@i16_array = global [3 x i16] [ i16 1, i16 2, i16 3 ] +; CHECK: @i16_array = global [6 x i8] c"\01\00\02\00\03\00" + +%s = type { i8, i8 } +@struct_array = global [2 x %s] [%s { i8 1, i8 2 }, %s { i8 3, i8 4 }] +; CHECK: @struct_array = global [4 x i8] c"\01\02\03\04" + +@vector = global <2 x i32> <i32 259, i32 520> +; CHECK: @vector = global [8 x i8] c"\03\01\00\00\08\02\00\00" + + +; Check that various attributes are preserved + +@constant_var = constant i32 259 +; CHECK: @constant_var = constant [4 x i8] c"\03\01\00\00" + +@weak_external_var = extern_weak global i32 +; CHECK: @weak_external_var = extern_weak global [4 x i8] + +@tls_var = external thread_local global i32 +; CHECK: @tls_var = external thread_local global [4 x i8] + +@aligned_var = global i32 260, align 8 +; CHECK: @aligned_var = global [4 x i8] c"\04\01\00\00", align 8 + + +; Check handling of global references + +@var1 = external global i32 +@var2 = external global i8 + +%ptrs1 = type { i32*, i8*, i32 } +@ptrs1 = global %ptrs1 { i32* @var1, i8* null, i32 259 } +; CHECK: @ptrs1 = global <{ i8*, [8 x i8] }> <{ i8* getelementptr inbounds ([4 x i8]* @var1, i32 0, i32 0), [8 x i8] c"\00\00\00\00\03\01\00\00" }> + +%ptrs2 = type { i32, i32*, i8* } +@ptrs2 = global %ptrs2 { i32 259, i32* @var1, i8* @var2 } +; CHECK: @ptrs2 = global <{ [4 x i8], i8*, i8* }> <{ [4 x i8] c"\03\01\00\00", i8* getelementptr inbounds ([4 x i8]* @var1, i32 0, i32 0), i8* getelementptr inbounds ([1 x i8]* @var2, i32 0, i32 0) }> + +%ptrs3 = type { i32*, [3 x i8], i8* } +@ptrs3 = global %ptrs3 { i32* @var1, [3 x i8] c"foo", i8* @var2 } +; CHECK: @ptrs3 = global <{ i8*, [4 x i8], i8* }> <{ i8* getelementptr inbounds ([4 x i8]* @var1, i32 0, i32 0), [4 x i8] c"foo\00", i8* getelementptr inbounds ([1 x i8]* @var2, i32 0, i32 0) }> + +@ptr = global i32* @var1 +; CHECK: @ptr = global i8* getelementptr inbounds ([4 x i8]* @var1, i32 0, i32 0) + +@func_ptr = global i32* ()* @get_address +; CHECK: @func_ptr = global i8* bitcast (i32* ()* @get_address to i8*) + +@block_addr = global i8* blockaddress(@func_with_block, %label) +; CHECK: @block_addr = global i8* blockaddress(@func_with_block, %label) + +@vector_reloc = global <2 x i32*> <i32* @var1, i32* @var1> +; CHECK: @vector_reloc = global <{ i8*, i8* }> <{ i8* getelementptr inbounds ([4 x i8]* @var1, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8]* @var1, i32 0, i32 0) }> + + +; Global references with addends + +@reloc_addend = global i32* getelementptr (%ptrs1* @ptrs1, i32 0, i32 2) +; CHECK: @reloc_addend = global i8* getelementptr (i8* bitcast (<{ i8*, [8 x i8] }>* @ptrs1 to i8*), i32 8) + +@negative_addend = global %ptrs1* getelementptr (%ptrs1* @ptrs1, i32 -1) +; CHECK: @negative_addend = global i8* getelementptr (i8* bitcast (<{ i8*, [8 x i8] }>* @ptrs1 to i8*), i32 -12) + +@const_ptr = global i32* getelementptr (%ptrs1* null, i32 0, i32 2) +; CHECK: @const_ptr = global [4 x i8] c"\08\00\00\00" + +@int_to_ptr = global i32* inttoptr (i16 260 to i32*) +; CHECK: @int_to_ptr = global [4 x i8] c"\04\01\00\00" + +; Clang allows "(uintptr_t) &var" as a global initializer, so we +; handle this case. +@ptr_to_int = global i32 ptrtoint (i8* @var2 to i32) +; CHECK: @ptr_to_int = global i8* getelementptr inbounds ([1 x i8]* @var2, i32 0, i32 0) + +; This is handled via Constant folding. The getelementptr is +; converted to an undef when it is created, so the pass does not see a +; getelementptr here. +@undef_gep = global i32* getelementptr (%ptrs1* undef, i32 0, i32 2) +; CHECK: @undef_gep = global [4 x i8] zeroinitializer + +; Adding an offset to a function address isn't useful, but check that +; the pass handles it anyway. +@func_addend = global i8* getelementptr ( + i8* bitcast (void ()* @func_with_block to i8*), i32 123) +; CHECK: @func_addend = global i8* getelementptr (i8* bitcast (void ()* @func_with_block to i8*), i32 123) + +; Similarly, adding an offset to a label address isn't useful, but +; check it anyway. +@block_addend = global i8* getelementptr ( + i8* blockaddress(@func_with_block, %label), i32 100) +; CHECK: @block_addend = global i8* getelementptr (i8* blockaddress(@func_with_block, %label), i32 100) + + +; Special cases + +; Leave vars with "appending" linkage alone. +@appending = appending global [1 x i32*] [i32* @var1] +; CHECK: @appending = appending global [1 x i32*] [i32* bitcast ([4 x i8]* @var1 to i32*)] + + +define i32* @get_address() { + ret i32* @var_i32 +} +; CHECK: define i32* @get_address() { +; CHECK-NEXT: ret i32* bitcast ([4 x i8]* @var_i32 to i32*) + + +define void @func_with_block() { + br label %label +label: + ret void +} |
