Skip to content

Commit

Permalink
Merge pull request #201 from AntelopeIO/extend-abi-non-contract
Browse files Browse the repository at this point in the history
Redesign abi generation for multi_index and singleton
  • Loading branch information
dimas1185 authored Jul 28, 2023
2 parents b5d71e2 + b2386d9 commit 0056647
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 75 deletions.
2 changes: 1 addition & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ add_unit_test( system_tests )
add_unit_test( time_tests )
add_unit_test( varint_tests )

add_test( NAME toolchain_tests COMMAND ${CMAKE_BINARY_DIR}/tools/toolchain-tester/toolchain-tester ${CMAKE_SOURCE_DIR}/tests/toolchain --cdt ${CMAKE_BINARY_DIR}/bin )
add_test( NAME toolchain_tests COMMAND ${CMAKE_BINARY_DIR}/tools/toolchain-tester/toolchain-tester ${CMAKE_SOURCE_DIR}/tests/toolchain --cdt ${CMAKE_BINARY_DIR}/bin --verbose )
set_property(TEST toolchain_tests PROPERTY LABELS toolchain_tests)

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/unit/version_tests.sh ${CMAKE_BINARY_DIR}/tests/unit/version_tests.sh COPYONLY)
Expand Down
50 changes: 50 additions & 0 deletions tests/toolchain/abigen-pass/exclude_from_abi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <eosio/eosio.hpp>
#include <eosio/name.hpp>
#include <eosio/singleton.hpp>
#include <eosio/multi_index.hpp>



struct [[eosio::table]] out_of_class {
uint64_t id;
uint64_t primary_key() const { return id; }
};
typedef eosio::multi_index<"mi.config55"_n, out_of_class> out_of_class_index;
using uout_of_class_index = eosio::multi_index<"mi.config551"_n, out_of_class>;

typedef eosio::singleton<"smpl.conf55"_n, eosio::name> smpl_config55;
typedef eosio::singleton<"config55"_n, out_of_class> config55;
typedef smpl_config55 smpl_config551;
typedef config55 config551;
using smpl_conf551 = eosio::singleton<"smpl.conf551"_n, eosio::name>;
using config552 = eosio::singleton<"config552"_n, out_of_class>;
using smpl_conf552 = smpl_conf551;
using config553 = config551;

class [[eosio::contract("singleton_contract_simple2")]] singleton_contract_simple2 : public eosio::contract {
public:
using eosio::contract::contract;

[[eosio::action]]
void whatever() {};

struct [[eosio::table]] inside_class {
uint64_t id;
uint64_t primary_key() const { return id; }
};
typedef eosio::singleton<"smpl.conf552"_n, eosio::name> smpl_conf552;
typedef eosio::singleton<"config552"_n, inside_class> config552;
typedef smpl_conf552 smpl_conf553;
typedef config552 config553;
using smpl_conf554 = eosio::singleton<"smpl.conf554"_n, eosio::name>;
using config554 = eosio::singleton<"config554"_n, inside_class>;
using smpl_conf555 = smpl_conf554;
using config555 = config554;



typedef eosio::multi_index<"mi.config553"_n, inside_class> inside_class_index;
using uinside_class_index = eosio::multi_index<"mi.config554"_n, inside_class>;
};
21 changes: 21 additions & 0 deletions tests/toolchain/abigen-pass/singleton_contract.abi
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,27 @@
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "config55",
"type": "out_of_class",
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "smpl.conf5",
"type": "name",
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "smpl.config",
"type": "name",
"index_type": "i64",
"key_names": [],
"key_types": []
}
],
"ricardian_clauses": [],
Expand Down
25 changes: 23 additions & 2 deletions tests/toolchain/abigen-pass/singleton_contract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,27 @@
#include <eosio/eosio.hpp>
#include <eosio/name.hpp>
#include <eosio/singleton.hpp>

#include "exclude_from_abi.hpp"

using namespace eosio;


struct [[eosio::table]] out_of_class2 {
uint64_t id;
uint64_t primary_key() const { return id; }
};
typedef eosio::multi_index<"mi.config5"_n, out_of_class2> out_of_class_index51;
using uout_of_class_index51 = eosio::multi_index<"mi.config51"_n, out_of_class2>;

typedef eosio::singleton<"smpl.conf5"_n, eosio::name> smpl_config5;
typedef eosio::singleton<"config5"_n, out_of_class2> config5;
typedef smpl_config5 smpl_config51;
typedef config5 config51;
using smpl_conf51 = eosio::singleton<"smpl.conf51"_n, eosio::name>;
using config52 = eosio::singleton<"config52"_n, out_of_class2>;
using smpl_conf52 = smpl_conf51;
using config53 = config51;

class [[eosio::contract("singleton_contract")]] singleton_contract : public contract {
public:
using contract::contract;
Expand All @@ -17,5 +35,8 @@ class [[eosio::contract("singleton_contract")]] singleton_contract : public cont
uint64_t x;
};

typedef eosio::singleton<"config"_n, tbl_config> config;
typedef eosio::singleton<"config"_n, tbl_config> config;
typedef eosio::singleton<"smpl.config"_n, name> smpl_config;
using smpl_config2 = smpl_config5;
typedef config551 config2; //from exclude_from_abi.hpp
};
31 changes: 0 additions & 31 deletions tests/toolchain/abigen-pass/singleton_contract_simple.abi

This file was deleted.

16 changes: 0 additions & 16 deletions tests/toolchain/abigen-pass/singleton_contract_simple.cpp

This file was deleted.

10 changes: 0 additions & 10 deletions tests/toolchain/abigen-pass/singleton_contract_simple.json

This file was deleted.

