1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 12:43:36 +01:00

[ms] [llvm-ml] Add REAL10 support (x87 extended precision)

Add MASM support for 80-bit reals in the x87 extended precision format.

Reviewed By: thakis

Differential Revision: https://reviews.llvm.org/D87402
This commit is contained in:
Eric Astor 2020-09-29 16:58:39 -04:00
parent 95792b92ea
commit 91cac48098
5 changed files with 74 additions and 21 deletions

View File

@ -13,6 +13,7 @@
#ifndef LLVM_MC_MCSTREAMER_H
#define LLVM_MC_MCSTREAMER_H
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
@ -673,6 +674,7 @@ public:
/// Special case of EmitValue that avoids the client having
/// to pass in a MCExpr for constant integers.
virtual void emitIntValue(uint64_t Value, unsigned Size);
virtual void emitIntValue(APInt Value);
/// Special case of EmitValue that avoids the client having to pass
/// in a MCExpr for constant integers & prints in Hex format for certain

View File

@ -634,6 +634,7 @@ private:
DK_DW,
DK_REAL4,
DK_REAL8,
DK_REAL10,
DK_ALIGN,
DK_ORG,
DK_ENDR,
@ -771,7 +772,7 @@ private:
bool parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
StringRef Name, SMLoc NameLoc);
// "real4", "real8"
// "real4", "real8", "real10"
bool emitRealValues(const fltSemantics &Semantics, unsigned *Count = nullptr);
bool addRealField(StringRef Name, const fltSemantics &Semantics, size_t Size);
bool parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics,
@ -2147,6 +2148,8 @@ bool MasmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
case DK_REAL8:
return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
case DK_REAL10:
return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
case DK_STRUCT:
case DK_UNION:
return parseDirectiveNestedStruct(IDVal, DirKind);
@ -2382,6 +2385,10 @@ bool MasmParser::parseStatement(ParseStatementInfo &Info,
Lex();
return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
IDVal, IDLoc);
case DK_REAL10:
Lex();
return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
10, IDVal, IDLoc);
case DK_STRUCT:
case DK_UNION:
Lex();
@ -3456,14 +3463,14 @@ bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
} else if (IDVal.consume_back("r") || IDVal.consume_back("R")) {
// MASM hexadecimal floating-point literal; no APFloat conversion needed.
// To match ML64.exe, ignore the initial sign.
unsigned Size = Value.getSizeInBits(Semantics);
if (Size != (IDVal.size() << 2))
unsigned SizeInBits = Value.getSizeInBits(Semantics);
if (SizeInBits != (IDVal.size() << 2))
return TokError("invalid floating point literal");
// Consume the numeric token.
Lex();
Res = APInt(Size, IDVal, 16);
Res = APInt(SizeInBits, IDVal, 16);
if (SignLoc.isValid())
return Warning(SignLoc, "MASM-style hex floats ignore explicit sign");
return false;
@ -3540,8 +3547,7 @@ bool MasmParser::emitRealValues(const fltSemantics &Semantics,
return true;
for (const APInt &AsInt : ValuesAsInt) {
getStreamer().emitIntValue(AsInt.getLimitedValue(),
AsInt.getBitWidth() / 8);
getStreamer().emitIntValue(AsInt);
}
if (Count)
*Count = ValuesAsInt.size();
@ -3571,7 +3577,7 @@ bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics,
}
/// parseDirectiveRealValue
/// ::= (real4 | real8) [ expression (, expression)* ]
/// ::= (real4 | real8 | real10) [ expression (, expression)* ]
bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
const fltSemantics &Semantics,
size_t Size) {
@ -3586,7 +3592,7 @@ bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
}
/// parseDirectiveNamedRealValue
/// ::= name (real4 | real8) [ expression (, expression)* ]
/// ::= name (real4 | real8 | real10) [ expression (, expression)* ]
bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
const fltSemantics &Semantics,
unsigned Size, StringRef Name,
@ -3680,8 +3686,20 @@ bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
const RealFieldInfo &Contents,
FieldInitializer &Initializer) {
const fltSemantics &Semantics =
(Field.Type == 4) ? APFloat::IEEEsingle() : APFloat::IEEEdouble();
const fltSemantics *Semantics;
switch (Field.Type) {
case 4:
Semantics = &APFloat::IEEEsingle();
break;
case 8:
Semantics = &APFloat::IEEEdouble();
break;
case 10:
Semantics = &APFloat::x87DoubleExtended();
break;
default:
llvm_unreachable("unknown real field type");
}
SMLoc Loc = getTok().getLoc();
@ -3689,20 +3707,20 @@ bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
if (parseOptionalToken(AsmToken::LCurly)) {
if (Field.LengthOf == 1)
return Error(Loc, "Cannot initialize scalar field with array value");
if (parseRealInstList(Semantics, AsIntValues, AsmToken::RCurly) ||
if (parseRealInstList(*Semantics, AsIntValues, AsmToken::RCurly) ||
parseToken(AsmToken::RCurly))
return true;
} else if (parseOptionalAngleBracketOpen()) {
if (Field.LengthOf == 1)
return Error(Loc, "Cannot initialize scalar field with array value");
if (parseRealInstList(Semantics, AsIntValues, AsmToken::Greater) ||
if (parseRealInstList(*Semantics, AsIntValues, AsmToken::Greater) ||
parseAngleBracketClose())
return true;
} else if (Field.LengthOf > 1) {
return Error(Loc, "Cannot initialize array field with scalar value");
} else {
AsIntValues.emplace_back();
if (parseRealValue(Semantics, AsIntValues.back()))
if (parseRealValue(*Semantics, AsIntValues.back()))
return true;
}
@ -6278,6 +6296,7 @@ void MasmParser::initializeDirectiveKindMap() {
DirectiveKindMap["sqword"] = DK_SQWORD;
DirectiveKindMap["real4"] = DK_REAL4;
DirectiveKindMap["real8"] = DK_REAL8;
DirectiveKindMap["real10"] = DK_REAL10;
DirectiveKindMap["align"] = DK_ALIGN;
// DirectiveKindMap[".org"] = DK_ORG;
DirectiveKindMap["extern"] = DK_EXTERN;
@ -6732,6 +6751,7 @@ bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const {
.CasesLower("qword", "dq", "sqword", 8)
.CaseLower("real4", 4)
.CaseLower("real8", 8)
.CaseLower("real10", 10)
.Default(0);
if (Size) {
Info.Name = Name;

View File

@ -138,6 +138,21 @@ void MCStreamer::emitIntValue(uint64_t Value, unsigned Size) {
unsigned Index = IsLittleEndian ? 0 : 8 - Size;
emitBytes(StringRef(reinterpret_cast<char *>(&Swapped) + Index, Size));
}
void MCStreamer::emitIntValue(APInt Value) {
if (Value.getNumWords() == 1) {
emitIntValue(Value.getLimitedValue(), Value.getBitWidth() / 8);
return;
}
const bool IsLittleEndianTarget = Context.getAsmInfo()->isLittleEndian();
const bool ShouldSwap = sys::IsLittleEndianHost != IsLittleEndianTarget;
const APInt Swapped = ShouldSwap ? Value.byteSwap() : Value;
const unsigned Size = Value.getBitWidth() / 8;
SmallString<10> Tmp;
Tmp.resize(Size);
StoreIntToMemory(Swapped, reinterpret_cast<uint8_t *>(Tmp.data()), Size);
emitBytes(Tmp.str());
}
/// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the
/// client having to pass in a MCExpr for constant integers.

View File

@ -65,20 +65,28 @@ t5_signed SQWORD -4611686018427387904
; CHECK-NEXT: .quad -4611686018427387904
t6_single REAL4 1.3
t6_double REAL8 1.3
t6_single_hex REAL4 3fa66666r
; CHECK-LABEL: t6_single:
; CHECK-NEXT: .long 1067869798
; CHECK-LABEL: t6_double:
; CHECK-LABEL: t6_single_hex:
; CHECK-NEXT: .long 1067869798
t7_double REAL8 1.3
t7_double_hex REAL8 3FF4CCCCCCCCCCCDR
; CHECK-LABEL: t7_double:
; CHECK-NEXT: .quad 4608533498688228557
; CHECK-LABEL: t7_double_hex:
; CHECK-NEXT: .quad 4608533498688228557
t7_single_hex REAL4 3f800000r
t7_double_hex REAL8 3FF0000000000000R
t8_extended REAL10 1.3
t8_extended_hex REAL10 3FFFA666666666666666r
; CHECK-LABEL: t7_single_hex:
; CHECK-NEXT: .long 1065353216
; CHECK-LABEL: t7_double_hex:
; CHECK-NEXT: .quad 4607182418800017408
; CHECK-LABEL: t8_extended:
; CHECK-NEXT: .ascii "fffffff\246\377?"
; CHECK-LABEL: t8_extended_hex:
; CHECK-NEXT: .ascii "fffffff\246\377?"
.code

View File

@ -196,6 +196,7 @@ mov eax, type(t6_signed)
t7_single REAL4 2 DUP (?)
t7_double REAL8 ?
t7_extended REAL10 3 DUP (?)
t7:
; CHECK-LABEL: t7:
@ -214,6 +215,13 @@ mov eax, type(t7_double)
; CHECK: mov eax, 1
; CHECK: mov eax, 8
mov eax, sizeof(t7_extended)
mov eax, lengthof(t7_extended)
mov eax, type(t7_extended)
; CHECK: mov eax, 30
; CHECK: mov eax, 3
; CHECK: mov eax, 10
t8_var FOO <>, <>