chore: import upstream snapshot with attribution
Lint / lint (push) Waiting to run
CI / MacOS (push) Waiting to run
CI / Windows (push) Waiting to run

This commit is contained in:
wehub-resource-sync
2026-07-13 13:36:25 +08:00
commit 26446540fa
3151 changed files with 974126 additions and 0 deletions
+246
View File
@@ -0,0 +1,246 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*!
* \file tvm/runtime/vm/bytecode.h
* \brief The bytecode for the virtual machine.
*/
#ifndef TVM_RUNTIME_VM_BYTECODE_H_
#define TVM_RUNTIME_VM_BYTECODE_H_
#include <tvm/ffi/dtype.h>
#include <tvm/ffi/error.h>
#include <iostream>
#include <vector>
namespace tvm {
namespace runtime {
namespace vm {
/*!
* \brief The storage type for the bytecode in the VM.
*/
using ExecWord = int64_t;
/*! \brief A register name. */
using RegName = ExecWord;
/*!
* \brief An alias for the integer type used ubiquitously in the VM.
*/
using Index = ExecWord;
/*!
* \brief An enumeration of Relax's opcodes.
*
* The opcode is used to implement instruction
* as a tagged union.
*/
enum class Opcode {
Call = 1U,
Ret = 2U,
Goto = 3U,
If = 4U,
};
/*! \brief A single virtual machine instruction.
*
* The representation of the instruction is as
* a tagged union.
*
* The first field represents which instruction,
* and by extension which field of the union
* is active.
*/
struct Instruction {
/*! \brief The number of bit for storing value. */
static constexpr ExecWord kKindBit = 8;
/*! \brief The number of bit for storing value. */
static constexpr ExecWord kValueBit = sizeof(ExecWord) * 8 - kKindBit;
/*! \brief The bit mask of the value part. */
static constexpr ExecWord kValueMask = (static_cast<ExecWord>(1) << kValueBit) - 1;
/*! \brief Maximum possible value, use 1 bit for sign. */
static constexpr ExecWord kValueMaxLimit = (static_cast<ExecWord>(1) << (kValueBit - 1)) - 1;
/*! \brief Minimum possible value, remove 1 slot to keep things symmetric. */
static constexpr ExecWord kValueMinLimit = -kValueMaxLimit;
/*! \brief Beginning of special register section. */
static constexpr RegName kBeginSpecialReg = static_cast<ExecWord>(1) << 54;
/*! \brief Random magic number that represents void argument, indicate null value */
static constexpr RegName kVoidRegister = kBeginSpecialReg + 0;
/*! \brief Random magic number that represents the VM context */
static constexpr RegName kVMRegister = kBeginSpecialReg + 1;
/*!
* \brief The kind of instruction's argument.
*/
enum class ArgKind : int { kRegister = 0, kImmediate = 1, kConstIdx = 2, kFuncIdx = 3 };
friend std::ostream& operator<<(std::ostream& os, const ArgKind& kind) {
switch (kind) {
case ArgKind::kRegister:
os << "kRegister";
break;
case ArgKind::kImmediate:
os << "kImmediate";
break;
case ArgKind::kConstIdx:
os << "kConstIdx";
break;
case ArgKind::kFuncIdx:
os << "kFuncIdx";
break;
default:
TVM_FFI_THROW(InternalError)
<< "Internal error: "
<< "Invalid ArgKind with integer value " << static_cast<int>(kind);
}
return os;
}
/*!
* \brief The auxiliary data structure for instruction argument.
*/
class Arg {
public:
/*! \brief Construct a void argument. */
Arg() : data_(Instruction::kVoidRegister) {}
/*!
* \brief construct Arg from data.
* \param data The data repr.
*/
static Arg FromData(ExecWord data) { return Arg(data); }
/*!
* \brief construct a register Arg.
* \param reg The register number.
* \return The constructed arg.
*/
static Arg Register(RegName reg) { return Arg(ArgKind::kRegister, reg); }
/*!
* \brief construct a ConstIdx arg.
* \param index The constant index.
* \return The constructed arg.
*/
static Arg ConstIdx(Index index) { return Arg(ArgKind::kConstIdx, index); }
/*!
* \brief construct a immediate arg.
* \param imm_value The immediate value.
* \return The constructed arg.
*/
static Arg Immediate(int64_t imm_value) { return Arg(ArgKind::kImmediate, imm_value); }
/*!
* \brief construct a FuncIdx arg.
* \param index The func index in the function table.
* \return The constructed arg.
*/
static Arg FuncIdx(Index index) { return Arg(ArgKind::kFuncIdx, index); }
/*!
* \brief Get the kind of argument.
* \return The kind of argument.
*/
ArgKind kind() const {
uint8_t kind = (data_ >> kValueBit) & 0xFF;
return Instruction::ArgKind(kind);
}
/*!
* \brief Get the value of argument.
* \return The value of argument.
* \note We store both positive and negative values by sign extension.
*/
ExecWord value() const { return ((data_ & kValueMask) << kKindBit) >> kKindBit; }
/*!
* \brief Get the raw data repr of the arg.
* \return The raw data.
*/
ExecWord data() const { return data_; }
private:
/*! \brief Construct from the data. */
explicit Arg(ExecWord data) : data_(data) {}
/*! \brief Construct from the kind and value. */
Arg(ArgKind kind, Index value) {
TVM_FFI_ICHECK_LE(value, kValueMaxLimit);
TVM_FFI_ICHECK_GE(value, kValueMinLimit);
data_ = (static_cast<ExecWord>(kind) << kValueBit) | (value & kValueMask);
}
/*! \brief The underlying stored data. */
ExecWord data_;
};
/*! \brief The instruction opcode. */
Opcode op;
union {
struct /* Call */ {
/*! \brief The destination register. */
RegName dst;
/*! \brief The index into the packed function table. */
Index func_idx;
/*! \brief The number of arguments to the packed function. */
Index num_args;
/*! \brief The arguments of the packed function. */
Arg* args;
};
struct /* Ret */ {
/*! \brief The return result. */
RegName result;
};
struct /* Goto */ {
/*! \brief The jump offset. */
Index pc_offset;
};
struct /* If */ {
/*! \brief The register containing the cond value. */
RegName cond;
/*! \brief The program counter offset for the false branch. */
Index false_offset;
};
};
/*!
* \brief Construct a Call instruction.
* \param func_idx The index of the function to call.
* \param num_args The number of arguments.
* \param args The input arguments.
* \param dst The destination register.
* \return The call instruction.
*/
static Instruction Call(Index func_idx, Index num_args, Arg* args, RegName dst);
/*!
* \brief Construct a return instruction.
* \param result The register containing the return value.
* \return The return instruction.
*/
static Instruction Ret(RegName result);
/*!
* \brief Construct a goto instruction.
* \param pc_offset The register containing the jump offset.
* \return The goto instruction.
*/
static Instruction Goto(RegName pc_offset);
/*!
* \brief Construct an If instruction.
* \param cond The register containing the cond value.
* \param false_offset The program counter offset for the false branch.
* \return The If instruction.
*/
static Instruction If(RegName cond, Index false_offset);
};
} // namespace vm
} // namespace runtime
} // namespace tvm
#endif // TVM_RUNTIME_VM_BYTECODE_H_