summaryrefslogtreecommitdiffstats
path: root/llvm/lib/AsmParser
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/AsmParser')
-rw-r--r--llvm/lib/AsmParser/Lexer.l60
-rw-r--r--llvm/lib/AsmParser/llvmAsmParser.y13
2 files changed, 64 insertions, 9 deletions
diff --git a/llvm/lib/AsmParser/Lexer.l b/llvm/lib/AsmParser/Lexer.l
index 390544d8c3d..5acbbacf60f 100644
--- a/llvm/lib/AsmParser/Lexer.l
+++ b/llvm/lib/AsmParser/Lexer.l
@@ -91,14 +91,40 @@ static uint64_t HexIntToVal(const char *Buffer) {
return Result;
}
-
-// HexToFP - Convert the ascii string in hexidecimal format to the floating
+// HexToFP - Convert the ascii string in hexadecimal format to the floating
// point representation of it.
//
static double HexToFP(const char *Buffer) {
return BitsToDouble(HexIntToVal(Buffer)); // Cast Hex constant to double
}
+static void HexToIntPair(const char *Buffer, uint64_t Pair[2]) {
+ Pair[0] = 0;
+ for (int i=0; i<16; i++, Buffer++) {
+ assert(*Buffer);
+ Pair[0] *= 16;
+ char C = *Buffer;
+ if (C >= '0' && C <= '9')
+ Pair[0] += C-'0';
+ else if (C >= 'A' && C <= 'F')
+ Pair[0] += C-'A'+10;
+ else if (C >= 'a' && C <= 'f')
+ Pair[0] += C-'a'+10;
+ }
+ Pair[1] = 0;
+ for (int i=0; i<16 && *Buffer; i++, Buffer++) {
+ Pair[1] *= 16;
+ char C = *Buffer;
+ if (C >= '0' && C <= '9')
+ Pair[1] += C-'0';
+ else if (C >= 'A' && C <= 'F')
+ Pair[1] += C-'A'+10;
+ else if (C >= 'a' && C <= 'f')
+ Pair[1] += C-'a'+10;
+ }
+ if (*Buffer)
+ GenerateError("constant bigger than 128 bits detected!");
+}
// UnEscapeLexed - Run through the specified buffer and change \xx codes to the
// appropriate character.
@@ -163,15 +189,28 @@ IntegerType i[0-9]+
PInteger [0-9]+
NInteger -[0-9]+
-/* FPConstant - A Floating point constant.
+/* FPConstant - A Floating point constant. Float and double only.
*/
FPConstant [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)?
/* HexFPConstant - Floating point constant represented in IEEE format as a
* hexadecimal number for when exponential notation is not precise enough.
+ * Float and double only.
*/
HexFPConstant 0x[0-9A-Fa-f]+
+/* F80HexFPConstant - x87 long double in hexadecimal format (10 bytes)
+ */
+HexFP80Constant 0xK[0-9A-Fa-f]+
+
+/* F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes)
+ */
+HexFP128Constant 0xL[0-9A-Fa-f]+
+
+/* PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes)
+ */
+HexPPC128Constant 0xM[0-9A-Fa-f]+
+
/* HexIntConstant - Hexadecimal constant generated by the CFE to avoid forcing
* it to deal with 64 bit numbers.
*/
@@ -441,6 +480,21 @@ shufflevector { RET_TOK(OtherOpVal, ShuffleVector, SHUFFLEVECTOR); }
{HexFPConstant} { llvmAsmlval.FPVal = new APFloat(HexToFP(yytext));
return FPVAL;
}
+{HexFP80Constant} { uint64_t Pair[2];
+ HexToIntPair(yytext, Pair);
+ llvmAsmlval.FPVal = new APFloat(APInt(80, 2, Pair));
+ return FPVAL;
+ }
+{HexFP128Constant} { uint64_t Pair[2];
+ HexToIntPair(yytext, Pair);
+ llvmAsmlval.FPVal = new APFloat(APInt(128, 2, Pair));
+ return FPVAL;
+ }
+{HexPPC128Constant} { uint64_t Pair[2];
+ HexToIntPair(yytext, Pair);
+ llvmAsmlval.FPVal = new APFloat(APInt(128, 2, Pair));
+ return FPVAL;
+ }
<<EOF>> {
/* Make sure to free the internal buffers for flex when we are
diff --git a/llvm/lib/AsmParser/llvmAsmParser.y b/llvm/lib/AsmParser/llvmAsmParser.y
index 6364b29bcd7..c0374daf3f1 100644
--- a/llvm/lib/AsmParser/llvmAsmParser.y
+++ b/llvm/lib/AsmParser/llvmAsmParser.y
@@ -416,9 +416,10 @@ static Value *getExistingVal(const Type *Ty, const ValID &D) {
GenerateError("FP constant invalid for type");
return 0;
}
- // Lexer has no type info, so builds all FP constants as double.
- // Fix this here.
- if (Ty==Type::FloatTy)
+ // Lexer has no type info, so builds all float and double FP constants
+ // as double. Fix this here. Long double does not need this.
+ if (&D.ConstPoolFP->getSemantics() == &APFloat::IEEEdouble &&
+ Ty==Type::FloatTy)
D.ConstPoolFP->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven);
return ConstantFP::get(Ty, *D.ConstPoolFP);
@@ -1868,9 +1869,9 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
| FPType FPVAL { // Float & Double constants
if (!ConstantFP::isValueValidForType($1, *$2))
GEN_ERROR("Floating point constant invalid for type");
- // Lexer has no type info, so builds all FP constants as double.
- // Fix this here.
- if ($1==Type::FloatTy)
+ // Lexer has no type info, so builds all float and double FP constants
+ // as double. Fix this here. Long double is done right.
+ if (&$2->getSemantics()==&APFloat::IEEEdouble && $1==Type::FloatTy)
$2->convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven);
$$ = ConstantFP::get($1, *$2);
delete $2;
OpenPOWER on IntegriCloud