summaryrefslogtreecommitdiff
path: root/lib/MC
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2013-08-14 14:23:31 +0000
committerTim Northover <tnorthover@apple.com>2013-08-14 14:23:31 +0000
commit337439d12d2e2a9e820e0aeee261bbdb935fc0a5 (patch)
tree605c854f4db448fa58f7d806c204947745dbfe60 /lib/MC
parent79663c1910ebf9bda8f758388eaa3171fb9a5134 (diff)
downloadllvm-337439d12d2e2a9e820e0aeee261bbdb935fc0a5.tar.gz
llvm-337439d12d2e2a9e820e0aeee261bbdb935fc0a5.tar.bz2
llvm-337439d12d2e2a9e820e0aeee261bbdb935fc0a5.tar.xz
Support C99 hexadecimal floating-point literals in assembly
It's useful to be able to write down floating-point numbers without having to worry about what they'll be rounded to (as C99 discovered), this extends that ability to the MC assembly parsers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188370 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/MCParser/AsmLexer.cpp54
1 files changed, 53 insertions, 1 deletions
diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp
index c1c594a746..1ce0cc2a1d 100644
--- a/lib/MC/MCParser/AsmLexer.cpp
+++ b/lib/MC/MCParser/AsmLexer.cpp
@@ -91,6 +91,53 @@ AsmToken AsmLexer::LexFloatLiteral() {
StringRef(TokStart, CurPtr - TokStart));
}
+/// LexHexFloatLiteral matches essentially (.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+
+/// while making sure there are enough actual digits around for the constant to
+/// be valid.
+///
+/// The leading "0x[0-9a-fA-F]*" (i.e. integer part) has already been consumed
+/// before we get here.
+AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
+ assert((*CurPtr == 'p' || *CurPtr == 'P' || *CurPtr == '.') &&
+ "unexpected parse state in floating hex");
+ bool NoFracDigits = true;
+
+ // Skip the fractional part if there is one
+ if (*CurPtr == '.') {
+ ++CurPtr;
+
+ const char *FracStart = CurPtr;
+ while (isxdigit(*CurPtr))
+ ++CurPtr;
+
+ NoFracDigits = CurPtr == FracStart;
+ }
+
+ if (NoIntDigits && NoFracDigits)
+ return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
+ "expected at least one significand digit");
+
+ // Make sure we do have some kind of proper exponent part
+ if (*CurPtr != 'p' && *CurPtr != 'P')
+ return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
+ "expected exponent part 'p'");
+ ++CurPtr;
+
+ if (*CurPtr == '+' || *CurPtr == '-')
+ ++CurPtr;
+
+ // N.b. exponent digits are *not* hex
+ const char *ExpStart = CurPtr;
+ while (isdigit(*CurPtr))
+ ++CurPtr;
+
+ if (CurPtr == ExpStart)
+ return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
+ "expected at least one exponent digit");
+
+ return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart));
+}
+
/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
static bool IsIdentifierChar(char c) {
return isalnum(c) || c == '_' || c == '$' || c == '.' || c == '@';
@@ -265,7 +312,12 @@ AsmToken AsmLexer::LexDigit() {
while (isxdigit(CurPtr[0]))
++CurPtr;
- // Requires at least one hex digit.
+ // "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be
+ // diagnosed by LexHexFloatLiteral).
+ if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P')
+ return LexHexFloatLiteral(NumStart == CurPtr);
+
+ // Otherwise requires at least one hex digit.
if (CurPtr == NumStart)
return ReturnError(CurPtr-2, "invalid hexadecimal number");