1*0fca6ea1SDimitry Andric //===- VarLenCodeEmitterGen.cpp - CEG for variable-length insts -----------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // The CodeEmitterGen component for variable-length instructions. 10*0fca6ea1SDimitry Andric // 11*0fca6ea1SDimitry Andric // The basic CodeEmitterGen is almost exclusively designed for fixed- 12*0fca6ea1SDimitry Andric // length instructions. A good analogy for its encoding scheme is how printf 13*0fca6ea1SDimitry Andric // works: The (immutable) formatting string represent the fixed values in the 14*0fca6ea1SDimitry Andric // encoded instruction. Placeholders (i.e. %something), on the other hand, 15*0fca6ea1SDimitry Andric // represent encoding for instruction operands. 16*0fca6ea1SDimitry Andric // ``` 17*0fca6ea1SDimitry Andric // printf("1101 %src 1001 %dst", <encoded value for operand `src`>, 18*0fca6ea1SDimitry Andric // <encoded value for operand `dst`>); 19*0fca6ea1SDimitry Andric // ``` 20*0fca6ea1SDimitry Andric // VarLenCodeEmitterGen in this file provides an alternative encoding scheme 21*0fca6ea1SDimitry Andric // that works more like a C++ stream operator: 22*0fca6ea1SDimitry Andric // ``` 23*0fca6ea1SDimitry Andric // OS << 0b1101; 24*0fca6ea1SDimitry Andric // if (Cond) 25*0fca6ea1SDimitry Andric // OS << OperandEncoding0; 26*0fca6ea1SDimitry Andric // OS << 0b1001 << OperandEncoding1; 27*0fca6ea1SDimitry Andric // ``` 28*0fca6ea1SDimitry Andric // You are free to concatenate arbitrary types (and sizes) of encoding 29*0fca6ea1SDimitry Andric // fragments on any bit position, bringing more flexibilities on defining 30*0fca6ea1SDimitry Andric // encoding for variable-length instructions. 31*0fca6ea1SDimitry Andric // 32*0fca6ea1SDimitry Andric // In a more specific way, instruction encoding is represented by a DAG type 33*0fca6ea1SDimitry Andric // `Inst` field. Here is an example: 34*0fca6ea1SDimitry Andric // ``` 35*0fca6ea1SDimitry Andric // dag Inst = (descend 0b1101, (operand "$src", 4), 0b1001, 36*0fca6ea1SDimitry Andric // (operand "$dst", 4)); 37*0fca6ea1SDimitry Andric // ``` 38*0fca6ea1SDimitry Andric // It represents the following instruction encoding: 39*0fca6ea1SDimitry Andric // ``` 40*0fca6ea1SDimitry Andric // MSB LSB 41*0fca6ea1SDimitry Andric // 1101<encoding for operand src>1001<encoding for operand dst> 42*0fca6ea1SDimitry Andric // ``` 43*0fca6ea1SDimitry Andric // For more details about DAG operators in the above snippet, please 44*0fca6ea1SDimitry Andric // refer to \file include/llvm/Target/Target.td. 45*0fca6ea1SDimitry Andric // 46*0fca6ea1SDimitry Andric // VarLenCodeEmitter will convert the above DAG into the same helper function 47*0fca6ea1SDimitry Andric // generated by CodeEmitter, `MCCodeEmitter::getBinaryCodeForInstr` (except 48*0fca6ea1SDimitry Andric // for few details). 49*0fca6ea1SDimitry Andric // 50*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 51*0fca6ea1SDimitry Andric 52*0fca6ea1SDimitry Andric #include "VarLenCodeEmitterGen.h" 53*0fca6ea1SDimitry Andric #include "CodeGenHwModes.h" 54*0fca6ea1SDimitry Andric #include "CodeGenInstruction.h" 55*0fca6ea1SDimitry Andric #include "CodeGenTarget.h" 56*0fca6ea1SDimitry Andric #include "InfoByHwMode.h" 57*0fca6ea1SDimitry Andric #include "llvm/ADT/ArrayRef.h" 58*0fca6ea1SDimitry Andric #include "llvm/ADT/DenseMap.h" 59*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h" 60*0fca6ea1SDimitry Andric #include "llvm/TableGen/Error.h" 61*0fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h" 62*0fca6ea1SDimitry Andric 63*0fca6ea1SDimitry Andric #include <algorithm> 64*0fca6ea1SDimitry Andric 65*0fca6ea1SDimitry Andric using namespace llvm; 66*0fca6ea1SDimitry Andric 67*0fca6ea1SDimitry Andric namespace { 68*0fca6ea1SDimitry Andric 69*0fca6ea1SDimitry Andric class VarLenCodeEmitterGen { 70*0fca6ea1SDimitry Andric RecordKeeper &Records; 71*0fca6ea1SDimitry Andric 72*0fca6ea1SDimitry Andric // Representaton of alternative encodings used for HwModes. 73*0fca6ea1SDimitry Andric using AltEncodingTy = int; 74*0fca6ea1SDimitry Andric // Mode identifier when only one encoding is defined. 75*0fca6ea1SDimitry Andric const AltEncodingTy Universal = -1; 76*0fca6ea1SDimitry Andric // The set of alternative instruction encodings with a descriptive 77*0fca6ea1SDimitry Andric // name suffix to improve readability of the generated code. 78*0fca6ea1SDimitry Andric std::map<AltEncodingTy, std::string> Modes; 79*0fca6ea1SDimitry Andric 80*0fca6ea1SDimitry Andric DenseMap<Record *, DenseMap<AltEncodingTy, VarLenInst>> VarLenInsts; 81*0fca6ea1SDimitry Andric 82*0fca6ea1SDimitry Andric // Emit based values (i.e. fixed bits in the encoded instructions) 83*0fca6ea1SDimitry Andric void emitInstructionBaseValues( 84*0fca6ea1SDimitry Andric raw_ostream &OS, 85*0fca6ea1SDimitry Andric ArrayRef<const CodeGenInstruction *> NumberedInstructions, 86*0fca6ea1SDimitry Andric CodeGenTarget &Target, AltEncodingTy Mode); 87*0fca6ea1SDimitry Andric 88*0fca6ea1SDimitry Andric std::string getInstructionCases(Record *R, CodeGenTarget &Target); 89*0fca6ea1SDimitry Andric std::string getInstructionCaseForEncoding(Record *R, AltEncodingTy Mode, 90*0fca6ea1SDimitry Andric const VarLenInst &VLI, 91*0fca6ea1SDimitry Andric CodeGenTarget &Target, int I); 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric public: 94*0fca6ea1SDimitry Andric explicit VarLenCodeEmitterGen(RecordKeeper &R) : Records(R) {} 95*0fca6ea1SDimitry Andric 96*0fca6ea1SDimitry Andric void run(raw_ostream &OS); 97*0fca6ea1SDimitry Andric }; 98*0fca6ea1SDimitry Andric } // end anonymous namespace 99*0fca6ea1SDimitry Andric 100*0fca6ea1SDimitry Andric // Get the name of custom encoder or decoder, if there is any. 101*0fca6ea1SDimitry Andric // Returns `{encoder name, decoder name}`. 102*0fca6ea1SDimitry Andric static std::pair<StringRef, StringRef> getCustomCoders(ArrayRef<Init *> Args) { 103*0fca6ea1SDimitry Andric std::pair<StringRef, StringRef> Result; 104*0fca6ea1SDimitry Andric for (const auto *Arg : Args) { 105*0fca6ea1SDimitry Andric const auto *DI = dyn_cast<DagInit>(Arg); 106*0fca6ea1SDimitry Andric if (!DI) 107*0fca6ea1SDimitry Andric continue; 108*0fca6ea1SDimitry Andric const Init *Op = DI->getOperator(); 109*0fca6ea1SDimitry Andric if (!isa<DefInit>(Op)) 110*0fca6ea1SDimitry Andric continue; 111*0fca6ea1SDimitry Andric // syntax: `(<encoder | decoder> "function name")` 112*0fca6ea1SDimitry Andric StringRef OpName = cast<DefInit>(Op)->getDef()->getName(); 113*0fca6ea1SDimitry Andric if (OpName != "encoder" && OpName != "decoder") 114*0fca6ea1SDimitry Andric continue; 115*0fca6ea1SDimitry Andric if (!DI->getNumArgs() || !isa<StringInit>(DI->getArg(0))) 116*0fca6ea1SDimitry Andric PrintFatalError("expected '" + OpName + 117*0fca6ea1SDimitry Andric "' directive to be followed by a custom function name."); 118*0fca6ea1SDimitry Andric StringRef FuncName = cast<StringInit>(DI->getArg(0))->getValue(); 119*0fca6ea1SDimitry Andric if (OpName == "encoder") 120*0fca6ea1SDimitry Andric Result.first = FuncName; 121*0fca6ea1SDimitry Andric else 122*0fca6ea1SDimitry Andric Result.second = FuncName; 123*0fca6ea1SDimitry Andric } 124*0fca6ea1SDimitry Andric return Result; 125*0fca6ea1SDimitry Andric } 126*0fca6ea1SDimitry Andric 127*0fca6ea1SDimitry Andric VarLenInst::VarLenInst(const DagInit *DI, const RecordVal *TheDef) 128*0fca6ea1SDimitry Andric : TheDef(TheDef), NumBits(0U), HasDynamicSegment(false) { 129*0fca6ea1SDimitry Andric buildRec(DI); 130*0fca6ea1SDimitry Andric for (const auto &S : Segments) 131*0fca6ea1SDimitry Andric NumBits += S.BitWidth; 132*0fca6ea1SDimitry Andric } 133*0fca6ea1SDimitry Andric 134*0fca6ea1SDimitry Andric void VarLenInst::buildRec(const DagInit *DI) { 135*0fca6ea1SDimitry Andric assert(TheDef && "The def record is nullptr ?"); 136*0fca6ea1SDimitry Andric 137*0fca6ea1SDimitry Andric std::string Op = DI->getOperator()->getAsString(); 138*0fca6ea1SDimitry Andric 139*0fca6ea1SDimitry Andric if (Op == "ascend" || Op == "descend") { 140*0fca6ea1SDimitry Andric bool Reverse = Op == "descend"; 141*0fca6ea1SDimitry Andric int i = Reverse ? DI->getNumArgs() - 1 : 0; 142*0fca6ea1SDimitry Andric int e = Reverse ? -1 : DI->getNumArgs(); 143*0fca6ea1SDimitry Andric int s = Reverse ? -1 : 1; 144*0fca6ea1SDimitry Andric for (; i != e; i += s) { 145*0fca6ea1SDimitry Andric const Init *Arg = DI->getArg(i); 146*0fca6ea1SDimitry Andric if (const auto *BI = dyn_cast<BitsInit>(Arg)) { 147*0fca6ea1SDimitry Andric if (!BI->isComplete()) 148*0fca6ea1SDimitry Andric PrintFatalError(TheDef->getLoc(), 149*0fca6ea1SDimitry Andric "Expecting complete bits init in `" + Op + "`"); 150*0fca6ea1SDimitry Andric Segments.push_back({BI->getNumBits(), BI}); 151*0fca6ea1SDimitry Andric } else if (const auto *BI = dyn_cast<BitInit>(Arg)) { 152*0fca6ea1SDimitry Andric if (!BI->isConcrete()) 153*0fca6ea1SDimitry Andric PrintFatalError(TheDef->getLoc(), 154*0fca6ea1SDimitry Andric "Expecting concrete bit init in `" + Op + "`"); 155*0fca6ea1SDimitry Andric Segments.push_back({1, BI}); 156*0fca6ea1SDimitry Andric } else if (const auto *SubDI = dyn_cast<DagInit>(Arg)) { 157*0fca6ea1SDimitry Andric buildRec(SubDI); 158*0fca6ea1SDimitry Andric } else { 159*0fca6ea1SDimitry Andric PrintFatalError(TheDef->getLoc(), "Unrecognized type of argument in `" + 160*0fca6ea1SDimitry Andric Op + "`: " + Arg->getAsString()); 161*0fca6ea1SDimitry Andric } 162*0fca6ea1SDimitry Andric } 163*0fca6ea1SDimitry Andric } else if (Op == "operand") { 164*0fca6ea1SDimitry Andric // (operand <operand name>, <# of bits>, 165*0fca6ea1SDimitry Andric // [(encoder <custom encoder>)][, (decoder <custom decoder>)]) 166*0fca6ea1SDimitry Andric if (DI->getNumArgs() < 2) 167*0fca6ea1SDimitry Andric PrintFatalError(TheDef->getLoc(), 168*0fca6ea1SDimitry Andric "Expecting at least 2 arguments for `operand`"); 169*0fca6ea1SDimitry Andric HasDynamicSegment = true; 170*0fca6ea1SDimitry Andric const Init *OperandName = DI->getArg(0), *NumBits = DI->getArg(1); 171*0fca6ea1SDimitry Andric if (!isa<StringInit>(OperandName) || !isa<IntInit>(NumBits)) 172*0fca6ea1SDimitry Andric PrintFatalError(TheDef->getLoc(), "Invalid argument types for `operand`"); 173*0fca6ea1SDimitry Andric 174*0fca6ea1SDimitry Andric auto NumBitsVal = cast<IntInit>(NumBits)->getValue(); 175*0fca6ea1SDimitry Andric if (NumBitsVal <= 0) 176*0fca6ea1SDimitry Andric PrintFatalError(TheDef->getLoc(), "Invalid number of bits for `operand`"); 177*0fca6ea1SDimitry Andric 178*0fca6ea1SDimitry Andric auto [CustomEncoder, CustomDecoder] = 179*0fca6ea1SDimitry Andric getCustomCoders(DI->getArgs().slice(2)); 180*0fca6ea1SDimitry Andric Segments.push_back({static_cast<unsigned>(NumBitsVal), OperandName, 181*0fca6ea1SDimitry Andric CustomEncoder, CustomDecoder}); 182*0fca6ea1SDimitry Andric } else if (Op == "slice") { 183*0fca6ea1SDimitry Andric // (slice <operand name>, <high / low bit>, <low / high bit>, 184*0fca6ea1SDimitry Andric // [(encoder <custom encoder>)][, (decoder <custom decoder>)]) 185*0fca6ea1SDimitry Andric if (DI->getNumArgs() < 3) 186*0fca6ea1SDimitry Andric PrintFatalError(TheDef->getLoc(), 187*0fca6ea1SDimitry Andric "Expecting at least 3 arguments for `slice`"); 188*0fca6ea1SDimitry Andric HasDynamicSegment = true; 189*0fca6ea1SDimitry Andric Init *OperandName = DI->getArg(0), *HiBit = DI->getArg(1), 190*0fca6ea1SDimitry Andric *LoBit = DI->getArg(2); 191*0fca6ea1SDimitry Andric if (!isa<StringInit>(OperandName) || !isa<IntInit>(HiBit) || 192*0fca6ea1SDimitry Andric !isa<IntInit>(LoBit)) 193*0fca6ea1SDimitry Andric PrintFatalError(TheDef->getLoc(), "Invalid argument types for `slice`"); 194*0fca6ea1SDimitry Andric 195*0fca6ea1SDimitry Andric auto HiBitVal = cast<IntInit>(HiBit)->getValue(), 196*0fca6ea1SDimitry Andric LoBitVal = cast<IntInit>(LoBit)->getValue(); 197*0fca6ea1SDimitry Andric if (HiBitVal < 0 || LoBitVal < 0) 198*0fca6ea1SDimitry Andric PrintFatalError(TheDef->getLoc(), "Invalid bit range for `slice`"); 199*0fca6ea1SDimitry Andric bool NeedSwap = false; 200*0fca6ea1SDimitry Andric unsigned NumBits = 0U; 201*0fca6ea1SDimitry Andric if (HiBitVal < LoBitVal) { 202*0fca6ea1SDimitry Andric NeedSwap = true; 203*0fca6ea1SDimitry Andric NumBits = static_cast<unsigned>(LoBitVal - HiBitVal + 1); 204*0fca6ea1SDimitry Andric } else { 205*0fca6ea1SDimitry Andric NumBits = static_cast<unsigned>(HiBitVal - LoBitVal + 1); 206*0fca6ea1SDimitry Andric } 207*0fca6ea1SDimitry Andric 208*0fca6ea1SDimitry Andric auto [CustomEncoder, CustomDecoder] = 209*0fca6ea1SDimitry Andric getCustomCoders(DI->getArgs().slice(3)); 210*0fca6ea1SDimitry Andric 211*0fca6ea1SDimitry Andric if (NeedSwap) { 212*0fca6ea1SDimitry Andric // Normalization: Hi bit should always be the second argument. 213*0fca6ea1SDimitry Andric Init *const NewArgs[] = {OperandName, LoBit, HiBit}; 214*0fca6ea1SDimitry Andric Segments.push_back({NumBits, 215*0fca6ea1SDimitry Andric DagInit::get(DI->getOperator(), nullptr, NewArgs, {}), 216*0fca6ea1SDimitry Andric CustomEncoder, CustomDecoder}); 217*0fca6ea1SDimitry Andric } else { 218*0fca6ea1SDimitry Andric Segments.push_back({NumBits, DI, CustomEncoder, CustomDecoder}); 219*0fca6ea1SDimitry Andric } 220*0fca6ea1SDimitry Andric } 221*0fca6ea1SDimitry Andric } 222*0fca6ea1SDimitry Andric 223*0fca6ea1SDimitry Andric void VarLenCodeEmitterGen::run(raw_ostream &OS) { 224*0fca6ea1SDimitry Andric CodeGenTarget Target(Records); 225*0fca6ea1SDimitry Andric auto Insts = Records.getAllDerivedDefinitions("Instruction"); 226*0fca6ea1SDimitry Andric 227*0fca6ea1SDimitry Andric auto NumberedInstructions = Target.getInstructionsByEnumValue(); 228*0fca6ea1SDimitry Andric 229*0fca6ea1SDimitry Andric for (const CodeGenInstruction *CGI : NumberedInstructions) { 230*0fca6ea1SDimitry Andric Record *R = CGI->TheDef; 231*0fca6ea1SDimitry Andric // Create the corresponding VarLenInst instance. 232*0fca6ea1SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" || 233*0fca6ea1SDimitry Andric R->getValueAsBit("isPseudo")) 234*0fca6ea1SDimitry Andric continue; 235*0fca6ea1SDimitry Andric 236*0fca6ea1SDimitry Andric // Setup alternative encodings according to HwModes 237*0fca6ea1SDimitry Andric if (const RecordVal *RV = R->getValue("EncodingInfos")) { 238*0fca6ea1SDimitry Andric if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { 239*0fca6ea1SDimitry Andric const CodeGenHwModes &HWM = Target.getHwModes(); 240*0fca6ea1SDimitry Andric EncodingInfoByHwMode EBM(DI->getDef(), HWM); 241*0fca6ea1SDimitry Andric for (auto &KV : EBM) { 242*0fca6ea1SDimitry Andric AltEncodingTy Mode = KV.first; 243*0fca6ea1SDimitry Andric Modes.insert({Mode, "_" + HWM.getMode(Mode).Name.str()}); 244*0fca6ea1SDimitry Andric Record *EncodingDef = KV.second; 245*0fca6ea1SDimitry Andric RecordVal *RV = EncodingDef->getValue("Inst"); 246*0fca6ea1SDimitry Andric DagInit *DI = cast<DagInit>(RV->getValue()); 247*0fca6ea1SDimitry Andric VarLenInsts[R].insert({Mode, VarLenInst(DI, RV)}); 248*0fca6ea1SDimitry Andric } 249*0fca6ea1SDimitry Andric continue; 250*0fca6ea1SDimitry Andric } 251*0fca6ea1SDimitry Andric } 252*0fca6ea1SDimitry Andric RecordVal *RV = R->getValue("Inst"); 253*0fca6ea1SDimitry Andric DagInit *DI = cast<DagInit>(RV->getValue()); 254*0fca6ea1SDimitry Andric VarLenInsts[R].insert({Universal, VarLenInst(DI, RV)}); 255*0fca6ea1SDimitry Andric } 256*0fca6ea1SDimitry Andric 257*0fca6ea1SDimitry Andric if (Modes.empty()) 258*0fca6ea1SDimitry Andric Modes.insert({Universal, ""}); // Base case, skip suffix. 259*0fca6ea1SDimitry Andric 260*0fca6ea1SDimitry Andric // Emit function declaration 261*0fca6ea1SDimitry Andric OS << "void " << Target.getName() 262*0fca6ea1SDimitry Andric << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" 263*0fca6ea1SDimitry Andric << " SmallVectorImpl<MCFixup> &Fixups,\n" 264*0fca6ea1SDimitry Andric << " APInt &Inst,\n" 265*0fca6ea1SDimitry Andric << " APInt &Scratch,\n" 266*0fca6ea1SDimitry Andric << " const MCSubtargetInfo &STI) const {\n"; 267*0fca6ea1SDimitry Andric 268*0fca6ea1SDimitry Andric // Emit instruction base values 269*0fca6ea1SDimitry Andric for (const auto &Mode : Modes) 270*0fca6ea1SDimitry Andric emitInstructionBaseValues(OS, NumberedInstructions, Target, Mode.first); 271*0fca6ea1SDimitry Andric 272*0fca6ea1SDimitry Andric if (Modes.size() > 1) { 273*0fca6ea1SDimitry Andric OS << " unsigned Mode = STI.getHwMode();\n"; 274*0fca6ea1SDimitry Andric } 275*0fca6ea1SDimitry Andric 276*0fca6ea1SDimitry Andric for (const auto &Mode : Modes) { 277*0fca6ea1SDimitry Andric // Emit helper function to retrieve base values. 278*0fca6ea1SDimitry Andric OS << " auto getInstBits" << Mode.second 279*0fca6ea1SDimitry Andric << " = [&](unsigned Opcode) -> APInt {\n" 280*0fca6ea1SDimitry Andric << " unsigned NumBits = Index" << Mode.second << "[Opcode][0];\n" 281*0fca6ea1SDimitry Andric << " if (!NumBits)\n" 282*0fca6ea1SDimitry Andric << " return APInt::getZeroWidth();\n" 283*0fca6ea1SDimitry Andric << " unsigned Idx = Index" << Mode.second << "[Opcode][1];\n" 284*0fca6ea1SDimitry Andric << " ArrayRef<uint64_t> Data(&InstBits" << Mode.second << "[Idx], " 285*0fca6ea1SDimitry Andric << "APInt::getNumWords(NumBits));\n" 286*0fca6ea1SDimitry Andric << " return APInt(NumBits, Data);\n" 287*0fca6ea1SDimitry Andric << " };\n"; 288*0fca6ea1SDimitry Andric } 289*0fca6ea1SDimitry Andric 290*0fca6ea1SDimitry Andric // Map to accumulate all the cases. 291*0fca6ea1SDimitry Andric std::map<std::string, std::vector<std::string>> CaseMap; 292*0fca6ea1SDimitry Andric 293*0fca6ea1SDimitry Andric // Construct all cases statement for each opcode 294*0fca6ea1SDimitry Andric for (Record *R : Insts) { 295*0fca6ea1SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" || 296*0fca6ea1SDimitry Andric R->getValueAsBit("isPseudo")) 297*0fca6ea1SDimitry Andric continue; 298*0fca6ea1SDimitry Andric std::string InstName = 299*0fca6ea1SDimitry Andric (R->getValueAsString("Namespace") + "::" + R->getName()).str(); 300*0fca6ea1SDimitry Andric std::string Case = getInstructionCases(R, Target); 301*0fca6ea1SDimitry Andric 302*0fca6ea1SDimitry Andric CaseMap[Case].push_back(std::move(InstName)); 303*0fca6ea1SDimitry Andric } 304*0fca6ea1SDimitry Andric 305*0fca6ea1SDimitry Andric // Emit initial function code 306*0fca6ea1SDimitry Andric OS << " const unsigned opcode = MI.getOpcode();\n" 307*0fca6ea1SDimitry Andric << " switch (opcode) {\n"; 308*0fca6ea1SDimitry Andric 309*0fca6ea1SDimitry Andric // Emit each case statement 310*0fca6ea1SDimitry Andric for (const auto &C : CaseMap) { 311*0fca6ea1SDimitry Andric const std::string &Case = C.first; 312*0fca6ea1SDimitry Andric const auto &InstList = C.second; 313*0fca6ea1SDimitry Andric 314*0fca6ea1SDimitry Andric ListSeparator LS("\n"); 315*0fca6ea1SDimitry Andric for (const auto &InstName : InstList) 316*0fca6ea1SDimitry Andric OS << LS << " case " << InstName << ":"; 317*0fca6ea1SDimitry Andric 318*0fca6ea1SDimitry Andric OS << " {\n"; 319*0fca6ea1SDimitry Andric OS << Case; 320*0fca6ea1SDimitry Andric OS << " break;\n" 321*0fca6ea1SDimitry Andric << " }\n"; 322*0fca6ea1SDimitry Andric } 323*0fca6ea1SDimitry Andric // Default case: unhandled opcode 324*0fca6ea1SDimitry Andric OS << " default:\n" 325*0fca6ea1SDimitry Andric << " std::string msg;\n" 326*0fca6ea1SDimitry Andric << " raw_string_ostream Msg(msg);\n" 327*0fca6ea1SDimitry Andric << " Msg << \"Not supported instr: \" << MI;\n" 328*0fca6ea1SDimitry Andric << " report_fatal_error(Msg.str().c_str());\n" 329*0fca6ea1SDimitry Andric << " }\n"; 330*0fca6ea1SDimitry Andric OS << "}\n\n"; 331*0fca6ea1SDimitry Andric } 332*0fca6ea1SDimitry Andric 333*0fca6ea1SDimitry Andric static void emitInstBits(raw_ostream &IS, raw_ostream &SS, const APInt &Bits, 334*0fca6ea1SDimitry Andric unsigned &Index) { 335*0fca6ea1SDimitry Andric if (!Bits.getNumWords()) { 336*0fca6ea1SDimitry Andric IS.indent(4) << "{/*NumBits*/0, /*Index*/0},"; 337*0fca6ea1SDimitry Andric return; 338*0fca6ea1SDimitry Andric } 339*0fca6ea1SDimitry Andric 340*0fca6ea1SDimitry Andric IS.indent(4) << "{/*NumBits*/" << Bits.getBitWidth() << ", " << "/*Index*/" 341*0fca6ea1SDimitry Andric << Index << "},"; 342*0fca6ea1SDimitry Andric 343*0fca6ea1SDimitry Andric SS.indent(4); 344*0fca6ea1SDimitry Andric for (unsigned I = 0; I < Bits.getNumWords(); ++I, ++Index) 345*0fca6ea1SDimitry Andric SS << "UINT64_C(" << utostr(Bits.getRawData()[I]) << "),"; 346*0fca6ea1SDimitry Andric } 347*0fca6ea1SDimitry Andric 348*0fca6ea1SDimitry Andric void VarLenCodeEmitterGen::emitInstructionBaseValues( 349*0fca6ea1SDimitry Andric raw_ostream &OS, ArrayRef<const CodeGenInstruction *> NumberedInstructions, 350*0fca6ea1SDimitry Andric CodeGenTarget &Target, AltEncodingTy Mode) { 351*0fca6ea1SDimitry Andric std::string IndexArray, StorageArray; 352*0fca6ea1SDimitry Andric raw_string_ostream IS(IndexArray), SS(StorageArray); 353*0fca6ea1SDimitry Andric 354*0fca6ea1SDimitry Andric IS << " static const unsigned Index" << Modes[Mode] << "[][2] = {\n"; 355*0fca6ea1SDimitry Andric SS << " static const uint64_t InstBits" << Modes[Mode] << "[] = {\n"; 356*0fca6ea1SDimitry Andric 357*0fca6ea1SDimitry Andric unsigned NumFixedValueWords = 0U; 358*0fca6ea1SDimitry Andric for (const CodeGenInstruction *CGI : NumberedInstructions) { 359*0fca6ea1SDimitry Andric Record *R = CGI->TheDef; 360*0fca6ea1SDimitry Andric 361*0fca6ea1SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" || 362*0fca6ea1SDimitry Andric R->getValueAsBit("isPseudo")) { 363*0fca6ea1SDimitry Andric IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\n"; 364*0fca6ea1SDimitry Andric continue; 365*0fca6ea1SDimitry Andric } 366*0fca6ea1SDimitry Andric 367*0fca6ea1SDimitry Andric const auto InstIt = VarLenInsts.find(R); 368*0fca6ea1SDimitry Andric if (InstIt == VarLenInsts.end()) 369*0fca6ea1SDimitry Andric PrintFatalError(R, "VarLenInst not found for this record"); 370*0fca6ea1SDimitry Andric auto ModeIt = InstIt->second.find(Mode); 371*0fca6ea1SDimitry Andric if (ModeIt == InstIt->second.end()) 372*0fca6ea1SDimitry Andric ModeIt = InstIt->second.find(Universal); 373*0fca6ea1SDimitry Andric if (ModeIt == InstIt->second.end()) { 374*0fca6ea1SDimitry Andric IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\t" << "// " << R->getName() 375*0fca6ea1SDimitry Andric << " no encoding\n"; 376*0fca6ea1SDimitry Andric continue; 377*0fca6ea1SDimitry Andric } 378*0fca6ea1SDimitry Andric const VarLenInst &VLI = ModeIt->second; 379*0fca6ea1SDimitry Andric unsigned i = 0U, BitWidth = VLI.size(); 380*0fca6ea1SDimitry Andric 381*0fca6ea1SDimitry Andric // Start by filling in fixed values. 382*0fca6ea1SDimitry Andric APInt Value(BitWidth, 0); 383*0fca6ea1SDimitry Andric auto SI = VLI.begin(), SE = VLI.end(); 384*0fca6ea1SDimitry Andric // Scan through all the segments that have fixed-bits values. 385*0fca6ea1SDimitry Andric while (i < BitWidth && SI != SE) { 386*0fca6ea1SDimitry Andric unsigned SegmentNumBits = SI->BitWidth; 387*0fca6ea1SDimitry Andric if (const auto *BI = dyn_cast<BitsInit>(SI->Value)) { 388*0fca6ea1SDimitry Andric for (unsigned Idx = 0U; Idx != SegmentNumBits; ++Idx) { 389*0fca6ea1SDimitry Andric auto *B = cast<BitInit>(BI->getBit(Idx)); 390*0fca6ea1SDimitry Andric Value.setBitVal(i + Idx, B->getValue()); 391*0fca6ea1SDimitry Andric } 392*0fca6ea1SDimitry Andric } 393*0fca6ea1SDimitry Andric if (const auto *BI = dyn_cast<BitInit>(SI->Value)) 394*0fca6ea1SDimitry Andric Value.setBitVal(i, BI->getValue()); 395*0fca6ea1SDimitry Andric 396*0fca6ea1SDimitry Andric i += SegmentNumBits; 397*0fca6ea1SDimitry Andric ++SI; 398*0fca6ea1SDimitry Andric } 399*0fca6ea1SDimitry Andric 400*0fca6ea1SDimitry Andric emitInstBits(IS, SS, Value, NumFixedValueWords); 401*0fca6ea1SDimitry Andric IS << '\t' << "// " << R->getName() << "\n"; 402*0fca6ea1SDimitry Andric if (Value.getNumWords()) 403*0fca6ea1SDimitry Andric SS << '\t' << "// " << R->getName() << "\n"; 404*0fca6ea1SDimitry Andric } 405*0fca6ea1SDimitry Andric IS.indent(4) << "{/*NumBits*/0, /*Index*/0}\n };\n"; 406*0fca6ea1SDimitry Andric SS.indent(4) << "UINT64_C(0)\n };\n"; 407*0fca6ea1SDimitry Andric 408*0fca6ea1SDimitry Andric OS << IndexArray << StorageArray; 409*0fca6ea1SDimitry Andric } 410*0fca6ea1SDimitry Andric 411*0fca6ea1SDimitry Andric std::string VarLenCodeEmitterGen::getInstructionCases(Record *R, 412*0fca6ea1SDimitry Andric CodeGenTarget &Target) { 413*0fca6ea1SDimitry Andric auto It = VarLenInsts.find(R); 414*0fca6ea1SDimitry Andric if (It == VarLenInsts.end()) 415*0fca6ea1SDimitry Andric PrintFatalError(R, "Parsed encoding record not found"); 416*0fca6ea1SDimitry Andric const auto &Map = It->second; 417*0fca6ea1SDimitry Andric 418*0fca6ea1SDimitry Andric // Is this instructions encoding universal (same for all modes)? 419*0fca6ea1SDimitry Andric // Allways true if there is only one mode. 420*0fca6ea1SDimitry Andric if (Map.size() == 1 && Map.begin()->first == Universal) { 421*0fca6ea1SDimitry Andric // Universal, just pick the first mode. 422*0fca6ea1SDimitry Andric AltEncodingTy Mode = Modes.begin()->first; 423*0fca6ea1SDimitry Andric const auto &Encoding = Map.begin()->second; 424*0fca6ea1SDimitry Andric return getInstructionCaseForEncoding(R, Mode, Encoding, Target, 6); 425*0fca6ea1SDimitry Andric } 426*0fca6ea1SDimitry Andric 427*0fca6ea1SDimitry Andric std::string Case; 428*0fca6ea1SDimitry Andric Case += " switch (Mode) {\n"; 429*0fca6ea1SDimitry Andric Case += " default: llvm_unreachable(\"Unhandled Mode\");\n"; 430*0fca6ea1SDimitry Andric for (const auto &Mode : Modes) { 431*0fca6ea1SDimitry Andric Case += " case " + itostr(Mode.first) + ": {\n"; 432*0fca6ea1SDimitry Andric const auto &It = Map.find(Mode.first); 433*0fca6ea1SDimitry Andric if (It == Map.end()) { 434*0fca6ea1SDimitry Andric Case += 435*0fca6ea1SDimitry Andric " llvm_unreachable(\"Undefined encoding in this mode\");\n"; 436*0fca6ea1SDimitry Andric } else { 437*0fca6ea1SDimitry Andric Case += 438*0fca6ea1SDimitry Andric getInstructionCaseForEncoding(R, It->first, It->second, Target, 8); 439*0fca6ea1SDimitry Andric } 440*0fca6ea1SDimitry Andric Case += " break;\n"; 441*0fca6ea1SDimitry Andric Case += " }\n"; 442*0fca6ea1SDimitry Andric } 443*0fca6ea1SDimitry Andric Case += " }\n"; 444*0fca6ea1SDimitry Andric return Case; 445*0fca6ea1SDimitry Andric } 446*0fca6ea1SDimitry Andric 447*0fca6ea1SDimitry Andric std::string VarLenCodeEmitterGen::getInstructionCaseForEncoding( 448*0fca6ea1SDimitry Andric Record *R, AltEncodingTy Mode, const VarLenInst &VLI, CodeGenTarget &Target, 449*0fca6ea1SDimitry Andric int I) { 450*0fca6ea1SDimitry Andric 451*0fca6ea1SDimitry Andric CodeGenInstruction &CGI = Target.getInstruction(R); 452*0fca6ea1SDimitry Andric 453*0fca6ea1SDimitry Andric std::string Case; 454*0fca6ea1SDimitry Andric raw_string_ostream SS(Case); 455*0fca6ea1SDimitry Andric // Populate based value. 456*0fca6ea1SDimitry Andric SS.indent(I) << "Inst = getInstBits" << Modes[Mode] << "(opcode);\n"; 457*0fca6ea1SDimitry Andric 458*0fca6ea1SDimitry Andric // Process each segment in VLI. 459*0fca6ea1SDimitry Andric size_t Offset = 0U; 460*0fca6ea1SDimitry Andric unsigned HighScratchAccess = 0U; 461*0fca6ea1SDimitry Andric for (const auto &ES : VLI) { 462*0fca6ea1SDimitry Andric unsigned NumBits = ES.BitWidth; 463*0fca6ea1SDimitry Andric const Init *Val = ES.Value; 464*0fca6ea1SDimitry Andric // If it's a StringInit or DagInit, it's a reference to an operand 465*0fca6ea1SDimitry Andric // or part of an operand. 466*0fca6ea1SDimitry Andric if (isa<StringInit>(Val) || isa<DagInit>(Val)) { 467*0fca6ea1SDimitry Andric StringRef OperandName; 468*0fca6ea1SDimitry Andric unsigned LoBit = 0U; 469*0fca6ea1SDimitry Andric if (const auto *SV = dyn_cast<StringInit>(Val)) { 470*0fca6ea1SDimitry Andric OperandName = SV->getValue(); 471*0fca6ea1SDimitry Andric } else { 472*0fca6ea1SDimitry Andric // Normalized: (slice <operand name>, <high bit>, <low bit>) 473*0fca6ea1SDimitry Andric const auto *DV = cast<DagInit>(Val); 474*0fca6ea1SDimitry Andric OperandName = cast<StringInit>(DV->getArg(0))->getValue(); 475*0fca6ea1SDimitry Andric LoBit = static_cast<unsigned>(cast<IntInit>(DV->getArg(2))->getValue()); 476*0fca6ea1SDimitry Andric } 477*0fca6ea1SDimitry Andric 478*0fca6ea1SDimitry Andric auto OpIdx = CGI.Operands.ParseOperandName(OperandName); 479*0fca6ea1SDimitry Andric unsigned FlatOpIdx = CGI.Operands.getFlattenedOperandNumber(OpIdx); 480*0fca6ea1SDimitry Andric StringRef CustomEncoder = 481*0fca6ea1SDimitry Andric CGI.Operands[OpIdx.first].EncoderMethodNames[OpIdx.second]; 482*0fca6ea1SDimitry Andric if (ES.CustomEncoder.size()) 483*0fca6ea1SDimitry Andric CustomEncoder = ES.CustomEncoder; 484*0fca6ea1SDimitry Andric 485*0fca6ea1SDimitry Andric SS.indent(I) << "Scratch.clearAllBits();\n"; 486*0fca6ea1SDimitry Andric SS.indent(I) << "// op: " << OperandName.drop_front(1) << "\n"; 487*0fca6ea1SDimitry Andric if (CustomEncoder.empty()) 488*0fca6ea1SDimitry Andric SS.indent(I) << "getMachineOpValue(MI, MI.getOperand(" 489*0fca6ea1SDimitry Andric << utostr(FlatOpIdx) << ")"; 490*0fca6ea1SDimitry Andric else 491*0fca6ea1SDimitry Andric SS.indent(I) << CustomEncoder << "(MI, /*OpIdx=*/" << utostr(FlatOpIdx); 492*0fca6ea1SDimitry Andric 493*0fca6ea1SDimitry Andric SS << ", /*Pos=*/" << utostr(Offset) << ", Scratch, Fixups, STI);\n"; 494*0fca6ea1SDimitry Andric 495*0fca6ea1SDimitry Andric SS.indent(I) << "Inst.insertBits(" << "Scratch.extractBits(" 496*0fca6ea1SDimitry Andric << utostr(NumBits) << ", " << utostr(LoBit) << ")" << ", " 497*0fca6ea1SDimitry Andric << Offset << ");\n"; 498*0fca6ea1SDimitry Andric 499*0fca6ea1SDimitry Andric HighScratchAccess = std::max(HighScratchAccess, NumBits + LoBit); 500*0fca6ea1SDimitry Andric } 501*0fca6ea1SDimitry Andric Offset += NumBits; 502*0fca6ea1SDimitry Andric } 503*0fca6ea1SDimitry Andric 504*0fca6ea1SDimitry Andric StringRef PostEmitter = R->getValueAsString("PostEncoderMethod"); 505*0fca6ea1SDimitry Andric if (!PostEmitter.empty()) 506*0fca6ea1SDimitry Andric SS.indent(I) << "Inst = " << PostEmitter << "(MI, Inst, STI);\n"; 507*0fca6ea1SDimitry Andric 508*0fca6ea1SDimitry Andric // Resize the scratch buffer if it's to small. 509*0fca6ea1SDimitry Andric std::string ScratchResizeStr; 510*0fca6ea1SDimitry Andric if (VLI.size() && !VLI.isFixedValueOnly()) { 511*0fca6ea1SDimitry Andric raw_string_ostream RS(ScratchResizeStr); 512*0fca6ea1SDimitry Andric RS.indent(I) << "if (Scratch.getBitWidth() < " << HighScratchAccess 513*0fca6ea1SDimitry Andric << ") { Scratch = Scratch.zext(" << HighScratchAccess 514*0fca6ea1SDimitry Andric << "); }\n"; 515*0fca6ea1SDimitry Andric } 516*0fca6ea1SDimitry Andric 517*0fca6ea1SDimitry Andric return ScratchResizeStr + Case; 518*0fca6ea1SDimitry Andric } 519*0fca6ea1SDimitry Andric 520*0fca6ea1SDimitry Andric namespace llvm { 521*0fca6ea1SDimitry Andric 522*0fca6ea1SDimitry Andric void emitVarLenCodeEmitter(RecordKeeper &R, raw_ostream &OS) { 523*0fca6ea1SDimitry Andric VarLenCodeEmitterGen(R).run(OS); 524*0fca6ea1SDimitry Andric } 525*0fca6ea1SDimitry Andric 526*0fca6ea1SDimitry Andric } // end namespace llvm 527