Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the

same LDC call.
This commit is contained in:
Christian Kamm
2009-03-07 14:25:30 +01:00
parent 5af82ee8d3
commit ed9591d81f
12 changed files with 201 additions and 169 deletions

View File

@@ -80,6 +80,7 @@ set_target_properties(
idgen impcnvgen PROPERTIES
LINKER_LANGUAGE CXX
RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${DMDFE_PATH}
COMPILE_FLAGS ${LLVM_CXXFLAGS}
)
get_target_property(IDGEN_LOC idgen LOCATION)
get_target_property(IMPCNVGEN_LOC impcnvgen LOCATION)

View File

@@ -2659,9 +2659,6 @@ TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, en
this->varargs = varargs;
this->linkage = linkage;
this->inuse = 0;
// LDC
this->fty = NULL;
}
Type *TypeFunction::syntaxCopy()

View File

@@ -23,8 +23,8 @@
// llvm
#include "../ir/irtype.h"
#include "../ir/irfuncty.h"
namespace llvm { class Type; }
struct IrFuncTy;
struct Scope;
struct Identifier;
@@ -437,7 +437,7 @@ struct TypeFunction : Type
unsigned totym();
// LDC
IrFuncTy* fty;
IrFuncTy fty;
};
struct TypeDelegate : Type

View File

