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.

llvm-svn: 114719
This commit is contained in:
Daniel Dunbar 2010-09-24 01:59:56 +00:00
parent 3068a93dc1
commit 2af1653032
2 changed files with 68 additions and 0 deletions

View File

@ -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() {

View File

@ -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