Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(828)

Side by Side Diff: src/IceGlobalContext.cpp

Issue 385273002: Subzero: Deal with substitutions in the primitive remangler. (Closed) Base URL: https://gerrit.chromium.org/gerrit/p/native_client/pnacl-subzero.git@master
Patch Set: Test that non-C++ symbols don't have substitutions updated Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceGlobalContext.cpp - Global context defs ---*- C++ -*-===// 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs ---*- C++ -*-===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file defines aspects of the compilation that persist across 10 // This file defines aspects of the compilation that persist across
11 // multiple functions. 11 // multiple functions.
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #include <ctype.h> // isdigit() 15 #include <ctype.h> // isdigit(), isupper()
16 16
17 #include "IceDefs.h" 17 #include "IceDefs.h"
18 #include "IceTypes.h" 18 #include "IceTypes.h"
19 #include "IceCfg.h" 19 #include "IceCfg.h"
20 #include "IceGlobalContext.h" 20 #include "IceGlobalContext.h"
21 #include "IceOperand.h" 21 #include "IceOperand.h"
22 #include "IceTargetLowering.h" 22 #include "IceTargetLowering.h"
23 23
24 namespace Ice { 24 namespace Ice {
25 25
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 }; 113 };
114 114
115 GlobalContext::GlobalContext(llvm::raw_ostream *OsDump, 115 GlobalContext::GlobalContext(llvm::raw_ostream *OsDump,
116 llvm::raw_ostream *OsEmit, VerboseMask Mask, 116 llvm::raw_ostream *OsEmit, VerboseMask Mask,
117 TargetArch Arch, OptLevel Opt, 117 TargetArch Arch, OptLevel Opt,
118 IceString TestPrefix) 118 IceString TestPrefix)
119 : StrDump(OsDump), StrEmit(OsEmit), VMask(Mask), 119 : StrDump(OsDump), StrEmit(OsEmit), VMask(Mask),
120 ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt), 120 ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt),
121 TestPrefix(TestPrefix), HasEmittedFirstMethod(false) {} 121 TestPrefix(TestPrefix), HasEmittedFirstMethod(false) {}
122 122
123 // Scan a string for S[0-9A-Z]*_ patterns and replace them with
124 // S<num>_ where <num> is the next base-36 value. If a type name
125 // legitimately contains that pattern, then the substitution will be
126 // made in error and most likely the link will fail. In this case,
127 // the test classes can be rewritten not to use that pattern, which is
128 // much simpler and more reliable than implementing a full demangling
129 // parser. Another substitution-in-error may occur if a type
130 // identifier ends with the pattern S[0-9A-Z]*, because an immediately
131 // following substitution string like "S1_" or "PS1_" may be combined
132 // with the previous type.
133 void GlobalContext::incrementSubstitutions(ManglerVector &OldName) const {
134 // Provide extra space in case the length of <num> increases.
135 ManglerVector NewName(OldName.size() * 2);
136 size_t OldPos = 0;
137 size_t NewPos = 0;
138 size_t OldLen = OldName.size();
139 for (; OldPos < OldLen; ++OldPos, ++NewPos) {
140 if (OldName[OldPos] == '\0')
141 break;
142 if (OldName[OldPos] == 'S') {
143 // Search forward until we find _ or invalid character (including \0).
144 bool AllZs = true;
145 bool Valid = true;
146 bool Found = false;
147 size_t Last;
148 for (Last = OldPos + 1; Last < OldLen && Valid; ++Last) {
jvoung (off chromium) 2014/07/11 20:40:08 There's an explicit break; when Valid is set to fa
Jim Stichnoth 2014/07/11 21:05:11 Done. BTW, it would also be possible to remove th
149 char Ch = OldName[Last];
150 if (Ch == '_') {
151 Found = true;
152 break;
153 } else if (std::isdigit(Ch) || std::isupper(Ch)) {
jvoung (off chromium) 2014/07/11 20:40:08 Should this explicitly pass as parameter the "C" l
Jim Stichnoth 2014/07/11 21:05:12 Done.
154 if (Ch != 'Z')
155 AllZs = false;
156 } else {
157 // Invalid character, stop searching.
158 Valid = false;
159 break;
160 }
161 }
162 if (Found) {
163 NewName[NewPos++] = OldName[OldPos++]; // 'S'
164 size_t Length = Last - OldPos;
165 // NewPos and OldPos point just past the 'S'.
166 assert(NewName[NewPos - 1] == 'S');
167 assert(OldName[OldPos - 1] == 'S');
168 assert(OldName[OldPos + Length] == '_');
169 if (AllZs) {
170 // Replace N 'Z' characters with N+1 '0' characters.
jvoung (off chromium) 2014/07/11 20:40:08 This case also handles the "S_" ?
Jim Stichnoth 2014/07/11 21:05:11 Yes. Added a comment to clarify.
171 for (size_t i = 0; i < Length + 1; ++i) {
172 NewName[NewPos++] = '0';
173 }
174 } else {
175 // Iterate right-to-left and increment the base-36 number.
176 bool Carry = true;
177 for (size_t i = 0; i < Length; ++i) {
178 size_t Offset = Length - 1 - i;
179 char Ch = OldName[OldPos + Offset];
180 if (Carry) {
181 Carry = false;
182 switch (Ch) {
183 case '9':
184 Ch = 'A';
185 break;
186 case 'Z':
187 Ch = '0';
188 Carry = true;
189 break;
190 default:
191 ++Ch;
192 break;
193 }
194 }
195 NewName[NewPos + Offset] = Ch;
196 }
197 NewPos += Length;
198 }
199 OldPos = Last;
200 // Fall through and let the '_' be copied across.
201 }
202 }
203 NewName[NewPos] = OldName[OldPos];
204 }
205 assert(NewName[NewPos] == '\0');
206 OldName = NewName;
207 }
208
123 // In this context, name mangling means to rewrite a symbol using a 209 // In this context, name mangling means to rewrite a symbol using a
124 // given prefix. For a C++ symbol, nest the original symbol inside 210 // given prefix. For a C++ symbol, nest the original symbol inside
125 // the "prefix" namespace. For other symbols, just prepend the 211 // the "prefix" namespace. For other symbols, just prepend the
126 // prefix. 212 // prefix.
127 IceString GlobalContext::mangleName(const IceString &Name) const { 213 IceString GlobalContext::mangleName(const IceString &Name) const {
128 // An already-nested name like foo::bar() gets pushed down one 214 // An already-nested name like foo::bar() gets pushed down one
129 // level, making it equivalent to Prefix::foo::bar(). 215 // level, making it equivalent to Prefix::foo::bar().
130 // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz 216 // _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
131 // A non-nested but mangled name like bar() gets nested, making it 217 // A non-nested but mangled name like bar() gets nested, making it
132 // equivalent to Prefix::bar(). 218 // equivalent to Prefix::bar().
133 // _Z3barxyz ==> ZN6Prefix3barExyz 219 // _Z3barxyz ==> ZN6Prefix3barExyz
134 // An unmangled, extern "C" style name, gets a simple prefix: 220 // An unmangled, extern "C" style name, gets a simple prefix:
135 // bar ==> Prefixbar 221 // bar ==> Prefixbar
136 if (getTestPrefix().empty()) 222 if (getTestPrefix().empty())
137 return Name; 223 return Name;
138 224
139 unsigned PrefixLength = getTestPrefix().length(); 225 unsigned PrefixLength = getTestPrefix().length();
140 llvm::SmallVector<char, 32> NameBase(1 + Name.length()); 226 ManglerVector NameBase(1 + Name.length());
141 const size_t BufLen = 30 + Name.length() + PrefixLength; 227 const size_t BufLen = 30 + Name.length() + PrefixLength;
142 llvm::SmallVector<char, 32> NewName(BufLen); 228 ManglerVector NewName(BufLen);
143 uint32_t BaseLength = 0; // using uint32_t due to sscanf format string 229 uint32_t BaseLength = 0; // using uint32_t due to sscanf format string
144 230
145 int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data()); 231 int ItemsParsed = sscanf(Name.c_str(), "_ZN%s", NameBase.data());
146 if (ItemsParsed == 1) { 232 if (ItemsParsed == 1) {
147 // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz 233 // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
148 // (splice in "6Prefix") ^^^^^^^ 234 // (splice in "6Prefix") ^^^^^^^
149 snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength, 235 snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength,
150 getTestPrefix().c_str(), NameBase.data()); 236 getTestPrefix().c_str(), NameBase.data());
151 // We ignore the snprintf return value (here and below). If we 237 // We ignore the snprintf return value (here and below). If we
152 // somehow miscalculated the output buffer length, the output will 238 // somehow miscalculated the output buffer length, the output will
153 // be truncated, but it will be truncated consistently for all 239 // be truncated, but it will be truncated consistently for all
154 // mangleName() calls on the same input string. 240 // mangleName() calls on the same input string.
241 incrementSubstitutions(NewName);
155 return NewName.data(); 242 return NewName.data();
156 } 243 }
157 244
158 // Artificially limit BaseLength to 9 digits (less than 1 billion) 245 // Artificially limit BaseLength to 9 digits (less than 1 billion)
159 // because sscanf behavior is undefined on integer overflow. If 246 // because sscanf behavior is undefined on integer overflow. If
160 // there are more than 9 digits (which we test by looking at the 247 // there are more than 9 digits (which we test by looking at the
161 // beginning of NameBase), then we consider this a failure to parse 248 // beginning of NameBase), then we consider this a failure to parse
162 // a namespace mangling, and fall back to the simple prefixing. 249 // a namespace mangling, and fall back to the simple prefixing.
163 ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data()); 250 ItemsParsed = sscanf(Name.c_str(), "_Z%9u%s", &BaseLength, NameBase.data());
164 if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) && 251 if (ItemsParsed == 2 && BaseLength <= strlen(NameBase.data()) &&
165 !isdigit(NameBase[0])) { 252 !isdigit(NameBase[0])) {
166 // Transform _Z3barxyz ==> _ZN6Prefix3barExyz 253 // Transform _Z3barxyz ==> _ZN6Prefix3barExyz
167 // ^^^^^^^^ ^ 254 // ^^^^^^^^ ^
168 // (splice in "N6Prefix", and insert "E" after "3bar") 255 // (splice in "N6Prefix", and insert "E" after "3bar")
169 // But an "I" after the identifier indicates a template argument 256 // But an "I" after the identifier indicates a template argument
170 // list terminated with "E"; insert the new "E" before/after the 257 // list terminated with "E"; insert the new "E" before/after the
171 // old "E". E.g.: 258 // old "E". E.g.:
172 // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz 259 // Transform _Z3barIabcExyz ==> _ZN6Prefix3barIabcEExyz
173 // ^^^^^^^^ ^ 260 // ^^^^^^^^ ^
174 // (splice in "N6Prefix", and insert "E" after "3barIabcE") 261 // (splice in "N6Prefix", and insert "E" after "3barIabcE")
175 llvm::SmallVector<char, 32> OrigName(Name.length()); 262 ManglerVector OrigName(Name.length());
176 llvm::SmallVector<char, 32> OrigSuffix(Name.length()); 263 ManglerVector OrigSuffix(Name.length());
177 uint32_t ActualBaseLength = BaseLength; 264 uint32_t ActualBaseLength = BaseLength;
178 if (NameBase[ActualBaseLength] == 'I') { 265 if (NameBase[ActualBaseLength] == 'I') {
179 ++ActualBaseLength; 266 ++ActualBaseLength;
180 while (NameBase[ActualBaseLength] != 'E' && 267 while (NameBase[ActualBaseLength] != 'E' &&
181 NameBase[ActualBaseLength] != '\0') 268 NameBase[ActualBaseLength] != '\0')
182 ++ActualBaseLength; 269 ++ActualBaseLength;
183 } 270 }
184 strncpy(OrigName.data(), NameBase.data(), ActualBaseLength); 271 strncpy(OrigName.data(), NameBase.data(), ActualBaseLength);
185 OrigName[ActualBaseLength] = '\0'; 272 OrigName[ActualBaseLength] = '\0';
186 strcpy(OrigSuffix.data(), NameBase.data() + ActualBaseLength); 273 strcpy(OrigSuffix.data(), NameBase.data() + ActualBaseLength);
187 snprintf(NewName.data(), BufLen, "_ZN%u%s%u%sE%s", PrefixLength, 274 snprintf(NewName.data(), BufLen, "_ZN%u%s%u%sE%s", PrefixLength,
188 getTestPrefix().c_str(), BaseLength, OrigName.data(), 275 getTestPrefix().c_str(), BaseLength, OrigName.data(),
189 OrigSuffix.data()); 276 OrigSuffix.data());
277 incrementSubstitutions(NewName);
190 return NewName.data(); 278 return NewName.data();
191 } 279 }
192 280
193 // Transform bar ==> Prefixbar 281 // Transform bar ==> Prefixbar
194 // ^^^^^^ 282 // ^^^^^^
195 return getTestPrefix() + Name; 283 return getTestPrefix() + Name;
196 } 284 }
197 285
198 GlobalContext::~GlobalContext() {} 286 GlobalContext::~GlobalContext() {}
199 287
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 374
287 void Timer::printElapsedUs(GlobalContext *Ctx, const IceString &Tag) const { 375 void Timer::printElapsedUs(GlobalContext *Ctx, const IceString &Tag) const {
288 if (Ctx->isVerbose(IceV_Timing)) { 376 if (Ctx->isVerbose(IceV_Timing)) {
289 // Prefixing with '#' allows timing strings to be included 377 // Prefixing with '#' allows timing strings to be included
290 // without error in textual assembly output. 378 // without error in textual assembly output.
291 Ctx->getStrDump() << "# " << getElapsedUs() << " usec " << Tag << "\n"; 379 Ctx->getStrDump() << "# " << getElapsedUs() << " usec " << Tag << "\n";
292 } 380 }
293 } 381 }
294 382
295 } // end of namespace Ice 383 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698