Skip to content

Commit fd59209

Browse files
committed
ARM IAS: support .personalityindex
The .personalityindex directive is equivalent to the .personality directive with the ARM EABI personality with the specific index (0, 1, 2). Both of these directives indicate personality routines, so enhance the personality directive handling to take into account personalityindex. Bonus fix: flush the UnwindContext at the beginning of a new function.
1 parent 8665e83 commit fd59209

File tree

5 files changed

+248
-3
lines changed

5 files changed

+248
-3
lines changed

include/llvm/MC/MCStreamer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class ARMTargetStreamer : public MCTargetStreamer {
8282
virtual void emitFnEnd() = 0;
8383
virtual void emitCantUnwind() = 0;
8484
virtual void emitPersonality(const MCSymbol *Personality) = 0;
85+
virtual void emitPersonalityIndex(unsigned Index) = 0;
8586
virtual void emitHandlerData() = 0;
8687
virtual void emitSetFP(unsigned FpReg, unsigned SpReg,
8788
int64_t Offset = 0) = 0;

lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ class UnwindContext {
121121
Locs FnStartLocs;
122122
Locs CantUnwindLocs;
123123
Locs PersonalityLocs;
124+
Locs PersonalityIndexLocs;
124125
Locs HandlerDataLocs;
125126
int FPReg;
126127

@@ -130,12 +131,15 @@ class UnwindContext {
130131
bool hasFnStart() const { return !FnStartLocs.empty(); }
131132
bool cantUnwind() const { return !CantUnwindLocs.empty(); }
132133
bool hasHandlerData() const { return !HandlerDataLocs.empty(); }
133-
bool hasPersonality() const { return !PersonalityLocs.empty(); }
134+
bool hasPersonality() const {
135+
return !(PersonalityLocs.empty() && PersonalityIndexLocs.empty());
136+
}
134137

135138
void recordFnStart(SMLoc L) { FnStartLocs.push_back(L); }
136139
void recordCantUnwind(SMLoc L) { CantUnwindLocs.push_back(L); }
137140
void recordPersonality(SMLoc L) { PersonalityLocs.push_back(L); }
138141
void recordHandlerData(SMLoc L) { HandlerDataLocs.push_back(L); }
142+
void recordPersonalityIndex(SMLoc L) { PersonalityIndexLocs.push_back(L); }
139143

140144
void saveFPReg(int Reg) { FPReg = Reg; }
141145
int getFPReg() const { return FPReg; }
@@ -157,15 +161,26 @@ class UnwindContext {
157161
}
158162
void emitPersonalityLocNotes() const {
159163
for (Locs::const_iterator PI = PersonalityLocs.begin(),
160-
PE = PersonalityLocs.end(); PI != PE; ++PI)
161-
Parser.Note(*PI, ".personality was specified here");
164+
PE = PersonalityLocs.end(),
165+
PII = PersonalityIndexLocs.begin(),
166+
PIE = PersonalityIndexLocs.end();
167+
PI != PE || PII != PIE;) {
168+
if (PI != PE && (PII == PIE || PI->getPointer() < PII->getPointer()))
169+
Parser.Note(*PI++, ".personality was specified here");
170+
else if (PII != PIE && (PI == PE || PII->getPointer() < PI->getPointer()))
171+
Parser.Note(*PII++, ".personalityindex was specified here");
172+
else
173+
llvm_unreachable(".personality and .personalityindex cannot be "
174+
"at the same location");
175+
}
162176
}
163177

164178
void reset() {
165179
FnStartLocs = Locs();
166180
CantUnwindLocs = Locs();
167181
PersonalityLocs = Locs();
168182
HandlerDataLocs = Locs();
183+
PersonalityIndexLocs = Locs();
169184
FPReg = -1;
170185
}
171186
};
@@ -278,6 +293,7 @@ class ARMAsmParser : public MCTargetAsmParser {
278293
bool parseDirectiveInst(SMLoc L, char Suffix = '\0');
279294
bool parseDirectiveLtorg(SMLoc L);
280295
bool parseDirectiveEven(SMLoc L);
296+
bool parseDirectivePersonalityIndex(SMLoc L);
281297

282298
StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
283299
bool &CarrySetting, unsigned &ProcessorIMod,
@@ -8003,6 +8019,8 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
80038019
parseDirectiveLtorg(DirectiveID.getLoc());
80048020
else if (IDVal == ".even")
80058021
parseDirectiveEven(DirectiveID.getLoc());
8022+
else if (IDVal == ".personalityindex")
8023+
parseDirectivePersonalityIndex(DirectiveID.getLoc());
80068024
else
80078025
return true;
80088026
return false;
@@ -8397,6 +8415,9 @@ bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) {
83978415
return false;
83988416
}
83998417

8418+
// Reset the unwind directives parser state
8419+
UC.reset();
8420+
84008421
getTargetStreamer().emitFnStart();
84018422

84028423
UC.recordFnStart(L);
@@ -8447,6 +8468,8 @@ bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) {
84478468
/// parseDirectivePersonality
84488469
/// ::= .personality name
84498470
bool ARMAsmParser::parseDirectivePersonality(SMLoc L) {
8471+
bool HasPersonality = UC.hasPersonality();
8472+
84508473
UC.recordPersonality(L);
84518474

84528475
// Check the ordering of unwind directives
@@ -8464,6 +8487,12 @@ bool ARMAsmParser::parseDirectivePersonality(SMLoc L) {
84648487
UC.emitHandlerDataLocNotes();
84658488
return false;
84668489
}
8490+
if (HasPersonality) {
8491+
Parser.eatToEndOfStatement();
8492+
Error(L, "multiple personality directives");
8493+
UC.emitPersonalityLocNotes();
8494+
return false;
8495+
}
84678496

84688497
// Parse the name of the personality routine
84698498
if (Parser.getTok().isNot(AsmToken::Identifier)) {
@@ -8773,6 +8802,60 @@ bool ARMAsmParser::parseDirectiveEven(SMLoc L) {
87738802
return false;
87748803
}
87758804

8805+
/// parseDirectivePersonalityIndex
8806+
/// ::= .personalityindex index
8807+
bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) {
8808+
bool HasPersonality = UC.hasPersonality();
8809+
8810+
UC.recordPersonalityIndex(L);
8811+
8812+
if (!UC.isValid()) {
8813+
Parser.eatToEndOfStatement();
8814+
Error(L, ".fnstart must precede .personalityindex directive");
8815+
return false;
8816+
}
8817+
if (UC.cantUnwind()) {
8818+
Parser.eatToEndOfStatement();
8819+
Error(L, ".personalityindex cannot be used with .cantunwind");
8820+
UC.emitCantUnwindLocNotes();
8821+
return false;
8822+
}
8823+
if (UC.hasHandlerData()) {
8824+
Parser.eatToEndOfStatement();
8825+
Error(L, ".personalityindex must precede .handlerdata directive");
8826+
UC.emitHandlerDataLocNotes();
8827+
return false;
8828+
}
8829+
if (HasPersonality) {
8830+
Parser.eatToEndOfStatement();
8831+
Error(L, "multiple personality directives");
8832+
UC.emitPersonalityLocNotes();
8833+
return false;
8834+
}
8835+
8836+
const MCExpr *IndexExpression;
8837+
SMLoc IndexLoc = Parser.getTok().getLoc();
8838+
if (Parser.parseExpression(IndexExpression)) {
8839+
Parser.eatToEndOfStatement();
8840+
return false;
8841+
}
8842+
8843+
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(IndexExpression);
8844+
if (!CE) {
8845+
Parser.eatToEndOfStatement();
8846+
Error(IndexLoc, "index must be a constant number");
8847+
return false;
8848+
}
8849+
if (CE->getValue() < 0 || CE->getValue() >= 3) {
8850+
Parser.eatToEndOfStatement();
8851+
Error(IndexLoc, "bad personality routine index");
8852+
return false;
8853+
}
8854+
8855+
getTargetStreamer().emitPersonalityIndex(CE->getValue());
8856+
return false;
8857+
}
8858+
87768859
/// Force static initialization.
87778860
extern "C" void LLVMInitializeARMAsmParser() {
87788861
RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);

lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class ARMTargetAsmStreamer : public ARMTargetStreamer {
117117
virtual void emitFnEnd();
118118
virtual void emitCantUnwind();
119119
virtual void emitPersonality(const MCSymbol *Personality);
120+
virtual void emitPersonalityIndex(unsigned Index);
120121
virtual void emitHandlerData();
121122
virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0);
122123
virtual void emitPad(int64_t Offset);
@@ -148,6 +149,9 @@ void ARMTargetAsmStreamer::emitCantUnwind() { OS << "\t.cantunwind\n"; }
148149
void ARMTargetAsmStreamer::emitPersonality(const MCSymbol *Personality) {
149150
OS << "\t.personality " << Personality->getName() << '\n';
150151
}
152+
void ARMTargetAsmStreamer::emitPersonalityIndex(unsigned Index) {
153+
OS << "\t.personalityindex " << Index << '\n';
154+
}
151155
void ARMTargetAsmStreamer::emitHandlerData() { OS << "\t.handlerdata\n"; }
152156
void ARMTargetAsmStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
153157
int64_t Offset) {
@@ -354,6 +358,7 @@ class ARMTargetELFStreamer : public ARMTargetStreamer {
354358
virtual void emitFnEnd();
355359
virtual void emitCantUnwind();
356360
virtual void emitPersonality(const MCSymbol *Personality);
361+
virtual void emitPersonalityIndex(unsigned Index);
357362
virtual void emitHandlerData();
358363
virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0);
359364
virtual void emitPad(int64_t Offset);
@@ -412,6 +417,7 @@ class ARMELFStreamer : public MCELFStreamer {
412417
void emitFnEnd();
413418
void emitCantUnwind();
414419
void emitPersonality(const MCSymbol *Per);
420+
void emitPersonalityIndex(unsigned index);
415421
void emitHandlerData();
416422
void emitSetFP(unsigned NewFpReg, unsigned NewSpReg, int64_t Offset = 0);
417423
void emitPad(int64_t Offset);
@@ -611,6 +617,9 @@ void ARMTargetELFStreamer::emitCantUnwind() { getStreamer().emitCantUnwind(); }
611617
void ARMTargetELFStreamer::emitPersonality(const MCSymbol *Personality) {
612618
getStreamer().emitPersonality(Personality);
613619
}
620+
void ARMTargetELFStreamer::emitPersonalityIndex(unsigned Index) {
621+
getStreamer().emitPersonalityIndex(Index);
622+
}
614623
void ARMTargetELFStreamer::emitHandlerData() {
615624
getStreamer().emitHandlerData();
616625
}
@@ -1133,6 +1142,13 @@ void ARMELFStreamer::emitPersonality(const MCSymbol *Per) {
11331142
UnwindOpAsm.setPersonality(Per);
11341143
}
11351144

1145+
void ARMELFStreamer::emitPersonalityIndex(unsigned Index) {
1146+
assert(Index < NUM_PERSONALITY_INDEX && "invalid index");
1147+
std::string Name = GetAEABIUnwindPersonalityName(Index);
1148+
Personality = getContext().GetOrCreateSymbol(StringRef(Name));
1149+
UnwindOpAsm.setPersonality(Personality);
1150+
}
1151+
11361152
void ARMELFStreamer::emitSetFP(unsigned NewFPReg, unsigned NewSPReg,
11371153
int64_t Offset) {
11381154
assert((NewSPReg == ARM::SP || NewSPReg == FPReg) &&
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
@ RUN: not llvm-mc -triple armv7-eabi -filetype asm -o /dev/null %s 2>&1 \
2+
@ RUN: | FileCheck %s
3+
4+
.syntax unified
5+
.thumb
6+
7+
.global function
8+
.type function,%function
9+
.thumb_func
10+
function:
11+
.personalityindex 0
12+
13+
@ CHECK: error: .fnstart must precede .personalityindex directive
14+
@ CHECK: .personalityindex 0
15+
@ CHECK: ^
16+
17+
.global ununwindable
18+
.type ununwindable,%function
19+
.thumb_func
20+
ununwindable:
21+
.fnstart
22+
.cantunwind
23+
.personalityindex 0
24+
.fnend
25+
26+
@ CHECK: error: .personalityindex cannot be used with .cantunwind
27+
@ CHECK: .personalityindex 0
28+
@ CHECK: ^
29+
@ CHECK: note: .cantunwind was specified here
30+
@ CHECK: .cantunwind
31+
@ CHECK: ^
32+
33+
.global nodata
34+
.type nodata,%function
35+
.thumb_func
36+
nodata:
37+
.fnstart
38+
.handlerdata
39+
.personalityindex 0
40+
.fnend
41+
42+
@ CHECK: error: .personalityindex must precede .handlerdata directive
43+
@ CHECK: .personalityindex 0
44+
@ CHECK: ^
45+
@ CHECK: note: .handlerdata was specified here
46+
@ CHECK: .handlerdata
47+
@ CHECK: ^
48+
49+
.global multiple_personality
50+
.type multiple_personality,%function
51+
.thumb_func
52+
multiple_personality:
53+
.fnstart
54+
.personality __aeabi_personality_pr0
55+
.personalityindex 0
56+
.fnend
57+
58+
@ CHECK: error: multiple personality directives
59+
@ CHECK: .personalityindex 0
60+
@ CHECK: ^
61+
@ CHECK: note: .personality was specified here
62+
@ CHECK: .personality __aeabi_personality_pr0
63+
@ CHECK: ^
64+
@ CHECK: note: .personalityindex was specified here
65+
@ CHECK: .personalityindex 0
66+
@ CHECK: ^
67+
68+
.global invalid_expression
69+
.type invalid_expression,%function
70+
.thumb_func
71+
invalid_expression:
72+
.fnstart
73+
.personalityindex <expression>
74+
.fnend
75+
76+
@ CHECK: error: unknown token in expression
77+
@ CHECK: .personalityindex <expression>
78+
@ CHECK: ^
79+
80+
.global nonconstant_expression
81+
.type nonconstant_expression,%function
82+
.thumb_func
83+
nonconstant_expression:
84+
.fnstart
85+
.personalityindex nonconstant_expression
86+
.fnend
87+
88+
@ CHECK: error: index must be a constant number
89+
@ CHECK: .personalityindex nonconstant_expression
90+
@ CHECK: ^
91+
92+
.global bad_index
93+
.type bad_index,%function
94+
.thumb_func
95+
bad_index:
96+
.fnstart
97+
.personalityindex 42
98+
.fnend
99+
100+
@ CHECK: error: bad personality routine index
101+
@ CHECK: .personalityindex 42
102+
@ CHECK: ^
103+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
@ RUN: llvm-mc -triple armv7-eabi -filetype obj -o - %s | llvm-readobj -s -sd \
2+
@ RUN: | FileCheck %s
3+
4+
.syntax unified
5+
.thumb
6+
7+
.section .pr0
8+
9+
.global pr0
10+
.type pr0,%function
11+
.thumb_func
12+
pr0:
13+
.fnstart
14+
.personalityindex 0
15+
bx lr
16+
.fnend
17+
18+
@ CHECK: Section {
19+
@ CHECK: Name: .ARM.exidx.pr0
20+
@ CHECK: SectionData (
21+
@ CHECK: 0000: 00000000 B0B0B000
22+
@ CHECK: )
23+
@ CHECK: }
24+
25+
.section .pr1
26+
27+
.global pr1
28+
.type pr1,%function
29+
.thumb_func
30+
pr1:
31+
.fnstart
32+
.personalityindex 1
33+
bx lr
34+
.fnend
35+
36+
@ CHECK: Section {
37+
@ CHECK: Name: .ARM.exidx.pr1
38+
@ CHECK: SectionData (
39+
@ CHECK: 0000: 00000000 00000000
40+
@ CHECK: )
41+
@ CHECK: }
42+

0 commit comments

Comments
 (0)