This repository has been archived by the owner on Apr 23, 2020. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197708 91177308-0d34-0410-b5e6-96231b3b80d8
- Loading branch information
Showing
5 changed files
with
582 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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: ^ |
Oops, something went wrong.