Skip to content

Commit

Permalink
[Rust] Second stage of Rust Refactor (apache#5527)
Browse files Browse the repository at this point in the history
* Add tvm-rt crate

* Backport changes from frontend branch

* Format

* Add ASF headers

* Address self-code review

* Replace with helper

* Fix lint

* Fix

* Clean up repro debugging

* WIP

* Remove global resgistry to fix one memory issue

* Fix

* Format

* Format

* Update rust/tvm-rt/README.md

Co-authored-by: Jason Knight <binarybana@gmail.com>

* Format

* Duplicate TVM macros

* Split macros

* Restore old macro for old crates

* Repair macros

* Fix format

* Format

Co-authored-by: Jason Knight <binarybana@gmail.com>
  • Loading branch information
2 people authored and Trevor Morris committed Jun 12, 2020
1 parent f4e8cf1 commit f12956b
Show file tree
Hide file tree
Showing 38 changed files with 3,240 additions and 14 deletions.
2 changes: 2 additions & 0 deletions include/tvm/ir/expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@

namespace tvm {

using tvm::runtime::String;

/*!
* \brief Base type of all the expressions.
* \sa Expr
Expand Down
19 changes: 19 additions & 0 deletions include/tvm/runtime/c_runtime_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,15 @@ TVM_DLL int TVMObjectGetTypeIndex(TVMObjectHandle obj, unsigned* out_tindex);
*/
TVM_DLL int TVMObjectTypeKey2Index(const char* type_key, unsigned* out_tindex);

/*!
* \brief Increase the reference count of an object.
*
* \param obj The object handle.
* \note Internally we increase the reference counter of the object.
* \return 0 when success, -1 when failure happens
*/
TVM_DLL int TVMObjectRetain(TVMObjectHandle obj);

/*!
* \brief Free the object.
*
Expand Down Expand Up @@ -564,6 +573,16 @@ TVM_DLL int TVMDeviceCopyDataFromTo(const void* from, size_t from_offset, void*
TVMContext ctx_to, DLDataType type_hint,
TVMStreamHandle stream);

/*!
* \brief Check that an object is derived from another.
* \param child_type_index The type index of the derived type.
* \param parent_type_index The type index of the parent type.
* \param is_derived A boolean representing whether this predicate holds.
* \return 0 when success, -1 when failure happens.
*/
TVM_DLL int TVMObjectDerivedFrom(uint32_t child_type_index, uint32_t parent_type_index,
int* is_derived);

#ifdef __cplusplus
} // TVM_EXTERN_C
#endif
Expand Down
17 changes: 13 additions & 4 deletions include/tvm/runtime/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -511,11 +511,20 @@ class ArrayNode : public Object, public InplaceArrayBase<ArrayNode, ObjectRef> {
};

/*!
* \brief Array container of ObjectRef in DSL graph.
* Array implements copy-on-write semantics, which means array is mutable
* but copy will happen when array is referenced in more than two places.
* \brief Array, container representing a contigious sequence of ObjectRefs.
*
* operator[] only provide const access, use Set to mutate the content.
* Array implements in-place copy-on-write semantics.
*
* As in typical copy-on-write, a method which would typically mutate the array
* instead opaquely copies the underlying container, and then acts on its copy.
*
* If the array has reference count equal to one, we directly update the
* container in place without copying. This is optimization is sound because
* when the reference count is equal to one this reference is guranteed to be
* the sole pointer to the container.
*
*
* operator[] only provides const access, use Set to mutate the content.
* \tparam T The content ObjectRef type.
*/
template <typename T,
Expand Down
2 changes: 1 addition & 1 deletion python/tvm/runtime/object_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def asobject(self):


def convert_to_object(value):
"""Convert a python value to corresponding object type.
"""Convert a Python value to corresponding object type.
Parameters
----------
Expand Down
3 changes: 2 additions & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ members = [
"frontend/tests/basics",
"frontend/tests/callback",
"frontend/examples/resnet",
"tvm-sys"
"tvm-sys",
"tvm-rt"
]
6 changes: 3 additions & 3 deletions rust/macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# under the License.

[package]
name = "tvm-macros"
name = "old-tvm-macros"
version = "0.1.1"
license = "Apache-2.0"
description = "Procedural macros of the TVM crate."
Expand All @@ -32,5 +32,5 @@ proc-macro = true
[dependencies]
goblin = "0.0.24"
proc-macro2 = "^1.0"
quote = "1.0"
syn = "1.0"
quote = "^1.0"
syn = { version = "1.0.17", features = ["full", "extra-traits"] }
2 changes: 1 addition & 1 deletion rust/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
tvm-common = { version = "0.1", path = "../common" }
tvm-macros = { version = "0.1", path = "../macros" }
old-tvm-macros = { version = "0.1", path = "../macros" }

[target.'cfg(not(any(target_arch = "wasm32", target_env = "sgx")))'.dependencies]
libloading = "0.5"
1 change: 1 addition & 0 deletions rust/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ extern crate num_cpus;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate old_tvm_macros as tvm_macros;
extern crate serde_json;
extern crate tvm_common;

Expand Down
36 changes: 36 additions & 0 deletions rust/tvm-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 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.

[package]
name = "tvm-macros"
version = "0.1.1"
license = "Apache-2.0"
description = "Procedural macros of the TVM crate."
repository = "https://github.com/apache/incubator-tvm"
readme = "README.md"
keywords = ["tvm"]
authors = ["TVM Contributors"]
edition = "2018"

[lib]
proc-macro = true

[dependencies]
goblin = "0.0.24"
proc-macro2 = "^1.0"
quote = "^1.0"
syn = { version = "1.0.17", features = ["full", "extra-traits"] }
160 changes: 160 additions & 0 deletions rust/tvm-macros/src/external.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* 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.
*/
use proc_macro2::Span;
use quote::quote;
use syn::parse::{Parse, ParseStream, Result};

use syn::{FnArg, Generics, Ident, Lit, Meta, NestedMeta, Pat, ReturnType, TraitItemMethod, Type};

struct External {
tvm_name: String,
ident: Ident,
generics: Generics,
inputs: Vec<FnArg>,
ret_type: ReturnType,
}

impl Parse for External {
fn parse(input: ParseStream) -> Result<Self> {
let method: TraitItemMethod = input.parse()?;
assert_eq!(method.attrs.len(), 1);
let sig = method.sig;
let tvm_name = method.attrs[0].parse_meta()?;
let tvm_name = match tvm_name {
Meta::List(meta_list) => {
let name = meta_list.path.get_ident().expect("name");
assert_eq!(name.to_string(), "name".to_string());
match meta_list.nested.first() {
Some(NestedMeta::Lit(Lit::Str(lit))) => lit.value(),
_ => panic!(),
}
}
_ => panic!(),
};
assert_eq!(method.default, None);
assert!(method.semi_token != None);
let ident = sig.ident;
let generics = sig.generics;
let inputs = sig.inputs.iter().map(|param| param.clone()).collect();
let ret_type = sig.output;

Ok(External {
tvm_name,
ident,
generics,
inputs,
ret_type,
})
}
}

struct ExternalInput {
externs: Vec<External>,
}

impl Parse for ExternalInput {
fn parse(input: ParseStream) -> Result<Self> {
let mut externs: Vec<External> = Vec::new();

loop {
if input.is_empty() {
break;
}
externs.push(input.parse()?);
}

Ok(ExternalInput { externs })
}
}

pub fn macro_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ext_input = syn::parse_macro_input!(input as ExternalInput);

let tvm_rt_crate = crate::util::get_tvm_rt_crate();

let err_type = quote! { #tvm_rt_crate::Error };

let mut items = Vec::new();

for external in &ext_input.externs {
let name = &external.ident;
let global_name = format!("global_{}", external.ident);
let global_name = Ident::new(&global_name, Span::call_site());
let ext_name = &external.tvm_name;

let ty_params: Vec<syn::TypeParam> = external
.generics
.params
.iter()
.map(|ty_param| match ty_param {
syn::GenericParam::Type(param) => param.clone(),
_ => panic!(),
})
.collect();

let args = &external.inputs;

let (args, tys): (Vec<Ident>, Vec<Type>) = args
.iter()
.map(|arg| match arg {
FnArg::Typed(pat_type) => match &*pat_type.pat {
Pat::Ident(pat_ident) => {
let ident: Ident = pat_ident.ident.clone();
let ty: Type = *pat_type.ty.clone();
(ident, ty)
}
_ => panic!(),
},
_ => panic!(),
})
.unzip();

let ret_type = match &external.ret_type {
ReturnType::Type(_, rtype) => *rtype.clone(),
_ => panic!(),
};

let global = quote! {
#[allow(non_upper_case_globals)]
static #global_name: ::once_cell::sync::Lazy<#tvm_rt_crate::Function> =
::once_cell::sync::Lazy::new(|| {
#tvm_rt_crate::Function::get(#ext_name)
.expect(concat!("unable to load external function", stringify!(#ext_name), "from TVM registry."))
});
};

items.push(global);

let wrapper = quote! {
pub fn #name<#(#ty_params),*>(#(#args : #tys),*) -> Result<#ret_type, #err_type> {
let func_ref: #tvm_rt_crate::Function = #global_name.clone();
let func_ref: Box<dyn Fn(#(#tys),*) -> Result<#ret_type, #err_type>> = func_ref.to_boxed_fn();
let res: #ret_type = func_ref(#(#args),*)?;
Ok(res)
}
};

items.push(wrapper);
}

proc_macro::TokenStream::from(quote! {
#(#items
)*
})
}

0 comments on commit f12956b

Please sign in to comment.