Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -272,6 +272,10 @@ SMLoc &EndLoc) override; bool parseAbsoluteExpression(int64_t &Res) override; + /// \brief Parse a floating point expression using the float \p Semantics + /// and set \p Res to the value. + bool parseRealValue(const fltSemantics &Semantics, APInt &Res); + /// \brief Parse an identifier or string (as a quoted identifier) /// and set \p Res to the identifier contents. bool parseIdentifier(StringRef &Res) override; @@ -384,6 +388,7 @@ DK_RELOC, DK_VALUE, DK_2BYTE, DK_LONG, DK_INT, DK_4BYTE, DK_QUAD, DK_8BYTE, DK_OCTA, DK_DC, DK_DC_A, DK_DC_B, DK_DC_D, DK_DC_L, DK_DC_S, DK_DC_W, DK_DC_X, + DK_DCB, DK_DCB_B, DK_DCB_D, DK_DCB_L, DK_DCB_S, DK_DCB_W, DK_DCB_X, DK_SINGLE, DK_FLOAT, DK_DOUBLE, DK_ALIGN, DK_ALIGN32, DK_BALIGN, DK_BALIGNW, DK_BALIGNL, DK_P2ALIGN, DK_P2ALIGNW, DK_P2ALIGNL, DK_ORG, DK_FILL, DK_ENDR, DK_BUNDLE_ALIGN_MODE, DK_BUNDLE_LOCK, DK_BUNDLE_UNLOCK, @@ -486,6 +491,10 @@ // ".space", ".skip" bool parseDirectiveSpace(StringRef IDVal); + // ".dcb" + bool parseDirectiveDCB(StringRef IDVal, unsigned Size); + bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &); + // .sleb128 (Signed=true) and .uleb128 (Signed=false) bool parseDirectiveLEB128(bool Signed); @@ -1921,7 +1930,19 @@ return parseDirectiveRealValue(APFloat::IEEEsingle); case DK_DC_W: return parseDirectiveValue(2); + case DK_DCB: + case DK_DCB_W: + return parseDirectiveDCB(IDVal, 2); + case DK_DCB_B: + return parseDirectiveDCB(IDVal, 1); + case DK_DCB_D: + return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble); + case DK_DCB_L: + return parseDirectiveDCB(IDVal, 4); + case DK_DCB_S: + return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle); case DK_DC_X: + case DK_DCB_X: return TokError(Twine(IDVal) + " not currently supported for this target"); } @@ -2823,6 +2844,46 @@ return false; } +bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) { + // 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)) { + Lexer.Lex(); + IsNeg = true; + } else if (getLexer().is(AsmToken::Plus)) + Lexer.Lex(); + + if (Lexer.is(AsmToken::Error)) + return TokError(Lexer.getErr()); + if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) && + Lexer.isNot(AsmToken::Identifier)) + return TokError("unexpected token in directive"); + + // Convert to an APFloat. + APFloat Value(Semantics); + StringRef IDVal = getTok().getString(); + if (getLexer().is(AsmToken::Identifier)) { + if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf")) + Value = APFloat::getInf(Semantics); + else if (!IDVal.compare_lower("nan")) + Value = APFloat::getNaN(Semantics, false, ~0); + else + return TokError("invalid floating point literal"); + } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) == + APFloat::opInvalidOp) + return TokError("invalid floating point literal"); + if (IsNeg) + Value.changeSign(); + + // Consume the numeric token. + Lex(); + + Res = Value.bitcastToAPInt(); + + return false; +} + /// parseDirectiveRealValue /// ::= (.single | .double) [ expression (, expression)* ] bool AsmParser::parseDirectiveRealValue(const fltSemantics &Semantics) { @@ -2830,42 +2891,10 @@ checkForValidSection(); while (true) { - // 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)) { - Lexer.Lex(); - IsNeg = true; - } else if (getLexer().is(AsmToken::Plus)) - Lexer.Lex(); - - if (Lexer.is(AsmToken::Error)) - return TokError(Lexer.getErr()); - if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) && - Lexer.isNot(AsmToken::Identifier)) - return TokError("unexpected token in directive"); - - // Convert to an APFloat. - APFloat Value(Semantics); - StringRef IDVal = getTok().getString(); - if (getLexer().is(AsmToken::Identifier)) { - if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf")) - Value = APFloat::getInf(Semantics); - else if (!IDVal.compare_lower("nan")) - Value = APFloat::getNaN(Semantics, false, ~0); - else - return TokError("invalid floating point literal"); - } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) == - APFloat::opInvalidOp) - return TokError("invalid floating point literal"); - if (IsNeg) - Value.changeSign(); - - // Consume the numeric token. - Lex(); + APInt AsInt; + if (parseRealValue(Semantics, AsInt)) + return true; - // Emit the value as an integer. - APInt AsInt = Value.bitcastToAPInt(); getStreamer().EmitIntValue(AsInt.getLimitedValue(), AsInt.getBitWidth() / 8); @@ -4226,6 +4255,84 @@ return false; } +/// parseDirectiveDCB +/// ::= .dcb.{b, l, w} expression, expression +bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) { + checkForValidSection(); + + SMLoc NumValuesLoc = Lexer.getLoc(); + int64_t NumValues; + if (parseAbsoluteExpression(NumValues)) + return true; + + if (NumValues < 0) { + Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); + return false; + } + + if (parseToken(AsmToken::Comma, + "unexpected token in '" + Twine(IDVal) + "' directive")) + return true; + + const MCExpr *Value; + SMLoc ExprLoc = getLexer().getLoc(); + if (parseExpression(Value)) + return true; + + // Special case constant expressions to match code generator. + if (const MCConstantExpr *MCE = dyn_cast(Value)) { + assert(Size <= 8 && "Invalid size"); + uint64_t IntValue = MCE->getValue(); + if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) + return Error(ExprLoc, "literal value out of range for directive"); + for (uint64_t i = 0, e = NumValues; i != e; ++i) + getStreamer().EmitIntValue(IntValue, Size); + } else { + for (uint64_t i = 0, e = NumValues; i != e; ++i) + getStreamer().EmitValue(Value, Size, ExprLoc); + } + + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '" + Twine(IDVal) + "' directive")) + return true; + + return false; +} + +/// parseDirectiveRealDCB +/// ::= .dcb.{d, s} expression, expression +bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) { + checkForValidSection(); + + SMLoc NumValuesLoc = Lexer.getLoc(); + int64_t NumValues; + if (parseAbsoluteExpression(NumValues)) + return true; + + if (NumValues < 0) { + Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); + return false; + } + + if (parseToken(AsmToken::Comma, + "unexpected token in '" + Twine(IDVal) + "' directive")) + return true; + + APInt AsInt; + if (parseRealValue(Semantics, AsInt)) + return true; + + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '" + Twine(IDVal) + "' directive")) + return true; + + for (uint64_t i = 0, e = NumValues; i != e; ++i) + getStreamer().EmitIntValue(AsInt.getLimitedValue(), + AsInt.getBitWidth() / 8); + + return false; +} + /// parseDirectiveLEB128 /// ::= (.sleb128 | .uleb128) [ expression (, expression)* ] bool AsmParser::parseDirectiveLEB128(bool Signed) { @@ -4869,6 +4976,13 @@ DirectiveKindMap[".dc.s"] = DK_DC_S; DirectiveKindMap[".dc.w"] = DK_DC_W; DirectiveKindMap[".dc.x"] = DK_DC_X; + DirectiveKindMap[".dcb"] = DK_DCB; + DirectiveKindMap[".dcb.b"] = DK_DCB_B; + DirectiveKindMap[".dcb.d"] = DK_DCB_D; + DirectiveKindMap[".dcb.l"] = DK_DCB_L; + DirectiveKindMap[".dcb.s"] = DK_DCB_S; + DirectiveKindMap[".dcb.w"] = DK_DCB_W; + DirectiveKindMap[".dcb.x"] = DK_DCB_X; } MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { Index: test/MC/AsmParser/directive_dcb.s =================================================================== --- /dev/null +++ test/MC/AsmParser/directive_dcb.s @@ -0,0 +1,59 @@ +# RUN: not llvm-mc -triple i386-unknown-unknown %s | FileCheck %s +# RUN: not llvm-mc -triple i386-unknown-unknown %s 2>&1 > /dev/null| FileCheck %s --check-prefix=CHECK-ERROR + +# CHECK: TEST0: +# CHECK: .byte 1 +# CHECK: .byte 1 +TEST0: + .dcb.b 2, 1 + +# CHECK: TEST1: +# CHECK: .short 3 +TEST1: + .dcb 1, 3 + +# CHECK: TEST2: +# CHECK: .short 3 +# CHECK: .short 3 +TEST2: + .dcb.w 2, 3 + +# CHECK: TEST3: +# CHECK: .long 8 +# CHECK: .long 8 +# CHECK: .long 8 +TEST3: + .dcb.l 3, 8 + +# CHECK: TEST5 +# CHECK: .long 1067412619 +# CHECK: .long 1067412619 +# CHECK: .long 1067412619 +# CHECK: .long 1067412619 +TEST5: + .dcb.s 4, 1.2455 + +# CHECK: TEST6 +# CHECK: .quad 4597526701198935065 +# CHECK: .quad 4597526701198935065 +# CHECK: .quad 4597526701198935065 +# CHECK: .quad 4597526701198935065 +# CHECK: .quad 4597526701198935065 +TEST6: + .dcb.d 5, .232 + +# CHECK-ERROR: error: .dcb.x not currently supported for this target +TEST7: + .dcb.x 3, 1.2e3 + +# CHECK-ERROR: warning: '.dcb' directive with negative repeat count has no effect +TEST8: + .dcb -1, 2 + +# CHECK-ERROR: error: unexpected token in '.dcb' directive +TEST9: + .dcb 1 2 + +# CHECK-ERROR: error: unexpected token in '.dcb' directive +TEST10: + .dcb 1, 2 3