Skip to content

Commit ee2d2aa

Browse files
committed
[DataLayout] Refactor parseSpecification
1 parent 3188e9b commit ee2d2aa

File tree

7 files changed

+185
-147
lines changed

7 files changed

+185
-147
lines changed

llvm/lib/IR/DataLayout.cpp

Lines changed: 43 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,6 @@ Expected<DataLayout> DataLayout::parse(StringRef LayoutString) {
268268
return Layout;
269269
}
270270

271-
static Error reportError(const Twine &Message) {
272-
return createStringError(inconvertibleErrorCode(), Message);
273-
}
274-
275271
static Error createSpecFormatError(Twine Format) {
276272
return createStringError("malformed specification, must be of the form \"" +
277273
Format + "\"");
@@ -336,46 +332,6 @@ static Error parseAlignment(StringRef Str, Align &Alignment, StringRef Name,
336332
return Error::success();
337333
}
338334

339-
/// Checked version of split, to ensure mandatory subparts.
340-
static Error split(StringRef Str, char Separator,
341-
std::pair<StringRef, StringRef> &Split) {
342-
assert(!Str.empty() && "parse error, string can't be empty here");
343-
Split = Str.split(Separator);
344-
if (Split.second.empty() && Split.first != Str)
345-
return reportError("Trailing separator in datalayout string");
346-
if (!Split.second.empty() && Split.first.empty())
347-
return reportError("Expected token before separator in datalayout string");
348-
return Error::success();
349-
}
350-
351-
/// Get an unsigned integer, including error checks.
352-
template <typename IntTy> static Error getInt(StringRef R, IntTy &Result) {
353-
bool error = R.getAsInteger(10, Result); (void)error;
354-
if (error)
355-
return reportError("not a number, or does not fit in an unsigned int");
356-
return Error::success();
357-
}
358-
359-
/// Get an unsigned integer representing the number of bits and convert it into
360-
/// bytes. Error out of not a byte width multiple.
361-
template <typename IntTy>
362-
static Error getIntInBytes(StringRef R, IntTy &Result) {
363-
if (Error Err = getInt<IntTy>(R, Result))
364-
return Err;
365-
if (Result % 8)
366-
return reportError("number of bits must be a byte width multiple");
367-
Result /= 8;
368-
return Error::success();
369-
}
370-
371-
static Error getAddrSpace(StringRef R, unsigned &AddrSpace) {
372-
if (Error Err = getInt(R, AddrSpace))
373-
return Err;
374-
if (!isUInt<24>(AddrSpace))
375-
return reportError("Invalid address space, must be a 24-bit integer");
376-
return Error::success();
377-
}
378-
379335
Error DataLayout::parsePrimitiveSpec(StringRef Spec) {
380336
// [ifv]<size>:<abi>[:<pref>]
381337
SmallVector<StringRef, 3> Components;
@@ -536,100 +492,90 @@ Error DataLayout::parseSpecification(StringRef Spec) {
536492
if (Specifier == 'p')
537493
return parsePointerSpec(Spec);
538494

539-
// Split at ':'.
540-
std::pair<StringRef, StringRef> Split;
541-
if (Error Err = ::split(Spec, ':', Split))
542-
return Err;
543-
544-
// Aliases used below.
545-
StringRef &Tok = Split.first; // Current token.
546-
StringRef &Rest = Split.second; // The rest of the string.
547-
548-
char SpecifierChar = Tok.front();
549-
Tok = Tok.substr(1);
550-
551-
switch (SpecifierChar) {
495+
StringRef Rest = Spec.drop_front();
496+
switch (Specifier) {
552497
case 's':
553498
// Deprecated, but ignoring here to preserve loading older textual llvm
554499
// ASM file
555500
break;
556-
case 'E':
557-
BigEndian = true;
558-
break;
559501
case 'e':
560-
BigEndian = false;
502+
case 'E':
503+
if (!Rest.empty())
504+
return createStringError(
505+
"malformed specification, must be just 'e' or 'E'");
506+
BigEndian = Specifier == 'E';
561507
break;
562508
case 'n': // Native integer types.
563-
while (true) {
564-
unsigned Width;
565-
if (Error Err = getInt(Tok, Width))
566-
return Err;
567-
if (Width == 0)
568-
return reportError(
569-
"Zero width native integer type in datalayout string");
570-
LegalIntWidths.push_back(Width);
571-
if (Rest.empty())
572-
break;
573-
if (Error Err = ::split(Rest, ':', Split))
509+
// n<size>[:<size>]...
510+
for (StringRef Str : split(Rest, ':')) {
511+
unsigned BitWidth;
512+
if (Error Err = parseSize(Str, BitWidth))
574513
return Err;
514+
LegalIntWidths.push_back(BitWidth);
575515
}
576516
break;
577517
case 'S': { // Stack natural alignment.
578-
uint64_t Alignment;
579-
if (Error Err = getIntInBytes(Tok, Alignment))
518+
// S<size>
519+
if (Rest.empty())
520+
return createSpecFormatError("S<size>");
521+
Align Alignment;
522+
if (Error Err = parseAlignment(Rest, Alignment, "stack natural"))
580523
return Err;
581-
if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment))
582-
return reportError("Alignment is neither 0 nor a power of 2");
583-
StackNaturalAlign = MaybeAlign(Alignment);
524+
StackNaturalAlign = Alignment;
584525
break;
585526
}
586527
case 'F': {
587-
switch (Tok.front()) {
528+
// F<type><abi>
529+
if (Rest.empty())
530+
return createSpecFormatError("F<type><abi>");
531+
char Type = Rest.front();
532+
Rest = Rest.drop_front();
533+
switch (Type) {
588534
case 'i':
589535
TheFunctionPtrAlignType = FunctionPtrAlignType::Independent;
590536
break;
591537
case 'n':
592538
TheFunctionPtrAlignType = FunctionPtrAlignType::MultipleOfFunctionAlign;
593539
break;
594540
default:
595-
return reportError("Unknown function pointer alignment type in "
596-
"datalayout string");
541+
return createStringError("unknown function pointer alignment type '" +
542+
Twine(Type) + "'");
597543
}
598-
Tok = Tok.substr(1);
599-
uint64_t Alignment;
600-
if (Error Err = getIntInBytes(Tok, Alignment))
544+
Align Alignment;
545+
if (Error Err = parseAlignment(Rest, Alignment, "ABI"))
601546
return Err;
602-
if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment))
603-
return reportError("Alignment is neither 0 nor a power of 2");
604-
FunctionPtrAlign = MaybeAlign(Alignment);
547+
FunctionPtrAlign = Alignment;
605548
break;
606549
}
607550
case 'P': { // Function address space.
608-
if (Error Err = getAddrSpace(Tok, ProgramAddrSpace))
551+
if (Rest.empty())
552+
return createSpecFormatError("P<address space>");
553+
if (Error Err = parseAddrSpace(Rest, ProgramAddrSpace))
609554
return Err;
610555
break;
611556
}
612557
case 'A': { // Default stack/alloca address space.
613-
if (Error Err = getAddrSpace(Tok, AllocaAddrSpace))
558+
if (Rest.empty())
559+
return createSpecFormatError("A<address space>");
560+
if (Error Err = parseAddrSpace(Rest, AllocaAddrSpace))
614561
return Err;
615562
break;
616563
}
617564
case 'G': { // Default address space for global variables.
618-
if (Error Err = getAddrSpace(Tok, DefaultGlobalsAddrSpace))
565+
if (Rest.empty())
566+
return createSpecFormatError("G<address space>");
567+
if (Error Err = parseAddrSpace(Rest, DefaultGlobalsAddrSpace))
619568
return Err;
620569
break;
621570
}
622571
case 'm':
623-
if (!Tok.empty())
624-
return reportError("Unexpected trailing characters after mangling "
625-
"specifier in datalayout string");
626-
if (Rest.empty())
627-
return reportError("Expected mangling specifier in datalayout string");
572+
if (!Rest.consume_front(":") || Rest.empty())
573+
return createSpecFormatError("m:<mangling>");
628574
if (Rest.size() > 1)
629-
return reportError("Unknown mangling specifier in datalayout string");
575+
return createStringError("unknown mangling mode");
630576
switch (Rest[0]) {
631577
default:
632-
return reportError("Unknown mangling in datalayout string");
578+
return createStringError("unknown mangling mode");
633579
case 'e':
634580
ManglingMode = MM_ELF;
635581
break;
@@ -654,7 +600,7 @@ Error DataLayout::parseSpecification(StringRef Spec) {
654600
}
655601
break;
656602
default:
657-
return reportError("Unknown specifier in datalayout string");
603+
return createStringError("unknown specifier '" + Twine(Specifier) + "'");
658604
}
659605

660606
return Error::success();

llvm/test/Assembler/invalid-datalayout-override.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
; RUN: llvm-as -data-layout "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" < %s
55

66
target datalayout = "A16777216"
7-
; CHECK: Invalid address space, must be a 24-bit integer
7+
; CHECK: address space must be a 24-bit integer

llvm/test/Bitcode/function-default-address-spaces.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s -check-prefixes CHECK,PROG-AS0
22
; RUN: llvm-as -data-layout "P200" %s -o - | llvm-dis | FileCheck %s -check-prefixes CHECK,PROG-AS200
33
; RUN: not llvm-as -data-layout "P123456789" %s -o /dev/null 2>&1 | FileCheck %s -check-prefix BAD-DATALAYOUT
4-
; BAD-DATALAYOUT: error: Invalid address space, must be a 24-bit integer
4+
; BAD-DATALAYOUT: error: address space must be a 24-bit integer
55

66
; PROG-AS0-NOT: target datalayout
77
; PROG-AS200: target datalayout = "P200"

llvm/test/Bitcode/invalid-functionptr-align.ll

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
; Bitcode with invalid natural stack alignment.
2+
3+
; RUN: not llvm-dis %s.bc -o - 2>&1 | FileCheck %s
4+
5+
CHECK: error: stack natural alignment must be a power of two times the byte width

0 commit comments

Comments
 (0)