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

Move functag_t into the type system. #969

Merged
merged 5 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions compiler/assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class RttiBuilder
uint32_t add_struct(Type* type);
uint32_t add_enumstruct(Type* type);
uint32_t encode_signature(FunctionDecl* decl);
void encode_signature_into(std::vector<uint8_t>& bytes, functag_t* ft);
void encode_signature_into(std::vector<uint8_t>& bytes, FunctionType* ft);
void encode_enum_into(std::vector<uint8_t>& bytes, Type* type);
void encode_type_into(std::vector<uint8_t>& bytes, Type* type);
void encode_type_into(std::vector<uint8_t>& bytes, QualType type);
Expand Down Expand Up @@ -500,7 +500,7 @@ uint32_t RttiBuilder::encode_signature(FunctionDecl* fun) {

bytes.push_back((uint8_t)argc);
if (fun->IsVariadic())
bytes.push_back(cb::kVariadic);
bytes.push_back(cb::kLegacyVariadic);

encode_type_into(bytes, fun->return_type());

Expand Down Expand Up @@ -680,17 +680,17 @@ RttiBuilder::encode_funcenum_into(std::vector<uint8_t>& bytes, Type* type, funce
}
}

void RttiBuilder::encode_signature_into(std::vector<uint8_t>& bytes, functag_t* ft) {
void RttiBuilder::encode_signature_into(std::vector<uint8_t>& bytes, FunctionType* ft) {
bytes.push_back(cb::kFunction);
bytes.push_back((uint8_t)ft->args.size());
bytes.push_back((uint8_t)ft->nargs());

if (!ft->args.empty() && ft->args[ft->args.size() - 1].is_varargs)
bytes.push_back(cb::kVariadic);
if (ft->variadic())
bytes.push_back(cb::kLegacyVariadic);

encode_type_into(bytes, ft->ret_type);
encode_type_into(bytes, ft->return_type());

for (const auto& arg : ft->args)
encode_type_into(bytes, QualType(arg.type, arg.is_const));
for (size_t i = 0; i < ft->nargs(); i++)
encode_type_into(bytes, ft->arg_type(i));
}

typedef SmxListSection<sp_file_natives_t> SmxNativeSection;
Expand Down
11 changes: 11 additions & 0 deletions compiler/errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,17 @@ MessageBuilder::operator <<(Type* type)
return *this;
}

MessageBuilder&
MessageBuilder::operator <<(QualType type)
{
std::string message;
if (type.is_const())
message += "const ";
message += type->prettyName();
args_.emplace_back(message);
return *this;
}

ReportManager::ReportManager(CompileContext& cc)
: cc_(cc)
{
Expand Down
1 change: 1 addition & 0 deletions compiler/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class MessageBuilder
return *this;
}
MessageBuilder& operator <<(Type* type);
MessageBuilder& operator <<(QualType type);

template <typename Integer,
std::enable_if_t<std::is_integral<Integer>::value, bool> = true>
Expand Down
35 changes: 17 additions & 18 deletions compiler/expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,12 +275,12 @@ static bool matchobjecttags(Type* formal, Type* actual, int flags) {
return false;
}

