diff options
author | David Peixotto <dpeixott@codeaurora.org> | 2013-12-19 18:12:36 +0000 |
---|---|---|
committer | David Peixotto <dpeixott@codeaurora.org> | 2013-12-19 18:12:36 +0000 |
commit | e407d093e82b654d214877fecdbf75975a97c635 (patch) | |
tree | ce56821cb41b2ed8964323be9d23574f25f7e6aa /llvm/test/MC/ARM | |
parent | e6153933565571e7e142facea5b5ea1a0e408d34 (diff) | |
download | bcm5719-llvm-e407d093e82b654d214877fecdbf75975a97c635.tar.gz bcm5719-llvm-e407d093e82b654d214877fecdbf75975a97c635.zip |
Implement the ldr-pseudo opcode for ARM assembly
The ldr-pseudo opcode is a convenience for loading 32-bit constants.
It is converted into a pc-relative load from a constant pool. For
example,
ldr r0, =0x10001
ldr r1, =bar
will generate this output in the final assembly
ldr r0, .Ltmp0
ldr r1, .Ltmp1
...
.Ltmp0: .long 0x10001
.Ltmp1: .long bar
Sketch of the LDR pseudo implementation:
Keep a map from Section => ConstantPool
When parsing ldr r0, =val
parse val as an MCExpr
get ConstantPool for current Section
Label = CreateTempSymbol()
remember val in ConstantPool at next free slot
add operand to ldr that is MCSymbolRef of Label
On finishParse() callback
Write out all non-empty constant pools
for each Entry in ConstantPool
Emit Entry.Label
Emit Entry.Value
Possible improvements to be added in a later patch:
1. Does not convert load of small constants to mov
(e.g. ldr r0, =0x1 => mov r0, 0x1)
2. Does reuse constant pool entries for same constant
The implementation was tested for ARM, Thumb1, and Thumb2 targets on
linux and darwin.
llvm-svn: 197708
Diffstat (limited to 'llvm/test/MC/ARM')
-rw-r--r-- | llvm/test/MC/ARM/ldr-pseudo-darwin.s | 241 | ||||
-rw-r--r-- | llvm/test/MC/ARM/ldr-pseudo-obj-errors.s | 17 | ||||
-rw-r--r-- | llvm/test/MC/ARM/ldr-pseudo-parse-errors.s | 10 | ||||
-rw-r--r-- | llvm/test/MC/ARM/ldr-pseudo.s | 221 |
4 files changed, 489 insertions, 0 deletions
diff --git a/llvm/test/MC/ARM/ldr-pseudo-darwin.s b/llvm/test/MC/ARM/ldr-pseudo-darwin.s new file mode 100644 index 00000000000..a77f6d5cb0e --- /dev/null +++ b/llvm/test/MC/ARM/ldr-pseudo-darwin.s @@ -0,0 +1,241 @@ +@ This test has a partner (ldr-pseudo.s) that contains matching +@ tests for the ldr-pseudo on linux targets. We need separate files +@ because the syntax for switching sections and temporary labels differs +@ between darwin and linux. Any tests added here should have a matching +@ test added there. + +@RUN: llvm-mc -triple armv7-apple-darwin %s | FileCheck %s +@RUN: llvm-mc -triple thumbv5-apple-darwin %s | FileCheck %s +@RUN: llvm-mc -triple thumbv7-apple-darwin %s | FileCheck %s + +@ +@ Check that large constants are converted to ldr from constant pool +@ +@ simple test +.section __TEXT,b,regular,pure_instructions +@ CHECK-LABEL: f3: +f3: + ldr r0, =0x10001 +@ CHECK: ldr r0, Ltmp0 + +@ loading multiple constants +.section __TEXT,c,regular,pure_instructions +@ CHECK-LABEL: f4: +f4: + ldr r0, =0x10002 +@ CHECK: ldr r0, Ltmp1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + ldr r0, =0x10003 +@ CHECK: ldr r0, Ltmp2 + adds r0, r0, #1 + adds r0, r0, #1 + +@ TODO: the same constants should have the same constant pool location +.section __TEXT,d,regular,pure_instructions +@ CHECK-LABEL: f5: +f5: + ldr r0, =0x10004 +@ CHECK: ldr r0, Ltmp3 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + ldr r0, =0x10004 +@ CHECK: ldr r0, Ltmp4 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + +@ a section defined in multiple pieces should be merged and use a single constant pool +.section __TEXT,e,regular,pure_instructions +@ CHECK-LABEL: f6: +f6: + ldr r0, =0x10006 +@ CHECK: ldr r0, Ltmp5 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + +.section __TEXT,f,regular,pure_instructions +@ CHECK-LABEL: f7: +f7: + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + +.section __TEXT,e,regular,pure_instructions +@ CHECK-LABEL: f8: +f8: + adds r0, r0, #1 + ldr r0, =0x10007 +@ CHECK: ldr r0, Ltmp6 + adds r0, r0, #1 + adds r0, r0, #1 + +@ +@ Check that symbols can be loaded using ldr pseudo +@ + +@ load an undefined symbol +.section __TEXT,g,regular,pure_instructions +@ CHECK-LABEL: f9: +f9: + ldr r0, =foo +@ CHECK: ldr r0, Ltmp7 + +@ load a symbol from another section +.section __TEXT,h,regular,pure_instructions +@ CHECK-LABEL: f10: +f10: + ldr r0, =f5 +@ CHECK: ldr r0, Ltmp8 + +@ load a symbol from the same section +.section __TEXT,i,regular,pure_instructions +@ CHECK-LABEL: f11: +f11: + ldr r0, =f12 +@ CHECK: ldr r0, Ltmp9 + +@ CHECK-LABEL: f12: +f12: + adds r0, r0, #1 + adds r0, r0, #1 + +.section __TEXT,j,regular,pure_instructions +@ mix of symbols and constants +@ CHECK-LABEL: f13: +f13: + adds r0, r0, #1 + adds r0, r0, #1 + ldr r0, =0x101 +@ CHECK: ldr r0, Ltmp10 + adds r0, r0, #1 + adds r0, r0, #1 + ldr r0, =bar +@ CHECK: ldr r0, Ltmp11 + adds r0, r0, #1 + adds r0, r0, #1 +@ +@ Check for correct usage in other contexts +@ + +@ usage in macro +.macro useit_in_a_macro + ldr r0, =0x10008 + ldr r0, =baz +.endm +.section __TEXT,k,regular,pure_instructions +@ CHECK-LABEL: f14: +f14: + useit_in_a_macro +@ CHECK: ldr r0, Ltmp12 +@ CHECK: ldr r0, Ltmp13 + +@ usage with expressions +.section __TEXT,l,regular,pure_instructions +@ CHECK-LABEL: f15: +f15: + ldr r0, =0x10001+8 +@ CHECK: ldr r0, Ltmp14 + adds r0, r0, #1 + ldr r0, =bar+4 +@ CHECK: ldr r0, Ltmp15 + adds r0, r0, #1 + +@ +@ Constant Pools +@ +@ CHECK: .section __TEXT,b,regular,pure_instructions +@ CHECK: .align 2 +@ CHECK: .data_region +@ CHECK-LABEL: Ltmp0: +@ CHECK: .long 65537 +@ CHECK: .end_data_region + +@ CHECK: .section __TEXT,c,regular,pure_instructions +@ CHECK: .align 2 +@ CHECK: .data_region +@ CHECK-LABEL: Ltmp1: +@ CHECK: .long 65538 +@ CHECK-LABEL: Ltmp2: +@ CHECK: .long 65539 +@ CHECK: .end_data_region + +@ CHECK: .section __TEXT,d,regular,pure_instructions +@ CHECK: .align 2 +@ CHECK: .data_region +@ CHECK-LABEL: Ltmp3: +@ CHECK: .long 65540 +@ CHECK-LABEL: Ltmp4: +@ CHECK: .long 65540 +@ CHECK: .end_data_region + +@ CHECK: .section __TEXT,e,regular,pure_instructions +@ CHECK: .align 2 +@ CHECK: .data_region +@ CHECK-LABEL: Ltmp5: +@ CHECK: .long 65542 +@ CHECK-LABEL: Ltmp6: +@ CHECK: .long 65543 +@ CHECK: .end_data_region + +@ Should not switch to section because it has no constant pool +@ CHECK-NOT: .section __TEXT,f,regular,pure_instructions + +@ CHECK: .section __TEXT,g,regular,pure_instructions +@ CHECK: .align 2 +@ CHECK: .data_region +@ CHECK-LABEL: Ltmp7: +@ CHECK: .long foo +@ CHECK: .end_data_region + +@ CHECK: .section __TEXT,h,regular,pure_instructions +@ CHECK: .align 2 +@ CHECK: .data_region +@ CHECK-LABEL: Ltmp8: +@ CHECK: .long f5 +@ CHECK: .end_data_region + +@ CHECK: .section __TEXT,i,regular,pure_instructions +@ CHECK: .align 2 +@ CHECK: .data_region +@ CHECK-LABEL: Ltmp9: +@ CHECK: .long f12 +@ CHECK: .end_data_region + +@ CHECK: .section __TEXT,j,regular,pure_instructions +@ CHECK: .align 2 +@ CHECK: .data_region +@ CHECK-LABEL: Ltmp10: +@ CHECK: .long 257 +@ CHECK-LABEL: Ltmp11: +@ CHECK: .long bar +@ CHECK: .end_data_region + +@ CHECK: .section __TEXT,k,regular,pure_instructions +@ CHECK: .align 2 +@ CHECK: .data_region +@ CHECK-LABEL: Ltmp12: +@ CHECK: .long 65544 +@ CHECK-LABEL: Ltmp13: +@ CHECK: .long baz +@ CHECK: .end_data_region + +@ CHECK: .section __TEXT,l,regular,pure_instructions +@ CHECK: .align 2 +@ CHECK: .data_region +@ CHECK-LABEL: Ltmp14: +@ CHECK: .long 65545 +@ CHECK-LABEL: Ltmp15: +@ CHECK: .long bar+4 +@ CHECK: .end_data_region diff --git a/llvm/test/MC/ARM/ldr-pseudo-obj-errors.s b/llvm/test/MC/ARM/ldr-pseudo-obj-errors.s new file mode 100644 index 00000000000..dce88f058f8 --- /dev/null +++ b/llvm/test/MC/ARM/ldr-pseudo-obj-errors.s @@ -0,0 +1,17 @@ +@RUN: not llvm-mc -triple=armv7-unknown-linux-gnueabi -filetype=obj %s -o %t1 2> %t2 +@RUN: cat %t2 | FileCheck %s +@RUN: not llvm-mc -triple=armv7-darwin-apple -filetype=obj %s -o %t1_darwin 2> %t2_darwin +@RUN: cat %t2_darwin | FileCheck %s + +@These tests look for errors that should be reported for invalid object layout +@with the ldr pseudo. They are tested separately from parse errors because they +@only trigger when the file has successfully parsed and the object file is about +@to be written out. + +.text +foo: + ldr r0, =0x101 + .space 8000 +@ CHECK: error: out of range pc-relative fixup value +@ CHECK: ldr r0, =0x101 +@ CHECK: ^ diff --git a/llvm/test/MC/ARM/ldr-pseudo-parse-errors.s b/llvm/test/MC/ARM/ldr-pseudo-parse-errors.s new file mode 100644 index 00000000000..2e6114d6fe0 --- /dev/null +++ b/llvm/test/MC/ARM/ldr-pseudo-parse-errors.s @@ -0,0 +1,10 @@ +@RUN: not llvm-mc -triple=armv7-unknown-linux-gnueabi < %s 2>&1 | FileCheck %s +@RUN: not llvm-mc -triple=armv7-apple-darwin < %s 2>&1 | FileCheck %s + +.text +bar: + mov r0, =0x101 +@ CHECK: error: unexpected token in operand +@ CHECK: mov r0, =0x101 +@ CHECK: ^ + diff --git a/llvm/test/MC/ARM/ldr-pseudo.s b/llvm/test/MC/ARM/ldr-pseudo.s new file mode 100644 index 00000000000..889cb8e7bcb --- /dev/null +++ b/llvm/test/MC/ARM/ldr-pseudo.s @@ -0,0 +1,221 @@ +@ This test has a partner (ldr-pseudo-darwin.s) that contains matching +@ tests for the ldr-pseudo on darwin targets. We need separate files +@ because the syntax for switching sections and temporary labels differs +@ between darwin and linux. Any tests added here should have a matching +@ test added there. + +@RUN: llvm-mc -triple armv7-unknown-linux-gnueabi %s | FileCheck %s +@RUN: llvm-mc -triple thumbv5-unknown-linux-gnueabi %s | FileCheck %s +@RUN: llvm-mc -triple thumbv7-unknown-linux-gnueabi %s | FileCheck %s + +@ +@ Check that large constants are converted to ldr from constant pool +@ +@ simple test +.section b,"ax",%progbits +@ CHECK-LABEL: f3: +f3: + ldr r0, =0x10001 +@ CHECK: ldr r0, .Ltmp0 + +@ loading multiple constants +.section c,"ax",%progbits +@ CHECK-LABEL: f4: +f4: + ldr r0, =0x10002 +@ CHECK: ldr r0, .Ltmp1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + ldr r0, =0x10003 +@ CHECK: ldr r0, .Ltmp2 + adds r0, r0, #1 + adds r0, r0, #1 + +@ TODO: the same constants should have the same constant pool location +.section d,"ax",%progbits +@ CHECK-LABEL: f5: +f5: + ldr r0, =0x10004 +@ CHECK: ldr r0, .Ltmp3 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + ldr r0, =0x10004 +@ CHECK: ldr r0, .Ltmp4 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + +@ a section defined in multiple pieces should be merged and use a single constant pool +.section e,"ax",%progbits +@ CHECK-LABEL: f6: +f6: + ldr r0, =0x10006 +@ CHECK: ldr r0, .Ltmp5 + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + +.section f, "ax", %progbits +@ CHECK-LABEL: f7: +f7: + adds r0, r0, #1 + adds r0, r0, #1 + adds r0, r0, #1 + +.section e, "ax", %progbits +@ CHECK-LABEL: f8: +f8: + adds r0, r0, #1 + ldr r0, =0x10007 +@ CHECK: ldr r0, .Ltmp6 + adds r0, r0, #1 + adds r0, r0, #1 + +@ +@ Check that symbols can be loaded using ldr pseudo +@ + +@ load an undefined symbol +.section g,"ax",%progbits +@ CHECK-LABEL: f9: +f9: + ldr r0, =foo +@ CHECK: ldr r0, .Ltmp7 + +@ load a symbol from another section +.section h,"ax",%progbits +@ CHECK-LABEL: f10: +f10: + ldr r0, =f5 +@ CHECK: ldr r0, .Ltmp8 + +@ load a symbol from the same section +.section i,"ax",%progbits +@ CHECK-LABEL: f11: +f11: + ldr r0, =f12 +@ CHECK: ldr r0, .Ltmp9 + +@ CHECK-LABEL: f12: +f12: + adds r0, r0, #1 + adds r0, r0, #1 + +.section j,"ax",%progbits +@ mix of symbols and constants +@ CHECK-LABEL: f13: +f13: + adds r0, r0, #1 + adds r0, r0, #1 + ldr r0, =0x101 +@ CHECK: ldr r0, .Ltmp10 + adds r0, r0, #1 + adds r0, r0, #1 + ldr r0, =bar +@ CHECK: ldr r0, .Ltmp11 + adds r0, r0, #1 + adds r0, r0, #1 +@ +@ Check for correct usage in other contexts +@ + +@ usage in macro +.macro useit_in_a_macro + ldr r0, =0x10008 + ldr r0, =baz +.endm +.section k,"ax",%progbits +@ CHECK-LABEL: f14: +f14: + useit_in_a_macro +@ CHECK: ldr r0, .Ltmp12 +@ CHECK: ldr r0, .Ltmp13 + +@ usage with expressions +.section l, "ax", %progbits +@ CHECK-LABEL: f15: +f15: + ldr r0, =0x10001+8 +@ CHECK: ldr r0, .Ltmp14 + adds r0, r0, #1 + ldr r0, =bar+4 +@ CHECK: ldr r0, .Ltmp15 + adds r0, r0, #1 + +@ +@ Constant Pools +@ +@ CHECK: .section b,"ax",%progbits +@ CHECK: .align 2 +@ CHECK-LABEL: .Ltmp0: +@ CHECK: .long 65537 + +@ CHECK: .section c,"ax",%progbits +@ CHECK: .align 2 +@ CHECK-LABEL: .Ltmp1: +@ CHECK: .long 65538 +@ CHECK-LABEL: .Ltmp2: +@ CHECK: .long 65539 + +@ CHECK: .section d,"ax",%progbits +@ CHECK: .align 2 +@ CHECK-LABEL: .Ltmp3: +@ CHECK: .long 65540 +@ CHECK-LABEL: .Ltmp4: +@ CHECK: .long 65540 + +@ CHECK: .section e,"ax",%progbits +@ CHECK: .align 2 +@ CHECK-LABEL: .Ltmp5: +@ CHECK: .long 65542 +@ CHECK-LABEL: .Ltmp6: +@ CHECK: .long 65543 + +@ Should not switch to section because it has no constant pool +@ CHECK-NOT: .section f,"ax",%progbits + +@ CHECK: .section g,"ax",%progbits +@ CHECK: .align 2 +@ CHECK-LABEL: .Ltmp7: +@ CHECK: .long foo + +@ CHECK: .section h,"ax",%progbits +@ CHECK: .align 2 +@ CHECK-LABEL: .Ltmp8: +@ CHECK: .long f5 + +@ CHECK: .section i,"ax",%progbits +@ CHECK: .align 2 +@ CHECK-LABEL: .Ltmp9: +@ CHECK: .long f12 + +@ CHECK: .section j,"ax",%progbits +@ CHECK: .align 2 +@ CHECK-LABEL: .Ltmp10: +@ CHECK: .long 257 +@ CHECK-LABEL: .Ltmp11: +@ CHECK: .long bar + +@ CHECK: .section k,"ax",%progbits +@ CHECK: .align 2 +@ CHECK-LABEL: .Ltmp12: +@ CHECK: .long 65544 +@ CHECK-LABEL: .Ltmp13: +@ CHECK: .long baz + +@ CHECK: .section l,"ax",%progbits +@ CHECK: .align 2 +@ CHECK-LABEL: .Ltmp14: +@ CHECK: .long 65545 +@ CHECK-LABEL: .Ltmp15: +@ CHECK: .long bar+4 |