llvm.org GIT mirror llvm / 0fa193b
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 David Peixotto 6 years ago
5 changed file(s) with 582 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
3535 #include "llvm/MC/MCRegisterInfo.h"
3636 #include "llvm/MC/MCStreamer.h"
3737 #include "llvm/MC/MCSubtargetInfo.h"
38 #include "llvm/MC/MCSymbol.h"
3839 #include "llvm/Support/ELF.h"
3940 #include "llvm/Support/MathExtras.h"
4041 #include "llvm/Support/SourceMgr.h"
4950
5051 enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
5152
53 // A class to keep track of assembler-generated constant pools that are use to
54 // implement the ldr-pseudo.
55 class ConstantPool {
56 typedef SmallVector, 4> EntryVecTy;
57 EntryVecTy Entries;
58
59 public:
60 // Initialize a new empty constant pool
61 ConstantPool() { }
62
63 // Add a new entry to the constant pool in the next slot.
64 // \param Value is the new entry to put in the constant pool.
65 //
66 // \returns a MCExpr that references the newly inserted value
67 const MCExpr *addEntry(const MCExpr *Value, MCContext &Context) {
68 MCSymbol *CPEntryLabel = Context.CreateTempSymbol();
69
70 Entries.push_back(std::make_pair(CPEntryLabel, Value));
71 return MCSymbolRefExpr::Create(CPEntryLabel, Context);
72 }
73
74 // Emit the contents of the constant pool using the provided streamer.
75 void emitEntries(MCStreamer &Streamer) const {
76 Streamer.EmitCodeAlignment(4); // align to 4-byte address
77 Streamer.EmitDataRegion(MCDR_DataRegion);
78 for (EntryVecTy::const_iterator I = Entries.begin(), E = Entries.end();
79 I != E; ++I) {
80 Streamer.EmitLabel(I->first);
81 Streamer.EmitValue(I->second, 4);
82 }
83 Streamer.EmitDataRegion(MCDR_DataRegionEnd);
84 }
85 };
86
87 // Map type used to keep track of per-Section constant pools used by the
88 // ldr-pseudo opcode. The map associates a section to its constant pool. The
89 // constant pool is a vector of (label, value) pairs. When the ldr
90 // pseudo is parsed we insert a new (label, value) pair into the constant pool
91 // for the current section and add MCSymbolRefExpr to the new label as
92 // an opcode to the ldr. After we have parsed all the user input we
93 // output the (label, value) pairs in each constant pool at the end of the
94 // section.
95 typedef std::map ConstantPoolMapTy;
96
5297 class ARMAsmParser : public MCTargetAsmParser {
5398 MCSubtargetInfo &STI;
5499 MCAsmParser &Parser;
55100 const MCInstrInfo &MII;
56101 const MCRegisterInfo *MRI;
102 ConstantPoolMapTy ConstantPools;
103
104 // Assembler created constant pools for ldr pseudo
105 ConstantPool *getConstantPool(const MCSection *Section) {
106 ConstantPoolMapTy::iterator CP = ConstantPools.find(Section);
107 if (CP == ConstantPools.end())
108 return 0;
109
110 return &CP->second;
111 }
112
113 ConstantPool &getOrCreateConstantPool(const MCSection *Section) {
114 return ConstantPools[Section];
115 }
57116
58117 ARMTargetStreamer &getTargetStreamer() {
59118 MCTargetStreamer &TS = getParser().getStreamer().getTargetStreamer();
295354 MCStreamer &Out, unsigned &ErrorInfo,
296355 bool MatchingInlineAsm);
297356 void onLabelParsed(MCSymbol *Symbol);
298
357 void finishParse();
299358 };
300359 } // end anonymous namespace
301360
46554714 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
46564715 return false;
46574716 }
4717 case AsmToken::Equal: {
4718 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
4719 return Error(Parser.getTok().getLoc(), "unexpected token in operand");
4720
4721 const MCSection *Section =
4722 getParser().getStreamer().getCurrentSection().first;
4723 assert(Section);
4724 Parser.Lex(); // Eat '='
4725 const MCExpr *SubExprVal;
4726 if (getParser().parseExpression(SubExprVal))
4727 return true;
4728 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4729
4730 const MCExpr *CPLoc =
4731 getOrCreateConstantPool(Section).addEntry(SubExprVal, getContext());
4732 Operands.push_back(ARMOperand::CreateImm(CPLoc, S, E));
4733 return false;
4734 }
46584735 }
46594736 }
46604737
83958472 }
83968473 return Match_InvalidOperand;
83978474 }
8475
8476 void ARMAsmParser::finishParse() {
8477 // Dump contents of assembler constant pools.
8478 MCStreamer &Streamer = getParser().getStreamer();
8479 for (ConstantPoolMapTy::iterator CPI = ConstantPools.begin(),
8480 CPE = ConstantPools.end();
8481 CPI != CPE; ++CPI) {
8482 const MCSection *Section = CPI->first;
8483 ConstantPool &CP = CPI->second;
8484
8485 // Dump assembler constant pools at the end of the section.
8486 Streamer.SwitchSection(Section);
8487 CP.emitEntries(Streamer);
8488 }
8489 }
0 @ This test has a partner (ldr-pseudo.s) that contains matching
1 @ tests for the ldr-pseudo on linux targets. We need separate files
2 @ because the syntax for switching sections and temporary labels differs
3 @ between darwin and linux. Any tests added here should have a matching
4 @ test added there.
5
6 @RUN: llvm-mc -triple armv7-apple-darwin %s | FileCheck %s
7 @RUN: llvm-mc -triple thumbv5-apple-darwin %s | FileCheck %s
8 @RUN: llvm-mc -triple thumbv7-apple-darwin %s | FileCheck %s
9
10 @
11 @ Check that large constants are converted to ldr from constant pool
12 @
13 @ simple test
14 .section __TEXT,b,regular,pure_instructions
15 @ CHECK-LABEL: f3:
16 f3:
17 ldr r0, =0x10001
18 @ CHECK: ldr r0, Ltmp0
19
20 @ loading multiple constants
21 .section __TEXT,c,regular,pure_instructions
22 @ CHECK-LABEL: f4:
23 f4:
24 ldr r0, =0x10002
25 @ CHECK: ldr r0, Ltmp1
26 adds r0, r0, #1
27 adds r0, r0, #1
28 adds r0, r0, #1
29 adds r0, r0, #1
30 ldr r0, =0x10003
31 @ CHECK: ldr r0, Ltmp2
32 adds r0, r0, #1
33 adds r0, r0, #1
34
35 @ TODO: the same constants should have the same constant pool location
36 .section __TEXT,d,regular,pure_instructions
37 @ CHECK-LABEL: f5:
38 f5:
39 ldr r0, =0x10004
40 @ CHECK: ldr r0, Ltmp3
41 adds r0, r0, #1
42 adds r0, r0, #1
43 adds r0, r0, #1
44 adds r0, r0, #1
45 adds r0, r0, #1
46 adds r0, r0, #1
47 adds r0, r0, #1
48 ldr r0, =0x10004
49 @ CHECK: ldr r0, Ltmp4
50 adds r0, r0, #1
51 adds r0, r0, #1
52 adds r0, r0, #1
53 adds r0, r0, #1
54 adds r0, r0, #1
55 adds r0, r0, #1
56
57 @ a section defined in multiple pieces should be merged and use a single constant pool
58 .section __TEXT,e,regular,pure_instructions
59 @ CHECK-LABEL: f6:
60 f6:
61 ldr r0, =0x10006
62 @ CHECK: ldr r0, Ltmp5
63 adds r0, r0, #1
64 adds r0, r0, #1
65 adds r0, r0, #1
66
67 .section __TEXT,f,regular,pure_instructions
68 @ CHECK-LABEL: f7:
69 f7:
70 adds r0, r0, #1
71 adds r0, r0, #1
72 adds r0, r0, #1
73
74 .section __TEXT,e,regular,pure_instructions
75 @ CHECK-LABEL: f8:
76 f8:
77 adds r0, r0, #1
78 ldr r0, =0x10007
79 @ CHECK: ldr r0, Ltmp6
80 adds r0, r0, #1
81 adds r0, r0, #1
82
83 @
84 @ Check that symbols can be loaded using ldr pseudo
85 @
86
87 @ load an undefined symbol
88 .section __TEXT,g,regular,pure_instructions
89 @ CHECK-LABEL: f9:
90 f9:
91 ldr r0, =foo
92 @ CHECK: ldr r0, Ltmp7
93
94 @ load a symbol from another section
95 .section __TEXT,h,regular,pure_instructions
96 @ CHECK-LABEL: f10:
97 f10:
98 ldr r0, =f5
99 @ CHECK: ldr r0, Ltmp8
100
101 @ load a symbol from the same section
102 .section __TEXT,i,regular,pure_instructions
103 @ CHECK-LABEL: f11:
104 f11:
105 ldr r0, =f12
106 @ CHECK: ldr r0, Ltmp9
107
108 @ CHECK-LABEL: f12:
109 f12:
110 adds r0, r0, #1
111 adds r0, r0, #1
112
113 .section __TEXT,j,regular,pure_instructions
114 @ mix of symbols and constants
115 @ CHECK-LABEL: f13:
116 f13:
117 adds r0, r0, #1
118 adds r0, r0, #1
119 ldr r0, =0x101
120 @ CHECK: ldr r0, Ltmp10
121 adds r0, r0, #1
122 adds r0, r0, #1
123 ldr r0, =bar
124 @ CHECK: ldr r0, Ltmp11
125 adds r0, r0, #1
126 adds r0, r0, #1
127 @
128 @ Check for correct usage in other contexts
129 @
130
131 @ usage in macro
132 .macro useit_in_a_macro
133 ldr r0, =0x10008
134 ldr r0, =baz
135 .endm
136 .section __TEXT,k,regular,pure_instructions
137 @ CHECK-LABEL: f14:
138 f14:
139 useit_in_a_macro
140 @ CHECK: ldr r0, Ltmp12
141 @ CHECK: ldr r0, Ltmp13
142
143 @ usage with expressions
144 .section __TEXT,l,regular,pure_instructions
145 @ CHECK-LABEL: f15:
146 f15:
147 ldr r0, =0x10001+8
148 @ CHECK: ldr r0, Ltmp14
149 adds r0, r0, #1
150 ldr r0, =bar+4
151 @ CHECK: ldr r0, Ltmp15
152 adds r0, r0, #1
153
154 @
155 @ Constant Pools
156 @
157 @ CHECK: .section __TEXT,b,regular,pure_instructions
158 @ CHECK: .align 2
159 @ CHECK: .data_region
160 @ CHECK-LABEL: Ltmp0:
161 @ CHECK: .long 65537
162 @ CHECK: .end_data_region
163
164 @ CHECK: .section __TEXT,c,regular,pure_instructions
165 @ CHECK: .align 2
166 @ CHECK: .data_region
167 @ CHECK-LABEL: Ltmp1:
168 @ CHECK: .long 65538
169 @ CHECK-LABEL: Ltmp2:
170 @ CHECK: .long 65539
171 @ CHECK: .end_data_region
172
173 @ CHECK: .section __TEXT,d,regular,pure_instructions
174 @ CHECK: .align 2
175 @ CHECK: .data_region
176 @ CHECK-LABEL: Ltmp3:
177 @ CHECK: .long 65540
178 @ CHECK-LABEL: Ltmp4:
179 @ CHECK: .long 65540
180 @ CHECK: .end_data_region
181
182 @ CHECK: .section __TEXT,e,regular,pure_instructions
183 @ CHECK: .align 2
184 @ CHECK: .data_region
185 @ CHECK-LABEL: Ltmp5:
186 @ CHECK: .long 65542
187 @ CHECK-LABEL: Ltmp6:
188 @ CHECK: .long 65543
189 @ CHECK: .end_data_region
190
191 @ Should not switch to section because it has no constant pool
192 @ CHECK-NOT: .section __TEXT,f,regular,pure_instructions
193
194 @ CHECK: .section __TEXT,g,regular,pure_instructions
195 @ CHECK: .align 2
196 @ CHECK: .data_region
197 @ CHECK-LABEL: Ltmp7:
198 @ CHECK: .long foo
199 @ CHECK: .end_data_region
200
201 @ CHECK: .section __TEXT,h,regular,pure_instructions
202 @ CHECK: .align 2
203 @ CHECK: .data_region
204 @ CHECK-LABEL: Ltmp8:
205 @ CHECK: .long f5
206 @ CHECK: .end_data_region
207
208 @ CHECK: .section __TEXT,i,regular,pure_instructions
209 @ CHECK: .align 2
210 @ CHECK: .data_region
211 @ CHECK-LABEL: Ltmp9:
212 @ CHECK: .long f12
213 @ CHECK: .end_data_region
214
215 @ CHECK: .section __TEXT,j,regular,pure_instructions
216 @ CHECK: .align 2
217 @ CHECK: .data_region
218 @ CHECK-LABEL: Ltmp10:
219 @ CHECK: .long 257
220 @ CHECK-LABEL: Ltmp11:
221 @ CHECK: .long bar
222 @ CHECK: .end_data_region
223
224 @ CHECK: .section __TEXT,k,regular,pure_instructions
225 @ CHECK: .align 2
226 @ CHECK: .data_region
227 @ CHECK-LABEL: Ltmp12:
228 @ CHECK: .long 65544
229 @ CHECK-LABEL: Ltmp13:
230 @ CHECK: .long baz
231 @ CHECK: .end_data_region
232
233 @ CHECK: .section __TEXT,l,regular,pure_instructions
234 @ CHECK: .align 2
235 @ CHECK: .data_region
236 @ CHECK-LABEL: Ltmp14:
237 @ CHECK: .long 65545
238 @ CHECK-LABEL: Ltmp15:
239 @ CHECK: .long bar+4
240 @ CHECK: .end_data_region
0 @RUN: not llvm-mc -triple=armv7-unknown-linux-gnueabi -filetype=obj %s -o %t1 2> %t2
1 @RUN: cat %t2 | FileCheck %s
2 @RUN: not llvm-mc -triple=armv7-darwin-apple -filetype=obj %s -o %t1_darwin 2> %t2_darwin
3 @RUN: cat %t2_darwin | FileCheck %s
4
5 @These tests look for errors that should be reported for invalid object layout
6 @with the ldr pseudo. They are tested separately from parse errors because they
7 @only trigger when the file has successfully parsed and the object file is about
8 @to be written out.
9
10 .text
11 foo:
12 ldr r0, =0x101
13 .space 8000
14 @ CHECK: error: out of range pc-relative fixup value
15 @ CHECK: ldr r0, =0x101
16 @ CHECK: ^
0 @RUN: not llvm-mc -triple=armv7-unknown-linux-gnueabi < %s 2>&1 | FileCheck %s
1 @RUN: not llvm-mc -triple=armv7-apple-darwin < %s 2>&1 | FileCheck %s
2
3 .text
4 bar:
5 mov r0, =0x101
6 @ CHECK: error: unexpected token in operand
7 @ CHECK: mov r0, =0x101
8 @ CHECK: ^
9
0 @ This test has a partner (ldr-pseudo-darwin.s) that contains matching
1 @ tests for the ldr-pseudo on darwin targets. We need separate files
2 @ because the syntax for switching sections and temporary labels differs
3 @ between darwin and linux. Any tests added here should have a matching
4 @ test added there.
5
6 @RUN: llvm-mc -triple armv7-unknown-linux-gnueabi %s | FileCheck %s
7 @RUN: llvm-mc -triple thumbv5-unknown-linux-gnueabi %s | FileCheck %s
8 @RUN: llvm-mc -triple thumbv7-unknown-linux-gnueabi %s | FileCheck %s
9
10 @
11 @ Check that large constants are converted to ldr from constant pool
12 @
13 @ simple test
14 .section b,"ax",%progbits
15 @ CHECK-LABEL: f3:
16 f3:
17 ldr r0, =0x10001
18 @ CHECK: ldr r0, .Ltmp0
19
20 @ loading multiple constants
21 .section c,"ax",%progbits
22 @ CHECK-LABEL: f4:
23 f4:
24 ldr r0, =0x10002
25 @ CHECK: ldr r0, .Ltmp1
26 adds r0, r0, #1
27 adds r0, r0, #1
28 adds r0, r0, #1
29 adds r0, r0, #1
30 ldr r0, =0x10003
31 @ CHECK: ldr r0, .Ltmp2
32 adds r0, r0, #1
33 adds r0, r0, #1
34
35 @ TODO: the same constants should have the same constant pool location
36 .section d,"ax",%progbits
37 @ CHECK-LABEL: f5:
38 f5:
39 ldr r0, =0x10004
40 @ CHECK: ldr r0, .Ltmp3
41 adds r0, r0, #1
42 adds r0, r0, #1
43 adds r0, r0, #1
44 adds r0, r0, #1
45 adds r0, r0, #1
46 adds r0, r0, #1
47 adds r0, r0, #1
48 ldr r0, =0x10004
49 @ CHECK: ldr r0, .Ltmp4
50 adds r0, r0, #1
51 adds r0, r0, #1
52 adds r0, r0, #1
53 adds r0, r0, #1
54 adds r0, r0, #1
55 adds r0, r0, #1
56
57 @ a section defined in multiple pieces should be merged and use a single constant pool
58 .section e,"ax",%progbits
59 @ CHECK-LABEL: f6:
60 f6:
61 ldr r0, =0x10006
62 @ CHECK: ldr r0, .Ltmp5
63 adds r0, r0, #1
64 adds r0, r0, #1
65 adds r0, r0, #1
66
67 .section f, "ax", %progbits
68 @ CHECK-LABEL: f7:
69 f7:
70 adds r0, r0, #1
71 adds r0, r0, #1
72 adds r0, r0, #1
73
74 .section e, "ax", %progbits
75 @ CHECK-LABEL: f8:
76 f8:
77 adds r0, r0, #1
78 ldr r0, =0x10007
79 @ CHECK: ldr r0, .Ltmp6
80 adds r0, r0, #1
81 adds r0, r0, #1
82
83 @
84 @ Check that symbols can be loaded using ldr pseudo
85 @
86
87 @ load an undefined symbol
88 .section g,"ax",%progbits
89 @ CHECK-LABEL: f9:
90 f9:
91 ldr r0, =foo
92 @ CHECK: ldr r0, .Ltmp7
93
94 @ load a symbol from another section
95 .section h,"ax",%progbits
96 @ CHECK-LABEL: f10:
97 f10:
98 ldr r0, =f5
99 @ CHECK: ldr r0, .Ltmp8
100
101 @ load a symbol from the same section
102 .section i,"ax",%progbits
103 @ CHECK-LABEL: f11:
104 f11:
105 ldr r0, =f12
106 @ CHECK: ldr r0, .Ltmp9
107
108 @ CHECK-LABEL: f12:
109 f12:
110 adds r0, r0, #1
111 adds r0, r0, #1
112
113 .section j,"ax",%progbits
114 @ mix of symbols and constants
115 @ CHECK-LABEL: f13:
116 f13:
117 adds r0, r0, #1
118 adds r0, r0, #1
119 ldr r0, =0x101
120 @ CHECK: ldr r0, .Ltmp10
121 adds r0, r0, #1
122 adds r0, r0, #1
123 ldr r0, =bar
124 @ CHECK: ldr r0, .Ltmp11
125 adds r0, r0, #1
126 adds r0, r0, #1
127 @
128 @ Check for correct usage in other contexts
129 @
130
131 @ usage in macro
132 .macro useit_in_a_macro
133 ldr r0, =0x10008
134 ldr r0, =baz
135 .endm
136 .section k,"ax",%progbits
137 @ CHECK-LABEL: f14:
138 f14:
139 useit_in_a_macro
140 @ CHECK: ldr r0, .Ltmp12
141 @ CHECK: ldr r0, .Ltmp13
142
143 @ usage with expressions
144 .section l, "ax", %progbits
145 @ CHECK-LABEL: f15:
146 f15:
147 ldr r0, =0x10001+8
148 @ CHECK: ldr r0, .Ltmp14
149 adds r0, r0, #1
150 ldr r0, =bar+4
151 @ CHECK: ldr r0, .Ltmp15
152 adds r0, r0, #1
153
154 @
155 @ Constant Pools
156 @
157 @ CHECK: .section b,"ax",%progbits
158 @ CHECK: .align 2
159 @ CHECK-LABEL: .Ltmp0:
160 @ CHECK: .long 65537
161
162 @ CHECK: .section c,"ax",%progbits
163 @ CHECK: .align 2
164 @ CHECK-LABEL: .Ltmp1:
165 @ CHECK: .long 65538
166 @ CHECK-LABEL: .Ltmp2:
167 @ CHECK: .long 65539
168
169 @ CHECK: .section d,"ax",%progbits
170 @ CHECK: .align 2
171 @ CHECK-LABEL: .Ltmp3:
172 @ CHECK: .long 65540
173 @ CHECK-LABEL: .Ltmp4:
174 @ CHECK: .long 65540
175
176 @ CHECK: .section e,"ax",%progbits
177 @ CHECK: .align 2
178 @ CHECK-LABEL: .Ltmp5:
179 @ CHECK: .long 65542
180 @ CHECK-LABEL: .Ltmp6:
181 @ CHECK: .long 65543
182
183 @ Should not switch to section because it has no constant pool
184 @ CHECK-NOT: .section f,"ax",%progbits
185
186 @ CHECK: .section g,"ax",%progbits
187 @ CHECK: .align 2
188 @ CHECK-LABEL: .Ltmp7:
189 @ CHECK: .long foo
190
191 @ CHECK: .section h,"ax",%progbits
192 @ CHECK: .align 2
193 @ CHECK-LABEL: .Ltmp8:
194 @ CHECK: .long f5
195
196 @ CHECK: .section i,"ax",%progbits
197 @ CHECK: .align 2
198 @ CHECK-LABEL: .Ltmp9:
199 @ CHECK: .long f12
200
201 @ CHECK: .section j,"ax",%progbits
202 @ CHECK: .align 2
203 @ CHECK-LABEL: .Ltmp10:
204 @ CHECK: .long 257
205 @ CHECK-LABEL: .Ltmp11:
206 @ CHECK: .long bar
207
208 @ CHECK: .section k,"ax",%progbits
209 @ CHECK: .align 2
210 @ CHECK-LABEL: .Ltmp12:
211 @ CHECK: .long 65544
212 @ CHECK-LABEL: .Ltmp13:
213 @ CHECK: .long baz
214
215 @ CHECK: .section l,"ax",%progbits
216 @ CHECK: .align 2
217 @ CHECK-LABEL: .Ltmp14:
218 @ CHECK: .long 65545
219 @ CHECK-LABEL: .Ltmp15:
220 @ CHECK: .long bar+4