Skip to content

Commit 13983f4

Browse files
committed
[DataLayout] Refactor parsing of "p" specification (llvm#104583)
Split off of llvm#104545 to reduce patch size. Similar to llvm#104546, this introduces `parseSize` and `parseAlignment`, which are improved versions of `getInt` tailored for specific needs. I'm not a GTest guru, so the tests are not ideal.
1 parent d867988 commit 13983f4

File tree

4 files changed

+308
-110
lines changed

4 files changed

+308
-110
lines changed

llvm/include/llvm/IR/DataLayout.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,21 @@ class DataLayout {
154154
/// Returns the default address space specification if not found.
155155
const PointerSpec &getPointerSpec(uint32_t AddrSpace) const;
156156

157-
/// Attempts to set the specification for pointer in the given address space.
158-
/// Returns an error description on failure.
159-
Error setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign,
160-
Align PrefAlign, uint32_t IndexBitWidth);
157+
/// Sets or updates the specification for pointer in the given address space.
158+
void setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign,
159+
Align PrefAlign, uint32_t IndexBitWidth);
161160

162161
/// Internal helper to get alignment for integer of given bitwidth.
163162
Align getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const;
164163

165164
/// Internal helper method that returns requested alignment for type.
166165
Align getAlignment(Type *Ty, bool abi_or_pref) const;
167166

167+
/// Attempts to parse a pointer specification ('p').
168+
Error parsePointerSpec(StringRef Spec);
169+
168170
/// Attempts to parse a single specification.
169-
Error parseSpecification(StringRef Specification);
171+
Error parseSpecification(StringRef Spec);
170172

171173
/// Attempts to parse a data layout string.
172174
Error parseLayoutString(StringRef LayoutString);

llvm/lib/IR/DataLayout.cpp

Lines changed: 108 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,54 @@ static Error parseAddrSpace(StringRef Str, unsigned &AddrSpace) {
288288
return Error::success();
289289
}
290290

