Program Listing for File base.h#
↰ Return to documentation for file (tvm/script/ir_builder/base.h)
/*
* 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.
*/
#ifndef TVM_SCRIPT_IR_BUILDER_BASE_H_
#define TVM_SCRIPT_IR_BUILDER_BASE_H_
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ir/expr.h>
#include <tvm/ir/function.h>
#include <tvm/ir/object_functor.h>
#include <cstdint>
#include <vector>
namespace tvm {
namespace script {
namespace ir_builder {
class TVM_TIRX_DLL IRBuilderFrameObj : public ffi::Object {
public:
IRBuilderFrameObj();
std::vector<ffi::TypedFunction<void()>> callbacks;
mutable Location loc = UnknownLoc();
static void RegisterReflection() {
namespace refl = tvm::ffi::reflection;
refl::ObjectDef<IRBuilderFrameObj>().def_ro("loc", &IRBuilderFrameObj::loc);
// `callbacks` is not registered as it's not visited.
}
static constexpr const bool _type_mutable = true;
TVM_FFI_DECLARE_OBJECT_INFO("script.ir_builder.IRBuilderFrame", IRBuilderFrameObj, ffi::Object);
public:
virtual ~IRBuilderFrameObj() = default;
virtual void EnterWithScope();
virtual void ExitWithScope();
void AddCallback(ffi::TypedFunction<void()> callback);
};
class IRBuilderFrame : public ffi::ObjectRef {
public:
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(IRBuilderFrame, ffi::ObjectRef, IRBuilderFrameObj);
protected:
IRBuilderFrame() = default;
explicit IRBuilderFrame(ffi::ObjectPtr<IRBuilderFrameObj> data) : ffi::ObjectRef(data) {}
public:
inline void EnterWithScope() {
TVM_FFI_ICHECK(data_ != nullptr);
static_cast<IRBuilderFrameObj*>(data_.get())->EnterWithScope();
}
inline void ExitWithScope() {
TVM_FFI_ICHECK(data_ != nullptr);
static_cast<IRBuilderFrameObj*>(data_.get())->ExitWithScope();
data_.reset();
}
};
class IRBuilderObj : public ffi::Object {
public:
ffi::Array<IRBuilderFrame> frames;
ffi::Optional<ffi::ObjectRef> result;
std::vector<Location> locs;
static void RegisterReflection() {
namespace refl = tvm::ffi::reflection;
refl::ObjectDef<IRBuilderObj>()
.def_ro("frames", &IRBuilderObj::frames)
.def_ro("result", &IRBuilderObj::result);
}
static constexpr const bool _type_mutable = true;
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("script.ir_builder.IRBuilder", IRBuilderObj, ffi::Object);
public:
template <typename TFrame>
inline ffi::Optional<TFrame> FindFrame() const;
template <typename TFrame>
inline ffi::Optional<TFrame> GetLastFrame() const;
template <typename TObjectRef>
inline TObjectRef Get() const;
int64_t PushLoc(Location loc) {
locs.push_back(std::move(loc));
return static_cast<int64_t>(locs.size()) - 1;
}
void UpdateLoc(int64_t index, Location loc) {
TVM_FFI_CHECK(index >= 0 && static_cast<size_t>(index) < locs.size(), ValueError)
<< "Invalid source location scope";
locs[index] = std::move(loc);
}
void PopLoc() {
TVM_FFI_CHECK(!locs.empty(), ValueError)
<< "ValueError: No source location exists in the builder scope";
locs.pop_back();
}
TVM_TIRX_DLL Location ResolveLoc(Location location = UnknownLoc()) const;
TVM_TIRX_DLL ffi::ObjectRef AttachLoc(ffi::ObjectRef obj, Location loc = UnknownLoc()) const;
};
class IRBuilder : public ffi::ObjectRef {
public:
IRBuilder() { data_ = ffi::make_object<IRBuilderObj>(); }
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(IRBuilder, ffi::ObjectRef, IRBuilderObj);
public:
TVM_TIRX_DLL void EnterWithScope();
TVM_TIRX_DLL void ExitWithScope();
TVM_TIRX_DLL static IRBuilder Current();
TVM_TIRX_DLL static bool IsInScope();
template <class TObjectRef>
inline static TObjectRef Name(ffi::String name, TObjectRef obj);
};
namespace detail {
class LocationAccessor {
public:
using FType = ObjectFunctor<Location*(const ffi::ObjectRef&)>;
TVM_TIRX_DLL static FType& vtable();
};
class Namer {
public:
using FType = ObjectFunctor<void(const ffi::ObjectRef&, ffi::String)>;
TVM_TIRX_DLL static FType& vtable();
TVM_TIRX_DLL static void Name(ffi::ObjectRef node, ffi::String name);
};
} // namespace detail
template <class TObjectRef>
inline TObjectRef IRBuilder::Name(ffi::String name, TObjectRef obj) {
detail::Namer::Name(obj, name);
return obj.template as_or_throw<TObjectRef>();
}
template <typename TFrame>
inline ffi::Optional<TFrame> IRBuilderObj::FindFrame() const {
using TFrameNode = typename TFrame::ContainerType;
for (auto it = frames.rbegin(); it != frames.rend(); ++it) {
if (const TFrameNode* p = (*it).template as<TFrameNode>()) {
return ffi::GetRef<TFrame>(p);
}
}
return std::nullopt;
}
template <typename TFrame>
inline ffi::Optional<TFrame> IRBuilderObj::GetLastFrame() const {
using TFrameNode = typename TFrame::ContainerType;
if (!frames.empty() && frames.back()->IsInstance<TFrameNode>()) {
return frames.back().template as_or_throw<TFrame>();
}
return std::nullopt;
}
template <typename TObjectRef>
inline TObjectRef IRBuilderObj::Get() const {
using TObject = typename TObjectRef::ContainerType;
TVM_FFI_CHECK(result.has_value(), IndexError) << "No result exists in IRBuilder yet";
const auto* n = result.as<TObject>();
TVM_FFI_CHECK(n != nullptr, TypeError)
<< "IRBuilder result is not of type: " << TObject::_type_key;
return ffi::GetRef<TObjectRef>(n);
}
} // namespace ir_builder
} // namespace script
} // namespace tvm
#endif // TVM_SCRIPT_IR_BUILDER_BASE_H_