From b95a079cae7bd5232d17be8a095fa63fe84f4e44 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Fri, 24 Sep 2010 01:59:56 +0000 Subject: [PATCH] MC/AsmParser: Support .single and .double for embedding floating point literals. - I believe more modern 'gas' supports a more enhanced set of arithmetic on them, but for now the only thing we can do is emit them as data. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114719 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCParser/AsmParser.cpp | 56 +++++++++++++++++++++++++++ test/MC/AsmParser/floating-literals.s | 12 ++++++ 2 files changed, 68 insertions(+) create mode 100644 test/MC/AsmParser/floating-literals.s diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index ffd5df1a238..baf174c680a 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" @@ -178,6 +179,7 @@ private: // Directive Parsing. bool ParseDirectiveAscii(bool ZeroTerminated); // ".ascii", ".asciiz" bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ... + bool ParseDirectiveRealValue(const fltSemantics &); // ".single", ... bool ParseDirectiveFill(); // ".fill" bool ParseDirectiveSpace(); // ".space" bool ParseDirectiveZero(); // ".zero" @@ -926,6 +928,10 @@ bool AsmParser::ParseStatement() { return ParseDirectiveValue(4); if (IDVal == ".quad") return ParseDirectiveValue(8); + if (IDVal == ".single") + return ParseDirectiveRealValue(APFloat::IEEEsingle); + if (IDVal == ".double") + return ParseDirectiveRealValue(APFloat::IEEEdouble); if (IDVal == ".align") { bool IsPow2 = !getContext().getAsmInfo().getAlignmentIsInBytes(); @@ -1409,6 +1415,56 @@ bool AsmParser::ParseDirectiveValue(unsigned Size) { return false; } +/// ParseDirectiveRealValue +/// ::= (.single | .double) [ expression (, expression)* ] +bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + CheckForValidSection(); + + for (;;) { + // We don't truly support arithmetic on floating point expressions, so we + // have to manually parse unary prefixes. + bool IsNeg = false; + if (getLexer().is(AsmToken::Minus)) { + Lex(); + IsNeg = true; + } else if (getLexer().is(AsmToken::Plus)) + Lex(); + + if (getLexer().isNot(AsmToken::Integer) && + getLexer().isNot(AsmToken::Real)) + return TokError("unexpected token in directive"); + + // Convert to an APFloat. + APFloat Value(Semantics); + if (Value.convertFromString(getTok().getString(), + APFloat::rmNearestTiesToEven) == + APFloat::opInvalidOp) + return TokError("invalid floating point literal"); + if (IsNeg) + Value.changeSign(); + + // Consume the numeric token. + Lex(); + + // Emit the value as an integer. + APInt AsInt = Value.bitcastToAPInt(); + getStreamer().EmitIntValue(AsInt.getLimitedValue(), + AsInt.getBitWidth() / 8, DEFAULT_ADDRSPACE); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + /// ParseDirectiveSpace /// ::= .space expression [ , expression ] bool AsmParser::ParseDirectiveSpace() { diff --git a/test/MC/AsmParser/floating-literals.s b/test/MC/AsmParser/floating-literals.s new file mode 100644 index 00000000000..44f8a5ab0a7 --- /dev/null +++ b/test/MC/AsmParser/floating-literals.s @@ -0,0 +1,12 @@ +# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s + +# CHECK: .long 1067412619 +# CHECK: .long 1075000115 +# CHECK: .long 1077936128 +# CHECK: .long 1082549862 +.single 1.2455, +2.3, 3, + 4.2 + +# CHECK: .quad 4617315517961601024 +# CHECK: .quad 4597526701198935065 +# CHECK: .quad -4600933674317040845 +.double 5, .232, -11.1 -- 2.34.1