static bool matchreturntag(const functag_t* formal, const functag_t* actual) {
if (formal->ret_type == actual->ret_type)
static bool matchreturntag(const FunctionType* formal, const FunctionType* actual) {
if (formal->return_type() == actual->return_type())
return true;

if (formal->ret_type->isVoid()) {
if (actual->ret_type->isInt())
if (formal->return_type()->isVoid()) {
if (actual->return_type()->isInt())
return true;
}
return false;
Expand All @@ -297,20 +297,17 @@ static bool IsValidImplicitArrayCast(Type* formal, Type* actual) {
return formal == actual;
}

static bool funcarg_compare(const typeinfo_t& formal, const typeinfo_t& actual) {
static bool funcarg_compare(QualType formal, QualType actual) {
// Check type.
if (actual.is_varargs != formal.is_varargs)
return false;

if (actual.type == formal.type)
if (actual == formal)
return true;

// :TODO: replace this mess with TypeChecker.

// Do not allow casting between different array strides, eg:
// any[] to char[] is illegal.
Type* formal_type = formal.type;
Type* actual_type = actual.type;
Type* formal_type = *formal;
Type* actual_type = *actual;
if (formal_type->isArray()) {
if (!IsValidImplicitArrayCast(formal_type, actual_type))
return false;
Expand Down Expand Up @@ -340,23 +337,25 @@ static bool funcarg_compare(const typeinfo_t& formal, const typeinfo_t& actual)
return true;
}

bool functag_compare(const functag_t* formal, const functag_t* actual) {
bool functag_compare(FunctionType* formal, FunctionType* actual) {
// Check return types.
if (!matchreturntag(formal, actual))
return false;

// Make sure there are no trailing arguments.
if (actual->args.size() > formal->args.size())
if (actual->nargs() > formal->nargs())
return false;
if (actual->variadic() != formal->variadic())
return false;

// Check arguments.
for (size_t i = 0; i < formal->args.size(); i++) {
const typeinfo_t& formal_arg = formal->args[i];
for (size_t i = 0; i < formal->nargs(); i++) {
auto formal_arg = formal->arg_type(i);

if (i >= actual->args.size())
if (i >= actual->nargs())
return false;

const typeinfo_t& actual_arg = actual->args[i];
auto actual_arg = actual->arg_type(i);
if (!funcarg_compare(formal_arg, actual_arg))
return false;
}
Expand All @@ -377,7 +376,7 @@ static bool matchfunctags(Type* formal, Type* actual) {
if (!actual_fe || actual_fe->entries.empty())
return false;

functag_t* actualfn = actual_fe->entries.back();
FunctionType* actualfn = actual_fe->entries.back();
if (!actualfn)
return false;

Expand Down
2 changes: 1 addition & 1 deletion compiler/expressions.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ bool checktag(Type* type, Type* expr_type);
bool checktag_string(int tag, const value* sym1);
bool checktag(int tag, int exprtag);
bool HasTagOnInheritanceChain(Type* type, Type* other);
bool functag_compare(const functag_t* formal, const functag_t* actual);
bool functag_compare(FunctionType* formal, FunctionType* actual);

} // namespace cc
} // namespace sp
28 changes: 12 additions & 16 deletions compiler/name-resolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,39 +299,35 @@ TypedefDecl::EnterNames(SemaContext& sc)
return true;
}

bool
TypedefDecl::Bind(SemaContext& sc)
{
bool TypedefDecl::Bind(SemaContext& sc) {
auto ft = type_->Bind(sc);
if (!ft)
return false;

new (&fe_->entries) PoolArray<functag_t*>({ft});
new (&fe_->entries) PoolArray<FunctionType*>({ft});
return true;
}

functag_t*
TypedefInfo::Bind(SemaContext& sc)
{
FunctionType* TypedefInfo::Bind(SemaContext& sc) {
if (!sc.BindType(pos, &ret_type))
return nullptr;

auto ft = new functag_t();
ft->ret_type = ret_type.type();

std::vector<typeinfo_t> ft_args;
bool variadic = false;
std::vector<std::pair<QualType, sp::Atom*>> ft_args;
for (auto& arg : args) {
if (!sc.BindType(pos, &arg->type))
return nullptr;

if (!arg->type.dim_exprs.empty())
ResolveArrayType(sc.sema(), pos, &arg->type, sARGUMENT);

ft_args.emplace_back(arg->type);
if (arg->type.is_varargs)
variadic = true;
else
ft_args.emplace_back(arg->type.qualified(), arg->name);
}
new (&ft->args) PoolArray<typeinfo_t>(ft_args);

return ft;
return sc.cc().types()->defineFunction(ret_type.type(), ft_args, variadic);
}

bool
Expand All @@ -351,7 +347,7 @@ TypesetDecl::Bind(SemaContext& sc)
{
bool ok = true;

std::vector<functag_t*> tags;
std::vector<FunctionType*> tags;
for (const auto& type : types_) {
auto ft = type->Bind(sc);
if (!ft) {
Expand All @@ -361,7 +357,7 @@ TypesetDecl::Bind(SemaContext& sc)
tags.emplace_back(ft);
}

new (&fe_->entries) PoolArray<functag_t*>(tags);
new (&fe_->entries) PoolArray<FunctionType*>(tags);
return ok;
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/parse-node.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ struct TypedefInfo : public PoolObject {
TypenameInfo ret_type;
PoolArray<declinfo_t*> args;

functag_t* Bind(SemaContext& sc);
FunctionType* Bind(SemaContext& sc);
};

class TypedefDecl : public Decl
Expand Down
18 changes: 11 additions & 7 deletions compiler/sctracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,21 @@ funcenum_t* funcenums_add(CompileContext& cc, Atom* name, bool anonymous) {
funcenum_t* funcenum_for_symbol(CompileContext& cc, Decl* sym) {
FunctionDecl* fun = sym->as<FunctionDecl>();

functag_t* ft = new functag_t;
ft->ret_type = sym->type();
bool variadic = false;
std::vector<std::pair<QualType, sp::Atom*>> args;
for (auto arg : fun->canonical()->args()) {
const auto& ti = arg->type_info();
if (ti.is_varargs)
variadic = true;
else
args.emplace_back(ti.qualified(), arg->name());
}

std::vector<typeinfo_t> args;
for (auto arg : fun->canonical()->args())
args.emplace_back(arg->type_info());
new (&ft->args) PoolArray<typeinfo_t>(args);
auto type = cc.types()->defineFunction(sym->type(), args, variadic);

auto name = ke::StringPrintf("::ft:%s", fun->name()->chars());
funcenum_t* fe = funcenums_add(cc, cc.atom(name), true);
new (&fe->entries) PoolArray<functag_t*>({ft});
new (&fe->entries) PoolArray<FunctionType*>({type});

return fe;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/sctracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct funcenum_t : public PoolObject
{}
Type* type;
Atom* name;
PoolArray<functag_t*> entries;
PoolArray<FunctionType*> entries;
bool anonymous;
};

Expand Down
31 changes: 15 additions & 16 deletions compiler/type-checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@
namespace sp {
namespace cc {

TypeChecker::TypeChecker(ParseNode* node, Type* formal, Type* actual, Context why, int flags)
: TypeChecker(node->pos(), formal, actual, why, flags)
{}

TypeChecker::TypeChecker(const token_pos_t& pos, Type* formal, Type* actual, Context why,
TypeChecker::TypeChecker(const token_pos_t& pos, QualType formal, QualType actual, Context why,
int flags)
: pos_(pos),
formal_(formal),
Expand Down Expand Up @@ -83,8 +79,8 @@ bool TypeChecker::CheckImpl() {
if (auto formal_array = formal_->as<ArrayType>())
return CheckArrays(formal_array, actual_->as<ArrayType>());

Type* formal = formal_;
Type* actual = actual_;
Type* formal = *formal_;
Type* actual = *actual_;
if (flags_ & AllowCoerce) {
if (formal->isReference())
formal = formal->inner();
Expand Down Expand Up @@ -262,7 +258,7 @@ bool TypeChecker::CheckFunction() {
if (!actual_fe || actual_fe->entries.empty())
return DiagnoseFailure();

functag_t* actualfn = actual_fe->entries.back();
FunctionType* actualfn = actual_fe->entries.back();
if (!actualfn)
return DiagnoseFailure();

Expand All @@ -278,24 +274,27 @@ bool TypeChecker::CheckFunction() {
return DiagnoseFunctionFailure();
}

bool TypeChecker::CheckFunctionSignature(functag_t* formal, functag_t* actual) {
if (formal->ret_type != actual->ret_type) {
if (formal->ret_type->isVoid() && actual->ret_type->isInt())
bool TypeChecker::CheckFunctionSignature(FunctionType* formal, FunctionType* actual) {
if (formal->return_type() != actual->return_type()) {
if (formal->return_type()->isVoid() && actual->return_type()->isInt())
return true;
return DiagnoseFunctionFailure();
}

if (formal->variadic() != actual->variadic())
return DiagnoseFunctionFailure();

// Make sure there are no trailing arguments.
if (actual->args.size() > formal->args.size())
if (actual->nargs() > formal->nargs())
return DiagnoseFunctionFailure();

// Check arguments.
for (size_t i = 0; i < formal->args.size(); i++) {
if (i >= actual->args.size())
for (size_t i = 0; i < formal->nargs(); i++) {
if (i >= actual->nargs())
return DiagnoseFunctionFailure();

Type* formal_type = formal->args[i].type;
Type* actual_type = actual->args[i].type;
auto formal_type = formal->arg_type(i);
auto actual_type = actual->arg_type(i);
TypeChecker tc(pos_, formal_type, actual_type, TypeChecker::Generic,
TypeChecker::FuncArg);
if (!tc.Check())
Expand Down
18 changes: 14 additions & 4 deletions compiler/type-checker.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,19 @@ class TypeChecker {
Ternary = 0x10,
};

TypeChecker(ParseNode* node, QualType formal, QualType actual, Context why,
int flags = None)
: TypeChecker(node->pos(), formal, actual, why, flags)
{}
TypeChecker(ParseNode* node, Type* formal, Type* actual, Context why,
int flags = None);
int flags = None)
: TypeChecker(node->pos(), QualType(formal), QualType(actual), why, flags)
{}
TypeChecker(const token_pos_t& pos, Type* formal, Type* actual, Context why,
int flags = None)
: TypeChecker(pos, QualType(formal), QualType(actual), why, flags)
{}
TypeChecker(const token_pos_t& pos, QualType formal, QualType actual, Context why,
int flags = None);

bool Check();
Expand All @@ -59,14 +69,14 @@ class TypeChecker {
bool CheckValueType(Type* formal, Type* actual);
bool CheckArrays(ArrayType* formal, ArrayType* actual);
bool CheckFunction();
bool CheckFunctionSignature(functag_t* formal, functag_t* actual);
bool CheckFunctionSignature(FunctionType* formal, FunctionType* actual);
bool DiagnoseFailure();
bool DiagnoseFunctionFailure();

private:
const token_pos_t& pos_;
Type* formal_;
Type* actual_;
QualType formal_;
QualType actual_;
Context why_;
int flags_;
AutoDeferReports defer_;
Expand Down
Loading
Loading