blob: f83240d6d87c5b70dc8300dbcfc280c23fe86859 [file]
/*
* 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 codegen_source_base.cc
*/
#include "codegen_source_base.h"
#include <algorithm>
namespace tvm {
namespace codegen {
void CodeGenSourceBase::ClearFuncState() {
name_supply_ = UniqueNameSupply();
ssa_assign_map_.clear();
var_idmap_.clear();
scope_mark_.clear();
}
std::string CodeGenSourceBase::SSAGetID(std::string src, const Type& t) {
TVM_FFI_ICHECK(t.as<PrimTypeNode>() || t.as<PointerTypeNode>())
<< "Cannot assign an SSA value of type " << t;
if (name_supply_->ContainsName(src)) return src;
auto it = ssa_assign_map_.find(src);
if (it != ssa_assign_map_.end()) {
if (scope_mark_.at(it->second.scope_id)) {
return it->second.vid;
}
}
SSAEntry e;
// use v_ prefix so it works for most systems
e.vid = name_supply_->FreshName("v_");
e.scope_id = static_cast<int>(scope_mark_.size() - 1);
ssa_assign_map_[src] = e;
this->PrintIndent();
PrintSSAAssign(e.vid, src, t);
return e.vid;
}
std::string CodeGenSourceBase::AllocVarID(const tirx::VarNode* v) { return AllocVarID(v, v->name); }
std::string CodeGenSourceBase::AllocVarID(const tirx::VarNode* v, std::string name_hint) {
TVM_FFI_ICHECK(!var_idmap_.count(v)) << "Need input to be in SSA form dup " << v->name;
std::string vid = name_supply_->FreshName(name_hint);
std::replace(vid.begin(), vid.end(), ':', '_');
std::replace(vid.begin(), vid.end(), '-', '_');
std::replace(vid.begin(), vid.end(), '.', '_');
var_idmap_[v] = vid;
return vid;
}
std::string CodeGenSourceBase::GetVarID(const tirx::VarNode* v) const {
auto it = var_idmap_.find(v);
TVM_FFI_ICHECK(it != var_idmap_.end()) << "Find undefined Variable " << v->name;
return it->second;
}
void CodeGenSourceBase::PrintIndent() {
for (int i = 0; i < indent_; ++i) {
this->stream << ' ';
}
}
void CodeGenSourceBase::MarkConst(std::string vid) {
auto it = ssa_assign_map_.find(vid);
if (it == ssa_assign_map_.end()) {
SSAEntry e;
e.vid = vid;
e.scope_id = 0;
ssa_assign_map_[vid] = e;
} else {
TVM_FFI_ICHECK_EQ(it->second.vid, vid);
}
}
int CodeGenSourceBase::BeginScope() {
int sid = static_cast<int>(scope_mark_.size());
scope_mark_.push_back(true);
indent_ += 2;
return sid;
}
void CodeGenSourceBase::EndScope(int scope_id) {
scope_mark_[scope_id] = false;
indent_ -= 2;
}
void CodeGenSourceBase::PrintType(const PrimType& type, std::ostream& os) { // NOLINT(*)
int lanes = type.lanes();
TVM_FFI_ICHECK_EQ(lanes, 1) << "do not yet support vector types";
if (type.IsVoid()) {
os << "void";
return;
}
// default c may be have bool type, can be handled in subclass
if (type.MatchesCode(kDLBool)) {
os << "int";
return;
}
if (type.MatchesCode(kDLFloat)) {
if (type.bits() == 32) {
os << "float";
return;
}
if (type.bits() == 64) {
os << "double";
return;
}
} else if (type.MatchesCode(kDLUInt)) {
switch (type.bits()) {
case 8:
case 16:
case 32:
case 64: {
os << "uint" << type.bits() << "_t";
return;
}
case 1:
os << "int";
return;
}
} else if (type.MatchesCode(kDLInt)) {
switch (type.bits()) {
case 8:
case 16:
case 32:
case 64: {
os << "int" << type.bits() << "_t";
return;
}
}
}
TVM_FFI_THROW(InternalError) << "Cannot convert type " << type << " to C type";
}
void CodeGenSourceBase::PrintType(const Type& type, std::ostream& os) { // NOLINT(*)
if (auto* ptr = type.as<PrimTypeNode>()) {
return PrintType(ffi::GetRef<PrimType>(ptr), os);
} else if (auto* ptr = type.as<PointerTypeNode>()) {
PrintType(ptr->element_type, os);
os << '*';
} else if (IsVoidType(type)) {
os << "void";
} else {
TVM_FFI_THROW(InternalError) << "Type " << type << " does not have a corresponding C Type";
}
}
} // namespace codegen
} // namespace tvm