Split codegen into separate build targets

To help with the transition to type-graph based CodeGen, we need to
reduce dependencies on legacy CodeGen from other parts of OI.

Pieces of CodeGen referenced by other files, but which only return
drgn data have been moved into a new "drgn_utils" target, allowing
us to remove CodeGen dependencies for these functions.

The new "symbol_service" build target can be used in the future by
other files only needing access to symbol information and not full
CodeGen.
This commit is contained in:
Alastair Robertson 2023-02-17 07:16:25 -08:00 committed by Alastair Robertson
parent 53ba312f1e
commit ccc90c3068
10 changed files with 144 additions and 85 deletions

View File

@ -224,19 +224,17 @@ add_library(oid_parser STATIC ${BISON_Parser_OUTPUTS} ${FLEX_Lexer_OUTPUTS})
target_link_libraries(oid_parser glog::glog)
### Core OI
add_subdirectory(src)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src)
add_library(oicore
src/ContainerInfo.cpp
src/Descs.cpp
src/FuncGen.cpp
src/Metrics.cpp
src/OICache.cpp
src/OICodeGen.cpp
src/OICompiler.cpp
src/OIUtils.cpp
src/PaddingHunter.cpp
src/Serialize.cpp
src/SymbolService.cpp
)
add_dependencies(oicore libdrgn)
set_project_warnings(oicore)
@ -245,10 +243,11 @@ target_compile_definitions(oicore PRIVATE ${LLVM_DEFINITIONS})
llvm_map_components_to_libnames(llvm_libs core native mcjit x86disassembler)
target_link_libraries(oicore
codegen
${Boost_LIBRARIES}
Boost::headers
glog::glog
tomlplusplus::tomlplusplus
)
if (FORCE_LLVM_STATIC)
target_link_libraries(oicore
@ -296,9 +295,11 @@ target_link_libraries(oil oicore)
add_executable(oilgen
tools/OILGen.cpp
src/OIGenerator.cpp
src/DrgnUtils.cpp
)
target_link_libraries(oilgen oicore)
target_link_libraries(oilgen
drgn_utils
oicore
)
### Object Introspection cache Printer (OIP)
add_executable(oip tools/OIP.cpp)

36
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,36 @@
add_library(drgn_utils DrgnUtils.cpp)
target_link_libraries(drgn_utils
glog::glog
"-L${DRGN_PATH}/.libs"
drgn
)
add_dependencies(drgn_utils libdrgn)
add_library(symbol_service
Descs.cpp
SymbolService.cpp
)
target_link_libraries(symbol_service
drgn_utils
Boost::headers
${Boost_LIBRARIES}
glog::glog
dw
)
add_library(codegen
ContainerInfo.cpp
FuncGen.cpp
OICodeGen.cpp
)
target_link_libraries(codegen
symbol_service
Boost::headers
${Boost_LIBRARIES}
glog::glog
tomlplusplus::tomlplusplus
)

View File

@ -16,6 +16,8 @@
#include "DrgnUtils.h"
#include <glog/logging.h>
extern "C" {
#include <drgn.h>
}
@ -93,3 +95,68 @@ const char* symbol::name(drgn_symbol* sym) {
}
} // namespace drgnplusplus
namespace drgn_utils {
void getDrgnArrayElementType(drgn_type* type, drgn_type** outElemType,
size_t& outNumElems) {
size_t elems = 1;
// for multi dimensional arrays
auto* arrayElementType = type;
while (drgn_type_kind(arrayElementType) == DRGN_TYPE_ARRAY) {
size_t l = drgn_type_length(arrayElementType);
elems *= l;
auto qtype = drgn_type_type(arrayElementType);
arrayElementType = qtype.type;
}
*outElemType = arrayElementType;
outNumElems = elems;
}
std::string typeToName(drgn_type* type) {
std::string typeName;
if (drgn_type_has_tag(type)) {
const char* typeTag = drgn_type_tag(type);
if (typeTag != nullptr) {
typeName = typeTag;
} else {
typeName = type->_private.oi_name;
}
// TODO: Lookup unnamed union in type->string flag
} else if (drgn_type_has_name(type)) {
typeName = drgn_type_name(type);
} else if (drgn_type_kind(type) == DRGN_TYPE_POINTER) {
char* defStr = nullptr;
drgn_qualified_type qtype = {type, {}};
if (drgn_format_type_name(qtype, &defStr) != nullptr) {
LOG(ERROR) << "Failed to get formatted string for " << type;
typeName = "";
} else {
typeName.assign(defStr);
free(defStr);
}
} else if (drgn_type_kind(type) == DRGN_TYPE_VOID) {
return "void";
} else if (drgn_type_kind(type) == DRGN_TYPE_ARRAY) {
size_t elems = 1;
drgn_type* arrayElementType = nullptr;
getDrgnArrayElementType(type, &arrayElementType, elems);
if (drgn_type_has_name(arrayElementType)) {
typeName = drgn_type_name(arrayElementType);
} else if (drgn_type_has_tag(arrayElementType)) {
typeName = drgn_type_tag(arrayElementType);
} else {
LOG(ERROR) << "Failed4 to get typename ";
return "";
}
} else {
LOG(ERROR) << "Failed3 to get typename ";
return "";
}
return typeName;
}
} // namespace drgn_utils

