Skip to content

Commit

Permalink
rewriter: add ApiSignature that stores args/return types
Browse files Browse the repository at this point in the history
More specifically, it stores the parameter names,
parameter types, and return type.
For the types, it stores the type name, the canonical type name, and a type ID.
  • Loading branch information
kkysen committed Feb 24, 2025
1 parent 184f2c5 commit d11f696
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 15 deletions.
13 changes: 13 additions & 0 deletions tools/rewriter/CAbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,20 @@ struct AbiSignature {
std::vector<ArgLocation> ret;
};

struct Param {
std::string name;
std::string type_name;
std::string canonical_type_name;
uint32_t type_id;
};

struct ApiSignature {
std::vector<Param> args;
Param ret;
};

struct FnSignature {
AbiSignature abi;
ApiSignature api;
bool variadic;
};
90 changes: 75 additions & 15 deletions tools/rewriter/DetermineAbi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,7 @@ AbiSignature determineAbiSignature(const clang::CodeGen::CGFunctionInfo &info,
return sig;
}

FnSignature determineFnSignature(const clang::CodeGen::CGFunctionInfo &info,
const clang::ASTContext &astContext, Arch arch) {
return (FnSignature){
.abi = determineAbiSignature(info, astContext, arch),
.variadic = info.isVariadic(),
};
}

FnSignature determineFnSignatureForDecl(const clang::FunctionDecl &fnDecl, Arch arch) {
AbiSignature determineAbiSignatureForDecl(const clang::FunctionDecl &fnDecl, Arch arch) {
clang::ASTContext &astContext = fnDecl.getASTContext();

// set up context for codegen so we can ask about function ABI
Expand Down Expand Up @@ -216,7 +208,7 @@ FnSignature determineFnSignatureForDecl(const clang::FunctionDecl &fnDecl, Arch

auto name = fnDecl.getNameInfo().getAsString();
const auto &info = cgFunctionInfo(cgm, fnDecl);
DEBUG(llvm::dbgs() << "determineFnSignatureForDecl: " << name << "\n");
DEBUG(llvm::dbgs() << "determineAbiSignatureForDecl: " << name << "\n");

const auto &convention = info.getEffectiveCallingConvention();

Expand All @@ -228,12 +220,12 @@ FnSignature determineFnSignatureForDecl(const clang::FunctionDecl &fnDecl, Arch
info.getASTCallingConvention());
abort();
}
return determineFnSignature(info, astContext, arch);
return determineAbiSignature(info, astContext, arch);
}

FnSignature determineFnSignatureForProtoType(const clang::FunctionProtoType &fpt,
clang::ASTContext &astContext, Arch arch) {
// FIXME: This is copied verbatim from determineFnSignatureForDecl and could be
AbiSignature determineAbiSignatureForProtoType(const clang::FunctionProtoType &fpt,
clang::ASTContext &astContext, Arch arch) {
// FIXME: This is copied verbatim from determineAbiSignatureForDecl and could be
// factored out. This depends on what we do with PR #78 so I'm leaving it as
// is for now.
#if LLVM_VERSION_MAJOR >= 15
Expand Down Expand Up @@ -261,5 +253,73 @@ FnSignature determineFnSignatureForProtoType(const clang::FunctionProtoType &fpt
cgm,
fpt.getCanonicalTypeUnqualified().castAs<clang::FunctionProtoType>());

return determineFnSignature(info, astContext, arch);
return determineAbiSignature(info, astContext, arch);
}

// Not thread safe.
std::unordered_map<std::string, uint32_t> type_ids;

uint32_t get_type_id(clang::QualType type) {
auto canonical_name = type.getCanonicalType().getAsString();
// Constructs the default value, 0, if the key doesn't exist yet.
auto type_id = type_ids[canonical_name];
if (type_id == 0) {
type_id = type_ids.size() + 1;
type_ids[canonical_name] = type_id;
}
return type_id;
}

Param determineParam(std::string name, clang::QualType type) {
return (Param) {
.name = name,
.type_name = type.getAsString(),
.canonical_type_name = type.getCanonicalType().getAsString(),
.type_id = get_type_id(type),
};
}

ApiSignature determineApiSignatureForDecl(const clang::FunctionDecl &fn_decl) {
ApiSignature api;

for (auto param_ptr : fn_decl.parameters()) {
auto &param = *param_ptr;
api.args.emplace_back(determineParam(param.getNameAsString(), param.getOriginalType()));
}

auto ret = fn_decl.getReturnType();
api.ret = determineParam("return", fn_decl.getReturnType());

return api;
}

ApiSignature determineApiSignatureForProtoType(const clang::FunctionProtoType &fpt,
clang::ASTContext &astContext) {
ApiSignature api;

auto i = 0;
for (auto param_type : fpt.param_types()) {
auto name = "arg_" + std::to_string(i++);
api.args.emplace_back(determineParam(name, param_type));
}
api.ret = determineParam("return", fpt.getReturnType());

return api;
}

FnSignature determineFnSignatureForDecl(const clang::FunctionDecl &fnDecl, Arch arch) {
return (FnSignature){
.abi = determineAbiSignatureForDecl(fnDecl, arch),
.api = determineApiSignatureForDecl(fnDecl),
.variadic = fnDecl.isVariadic(),
};
}

FnSignature determineFnSignatureForProtoType(const clang::FunctionProtoType &fpt,
clang::ASTContext &astContext, Arch arch) {
return (FnSignature){
.abi = determineAbiSignatureForProtoType(fpt, astContext, arch),
.api = determineApiSignatureForProtoType(fpt, astContext),
.variadic = fpt.isVariadic(),
};
}

0 comments on commit d11f696

Please sign in to comment.