@@ -647,20 +647,20 @@ void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) {
if (tf->linkage != LINKd) {
// TODO: See if this is correct for more than just extern(C).
IrFuncTy* fty = tf->fty;
IrFuncTy& fty = tf->fty;
if (!fty->arg_sret) {
if (!fty.arg_sret) {
Logger::println("x86-64 ABI: Transforming return type");
Type* rt = fty->ret->type->toBasetype();
Type* rt = fty.ret->type->toBasetype();
if (rt != Type::tvoid)
fixup(*fty->ret);
fixup(*fty.ret);
}
Logger::println("x86-64 ABI: Transforming arguments");
LOG_SCOPE;
for (IrFuncTy::ArgIter I = fty->args.begin(), E = fty->args.end(); I != E; ++I) {
for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) {
IrFuncTyArg& arg = **I;
if (Logger::enabled())

View File

@@ -167,8 +167,8 @@ struct X86TargetABI : TargetABI
void rewriteFunctionType(TypeFunction* tf)
{
IrFuncTy* fty = tf->fty;
Type* rt = fty->ret->type->toBasetype();
IrFuncTy& fty = tf->fty;
Type* rt = fty.ret->type->toBasetype();
// extern(D)
if (tf->linkage == LINKd)
@@ -179,31 +179,31 @@ struct X86TargetABI : TargetABI
if (rt->iscomplex())
{
Logger::println("Rewriting complex return value");
fty->ret->rewrite = &swapComplex;
fty.ret->rewrite = &swapComplex;
}
// IMPLICIT PARAMETERS
// mark this/nested params inreg
if (fty->arg_this)
if (fty.arg_this)
{
Logger::println("Putting 'this' in register");
fty->arg_this->attrs = llvm::Attribute::InReg;
fty.arg_this->attrs = llvm::Attribute::InReg;
}
else if (fty->arg_nest)
else if (fty.arg_nest)
{
Logger::println("Putting context ptr in register");
fty->arg_nest->attrs = llvm::Attribute::InReg;
fty.arg_nest->attrs = llvm::Attribute::InReg;
}
// otherwise try to mark the last param inreg
else if (!fty->arg_sret && !fty->args.empty())
else if (!fty.arg_sret && !fty.args.empty())
{
// The last parameter is passed in EAX rather than being pushed on the stack if the following conditions are met:
// * It fits in EAX.
// * It is not a 3 byte struct.
// * It is not a floating point type.
IrFuncTyArg* last = fty->args.back();
IrFuncTyArg* last = fty.args.back();
Type* lastTy = last->type->toBasetype();
unsigned sz = lastTy->size();
@@ -234,9 +234,9 @@ struct X86TargetABI : TargetABI
// reverse parameter order
// for non variadics
if (!fty->args.empty() && tf->varargs != 1)
if (!fty.args.empty() && tf->varargs != 1)
{
fty->reverseParams = true;
fty.reverseParams = true;
}
}
@@ -248,8 +248,8 @@ struct X86TargetABI : TargetABI
// cfloat -> i64
if (tf->next->toBasetype() == Type::tcomplex32)
{
fty->ret->rewrite = &cfloatToInt;
fty->ret->ltype = LLType::Int64Ty;
fty.ret->rewrite = &cfloatToInt;
fty.ret->ltype = LLType::Int64Ty;
}
// IMPLICIT PARAMETERS

View File

@@ -33,16 +33,15 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
// already built ?
if (type->ir.type != NULL) {
assert(f->fty != NULL);
//assert(f->fty != NULL);
return llvm::cast<llvm::FunctionType>(type->ir.type->get());
}
// Tell the ABI we're resolving a new function type
gABI->newFunctionType(f);
// create new ir funcTy
assert(f->fty == NULL);
f->fty = new IrFuncTy();
// start new ir funcTy
f->fty.reset();
// llvm idx counter
size_t lidx = 0;
@@ -50,7 +49,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
// main needs a little special handling
if (ismain)
{
f->fty->ret = new IrFuncTyArg(Type::tint32, false);
f->fty.ret = new IrFuncTyArg(Type::tint32, false);
}
// sane return value
else
@@ -60,7 +59,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
// sret return
if (gABI->returnInArg(f))
{
f->fty->arg_sret = new IrFuncTyArg(rt, true, llvm::Attribute::StructRet);
f->fty.arg_sret = new IrFuncTyArg(rt, true, llvm::Attribute::StructRet);
rt = Type::tvoid;
lidx++;
}
@@ -69,7 +68,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
{
a = se;
}
f->fty->ret = new IrFuncTyArg(rt, false, a);
f->fty.ret = new IrFuncTyArg(rt, false, a);
}
lidx++;
@@ -77,14 +76,14 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
if (thistype)
{
bool toref = (thistype->toBasetype()->ty == Tstruct);
f->fty->arg_this = new IrFuncTyArg(thistype, toref);
f->fty.arg_this = new IrFuncTyArg(thistype, toref);
lidx++;
}
// and nested functions
else if (nesttype)
{
f->fty->arg_nest = new IrFuncTyArg(nesttype, false);
f->fty.arg_nest = new IrFuncTyArg(nesttype, false);
lidx++;
}
@@ -98,16 +97,16 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
if (f->varargs == 1)
{
// _arguments
f->fty->arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false);
f->fty.arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false);
lidx++;
// _argptr
f->fty->arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false);
f->fty.arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false);
lidx++;
}
}
else if (f->linkage == LINKc)
{
f->fty->c_vararg = true;
f->fty.c_vararg = true;
}
else
{
@@ -122,7 +121,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
if (ismain && nargs == 0)
{
Type* mainargs = Type::tchar->arrayOf()->arrayOf();
f->fty->args.push_back(new IrFuncTyArg(mainargs, false));
f->fty.args.push_back(new IrFuncTyArg(mainargs, false));
lidx++;
}
// add explicit parameters
@@ -157,7 +156,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
a |= DtoShouldExtend(argtype);
}
f->fty->args.push_back(new IrFuncTyArg(argtype, byref, a));
f->fty.args.push_back(new IrFuncTyArg(argtype, byref, a));
lidx++;
}
@@ -171,26 +170,26 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
std::vector<const LLType*> argtypes;
argtypes.reserve(lidx);
if (f->fty->arg_sret) argtypes.push_back(f->fty->arg_sret->ltype);
if (f->fty->arg_this) argtypes.push_back(f->fty->arg_this->ltype);
if (f->fty->arg_nest) argtypes.push_back(f->fty->arg_nest->ltype);
if (f->fty->arg_arguments) argtypes.push_back(f->fty->arg_arguments->ltype);
if (f->fty->arg_argptr) argtypes.push_back(f->fty->arg_argptr->ltype);
if (f->fty.arg_sret) argtypes.push_back(f->fty.arg_sret->ltype);
if (f->fty.arg_this) argtypes.push_back(f->fty.arg_this->ltype);
if (f->fty.arg_nest) argtypes.push_back(f->fty.arg_nest->ltype);
if (f->fty.arg_arguments) argtypes.push_back(f->fty.arg_arguments->ltype);
if (f->fty.arg_argptr) argtypes.push_back(f->fty.arg_argptr->ltype);
size_t beg = argtypes.size();
size_t nargs2 = f->fty->args.size();
size_t nargs2 = f->fty.args.size();
for (size_t i = 0; i < nargs2; i++)
{
argtypes.push_back(f->fty->args[i]->ltype);
argtypes.push_back(f->fty.args[i]->ltype);
}
// reverse params?
if (f->fty->reverseParams && nargs2 > 1)
if (f->fty.reverseParams && nargs2 > 1)
{
std::reverse(argtypes.begin() + beg, argtypes.end());
}
llvm::FunctionType* functype = llvm::FunctionType::get(f->fty->ret->ltype, argtypes, f->fty->c_vararg);
llvm::FunctionType* functype = llvm::FunctionType::get(f->fty.ret->ltype, argtypes, f->fty.c_vararg);
f->ir.type = new llvm::PATypeHolder(functype);
Logger::cout() << "Final function type: " << *functype << "\n";
@@ -211,17 +210,16 @@ static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
const llvm::FunctionType* fty = 0;
// create new ir funcTy
assert(f->fty == NULL);
f->fty = new IrFuncTy();
f->fty->ret = new IrFuncTyArg(Type::tvoid, false);
f->fty.reset();
f->fty.ret = new IrFuncTyArg(Type::tvoid, false);
f->fty->args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
f->fty.args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
if (fdecl->llvmInternal == LLVMva_start)
fty = GET_INTRINSIC_DECL(vastart)->getFunctionType();
else if (fdecl->llvmInternal == LLVMva_copy) {
fty = GET_INTRINSIC_DECL(vacopy)->getFunctionType();
f->fty->args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
f->fty.args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
}
else if (fdecl->llvmInternal == LLVMva_end)
fty = GET_INTRINSIC_DECL(vaend)->getFunctionType();
@@ -359,10 +357,10 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati
// handle implicit args
#define ADD_PA(X) \
if (f->fty->X) { \
if (f->fty->X->attrs) { \
if (f->fty.X) { \
if (f->fty.X->attrs) { \
PAWI.Index = idx; \
PAWI.Attrs = f->fty->X->attrs; \
PAWI.Attrs = f->fty.X->attrs; \
attrs.push_back(PAWI); \
} \
idx++; \
@@ -386,11 +384,11 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati
Argument* fnarg = Argument::getNth(f->parameters, k);
assert(fnarg);
attrptr[k] = f->fty->args[k]->attrs;
attrptr[k] = f->fty.args[k]->attrs;
}
// reverse params?
if (f->fty->reverseParams)
if (f->fty.reverseParams)
{
std::reverse(attrptr.begin(), attrptr.end());
}
@@ -500,26 +498,26 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
// name parameters
llvm::Function::arg_iterator iarg = func->arg_begin();
if (f->fty->arg_sret) {
if (f->fty.arg_sret) {
iarg->setName(".sret_arg");
fdecl->ir.irFunc->retArg = iarg;
++iarg;
}
if (f->fty->arg_this) {
if (f->fty.arg_this) {
iarg->setName(".this_arg");
fdecl->ir.irFunc->thisArg = iarg;
assert(fdecl->ir.irFunc->thisArg);
++iarg;
}
else if (f->fty->arg_nest) {
else if (f->fty.arg_nest) {
iarg->setName(".nest_arg");
fdecl->ir.irFunc->nestArg = iarg;
assert(fdecl->ir.irFunc->nestArg);
++iarg;
}
if (f->fty->arg_argptr) {
if (f->fty.arg_argptr) {
iarg->setName("._arguments");
fdecl->ir.irFunc->_arguments = iarg;
++iarg;
@@ -535,7 +533,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
if (fdecl->parameters && fdecl->parameters->dim > k)
{
Dsymbol* argsym;
if (f->fty->reverseParams)
if (f->fty.reverseParams)
argsym = (Dsymbol*)fdecl->parameters->data[fdecl->parameters->dim-k-1];
else
argsym = (Dsymbol*)fdecl->parameters->data[k];
@@ -655,7 +653,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
}
// give the 'this' argument storage and debug info
if (f->fty->arg_this)
if (f->fty.arg_this)
{
LLValue* thisvar = irfunction->thisArg;
assert(thisvar);
@@ -685,7 +683,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
// and debug info
if (fd->parameters)
{
size_t n = f->fty->args.size();
size_t n = f->fty.args.size();
assert(n == fd->parameters->dim);
for (int i=0; i < n; ++i)
{
@@ -708,7 +706,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
bool refout = vd->storage_class & (STCref | STCout);
bool lazy = vd->storage_class & STClazy;
if (!refout && (!f->fty->args[i]->byref || lazy))
if (!refout && (!f->fty.args[i]->byref || lazy))
{
// alloca a stack slot for this first class value arg
const LLType* argt;
@@ -720,7 +718,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
// let the abi transform the argument back first
DImValue arg_dval(vd->type, irloc->value);
f->fty->getParam(vd->type, i, &arg_dval, mem);
f->fty.getParam(vd->type, i, &arg_dval, mem);
// set the arg var value to the alloca
irloc->value = mem;

View File

@@ -92,7 +92,7 @@ void ReturnStatement::toIR(IRState* p)
if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
// do abi specific transformations on the return value
LLValue* v = p->func()->type->fty->putRet(exp->type, exp->toElem(p));
LLValue* v = p->func()->type->fty.putRet(exp->type, exp->toElem(p));
if (Logger::enabled())
Logger::cout() << "return value is '" <<*v << "'\n";

View File

@@ -201,11 +201,11 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args, std::vector<llvm::Attribut
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
args.push_back(argval->getRVal());
if (tf->fty->args[i]->attrs)
if (tf->fty.args[i]->attrs)
{
llvm::AttributeWithIndex Attr;
Attr.Index = argidx;
Attr.Attrs = tf->fty->args[i]->attrs;
Attr.Attrs = tf->fty.args[i]->attrs;
attrs.push_back(Attr);
}
@@ -239,10 +239,10 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
TypeFunction* tf = DtoTypeFunction(fnval);
// misc
bool retinptr = tf->fty->arg_sret;
bool thiscall = tf->fty->arg_this;
bool retinptr = tf->fty.arg_sret;
bool thiscall = tf->fty.arg_this;
bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate);
bool nestedcall = tf->fty->arg_nest;
bool nestedcall = tf->fty.arg_nest;
bool dvarargs = (tf->linkage == LINKd && tf->varargs == 1);
unsigned callconv = DtoCallingConv(loc, tf->linkage);
@@ -267,16 +267,16 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
llvm::AttributeWithIndex Attr;
// return attrs
if (tf->fty->ret->attrs)
if (tf->fty.ret->attrs)
{
Attr.Index = 0;
Attr.Attrs = tf->fty->ret->attrs;
Attr.Attrs = tf->fty.ret->attrs;
attrs.push_back(Attr);
}
// handle implicit arguments
std::vector<LLValue*> args;
args.reserve(tf->fty->args.size());
args.reserve(tf->fty.args.size());
// return in hidden ptr is first
if (retinptr)
@@ -332,16 +332,16 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
}
// add attributes for context argument
if (tf->fty->arg_this && tf->fty->arg_this->attrs)
if (tf->fty.arg_this && tf->fty.arg_this->attrs)
{
Attr.Index = retinptr ? 2 : 1;
Attr.Attrs = tf->fty->arg_this->attrs;
Attr.Attrs = tf->fty.arg_this->attrs;
attrs.push_back(Attr);
}
else if (tf->fty->arg_nest && tf->fty->arg_nest->attrs)
else if (tf->fty.arg_nest && tf->fty.arg_nest->attrs)
{
Attr.Index = retinptr ? 2 : 1;
Attr.Attrs = tf->fty->arg_nest->attrs;
Attr.Attrs = tf->fty.arg_nest->attrs;
attrs.push_back(Attr);
}
}
@@ -402,14 +402,14 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
}
// give the ABI a say
LLValue* arg = tf->fty->putParam(argval->getType(), i, argval);
LLValue* arg = tf->fty.putParam(argval->getType(), i, argval);
if (Logger::enabled()) {
Logger::cout() << "Argument after ABI: " << *arg << '\n';
Logger::cout() << "Argument type after ABI: " << *arg->getType() << '\n';
}
int j = tf->fty->reverseParams ? beg + n - i - 1 : beg + i;
int j = tf->fty.reverseParams ? beg + n - i - 1 : beg + i;
// Hack around LDC assuming structs are in memory:
// If the function wants a struct, and the argument value is a
@@ -434,14 +434,14 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
}
// param attrs
attrptr[i] = tf->fty->args[i]->attrs;
attrptr[i] = tf->fty.args[i]->attrs;
++argiter;
args.push_back(arg);
}
// reverse the relevant params as well as the param attrs
if (tf->fty->reverseParams)
if (tf->fty.reverseParams)
{
std::reverse(args.begin() + beg, args.end());
std::reverse(attrptr.begin(), attrptr.end());
@@ -507,7 +507,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
{
// do abi specific return value fixups
DImValue dretval(tf->next, retllval);
retllval = tf->fty->getRet(tf->next, &dretval);
retllval = tf->fty.getRet(tf->next, &dretval);
}
// Hack around LDC assuming structs are in memory:

View File

@@ -5,6 +5,7 @@
#include "gen/dvalue.h"
#include "gen/logger.h"
#include "ir/irfunction.h"
#include "ir/irfuncty.h"
#include <sstream>
@@ -21,6 +22,10 @@ IrFuncTyArg::IrFuncTyArg(Type* t, bool bref, unsigned a)
rewrite = NULL;
}
bool IrFuncTyArg::isInReg() const { return (attrs & llvm::Attribute::InReg) != 0; }
bool IrFuncTyArg::isSRet() const { return (attrs & llvm::Attribute::StructRet) != 0; }
bool IrFuncTyArg::isByVal() const { return (attrs & llvm::Attribute::ByVal) != 0; }
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

View File

@@ -9,90 +9,6 @@
#include <stack>
#include <map>
struct ABIRewrite;
// represents a function type argument
// both explicit and implicit as well as return values
struct IrFuncTyArg : IrBase
{
/** This is the original D type as the frontend knows it
* May NOT be rewritten!!! */
Type* type;
/// This is the final LLVM Type used for the parameter/return value type
const llvm::Type* ltype;
/** These are the final LLVM attributes used for the function.
* Must be valid for the LLVM Type and byref setting */
unsigned attrs;
/** 'true' if the final LLVM argument is a LLVM reference type.
* Must be true when the D Type is a value type, but the final
* LLVM Type is a reference type! */
bool byref;
/** Pointer to the ABIRewrite structure needed to rewrite LLVM ValueS
* to match the final LLVM Type when passing arguments and getting
* return values */
ABIRewrite* rewrite;
/// Helper to check if the 'inreg' attribute is set
bool isInReg() const { return (attrs & llvm::Attribute::InReg) != 0; }
/// Helper to check if the 'sret' attribute is set
bool isSRet() const { return (attrs & llvm::Attribute::StructRet) != 0; }
/// Helper to check if the 'byval' attribute is set
bool isByVal() const { return (attrs & llvm::Attribute::ByVal) != 0; }
/** @param t D type of argument/return value as known by the frontend
* @param byref Initial value for the 'byref' field. If true the initial
* LLVM Type will be of DtoType(type->pointerTo()), instead
* of just DtoType(type) */
IrFuncTyArg(Type* t, bool byref, unsigned a = 0);
};
// represents a function type
struct IrFuncTy : IrBase
{
// return value
IrFuncTyArg* ret;
// null if not applicable
IrFuncTyArg* arg_sret;
IrFuncTyArg* arg_this;
IrFuncTyArg* arg_nest;
IrFuncTyArg* arg_arguments;
IrFuncTyArg* arg_argptr;
// normal explicit arguments
typedef LLSmallVector<IrFuncTyArg*, 4> ArgList;
typedef ArgList::iterator ArgIter;
ArgList args;
// C varargs
bool c_vararg;
// range of normal parameters to reverse
bool reverseParams;
IrFuncTy()
: ret(NULL),
arg_sret(NULL),
arg_this(NULL),
arg_nest(NULL),
arg_arguments(NULL),
arg_argptr(NULL),
c_vararg(false),
reverseParams(false)
{}
llvm::Value* putRet(Type* dty, DValue* dval);
llvm::Value* getRet(Type* dty, DValue* dval);
llvm::Value* putParam(Type* dty, int idx, DValue* dval);
llvm::Value* getParam(Type* dty, int idx, DValue* dval);
void getParam(Type* dty, int idx, DValue* dval, llvm::Value* lval);
};
// represents a function
struct IrFunction : IrBase
{

108
ir/irfuncty.h Normal file
View File

@@ -0,0 +1,108 @@
#ifndef LDC_IR_IRFUNCTY_H
#define LDC_IR_IRFUNCTY_H
#include "ir/ir.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
struct ABIRewrite;
namespace llvm {
class Type;
class Value;
class Instruction;
class Function;
}
// represents a function type argument
// both explicit and implicit as well as return values
struct IrFuncTyArg : IrBase
{
/** This is the original D type as the frontend knows it
* May NOT be rewritten!!! */
Type* type;
/// This is the final LLVM Type used for the parameter/return value type
const llvm::Type* ltype;
/** These are the final LLVM attributes used for the function.
* Must be valid for the LLVM Type and byref setting */
unsigned attrs;
/** 'true' if the final LLVM argument is a LLVM reference type.
* Must be true when the D Type is a value type, but the final
* LLVM Type is a reference type! */
bool byref;
/** Pointer to the ABIRewrite structure needed to rewrite LLVM ValueS
* to match the final LLVM Type when passing arguments and getting
* return values */
ABIRewrite* rewrite;
/// Helper to check if the 'inreg' attribute is set
bool isInReg() const;
/// Helper to check if the 'sret' attribute is set
bool isSRet() const;
/// Helper to check if the 'byval' attribute is set
bool isByVal() const;
/** @param t D type of argument/return value as known by the frontend
* @param byref Initial value for the 'byref' field. If true the initial
* LLVM Type will be of DtoType(type->pointerTo()), instead
* of just DtoType(type) */
IrFuncTyArg(Type* t, bool byref, unsigned a = 0);
};
// represents a function type
struct IrFuncTy : IrBase
{
// return value
IrFuncTyArg* ret;
// null if not applicable
IrFuncTyArg* arg_sret;
IrFuncTyArg* arg_this;
IrFuncTyArg* arg_nest;
IrFuncTyArg* arg_arguments;
IrFuncTyArg* arg_argptr;
// normal explicit arguments
// typedef llvm::SmallVector<IrFuncTyArg*, 4> ArgList;
typedef std::vector<IrFuncTyArg*> ArgList;
typedef ArgList::iterator ArgIter;
ArgList args;
// C varargs
bool c_vararg;
// range of normal parameters to reverse
bool reverseParams;
IrFuncTy()
: ret(NULL),
arg_sret(NULL),
arg_this(NULL),
arg_nest(NULL),
arg_arguments(NULL),
arg_argptr(NULL),
c_vararg(false),
reverseParams(false)
{}
void reset() {
ret = NULL;
arg_sret = arg_this = arg_nest = arg_arguments = arg_argptr = NULL;
args.clear();
c_vararg = false;
reverseParams = false;
}
llvm::Value* putRet(Type* dty, DValue* dval);
llvm::Value* getRet(Type* dty, DValue* dval);
llvm::Value* putParam(Type* dty, int idx, DValue* dval);
llvm::Value* getParam(Type* dty, int idx, DValue* dval);
void getParam(Type* dty, int idx, DValue* dval, llvm::Value* lval);
};
#endif

View File

@@ -7,6 +7,13 @@
#include <deque>
#include <stack>
namespace llvm {
class Type;
class Value;
class BasicBlock;
class Function;
}
// only to be used within IRLandingPad
// holds information about a single catch or finally
struct IRLandingPadInfo
@@ -57,7 +64,7 @@ struct IRLandingPad
llvm::BasicBlock* get();
// creates or gets storage for exception object
LLValue* getExceptionStorage();
llvm::Value* getExceptionStorage();
private:
// constructs the landing pad from infos
@@ -77,7 +84,7 @@ private:
std::map<ClassDeclaration*, int> catchToInt;
// storage for the catch variable
LLValue* catch_var;
llvm::Value* catch_var;
};
#endif