diff options
author | Tim Northover <tnorthover@apple.com> | 2013-08-14 14:23:31 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2013-08-14 14:23:31 +0000 |
commit | 337439d12d2e2a9e820e0aeee261bbdb935fc0a5 (patch) | |
tree | 605c854f4db448fa58f7d806c204947745dbfe60 | |
parent | 79663c1910ebf9bda8f758388eaa3171fb9a5134 (diff) | |
download | llvm-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
-rw-r--r-- | include/llvm/MC/MCParser/AsmLexer.h | 1 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmLexer.cpp | 54 | ||||
-rw-r--r-- | test/MC/AsmParser/floating-literals.s | 37 |
3 files changed, 90 insertions, 2 deletions
diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 0dab31489f..1b3ab57751 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -63,6 +63,7 @@ private: AsmToken LexSingleQuote(); AsmToken LexQuote(); AsmToken LexFloatLiteral(); + AsmToken LexHexFloatLiteral(bool NoIntDigits); }; } // end namespace llvm 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"); diff --git a/test/MC/AsmParser/floating-literals.s b/test/MC/AsmParser/floating-literals.s index d44bb9830c..512b7b3620 100644 --- a/test/MC/AsmParser/floating-literals.s +++ b/test/MC/AsmParser/floating-literals.s @@ -1,4 +1,5 @@ -# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s +# RUN: not llvm-mc -triple i386-unknown-unknown %s 2> /dev/null | FileCheck %s +# RUN: not llvm-mc -triple i386-unknown-unknown %s 2>&1 > /dev/null| FileCheck %s --check-prefix=CHECK-ERROR # CHECK: .long 1067412619 # CHECK: .long 1075000115 @@ -42,3 +43,37 @@ // APFloat should reject these with an error, not crash: //.double -1.2e+ //.double -1.2e + +# CHECK: .long 1310177520 +.float 0x12f7.1ep+17 +# CHECK: .long 1084227584 +.float 0x.ap+3 +# CHECK: .quad 4602678819172646912 +.double 0x2.p-2 +# CHECK: .long 1094713344 +.float 0x3p2 +# CHECK: .long 872284160 +.float 0x7fp-30 +# CHECK: .long 3212836864 +.float -0x1.0p0 + +# CHECK-ERROR: invalid hexadecimal floating-point constant: expected at least one exponent digit +# CHECK-ERROR: unexpected token in directive +.float 0xa.apa + +# CHECK-ERROR: invalid hexadecimal floating-point constant: expected at least one exponent digit +# CHECK-ERROR: unexpected token in directive +.double -0x1.2p+ + +# CHECK-ERROR: invalid hexadecimal floating-point constant: expected at least one exponent digit +# CHECK-ERROR: unexpected token in directive +.double -0x1.2p + +# CHECK-ERROR: invalid hexadecimal floating-point constant: expected at least one significand digit +# CHECK-ERROR: unexpected token in directive +.float 0xp2 + +# CHECK-ERROR: invalid hexadecimal floating-point constant: expected at least one significand digit +# CHECK-ERROR: unexpected token in directive +.float 0x.p5 + |