291+
/// Attempts to parse a size component of a specification.
292+
static Error parseSize(StringRef Str, unsigned &BitWidth,
293+
StringRef Name = "size") {
294+
if (Str.empty())
295+
return createStringError(Name + " component cannot be empty");
296+
297+
if (!to_integer(Str, BitWidth, 10) || BitWidth == 0 || !isUInt<24>(BitWidth))
298+
return createStringError(Name + " must be a non-zero 24-bit integer");
299+
300+
return Error::success();
301+
}
302+
303+
/// Attempts to parse an alignment component of a specification.
304+
///
305+
/// On success, returns the value converted to byte amount in \p Alignment.
306+
/// If the value is zero and \p AllowZero is true, \p Alignment is set to one.
307+
///
308+
/// Return an error in a number of cases:
309+
/// - \p Str is empty or contains characters other than decimal digits;
310+
/// - the value is zero and \p AllowZero is false;
311+
/// - the value is too large;
312+
/// - the value is not a multiple of the byte width;
313+
/// - the value converted to byte amount is not not a power of two.
314+
static Error parseAlignment(StringRef Str, Align &Alignment, StringRef Name,
315+
bool AllowZero = false) {
316+
if (Str.empty())
317+
return createStringError(Name + " alignment component cannot be empty");
318+
319+
unsigned Value;
320+
if (!to_integer(Str, Value, 10) || !isUInt<16>(Value))
321+
return createStringError(Name + " alignment must be a 16-bit integer");
322+
323+
if (Value == 0) {
324+
if (!AllowZero)
325+
return createStringError(Name + " alignment must be non-zero");
326+
Alignment = Align(1);
327+
return Error::success();
328+
}
329+
330+
constexpr unsigned ByteWidth = 8;
331+
if (Value % ByteWidth || !isPowerOf2_32(Value / ByteWidth))
332+
return createStringError(
333+
Name + " alignment must be a power of two times the byte width");
334+
335+
Alignment = Align(Value / ByteWidth);
336+
return Error::success();
337+
}
338+
291339
/// Checked version of split, to ensure mandatory subparts.
292340
static Error split(StringRef Str, char Separator,
293341
std::pair<StringRef, StringRef> &Split) {
@@ -328,6 +376,56 @@ static Error getAddrSpace(StringRef R, unsigned &AddrSpace) {
328376
return Error::success();
329377
}
330378

379+
Error DataLayout::parsePointerSpec(StringRef Spec) {
380+
// p[<n>]:<size>:<abi>[:<pref>[:<idx>]]
381+
SmallVector<StringRef, 5> Components;
382+
assert(Spec.front() == 'p');
383+
Spec.drop_front().split(Components, ':');
384+
385+
if (Components.size() < 3 || Components.size() > 5)
386+
return createSpecFormatError("p[<n>]:<size>:<abi>[:<pref>[:<idx>]]");
387+
388+
// Address space. Optional, defaults to 0.
389+
unsigned AddrSpace = 0;
390+
if (!Components[0].empty())
391+
if (Error Err = parseAddrSpace(Components[0], AddrSpace))
392+
return Err;
393+
394+
// Size. Required, cannot be zero.
395+
unsigned BitWidth;
396+
if (Error Err = parseSize(Components[1], BitWidth, "pointer size"))
397+
return Err;
398+
399+
// ABI alignment. Required, cannot be zero.
400+
Align ABIAlign;
401+
if (Error Err = parseAlignment(Components[2], ABIAlign, "ABI"))
402+
return Err;
403+
404+
// Preferred alignment. Optional, defaults to the ABI alignment.
405+
// Cannot be zero.
406+
Align PrefAlign = ABIAlign;
407+
if (Components.size() > 3)
408+
if (Error Err = parseAlignment(Components[3], PrefAlign, "preferred"))
409+
return Err;
410+
411+
if (PrefAlign < ABIAlign)
412+
return createStringError(
413+
"preferred alignment cannot be less than the ABI alignment");
414+
415+
// Index size. Optional, defaults to pointer size. Cannot be zero.
416+
unsigned IndexBitWidth = BitWidth;
417+
if (Components.size() > 4)
418+
if (Error Err = parseSize(Components[4], IndexBitWidth, "index size"))
419+
return Err;
420+
421+
if (IndexBitWidth > BitWidth)
422+
return createStringError(
423+
"index size cannot be larger than the pointer size");
424+
425+
setPointerSpec(AddrSpace, BitWidth, ABIAlign, PrefAlign, IndexBitWidth);
426+
return Error::success();
427+
}
428+
331429
Error DataLayout::parseSpecification(StringRef Spec) {
332430
// The "ni" specifier is the only two-character specifier. Handle it first.
333431
if (Spec.starts_with("ni")) {
@@ -349,6 +447,13 @@ Error DataLayout::parseSpecification(StringRef Spec) {
349447
return Error::success();
350448
}
351449

450+
// The rest of the specifiers are single-character.
451+
assert(!Spec.empty() && "Empty specification is handled by the caller");
452+
char Specifier = Spec.front();
453+
454+
if (Specifier == 'p')
455+
return parsePointerSpec(Spec);
456+
352457
// Split at ':'.
353458
std::pair<StringRef, StringRef> Split;
354459
if (Error Err = ::split(Spec, ':', Split))
@@ -372,69 +477,6 @@ Error DataLayout::parseSpecification(StringRef Spec) {
372477
case 'e':
373478
BigEndian = false;
374479
break;
375-
case 'p': {
376-
// Address space.
377-
unsigned AddrSpace = 0;
378-
if (!Tok.empty())
379-
if (Error Err = getInt(Tok, AddrSpace))
380-
return Err;
381-
if (!isUInt<24>(AddrSpace))
382-
return reportError("Invalid address space, must be a 24-bit integer");
383-
384-
// Size.
385-
if (Rest.empty())
386-
return reportError(
387-
"Missing size specification for pointer in datalayout string");
388-
if (Error Err = ::split(Rest, ':', Split))
389-
return Err;
390-
unsigned PointerMemSize;
391-
if (Error Err = getInt(Tok, PointerMemSize))
392-
return Err;
393-
if (!PointerMemSize)
394-
return reportError("Invalid pointer size of 0 bytes");
395-
396-
// ABI alignment.
397-
if (Rest.empty())
398-
return reportError(
399-
"Missing alignment specification for pointer in datalayout string");
400-
if (Error Err = ::split(Rest, ':', Split))
401-
return Err;
402-
unsigned PointerABIAlign;
403-
if (Error Err = getIntInBytes(Tok, PointerABIAlign))
404-
return Err;
405-
if (!isPowerOf2_64(PointerABIAlign))
406-
return reportError("Pointer ABI alignment must be a power of 2");
407-
408-
// Size of index used in GEP for address calculation.
409-
// The parameter is optional. By default it is equal to size of pointer.
410-
unsigned IndexSize = PointerMemSize;
411-
412-
// Preferred alignment.
413-
unsigned PointerPrefAlign = PointerABIAlign;
414-
if (!Rest.empty()) {
415-
if (Error Err = ::split(Rest, ':', Split))
416-
return Err;
417-
if (Error Err = getIntInBytes(Tok, PointerPrefAlign))
418-
return Err;
419-
if (!isPowerOf2_64(PointerPrefAlign))
420-
return reportError("Pointer preferred alignment must be a power of 2");
421-
422-
// Now read the index. It is the second optional parameter here.
423-
if (!Rest.empty()) {
424-
if (Error Err = ::split(Rest, ':', Split))
425-
return Err;
426-
if (Error Err = getInt(Tok, IndexSize))
427-
return Err;
428-
if (!IndexSize)
429-
return reportError("Invalid index size of 0 bytes");
430-
}
431-
}
432-
if (Error Err = setPointerSpec(AddrSpace, PointerMemSize,
433-
assumeAligned(PointerABIAlign),
434-
assumeAligned(PointerPrefAlign), IndexSize))
435-
return Err;
436-
break;
437-
}
438480
case 'i':
439481
case 'v':
440482
case 'f':
@@ -680,15 +722,9 @@ DataLayout::getPointerSpec(uint32_t AddrSpace) const {
680722
return PointerSpecs[0];
681723
}
682724

683-
Error DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth,
684-
Align ABIAlign, Align PrefAlign,
685-
uint32_t IndexBitWidth) {
686-
if (PrefAlign < ABIAlign)
687-
return reportError(
688-
"Preferred alignment cannot be less than the ABI alignment");
689-
if (IndexBitWidth > BitWidth)
690-
return reportError("Index width cannot be larger than pointer width");
691-
725+
void DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth,
726+
Align ABIAlign, Align PrefAlign,
727+
uint32_t IndexBitWidth) {
692728
auto I = lower_bound(PointerSpecs, AddrSpace, LessPointerAddrSpace());
693729
if (I == PointerSpecs.end() || I->AddrSpace != AddrSpace) {
694730
PointerSpecs.insert(I, PointerSpec{AddrSpace, BitWidth, ABIAlign, PrefAlign,
@@ -699,7 +735,6 @@ Error DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth,
699735
I->PrefAlign = PrefAlign;
700736
I->IndexBitWidth = IndexBitWidth;
701737
}
702-
return Error::success();
703738
}
704739

705740
Align DataLayout::getIntegerAlignment(uint32_t BitWidth,

llvm/test/Assembler/getInt.ll

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)