//===- VarLenCodeEmitterGen.cpp - CEG for variable-length insts -----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // The CodeEmitterGen component for variable-length instructions. // // The basic CodeEmitterGen is almost exclusively designed for fixed- // length instructions. A good analogy for its encoding scheme is how printf // works: The (immutable) formatting string represent the fixed values in the // encoded instruction. Placeholders (i.e. %something), on the other hand, // represent encoding for instruction operands. // ``` // printf("1101 %src 1001 %dst", <encoded value for operand `src`>, // <encoded value for operand `dst`>); // ``` // VarLenCodeEmitterGen in this file provides an alternative encoding scheme // that works more like a C++ stream operator: // ``` // OS << 0b1101; // if (Cond) // OS << OperandEncoding0; // OS << 0b1001 << OperandEncoding1; // ``` // You are free to concatenate arbitrary types (and sizes) of encoding // fragments on any bit position, bringing more flexibilities on defining // encoding for variable-length instructions. // // In a more specific way, instruction encoding is represented by a DAG type // `Inst` field. Here is an example: // ``` // dag Inst = (descend 0b1101, (operand "$src", 4), 0b1001, // (operand "$dst", 4)); // ``` // It represents the following instruction encoding: // ``` // MSB LSB // 1101<encoding for operand src>1001<encoding for operand dst> // ``` // For more details about DAG operators in the above snippet, please // refer to \file include/llvm/Target/Target.td. // // VarLenCodeEmitter will convert the above DAG into the same helper function // generated by CodeEmitter, `MCCodeEmitter::getBinaryCodeForInstr` (except // for few details). // //===----------------------------------------------------------------------===// #include "VarLenCodeEmitterGen.h" #include "CodeGenHwModes.h" #include "CodeGenInstruction.h" #include "CodeGenTarget.h" #include "InfoByHwMode.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include <algorithm> usingnamespacellvm; namespace { class VarLenCodeEmitterGen { … }; } // end anonymous namespace // Get the name of custom encoder or decoder, if there is any. // Returns `{encoder name, decoder name}`. static std::pair<StringRef, StringRef> getCustomCoders(ArrayRef<Init *> Args) { … } VarLenInst::VarLenInst(const DagInit *DI, const RecordVal *TheDef) : … { … } void VarLenInst::buildRec(const DagInit *DI) { … } void VarLenCodeEmitterGen::run(raw_ostream &OS) { … } static void emitInstBits(raw_ostream &IS, raw_ostream &SS, const APInt &Bits, unsigned &Index) { … } void VarLenCodeEmitterGen::emitInstructionBaseValues( raw_ostream &OS, ArrayRef<const CodeGenInstruction *> NumberedInstructions, const CodeGenTarget &Target, AltEncodingTy Mode) { … } std::string VarLenCodeEmitterGen::getInstructionCases(const Record *R, const CodeGenTarget &Target) { … } std::string VarLenCodeEmitterGen::getInstructionCaseForEncoding( const Record *R, AltEncodingTy Mode, const VarLenInst &VLI, const CodeGenTarget &Target, int Indent) { … } void llvm::emitVarLenCodeEmitter(const RecordKeeper &R, raw_ostream &OS) { … }