@@ -11,21 +11,61 @@ namespace Codegen

namespace fir
{
FunctionType::FunctionType(std::deque<Type*> args, Type* ret, bool isva) : Type(FTypeKind::Function)
FunctionType::FunctionType(std::deque<Type*> args, Type* ret, bool isvariadic, bool iscva) : Type(FTypeKind::Function)
{
this->functionParams = args;
this->functionRetType = ret;
this->isFnVarArg = isva;
this->isFnVariadic = isvariadic;

this->isFnCStyleVarArg = iscva;
}






// functions
FunctionType* FunctionType::getCVariadicFunc(std::deque<Type*> args, Type* ret, FTContext* tc)
{
if(!tc) tc = getDefaultFTContext();
iceAssert(tc && "null type context");

// create.
FunctionType* type = new FunctionType(args, ret, false, true);
return dynamic_cast<FunctionType*>(tc->normaliseType(type));
}

FunctionType* FunctionType::getCVariadicFunc(std::vector<Type*> args, Type* ret, FTContext* tc)
{
std::deque<Type*> dargs;
for(auto a : args)
dargs.push_back(a);

return getCVariadicFunc(dargs, ret, tc);
}

FunctionType* FunctionType::getCVariadicFunc(std::initializer_list<Type*> args, Type* ret, FTContext* tc)
{
std::deque<Type*> dargs;
for(auto a : args)
dargs.push_back(a);

return getCVariadicFunc(dargs, ret, tc);
}






FunctionType* FunctionType::get(std::deque<Type*> args, Type* ret, bool isVarArg, FTContext* tc)
{
if(!tc) tc = getDefaultFTContext();
iceAssert(tc && "null type context");

// create.
FunctionType* type = new FunctionType(args, ret, isVarArg);
FunctionType* type = new FunctionType(args, ret, isVarArg, false);
return dynamic_cast<FunctionType*>(tc->normaliseType(type));
}

@@ -84,17 +124,23 @@ namespace fir
return this->functionRetType;
}

bool FunctionType::isVarArg()
bool FunctionType::isCStyleVarArg()
{
return this->isFnCStyleVarArg;
}

bool FunctionType::isVariadicFunc()
{
return this->isFnVarArg;
return this->isFnVariadic;
}


bool FunctionType::isTypeEqual(Type* other)
{
FunctionType* of = dynamic_cast<FunctionType*>(other);
if(!of) return false;
if(this->isFnVarArg != of->isFnVarArg) return false;
if(this->isFnCStyleVarArg != of->isFnCStyleVarArg) return false;
if(this->isFnVariadic != of->isFnVariadic) return false;
if(this->functionParams.size() != of->functionParams.size()) return false;
if(!this->functionRetType->isTypeEqual(of->functionRetType)) return false;

@@ -53,7 +53,9 @@ namespace fir
friend struct Argument;
friend struct IRBuilder;

bool isVarArg();
bool isCStyleVarArg();
bool isVariadic();

std::string getName();
Type* getReturnType();
size_t getArgumentCount();
@@ -385,27 +385,35 @@ namespace fir
std::deque<Type*> getArgumentTypes();
Type* getArgumentN(size_t n);
Type* getReturnType();
bool isVarArg();

bool isCStyleVarArg();
bool isVariadicFunc();


virtual std::string str() override;
virtual bool isTypeEqual(Type* other) override;

// protected constructor
protected:
FunctionType(std::deque<Type*> args, Type* ret, bool isva);
FunctionType(std::deque<Type*> args, Type* ret, bool isvariadic, bool iscva);
virtual ~FunctionType() override { }

// fields (protected)
bool isFnVarArg;
bool isFnCStyleVarArg;
bool isFnVariadic;

std::deque<Type*> functionParams;
Type* functionRetType;

// static funcs
public:
static FunctionType* get(std::deque<Type*> args, Type* ret, bool isVarArg, FTContext* tc = 0);
static FunctionType* get(std::vector<Type*> args, Type* ret, bool isVarArg, FTContext* tc = 0);
static FunctionType* get(std::initializer_list<Type*> args, Type* ret, bool isVarArg, FTContext* tc = 0);
static FunctionType* getCVariadicFunc(std::deque<Type*> args, Type* ret, FTContext* tc = 0);
static FunctionType* getCVariadicFunc(std::vector<Type*> args, Type* ret, FTContext* tc = 0);
static FunctionType* getCVariadicFunc(std::initializer_list<Type*> args, Type* ret, FTContext* tc = 0);

static FunctionType* get(std::deque<Type*> args, Type* ret, bool isVariadic, FTContext* tc = 0);
static FunctionType* get(std::vector<Type*> args, Type* ret, bool isVariadic, FTContext* tc = 0);
static FunctionType* get(std::initializer_list<Type*> args, Type* ret, bool isVariadic, FTContext* tc = 0);
};
}