mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-30 03:23:19 +01:00
Automated merge with http://hg.dsource.org/projects/ldc
This commit is contained in:
@@ -45,8 +45,9 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
|
||||
gABI->newFunctionType(f);
|
||||
}
|
||||
|
||||
// start new ir funcTy
|
||||
f->fty.reset();
|
||||
// Do not modify f->fty yet; this function may be called recursively if any
|
||||
// of the argument types refer to this type.
|
||||
IrFuncTy fty;
|
||||
|
||||
// llvm idx counter
|
||||
size_t lidx = 0;
|
||||
@@ -54,7 +55,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);
|
||||
fty.ret = new IrFuncTyArg(Type::tint32, false);
|
||||
}
|
||||
// sane return value
|
||||
else
|
||||
@@ -65,7 +66,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
|
||||
if (f->linkage != LINKintrinsic)
|
||||
if (gABI->returnInArg(f))
|
||||
{
|
||||
f->fty.arg_sret = new IrFuncTyArg(rt, true, StructRet | NoAlias | NoCapture);
|
||||
fty.arg_sret = new IrFuncTyArg(rt, true, StructRet | NoAlias | NoCapture);
|
||||
rt = Type::tvoid;
|
||||
lidx++;
|
||||
}
|
||||
@@ -74,7 +75,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
|
||||
{
|
||||
a = se;
|
||||
}
|
||||
f->fty.ret = new IrFuncTyArg(rt, false, a);
|
||||
fty.ret = new IrFuncTyArg(rt, false, a);
|
||||
}
|
||||
lidx++;
|
||||
|
||||
@@ -82,14 +83,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);
|
||||
fty.arg_this = new IrFuncTyArg(thistype, toref);
|
||||
lidx++;
|
||||
}
|
||||
|
||||
// and nested functions
|
||||
else if (nesttype)
|
||||
{
|
||||
f->fty.arg_nest = new IrFuncTyArg(nesttype, false);
|
||||
fty.arg_nest = new IrFuncTyArg(nesttype, false);
|
||||
lidx++;
|
||||
}
|
||||
|
||||
@@ -103,16 +104,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);
|
||||
fty.arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false);
|
||||
lidx++;
|
||||
// _argptr
|
||||
f->fty.arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false, NoAlias | NoCapture);
|
||||
fty.arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false, NoAlias | NoCapture);
|
||||
lidx++;
|
||||
}
|
||||
}
|
||||
else if (f->linkage == LINKc)
|
||||
{
|
||||
f->fty.c_vararg = true;
|
||||
fty.c_vararg = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -127,7 +128,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));
|
||||
fty.args.push_back(new IrFuncTyArg(mainargs, false));
|
||||
lidx++;
|
||||
}
|
||||
// add explicit parameters
|
||||
@@ -163,10 +164,34 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
|
||||
a |= DtoShouldExtend(argtype);
|
||||
}
|
||||
|
||||
f->fty.args.push_back(new IrFuncTyArg(argtype, byref, a));
|
||||
fty.args.push_back(new IrFuncTyArg(argtype, byref, a));
|
||||
lidx++;
|
||||
}
|
||||
|
||||
// If the function type was forward referenced by one of the parameter types,
|
||||
// it has now been set.
|
||||
if (f->ir.type) {
|
||||
// Notify ABI that we won't be needing it for this function type anymore.
|
||||
gABI->doneWithFunctionType();
|
||||
|
||||
// Some cleanup of memory we won't use
|
||||
delete fty.ret;
|
||||
delete fty.arg_sret;
|
||||
delete fty.arg_this;
|
||||
delete fty.arg_nest;
|
||||
delete fty.arg_arguments;
|
||||
delete fty.arg_argptr;
|
||||
for (IrFuncTy::ArgIter It = fty.args.begin(), E = fty.args.end(); It != E; ++It) {
|
||||
delete *It;
|
||||
}
|
||||
|
||||
Logger::cout() << "Final function type: " << **f->ir.type << '\n';
|
||||
return llvm::cast<LLFunctionType>(*f->ir.type);
|
||||
}
|
||||
|
||||
// Now we can modify f->fty safely.
|
||||
f->fty = fty;
|
||||
|
||||
if (f->linkage != LINKintrinsic) {
|
||||
// let the abi rewrite the types as necesary
|
||||
gABI->rewriteFunctionType(f);
|
||||
|
||||
@@ -426,10 +426,14 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
|
||||
vd->ir.irLocal->nestedDepth = depth;
|
||||
if (vd->isParameter()) {
|
||||
// Parameters already have storage associated with them (to handle byref etc.),
|
||||
// so handle specially for now by storing a pointer instead of a value.
|
||||
// so handle those cases specially by storing a pointer instead of a value.
|
||||
assert(vd->ir.irLocal->value);
|
||||
// FIXME: don't do this for normal parameters?
|
||||
types.push_back(vd->ir.irLocal->value->getType());
|
||||
LLValue* value = vd->ir.irLocal->value;
|
||||
const LLType* type = value->getType();
|
||||
if (llvm::isa<llvm::AllocaInst>(value->getUnderlyingObject()))
|
||||
// This will be copied to the nesting frame.
|
||||
type = type->getContainedType(0);
|
||||
types.push_back(type);
|
||||
} else if (vd->isRef() || vd->isOut()) {
|
||||
// Foreach variables can also be by reference, for instance.
|
||||
types.push_back(DtoType(vd->type->pointerTo()));
|
||||
@@ -453,6 +457,8 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
|
||||
|
||||
// Create frame for current function and append to frames list
|
||||
// FIXME: For D2, this should be a gc_malloc (or similar) call, not alloca
|
||||
// (Note that it'd also require more aggressive copying of
|
||||
// by-value parameters instead of just alloca'd ones)
|
||||
LLValue* frame = DtoAlloca(frameType, ".frame");
|
||||
|
||||
// copy parent frames into beginning
|
||||
@@ -491,8 +497,26 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
|
||||
LLValue* gep = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
|
||||
if (vd->isParameter()) {
|
||||
Logger::println("nested param: %s", vd->toChars());
|
||||
DtoAlignedStore(vd->ir.irLocal->value, gep);
|
||||
vd->ir.irLocal->byref = true;
|
||||
LOG_SCOPE
|
||||
LLValue* value = vd->ir.irLocal->value;
|
||||
if (llvm::isa<llvm::AllocaInst>(value->getUnderlyingObject())) {
|
||||
Logger::println("Copying to nested frame");
|
||||
// The parameter value is an alloca'd stack slot.
|
||||
// Copy to the nesting frame and leave the alloca for
|
||||
// the optimizers to clean up.
|
||||
DtoStore(DtoLoad(value), gep);
|
||||
gep->takeName(value);
|
||||
vd->ir.irLocal->value = gep;
|
||||
vd->ir.irLocal->byref = false;
|
||||
} else {
|
||||
Logger::println("Adding pointer to nested frame");
|
||||
// The parameter value is something else, such as a
|
||||
// passed-in pointer (for 'ref' or 'out' parameters) or
|
||||
// a pointer arg with byval attribute.
|
||||
// Store the address into the frame and set the byref flag.
|
||||
DtoAlignedStore(vd->ir.irLocal->value, gep);
|
||||
vd->ir.irLocal->byref = true;
|
||||
}
|
||||
} else if (vd->isRef() || vd->isOut()) {
|
||||
// This slot is initialized in DtoNestedInit, to handle things like byref foreach variables
|
||||
// which move around in memory.
|
||||
|
||||
53
gen/toir.cpp
53
gen/toir.cpp
@@ -1825,10 +1825,6 @@ DValue* AndAndExp::toElem(IRState* p)
|
||||
Logger::print("AndAndExp::toElem: %s @ %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// allocate a temporary for the final result. failed to come up with a better way :/
|
||||
LLValue* resval = 0;
|
||||
resval = DtoAlloca(LLType::Int1Ty,"andandtmp");
|
||||
|
||||
DValue* u = e1->toElem(p);
|
||||
|
||||
llvm::BasicBlock* oldend = p->scopeend();
|
||||
@@ -1836,23 +1832,36 @@ DValue* AndAndExp::toElem(IRState* p)
|
||||
llvm::BasicBlock* andandend = llvm::BasicBlock::Create("andandend", gIR->topfunc(), oldend);
|
||||
|
||||
LLValue* ubool = DtoCast(loc, u, Type::tbool)->getRVal();
|
||||
DtoStore(ubool,resval);
|
||||
|
||||
llvm::BasicBlock* oldblock = p->scopebb();
|
||||
llvm::BranchInst::Create(andand,andandend,ubool,p->scopebb());
|
||||
|
||||
p->scope() = IRScope(andand, andandend);
|
||||
DValue* v = e2->toElem(p);
|
||||
|
||||
LLValue* vbool = 0;
|
||||
if (!v->isFunc() && v->getType() != Type::tvoid)
|
||||
{
|
||||
LLValue* vbool = DtoCast(loc, v, Type::tbool)->getRVal();
|
||||
LLValue* uandvbool = llvm::BinaryOperator::Create(llvm::BinaryOperator::And, ubool, vbool,"tmp",p->scopebb());
|
||||
DtoStore(uandvbool,resval);
|
||||
vbool = DtoCast(loc, v, Type::tbool)->getRVal();
|
||||
}
|
||||
|
||||
llvm::BasicBlock* newblock = p->scopebb();
|
||||
llvm::BranchInst::Create(andandend,p->scopebb());
|
||||
p->scope() = IRScope(andandend, oldend);
|
||||
|
||||
resval = DtoLoad(resval);
|
||||
LLValue* resval = 0;
|
||||
if (ubool == vbool || !vbool) {
|
||||
// No need to create a PHI node.
|
||||
resval = ubool;
|
||||
} else {
|
||||
llvm::PHINode* phi = p->ir->CreatePHI(LLType::Int1Ty, "andandval");
|
||||
// If we jumped over evaluation of the right-hand side,
|
||||
// the result is false. Otherwise it's the value of the right-hand side.
|
||||
phi->addIncoming(LLConstantInt::getFalse(), oldblock);
|
||||
phi->addIncoming(vbool, newblock);
|
||||
resval = phi;
|
||||
}
|
||||
|
||||
return new DImValue(type, resval);
|
||||
}
|
||||
|
||||
@@ -1863,10 +1872,6 @@ DValue* OrOrExp::toElem(IRState* p)
|
||||
Logger::print("OrOrExp::toElem: %s @ %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// allocate a temporary for the final result. failed to come up with a better way :/
|
||||
LLValue* resval = 0;
|
||||
resval = DtoAlloca(LLType::Int1Ty,"orortmp");
|
||||
|
||||
DValue* u = e1->toElem(p);
|
||||
|
||||
llvm::BasicBlock* oldend = p->scopeend();
|
||||
@@ -1874,22 +1879,36 @@ DValue* OrOrExp::toElem(IRState* p)
|
||||
llvm::BasicBlock* ororend = llvm::BasicBlock::Create("ororend", gIR->topfunc(), oldend);
|
||||
|
||||
LLValue* ubool = DtoCast(loc, u, Type::tbool)->getRVal();
|
||||
DtoStore(ubool,resval);
|
||||
|
||||
llvm::BasicBlock* oldblock = p->scopebb();
|
||||
llvm::BranchInst::Create(ororend,oror,ubool,p->scopebb());
|
||||
|
||||
p->scope() = IRScope(oror, ororend);
|
||||
DValue* v = e2->toElem(p);
|
||||
|
||||
LLValue* vbool = 0;
|
||||
if (!v->isFunc() && v->getType() != Type::tvoid)
|
||||
{
|
||||
LLValue* vbool = DtoCast(loc, v, Type::tbool)->getRVal();
|
||||
DtoStore(vbool,resval);
|
||||
vbool = DtoCast(loc, v, Type::tbool)->getRVal();
|
||||
}
|
||||
|
||||
llvm::BasicBlock* newblock = p->scopebb();
|
||||
llvm::BranchInst::Create(ororend,p->scopebb());
|
||||
p->scope() = IRScope(ororend, oldend);
|
||||
|
||||
resval = DtoLoad(resval);
|
||||
LLValue* resval = 0;
|
||||
if (ubool == vbool || !vbool) {
|
||||
// No need to create a PHI node.
|
||||
resval = ubool;
|
||||
} else {
|
||||
llvm::PHINode* phi = p->ir->CreatePHI(LLType::Int1Ty, "ororval");
|
||||
// If we jumped over evaluation of the right-hand side,
|
||||
// the result is true. Otherwise, it's the value of the right-hand side.
|
||||
phi->addIncoming(LLConstantInt::getTrue(), oldblock);
|
||||
phi->addIncoming(vbool, newblock);
|
||||
resval = phi;
|
||||
}
|
||||
|
||||
return new DImValue(type, resval);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user