60 changes: 58 additions & 2 deletions tools/include/eosio/abigen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,7 @@ namespace eosio { namespace cdt {
private:
bool has_added_clauses = false;
abigen& ag = abigen::get();
const clang::CXXRecordDecl* contract_class = NULL;

public:
explicit eosio_abigen_visitor(CompilerInstance *CI) {
Expand Down Expand Up @@ -799,10 +800,66 @@ namespace eosio { namespace cdt {
}
return true;
}

const clang::CXXRecordDecl* find_contract_class(const clang::ASTContext &ctx) const {
const auto* translation_unit = ctx.getTranslationUnitDecl();
// scanning entire translation unit to find contract class
for (const clang::Decl* cur_decl : translation_unit->decls()) {
if (const auto* cxx_decl = llvm::dyn_cast<clang::CXXRecordDecl>(cur_decl)) {

if (cxx_decl->isEosioContract()) {
auto attr_name = cxx_decl->getEosioContractAttr()->getName();
auto name = attr_name.empty() ? cxx_decl->getName() : attr_name;
if (name == llvm::StringRef(ag.get_contract_name()))
return cxx_decl;
}
}
}

return nullptr;
}

bool is_same_type(const clang::Decl* decl1, const clang::CXXRecordDecl* decl2) const {
if (!decl1 || !decl2)
return false;
if (decl1 == decl2)
return true;

// checking if declaration is a typedef or using
if (const clang::TypedefNameDecl* typedef_decl = llvm::dyn_cast<clang::TypedefNameDecl>(decl1)) {
if (const auto* cur_type = typedef_decl->getUnderlyingType().getTypePtrOrNull()) {
if (decl2 == cur_type->getAsCXXRecordDecl()) {
return true;
}
}
}

return false;
}

bool defined_in_contract(const clang::ClassTemplateSpecializationDecl* decl) {

if (!contract_class) {
contract_class = find_contract_class(decl->getASTContext());
if (!contract_class) {
// currently this is unreachable as we do not traverse non-main file translation units
CDT_WARN("codegen_warning", decl->getLocation(), "contract class not found");
return false;
}
}

for (const clang::Decl* cur_decl : contract_class->decls()) {
if (is_same_type(cur_decl, decl))
return true;
}

return false;
}

virtual bool VisitDecl(clang::Decl* decl) {
if (const auto* d = dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
bool is_singleton = d->getName() == "singleton";
if (d->getName() == "multi_index" || is_singleton) {
if ((d->getName() == "multi_index" || is_singleton) && defined_in_contract(d)) {
ag.add_table(d->getTemplateArgs()[0].getAsIntegral().getExtValue(),
d->getTemplateArgs()[1].getAsType().getTypePtr()->getAsCXXRecordDecl(), is_singleton);
}
Expand All @@ -826,7 +883,6 @@ namespace eosio { namespace cdt {
auto& f_mgr = src_mgr.getFileManager();
auto main_fe = f_mgr.getFile(main_file);
if (main_fe) {
auto fid = src_mgr.getOrCreateFileID(f_mgr.getFile(main_file), SrcMgr::CharacteristicKind::C_User);
visitor->TraverseDecl(Context.getTranslationUnitDecl());
}
}
Expand Down
8 changes: 5 additions & 3 deletions tools/include/eosio/error_emitter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ namespace eosio { namespace cdt {
#define CDT_ERROR(e, l, s) \
get_error_emitter().emit_error(l, get_error_emitter().diags.get(e), s);

#define CDT_INTERNAL_ERROR(s) \
std::cerr << s << "\n"; \
throw internal_error_ex;
#define CDT_INTERNAL_ERROR(s) \
do { \
std::cerr << s << "\n"; \
throw internal_error_ex; \
} while (false)
20 changes: 10 additions & 10 deletions tools/include/eosio/gen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ struct generation_utils {


inline void set_contract_name( const std::string& cn ) { contract_name = cn; }
inline std::string get_contract_name()const { return contract_name; }
inline const std::string& get_contract_name()const { return contract_name; }
static inline std::string get_parsed_contract_name() { return parsed_contract_name; }
inline void set_resource_dirs( const std::vector<std::string>& rd ) {
llvm::SmallString<128> cwd;
Expand Down Expand Up @@ -274,30 +274,30 @@ struct generation_utils {
}

static inline bool is_eosio_contract( const clang::CXXMethodDecl* decl, const std::string& cn ) {
std::string name = "";
llvm::StringRef name;
if (decl->isEosioContract())
name = decl->getEosioContractAttr()->getName();
else if (decl->getParent()->isEosioContract())
name = decl->getParent()->getEosioContractAttr()->getName();
if (name.empty()) {
name = decl->getParent()->getName().str();
name = decl->getParent()->getName();
}
parsed_contract_name = name;
parsed_contract_name = name.str();
return cn == parsed_contract_name;
}

static inline bool is_eosio_contract( const clang::CXXRecordDecl* decl, const std::string& cn ) {
std::string name = "";
llvm::StringRef name;
auto pd = llvm::dyn_cast<clang::CXXRecordDecl>(decl->getParent());
if (decl->isEosioContract()) {
auto nm = decl->getEosioContractAttr()->getName().str();
name = nm.empty() ? decl->getName().str() : nm;
auto nm = decl->getEosioContractAttr()->getName();
name = nm.empty() ? decl->getName() : nm;
}
else if (pd && pd->isEosioContract()) {
auto nm = pd->getEosioContractAttr()->getName().str();
name = nm.empty() ? pd->getName().str() : nm;
auto nm = pd->getEosioContractAttr()->getName();
name = nm.empty() ? pd->getName() : nm;
}
parsed_contract_name = name;
parsed_contract_name = name.str();
return cn == parsed_contract_name;
}

Expand Down

0 comments on commit 0056647

Please sign in to comment.