Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

find_include_path bugfix #2197

Closed
wants to merge 12 commits into from
60 changes: 60 additions & 0 deletions python/tvm/_ffi/libinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,66 @@ def find_lib_path(name=None, search_path=None, optional=False):
return lib_found


def find_include_path(name=None, search_path=None, optional=False):
"""Find header files for C compilation.

Parameters
----------
name : list of str
List of directory names to be searched.

Returns
-------
include_path : list(string)
List of all found paths to header files.
"""
ffi_dir = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
source_dir = os.path.join(ffi_dir, "..", "..", "..")
install_include_dir = os.path.join(ffi_dir, "..", "..", "..", "..")
third_party_dir = os.path.join(source_dir, "3rdparty")

header_path = []

if os.environ.get('TVM_INCLUDE_PATH', None):
header_path.append(os.environ['TVM_INCLUDE_PATH'])

header_path.append(install_include_dir)
header_path.append(source_dir)
header_path.append(third_party_dir)

header_path = [os.path.abspath(x) for x in header_path]
if search_path is not None:
if search_path is list:
header_path = header_path + search_path
else:
header_path.append(search_path)
if name is not None:
if isinstance(name, list):
tvm_include_path = []
for n in name:
tvm_include_path += [os.path.join(p, n) for p in header_path]
else:
tvm_include_path = [os.path.join(p, name) for p in header_path]
dlpack_include_path = []
else:
tvm_include_path = [os.path.join(p, 'include') for p in header_path]
dlpack_include_path = [os.path.join(p, 'dlpack/include') for p in header_path]

# try to find include path
include_found = [p for p in tvm_include_path if os.path.exists(p) and os.path.isdir(p)]
include_found += [p for p in dlpack_include_path if os.path.exists(p) and os.path.isdir(p)]

if not include_found:
message = ('Cannot find the files.\n' +
'List of candidates:\n' +
str('\n'.join(tvm_include_path + dlpack_include_path)))
if not optional:
raise RuntimeError(message)
return None

return include_found


# current version
# We use the version of the incoming release for code
# that is under development.
Expand Down
1 change: 1 addition & 0 deletions python/tvm/_ffi/runtime_ctypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class TVMContext(ctypes.Structure):
'llvm': 1,
'stackvm': 1,
'cpu': 1,
'c': 1,
'gpu': 2,
'cuda': 2,
'nvptx': 2,
Expand Down
15 changes: 11 additions & 4 deletions python/tvm/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from ._ffi.function import ModuleBase, _set_class_module
from ._ffi.function import _init_api
from ._ffi.libinfo import find_include_path
from .contrib import cc as _cc, tar as _tar, util as _util

ProfileResult = namedtuple("ProfileResult", ["mean", "results"])
Expand Down Expand Up @@ -97,17 +98,21 @@ def export_library(self,
self.save(file_name)
return

if self.type_key != "llvm":
raise ValueError("Module[%s]: Only llvm support export shared" % self.type_key)
if not (self.type_key == "llvm" or self.type_key == "c"):
raise ValueError("Module[%s]: Only llvm and c support export shared" % self.type_key)
temp = _util.tempdir()
if fcompile is not None and hasattr(fcompile, "object_format"):
object_format = fcompile.object_format
else:
object_format = "o"
if self.type_key == "llvm":
object_format = "o"
else:
assert self.type_key == "c"
object_format = "cc"
path_obj = temp.relpath("lib." + object_format)
self.save(path_obj)
files = [path_obj]
is_system_lib = self.get_function("__tvm_is_system_module")()
is_system_lib = self.type_key == "llvm" and self.get_function("__tvm_is_system_module")()
if self.imported_modules:
path_cc = temp.relpath("devc.cc")
with open(path_cc, "w") as f:
Expand All @@ -118,6 +123,8 @@ def export_library(self,
fcompile = _tar.tar
else:
fcompile = _cc.create_shared
if self.type_key == "c":
kwargs.update({'options': ["-I" + path for path in find_include_path()]})
fcompile(file_name, files, **kwargs)

def time_evaluator(self, func_name, ctx, number, repeat=1):
Expand Down
44 changes: 39 additions & 5 deletions src/codegen/codegen_c.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,43 @@ void CodeGenC::InitFuncState(LoweredFunc f) {
handle_data_type_.clear();
CodeGenSourceBase::ClearFuncState();
}
void CodeGenC::AddFunction(LoweredFunc f) {
// clear previous generated state.
this->InitFuncState(f);

void CodeGenC::ReserveKeywordsAsUnique() {
// skip the first underscore, so SSA variable starts from _1
GetUniqueName("_");
GetUniqueName("extern");
GetUniqueName("void");
GetUniqueName("int");
GetUniqueName("float");
GetUniqueName("double");
GetUniqueName("char");
GetUniqueName("unsigned");
GetUniqueName("short");
GetUniqueName("long");
GetUniqueName("if");
GetUniqueName("else");
GetUniqueName("switch");
GetUniqueName("case");
GetUniqueName("default");
GetUniqueName("for");
GetUniqueName("do");
GetUniqueName("while");
GetUniqueName("goto");
GetUniqueName("register");
GetUniqueName("continue");
GetUniqueName("break");
GetUniqueName("typedef");
GetUniqueName("struct");
GetUniqueName("enum");
GetUniqueName("union");
GetUniqueName("return");
}

void CodeGenC::AddFunction(LoweredFunc f) {
// clear previous generated state.
this->InitFuncState(f);
// reserve keywords
ReserveKeywordsAsUnique();
// add to alloc buffer type.
for (const auto & kv : f->handle_data_type) {
RegisterHandleType(kv.first.get(), kv.second.type());
Expand Down Expand Up @@ -187,6 +218,7 @@ std::string CodeGenC::GetStructRef(
case intrinsic::kArrNDim: os << "ndim"; break;
case intrinsic::kArrTypeCode: os << "dtype.code"; break;
case intrinsic::kArrTypeBits: os << "dtype.bits"; break;
case intrinsic::kArrByteOffset: os << "byte_offset"; break;
case intrinsic::kArrTypeLanes: os << "dtype.lanes"; break;
case intrinsic::kArrDeviceId: os << "ctx.device_id"; break;
case intrinsic::kArrDeviceType: os << "ctx.device_type"; break;
Expand Down Expand Up @@ -834,8 +866,10 @@ void CodeGenC::VisitStmt_(const Evaluate *op) {
}
}
std::string vid = this->PrintExpr(op->value);
this->PrintIndent();
this->stream << "(void)" << vid << ";\n";
if (vid != "") {
this->PrintIndent();
this->stream << "(void)" << vid << ";\n";
}
}

void CodeGenC::VisitStmt_(const ProducerConsumer *op) {
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/codegen_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ class CodeGenC :
std::unordered_map<const Variable*, std::string> alloc_storage_scope_;
/*! \brief the data type of allocated buffers */
std::unordered_map<const Variable*, Type> handle_data_type_;
/*! \brief reserves common C keywords */
void ReserveKeywordsAsUnique();

private:
/*! \brief whether to print in SSA form */
Expand Down
Loading