diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -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 @@ /// 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 diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -634,6 +634,7 @@ DK_DW, DK_REAL4, DK_REAL8, + DK_REAL10, DK_ALIGN, DK_ORG, DK_ENDR, @@ -771,7 +772,7 @@ 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 @@ 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 @@ 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(); @@ -3453,14 +3460,14 @@ } else if (IDVal.consume_back("r") || IDVal.consume_back("R")) { // MASM hexadecimal floating-point literal; no APFloat conversion needed. // Also, 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); return false; } else if (errorToBool( Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) @@ -3535,8 +3542,7 @@ return true; for (const APInt &AsInt : ValuesAsInt) { - getStreamer().emitIntValue(AsInt.getLimitedValue(), - AsInt.getBitWidth() / 8); + getStreamer().emitIntValue(AsInt); } if (Count) *Count = ValuesAsInt.size(); @@ -3566,7 +3572,7 @@ } /// parseDirectiveRealValue -/// ::= (real4 | real8) [ expression (, expression)* ] +/// ::= (real4 | real8 | real10) [ expression (, expression)* ] bool MasmParser::parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics, size_t Size) { @@ -3581,7 +3587,7 @@ } /// parseDirectiveNamedRealValue -/// ::= name (real4 | real8) [ expression (, expression)* ] +/// ::= name (real4 | real8 | real10) [ expression (, expression)* ] bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName, const fltSemantics &Semantics, unsigned Size, StringRef Name, @@ -3675,8 +3681,20 @@ 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(); @@ -3684,20 +3702,20 @@ 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; } @@ -6273,6 +6291,7 @@ 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; @@ -6727,6 +6746,7 @@ .CasesLower("qword", "dq", "sqword", 8) .CaseLower("real4", 4) .CaseLower("real8", 8) + .CaseLower("real10", 10) .Default(0); if (Size) { Info.Name = Name; diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -138,6 +138,21 @@ unsigned Index = IsLittleEndian ? 0 : 8 - Size; emitBytes(StringRef(reinterpret_cast(&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(Tmp.data()), Size); + emitBytes(Tmp.str()); +} /// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. diff --git a/llvm/test/tools/llvm-ml/builtin_types.test b/llvm/test/tools/llvm-ml/builtin_types.test --- a/llvm/test/tools/llvm-ml/builtin_types.test +++ b/llvm/test/tools/llvm-ml/builtin_types.test @@ -65,20 +65,28 @@ ; 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-NEXT: .quad 4608533498688228557 +; CHECK-LABEL: t6_single_hex: +; CHECK-NEXT: .long 1067869798 -t7_single_hex REAL4 3f800000r -t7_double_hex REAL8 3FF0000000000000R +t7_double REAL8 1.3 +t7_double_hex REAL8 3FF4CCCCCCCCCCCDR -; CHECK-LABEL: t7_single_hex: -; CHECK-NEXT: .long 1065353216 +; CHECK-LABEL: t7_double: +; CHECK-NEXT: .quad 4608533498688228557 ; CHECK-LABEL: t7_double_hex: -; CHECK-NEXT: .quad 4607182418800017408 +; CHECK-NEXT: .quad 4608533498688228557 + +t8_extended REAL10 1.3 +t8_extended_hex REAL10 3FFFA666666666666666r + +; CHECK-LABEL: t8_extended: +; CHECK-NEXT: .ascii "fffffff\246\377?" +; CHECK-LABEL: t8_extended_hex: +; CHECK-NEXT: .ascii "fffffff\246\377?" .code diff --git a/llvm/test/tools/llvm-ml/type_operators.test b/llvm/test/tools/llvm-ml/type_operators.test --- a/llvm/test/tools/llvm-ml/type_operators.test +++ b/llvm/test/tools/llvm-ml/type_operators.test @@ -196,6 +196,7 @@ t7_single REAL4 2 DUP (?) t7_double REAL8 ? +t7_extended REAL10 3 DUP (?) t7: ; CHECK-LABEL: t7: @@ -214,6 +215,13 @@ ; 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 <>, <>