Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -13,6 +13,7 @@ #include "SIDefines.h" #include "Utils/AMDGPUBaseInfo.h" #include "Utils/AMDKernelCodeTUtils.h" +#include "Utils/AMDGPUAsmParserPrinter.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" @@ -37,54 +38,6 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" -// FIXME ODR: Move this to some common place for AsmParser and InstPrinter -namespace llvm { -namespace AMDGPU { -namespace SendMsg { - -// This must be in sync with llvm::AMDGPU::SendMsg::Id enum members. -static -const char* const IdSymbolic[] = { - nullptr, - "MSG_INTERRUPT", - "MSG_GS", - "MSG_GS_DONE", - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - "MSG_SYSMSG" -}; - -// These two must be in sync with llvm::AMDGPU::SendMsg::Op enum members. -static -const char* const OpSysSymbolic[] = { - nullptr, - "SYSMSG_OP_ECC_ERR_INTERRUPT", - "SYSMSG_OP_REG_RD", - "SYSMSG_OP_HOST_TRAP_ACK", - "SYSMSG_OP_TTRACE_PC" -}; - -static -const char* const OpGsSymbolic[] = { - "GS_OP_NOP", - "GS_OP_CUT", - "GS_OP_EMIT", - "GS_OP_EMIT_CUT" -}; - -} // namespace SendMsg -} // namespace AMDGPU -} // namespace llvm - using namespace llvm; namespace { @@ -637,7 +590,6 @@ bool parseCnt(int64_t &IntVal); OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands); - bool parseHwregOperand(int64_t &HwRegCode, int64_t &Offset, int64_t &Width, bool &IsIdentifier); OperandMatchResultTy parseHwreg(OperandVector &Operands); private: @@ -647,8 +599,8 @@ OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { } }; - bool parseSendMsg(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId); - + bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId); + bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width); public: OperandMatchResultTy parseOptionalOperand(OperandVector &Operands); @@ -1669,7 +1621,9 @@ return MatchOperand_Success; } -bool AMDGPUAsmParser::parseHwregOperand(int64_t &HwRegCode, int64_t &Offset, int64_t &Width, bool &IsIdentifier) { +bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width) { + using namespace llvm::AMDGPU::Hwreg; + if (Parser.getTok().getString() != "hwreg") return true; Parser.Lex(); @@ -1679,22 +1633,21 @@ Parser.Lex(); if (getLexer().is(AsmToken::Identifier)) { - IsIdentifier = true; - HwRegCode = StringSwitch(Parser.getTok().getString()) - .Case("HW_REG_MODE" , 1) - .Case("HW_REG_STATUS" , 2) - .Case("HW_REG_TRAPSTS" , 3) - .Case("HW_REG_HW_ID" , 4) - .Case("HW_REG_GPR_ALLOC", 5) - .Case("HW_REG_LDS_ALLOC", 6) - .Case("HW_REG_IB_STS" , 7) - .Default(-1); + HwReg.IsSymbolic = true; + HwReg.Id = ID_UNKNOWN_; + const StringRef tok = Parser.getTok().getString(); + for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) { + if (tok == IdSymbolic[i]) { + HwReg.Id = i; + break; + } + } Parser.Lex(); } else { - IsIdentifier = false; + HwReg.IsSymbolic = false; if (getLexer().isNot(AsmToken::Integer)) return true; - if (getParser().parseAbsoluteExpression(HwRegCode)) + if (getParser().parseAbsoluteExpression(HwReg.Id)) return true; } @@ -1731,6 +1684,8 @@ AMDGPUAsmParser::OperandMatchResultTy AMDGPUAsmParser::parseHwreg(OperandVector &Operands) { + using namespace llvm::AMDGPU::Hwreg; + int64_t Imm16Val = 0; SMLoc S = Parser.getTok().getLoc(); @@ -1739,7 +1694,7 @@ case AsmToken::Integer: // The operand can be an integer value. if (getParser().parseAbsoluteExpression(Imm16Val)) - return MatchOperand_ParseFail; + return MatchOperand_NoMatch; if (!isInt<16>(Imm16Val) && !isUInt<16>(Imm16Val)) { Error(S, "invalid immediate: only 16-bit values are legal"); // Do not return error code, but create an imm operand anyway and proceed @@ -1748,26 +1703,22 @@ break; case AsmToken::Identifier: { - bool IsIdentifier = false; - int64_t HwRegCode = -1; - int64_t Offset = 0; // default - int64_t Width = 32; // default - if (parseHwregOperand(HwRegCode, Offset, Width, IsIdentifier)) + OperandInfoTy HwReg(ID_UNKNOWN_); + int64_t Offset = OFFSET_DEFAULT_; + int64_t Width = WIDTH_DEFAULT_; + if (parseHwregConstruct(HwReg, Offset, Width)) return MatchOperand_ParseFail; - // HwRegCode (6) [5:0] - // Offset (5) [10:6] - // WidthMinusOne (5) [15:11] - if (HwRegCode < 0 || HwRegCode > 63) { - if (IsIdentifier) + if ((HwReg.Id & ~(ID_MASK_ >> ID_SHIFT_)) != 0) { + if (HwReg.IsSymbolic) Error(S, "invalid symbolic name of hardware register"); else Error(S, "invalid code of hardware register: only 6-bit values are legal"); } - if (Offset < 0 || Offset > 31) + if ((Offset & ~(OFFSET_MASK_ >> OFFSET_SHIFT_)) != 0) Error(S, "invalid bit offset: only 5-bit values are legal"); - if (Width < 1 || Width > 32) + if (((Width-1) & ~(WIDTH_MINUS_ONE_MASK_ >> WIDTH_MINUS_ONE_SHIFT_)) != 0) Error(S, "invalid bitfield width: only values from 1 to 32 are legal"); - Imm16Val = HwRegCode | (Offset << 6) | ((Width-1) << 11); + Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_MINUS_ONE_SHIFT_); } break; } @@ -1787,7 +1738,7 @@ return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyHwreg); } -bool AMDGPUAsmParser::parseSendMsg(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) { +bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) { using namespace llvm::AMDGPU::SendMsg; if (Parser.getTok().getString() != "sendmsg") @@ -1844,7 +1795,7 @@ const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic; const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_; const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_; - const std::string Tok = Parser.getTok().getString(); + const StringRef Tok = Parser.getTok().getString(); for (int i = F; i < L; ++i) { if (Tok == S[i]) { Operation.Id = i; @@ -1906,9 +1857,9 @@ case AsmToken::Identifier: { OperandInfoTy Msg(ID_UNKNOWN_); OperandInfoTy Operation(OP_UNKNOWN_); - int64_t StreamId = STREAM_ID_DEFAULT; - if (parseSendMsg(Msg, Operation, StreamId)) - return MatchOperand_NoMatch; + int64_t StreamId = STREAM_ID_DEFAULT_; + if (parseSendMsgConstruct(Msg, Operation, StreamId)) + return MatchOperand_ParseFail; do { // Validate and encode message ID. if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE) @@ -1919,7 +1870,7 @@ Error(S, "invalid/unsupported code of message"); break; } - Imm16Val = Msg.Id; + Imm16Val = (Msg.Id << ID_SHIFT_); // Validate and encode operation ID. if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) { if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) { Index: lib/Target/AMDGPU/Disassembler/CMakeLists.txt =================================================================== --- lib/Target/AMDGPU/Disassembler/CMakeLists.txt +++ lib/Target/AMDGPU/Disassembler/CMakeLists.txt @@ -4,4 +4,4 @@ AMDGPUDisassembler.cpp ) -add_dependencies(LLVMAMDGPUDisassembler AMDGPUCommonTableGen) +add_dependencies(LLVMAMDGPUDisassembler AMDGPUCommonTableGen LLVMAMDGPUUtils) Index: lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp =================================================================== --- lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp +++ lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp @@ -11,6 +11,7 @@ #include "AMDGPUInstPrinter.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" #include "SIDefines.h" +#include "Utils/AMDGPUAsmParserPrinter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" @@ -20,54 +21,6 @@ #include -// FIXME ODR: Move this to some common place for AsmParser and InstPrinter -namespace llvm { -namespace AMDGPU { -namespace SendMsg { - -// This must be in sync with llvm::AMDGPU::SendMsg::Id enum members. -static -const char* const IdSymbolic[] = { - nullptr, - "MSG_INTERRUPT", - "MSG_GS", - "MSG_GS_DONE", - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - "MSG_SYSMSG" -}; - -// These two must be in sync with llvm::AMDGPU::SendMsg::Op enum members. -static -const char* const OpSysSymbolic[] = { - nullptr, - "SYSMSG_OP_ECC_ERR_INTERRUPT", - "SYSMSG_OP_REG_RD", - "SYSMSG_OP_HOST_TRAP_ACK", - "SYSMSG_OP_TTRACE_PC" -}; - -static -const char* const OpGsSymbolic[] = { - "GS_OP_NOP", - "GS_OP_CUT", - "GS_OP_EMIT", - "GS_OP_EMIT_CUT" -}; - -} // namespace SendMsg -} // namespace AMDGPU -} // namespace llvm - using namespace llvm; void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, @@ -886,23 +839,20 @@ void AMDGPUInstPrinter::printHwreg(const MCInst *MI, unsigned OpNo, raw_ostream &O) { + using namespace llvm::AMDGPU::Hwreg; + unsigned SImm16 = MI->getOperand(OpNo).getImm(); - const unsigned HwRegCode = SImm16 & 0x3F; - const unsigned Offset = (SImm16 >> 6) & 0x1f; - const unsigned Width = ((SImm16 >> 11) & 0x1F) + 1; + const unsigned Id = (SImm16 & ID_MASK_) >> ID_SHIFT_; + const unsigned Offset = (SImm16 & OFFSET_MASK_) >> OFFSET_SHIFT_; + const unsigned Width = ((SImm16 & WIDTH_MINUS_ONE_MASK_) >> WIDTH_MINUS_ONE_SHIFT_) + 1; O << "hwreg("; - switch(HwRegCode) { - case 1: O << "HW_REG_MODE" ; break; - case 2: O << "HW_REG_STATUS" ; break; - case 3: O << "HW_REG_TRAPSTS" ; break; - case 4: O << "HW_REG_HW_ID" ; break; - case 5: O << "HW_REG_GPR_ALLOC" ; break; - case 6: O << "HW_REG_LDS_ALLOC" ; break; - case 7: O << "HW_REG_IB_STS" ; break; - default: O << HwRegCode; break; - } - if (! (Width == 32 && Offset == 0)) { + if (ID_SYMBOLIC_FIRST_ <= Id && Id < ID_SYMBOLIC_LAST_) { + O << IdSymbolic[Id]; + } else { + O << Id; + } + if (Width != WIDTH_DEFAULT_ || Offset != OFFSET_DEFAULT_) { O << ", " << Offset << ", " << Width; } O << ')'; Index: lib/Target/AMDGPU/InstPrinter/CMakeLists.txt =================================================================== --- lib/Target/AMDGPU/InstPrinter/CMakeLists.txt +++ lib/Target/AMDGPU/InstPrinter/CMakeLists.txt @@ -1,3 +1,5 @@ add_llvm_library(LLVMAMDGPUAsmPrinter AMDGPUInstPrinter.cpp ) + +add_dependencies(LLVMAMDGPUAsmPrinter LLVMAMDGPUUtils) Index: lib/Target/AMDGPU/InstPrinter/LLVMBuild.txt =================================================================== --- lib/Target/AMDGPU/InstPrinter/LLVMBuild.txt +++ lib/Target/AMDGPU/InstPrinter/LLVMBuild.txt @@ -19,6 +19,6 @@ type = Library name = AMDGPUAsmPrinter parent = AMDGPU -required_libraries = MC Support +required_libraries = MC Support AMDGPUUtils add_to_library_groups = AMDGPU Index: lib/Target/AMDGPU/SIDefines.h =================================================================== --- lib/Target/AMDGPU/SIDefines.h +++ lib/Target/AMDGPU/SIDefines.h @@ -130,11 +130,13 @@ ID_SYSMSG = 15, ID_GAPS_LAST_, // Indicate that sequence has gaps. ID_GAPS_FIRST_ = ID_INTERRUPT, - ID_MASK_ = 0xf + ID_SHIFT_ = 0, + ID_MASK_ = (0xf << ID_SHIFT_) }; enum Op { // Both GS and SYS operation IDs. OP_UNKNOWN_ = -1, + OP_SHIFT_ = 4, // width(2) [5:4] OP_GS_NOP = 0, OP_GS_CUT, @@ -142,7 +144,7 @@ OP_GS_EMIT_CUT, OP_GS_LAST_, OP_GS_FIRST_ = OP_GS_NOP, - OP_GS_MASK_ = (0x3 << 4), + OP_GS_MASK_ = (0x3 << OP_SHIFT_), // width(3) [6:4] OP_SYS_ECC_ERR_INTERRUPT = 1, OP_SYS_REG_RD, @@ -150,19 +152,42 @@ OP_SYS_TTRACE_PC, OP_SYS_LAST_, OP_SYS_FIRST_ = OP_SYS_ECC_ERR_INTERRUPT, - OP_SYS_MASK_ = (0x7 << 4), - OP_SHIFT_ = 4 + OP_SYS_MASK_ = (0x7 << OP_SHIFT_) }; enum StreamId { // Stream ID, (2) [9:8]. - STREAM_ID_DEFAULT = 0, + STREAM_ID_DEFAULT_ = 0, STREAM_ID_LAST_ = 4, - STREAM_ID_FIRST_ = STREAM_ID_DEFAULT, - STREAM_ID_MASK_ = (0x3 << 8), - STREAM_ID_SHIFT_ = 8 + STREAM_ID_FIRST_ = STREAM_ID_DEFAULT_, + STREAM_ID_SHIFT_ = 8, + STREAM_ID_MASK_ = (0x3 << STREAM_ID_SHIFT_) }; } // namespace SendMsg + +namespace Hwreg { // Encoding of SIMM16 used in s_setreg/getreg* insns. + +enum Id { // HwRegCode, (6) [5:0] + ID_UNKNOWN_ = -1, + ID_SYMBOLIC_FIRST_ = 1, // There are corresponding symbolic names defined. + ID_SYMBOLIC_LAST_ = 8, + ID_SHIFT_ = 0, + ID_MASK_ = (0x3f << ID_SHIFT_) +}; + +enum Offset { // Offset, (5) [10:6] + OFFSET_DEFAULT_ = 0, + OFFSET_SHIFT_ = 6, + OFFSET_MASK_ = (0x1f << OFFSET_SHIFT_) +}; + +enum Width { // WidthMinusOne, (5) [15:11] + WIDTH_DEFAULT_ = 32, + WIDTH_MINUS_ONE_SHIFT_ = 11, + WIDTH_MINUS_ONE_MASK_ = (0x1f << WIDTH_MINUS_ONE_SHIFT_) +}; + +} // namespace Hwreg } // namespace AMDGPU } // namespace llvm Index: lib/Target/AMDGPU/Utils/AMDGPUAsmParserPrinter.h =================================================================== --- /dev/null +++ lib/Target/AMDGPU/Utils/AMDGPUAsmParserPrinter.h @@ -0,0 +1,31 @@ +//===-- AMDGPUAsmParserPrinter.h - Common code for AsmParser/InstPrinter --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AMDGPU_UTILS_AMDGPUASMPARSERPRINTER_H +#define LLVM_LIB_TARGET_AMDGPU_UTILS_AMDGPUASMPARSERPRINTER_H + +namespace llvm { +namespace AMDGPU { +namespace SendMsg { // Symbolic names for the sendmsg(...) syntax. + +extern const char* const IdSymbolic[]; +extern const char* const OpSysSymbolic[]; +extern const char* const OpGsSymbolic[]; + +} // namespace SendMsg + +namespace Hwreg { // Symbolic names for the hwreg(...) syntax. + +extern const char* const IdSymbolic[]; + +} // namespace Hwreg +} // namespace AMDGPU +} // namespace llvm + +#endif Index: lib/Target/AMDGPU/Utils/AMDGPUAsmParserPrinter.cpp =================================================================== --- /dev/null +++ lib/Target/AMDGPU/Utils/AMDGPUAsmParserPrinter.cpp @@ -0,0 +1,69 @@ +//===-- AMDGPUAsmParserPrinter.cpp - Common code for AsmParser/InstPrinter ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "AMDGPUAsmParserPrinter.h" + +namespace llvm { +namespace AMDGPU { +namespace SendMsg { + +// This must be in sync with llvm::AMDGPU::SendMsg::Id enum members, see SIDefines.h. +const char* const IdSymbolic[] = { + nullptr, + "MSG_INTERRUPT", + "MSG_GS", + "MSG_GS_DONE", + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + "MSG_SYSMSG" +}; + +// These two must be in sync with llvm::AMDGPU::SendMsg::Op enum members, see SIDefines.h. +const char* const OpSysSymbolic[] = { + nullptr, + "SYSMSG_OP_ECC_ERR_INTERRUPT", + "SYSMSG_OP_REG_RD", + "SYSMSG_OP_HOST_TRAP_ACK", + "SYSMSG_OP_TTRACE_PC" +}; + +const char* const OpGsSymbolic[] = { + "GS_OP_NOP", + "GS_OP_CUT", + "GS_OP_EMIT", + "GS_OP_EMIT_CUT" +}; + +} // namespace SendMsg + +namespace Hwreg { + +// This must be in sync with llvm::AMDGPU::Hwreg::ID_SYMBOLIC_FIRST_/LAST_, see SIDefines.h. +const char* const IdSymbolic[] = { + nullptr, + "HW_REG_MODE", + "HW_REG_STATUS", + "HW_REG_TRAPSTS", + "HW_REG_HW_ID", + "HW_REG_GPR_ALLOC", + "HW_REG_LDS_ALLOC", + "HW_REG_IB_STS" +}; + +} // namespace Hwreg +} // namespace AMDGPU +} // namespace llvm Index: lib/Target/AMDGPU/Utils/CMakeLists.txt =================================================================== --- lib/Target/AMDGPU/Utils/CMakeLists.txt +++ lib/Target/AMDGPU/Utils/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMAMDGPUUtils AMDGPUBaseInfo.cpp AMDKernelCodeTUtils.cpp + AMDGPUAsmParserPrinter.cpp ) Index: test/MC/AMDGPU/sopp-err.s =================================================================== --- test/MC/AMDGPU/sopp-err.s +++ test/MC/AMDGPU/sopp-err.s @@ -9,16 +9,16 @@ // GCN: error: invalid/unsupported symbolic name of message s_sendmsg sendmsg(MSG_INTERRUPT, 0) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(MSG_GS) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(MSG_GS, GS_OP_NOP) // GCN: error: invalid GS_OP: NOP is for GS_DONE only s_sendmsg sendmsg(MSG_GS, GS_OP_CUT, 0, 0) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(MSG_GSX, GS_OP_CUT, 0) // GCN: error: invalid/unsupported symbolic name of message @@ -30,13 +30,13 @@ // GCN: error: invalid stream id: only 2-bit values are legal s_sendmsg sendmsg(2) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(2, 0) // GCN: error: invalid GS_OP: NOP is for GS_DONE only s_sendmsg sendmsg(2, 3, 0, 0) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(2, 4, 1) // GCN: error: invalid code of GS_OP: only 2-bit values are legal @@ -45,16 +45,16 @@ // GCN: error: invalid stream id: only 2-bit values are legal s_sendmsg sendmsg(2, 2, 0, 0) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(MSG_GS_DONE, GS_OP_NOP, 0) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(15) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(15, 1, 0) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(15, 0) // GCN: error: invalid/unsupported code of SYSMSG_OP @@ -63,10 +63,10 @@ // GCN: error: invalid/unsupported code of SYSMSG_OP s_sendmsg sendmsg(MSG_SYSMSG) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(MSG_SYSMSG, SYSMSG_OP_ECC_ERR_INTERRUPT, 0) -// GCN: error: not a valid operand +// GCN: error: failed parsing operand s_sendmsg sendmsg(MSG_SYSMSG, 0) // GCN: error: invalid/unsupported code of SYSMSG_OP