View File

@ -31,6 +31,7 @@ struct drgn_func_iterator;
struct drgn_program;
struct drgn_qualified_type;
struct drgn_symbol;
struct drgn_type;
}
namespace drgnplusplus {
@ -125,3 +126,19 @@ const char* name(drgn_symbol*);
}
} // namespace drgnplusplus
namespace drgn_utils {
/*
* These utils are not intended to be permanent. As part of the transition to
* type-graph based CodeGen, we need to break dependencies on legacy OICodeGen
* from other parts of OI.
*
* Parts of OICodeGen used by other parts of OI, but which only return drgn
* data can be moved here.
*/
void getDrgnArrayElementType(drgn_type* type, drgn_type** outElemType,
size_t& outNumElems);
std::string typeToName(drgn_type* type);
} // namespace drgn_utils

View File

@ -31,6 +31,7 @@
#include <unordered_map>
#include <unordered_set>
#include "DrgnUtils.h"
#include "FuncGen.h"
#include "OIParser.h"
#include "PaddingHunter.h"
@ -532,7 +533,7 @@ bool OICodeGen::buildNameInt(drgn_type *type, std::string &nameWithoutTemplate,
} else if (drgn_type_kind(p.type) == DRGN_TYPE_ARRAY) {
size_t elems = 1;
drgn_type *arrayElementType = nullptr;
getDrgnArrayElementType(p.type, &arrayElementType, elems);
drgn_utils::getDrgnArrayElementType(p.type, &arrayElementType, elems);
if (drgn_type_has_name(arrayElementType)) {
templateParamName = drgn_type_name(arrayElementType);
@ -927,55 +928,11 @@ bool OICodeGen::getMemberDefinition(drgn_type *type) {
}
std::string OICodeGen::typeToTransformedName(drgn_type *type) {
auto typeName = typeToName(type);
auto typeName = drgn_utils::typeToName(type);
typeName = transformTypeName(type, typeName);
return typeName;
}
std::string OICodeGen::typeToName(drgn_type *type) {
std::string typeName;
if (drgn_type_has_tag(type)) {
const char *typeTag = drgn_type_tag(type);
if (typeTag != nullptr) {
typeName = typeTag;
} else {
typeName = type->_private.oi_name;
}
// TODO: Lookup unnamed union in type->string flag
} else if (drgn_type_has_name(type)) {
typeName = drgn_type_name(type);
} else if (drgn_type_kind(type) == DRGN_TYPE_POINTER) {
char *defStr = nullptr;
drgn_qualified_type qtype = {type, {}};
if (drgn_format_type_name(qtype, &defStr) != nullptr) {
LOG(ERROR) << "Failed to get formatted string for " << type;
typeName = "";
} else {
typeName.assign(defStr);
free(defStr);
}
} else if (drgn_type_kind(type) == DRGN_TYPE_VOID) {
return "void";
} else if (drgn_type_kind(type) == DRGN_TYPE_ARRAY) {
size_t elems = 1;
drgn_type *arrayElementType = nullptr;
getDrgnArrayElementType(type, &arrayElementType, elems);
if (drgn_type_has_name(arrayElementType)) {
typeName = drgn_type_name(arrayElementType);
} else if (drgn_type_has_tag(arrayElementType)) {
typeName = drgn_type_tag(arrayElementType);
} else {
LOG(ERROR) << "Failed4 to get typename ";
return "";
}
} else {
LOG(ERROR) << "Failed3 to get typename ";
return "";
}
return typeName;
}
bool OICodeGen::recordChildren(drgn_type *type) {
drgn_type_template_parameter *parents = drgn_type_parents(type);
@ -2365,24 +2322,6 @@ bool OICodeGen::generateStructDef(drgn_type *e, std::string &code) {
return true;
}
void OICodeGen::getDrgnArrayElementType(drgn_type *type,
drgn_type **outElemType,
size_t &outNumElems) {
size_t elems = 1;
// for multi dimensional arrays
auto *arrayElementType = type;
while (drgn_type_kind(arrayElementType) == DRGN_TYPE_ARRAY) {
size_t l = drgn_type_length(arrayElementType);
elems *= l;
auto qtype = drgn_type_type(arrayElementType);
arrayElementType = qtype.type;
}
*outElemType = arrayElementType;
outNumElems = elems;
}
bool OICodeGen::isNumMemberGreaterThanZero(drgn_type *type) {
if (drgn_type_num_members(type) > 0) {
return true;
@ -2495,7 +2434,7 @@ std::optional<uint64_t> OICodeGen::generateMember(
size_t elems = 1;
drgn_type *arrayElementType = nullptr;
getDrgnArrayElementType(memberType, &arrayElementType, elems);
drgn_utils::getDrgnArrayElementType(memberType, &arrayElementType, elems);
auto tmpStr = getNameForType(arrayElementType);
if (!tmpStr.has_value()) {
@ -3416,7 +3355,7 @@ bool OICodeGen::generateJitCode(std::string &code) {
/* Start function definitions. First define top level func for root object
*/
auto rawTypeName = typeToName(type);
auto rawTypeName = drgn_utils::typeToName(type);
if (config.useDataSegment) {
if (rootTypeStr.starts_with("unique_ptr") ||
rootTypeStr.starts_with("LowPtr") ||

View File

@ -97,9 +97,6 @@ class OICodeGen {
TypeHierarchy getTypeHierarchy();
std::map<std::string, PaddingInfo> getPaddingInfo();
static void getDrgnArrayElementType(drgn_type *type, drgn_type **outElemType,
size_t &outNumElems);
bool isContainer(drgn_type *type);
static drgn_type *drgnUnderlyingType(drgn_type *type);
@ -107,7 +104,6 @@ class OICodeGen {
bool buildName(drgn_type *type, std::string &text, std::string &outName);
std::string typeToTransformedName(drgn_type *type);
static std::string typeToName(drgn_type *type);
bool enumerateTypesRecurse(drgn_type *type);
static std::string_view drgnKindStr(drgn_type *type);

View File

@ -19,7 +19,9 @@
#include "OICompiler.h"
namespace OIUtils {
bool processConfigFile(const std::string& configFilePath,
OICompiler::Config& compilerConfig,
OICodeGen::Config& generatorConfig);
}
} // namespace OIUtils

View File

@ -20,7 +20,7 @@
#include <boost/serialization/version.hpp>
#include <stdexcept>
#include "OICodeGen.h"
#include "DrgnUtils.h"
namespace boost::serialization {
@ -319,7 +319,7 @@ void serialize(Archive &ar, struct drgn_type &type,
// `serialize_c_string`.
std::string oi_name;
if (Archive::is_saving::value) {
oi_name = OICodeGen::typeToName(&type);
oi_name = drgn_utils::typeToName(&type);
type._private.oi_name = oi_name.c_str();
}
serialize_c_string(ar, const_cast<char **>(&type._private.oi_name));

View File

@ -23,7 +23,7 @@
#include <cstring>
#include <fstream>
#include "OICodeGen.h"
#include "DrgnUtils.h"
#include "OIParser.h"
extern "C" {
@ -733,7 +733,7 @@ std::string SymbolService::getTypeName(struct drgn_type *type) {
if (drgn_type_kind(type) == DRGN_TYPE_POINTER) {
type = drgn_type_type(type).type;
}
return OICodeGen::typeToName(type);
return drgn_utils::typeToName(type);
}
std::optional<RootInfo> SymbolService::getRootType(const irequest &req) {

View File

@ -26,6 +26,7 @@
#include <stdexcept>
#include "ContainerInfo.h"
#include "DrgnUtils.h"
#include "Metrics.h"
#include "OICodeGen.h"
#include "PaddingHunter.h"
@ -275,7 +276,7 @@ void TreeBuilder::setPaddedStructs(
static std::string drgnTypeToName(struct drgn_type *type) {
if (type->_private.program != nullptr) {
return OICodeGen::typeToName(type);
return drgn_utils::typeToName(type);
}
return type->_private.oi_name ? type->_private.oi_name : "";
@ -531,8 +532,8 @@ void TreeBuilder::processContainer(const Variable &variable, Node &node) {
kind = ARRAY_TYPE;
struct drgn_type *arrayElementType = nullptr;
size_t numElems = 0;
OICodeGen::getDrgnArrayElementType(variable.type, &arrayElementType,
numElems);
drgn_utils::getDrgnArrayElementType(variable.type, &arrayElementType,
numElems);
assert(numElems > 0);
elementTypes.push_back(
drgn_qualified_type{arrayElementType, (enum drgn_qualifiers)(0)});