mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-12 05:47:11 +03:00
Refactor defining a function's explicit parameters
This commit is contained in:
parent
dd21a805ee
commit
0f41c0c681
1 changed files with 56 additions and 37 deletions
|
@ -660,6 +660,57 @@ void verifyScopedDestructionInClosure(FuncDeclaration* fd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Gives all explicit parameters storage and debug info.
|
||||||
|
// All explicit D parameters are lvalues, just like regular local variables.
|
||||||
|
void defineParameters(IrFuncTy &irFty, VarDeclarations ¶meters) {
|
||||||
|
// Not all arguments are necessarily passed on the LLVM level
|
||||||
|
// (e.g. zero-member structs), so we need to keep track of the
|
||||||
|
// index in the IrFuncTy args array separately.
|
||||||
|
size_t llArgIdx = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < parameters.dim; ++i) {
|
||||||
|
auto *const vd = parameters[i];
|
||||||
|
IrParameter *irparam = getIrParameter(vd);
|
||||||
|
|
||||||
|
// vd->type (parameter) and irparam->arg->type (argument) don't always
|
||||||
|
// match.
|
||||||
|
// E.g., for a lazy parameter of type T, vd->type is T (with lazy storage
|
||||||
|
// class) while irparam->arg->type is the delegate type.
|
||||||
|
Type *const paramType = (irparam ? irparam->arg->type : vd->type);
|
||||||
|
|
||||||
|
if (!irparam) {
|
||||||
|
// This is a parameter that is not passed on the LLVM level.
|
||||||
|
// Create the param here and set it to a "dummy" alloca that
|
||||||
|
// we do not store to here.
|
||||||
|
irparam = getIrParameter(vd, true);
|
||||||
|
irparam->value = DtoAlloca(vd, vd->ident->toChars());
|
||||||
|
} else {
|
||||||
|
assert(irparam->value);
|
||||||
|
|
||||||
|
if (irparam->arg->byref) {
|
||||||
|
// The argument is an appropriate lvalue passed by reference.
|
||||||
|
// Use the passed pointer as parameter storage.
|
||||||
|
assert(irparam->value->getType() == DtoPtrToType(paramType));
|
||||||
|
} else {
|
||||||
|
// Let the ABI transform the parameter back to an lvalue.
|
||||||
|
irparam->value =
|
||||||
|
irFty.getParamLVal(paramType, llArgIdx, irparam->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
irparam->value->setName(vd->ident->toChars());
|
||||||
|
|
||||||
|
++llArgIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global.params.symdebug)
|
||||||
|
gIR->DBuilder.EmitLocalVariable(irparam->value, vd, paramType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
void DtoDefineFunction(FuncDeclaration *fd) {
|
void DtoDefineFunction(FuncDeclaration *fd) {
|
||||||
IF_LOG Logger::println("DtoDefineFunction(%s): %s", fd->toPrettyChars(),
|
IF_LOG Logger::println("DtoDefineFunction(%s): %s", fd->toPrettyChars(),
|
||||||
fd->loc.toChars());
|
fd->loc.toChars());
|
||||||
|
@ -868,7 +919,7 @@ void DtoDefineFunction(FuncDeclaration *fd) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// give the 'this' argument storage and debug info
|
// give the 'this' parameter (an lvalue) storage and debug info
|
||||||
if (irFty.arg_this) {
|
if (irFty.arg_this) {
|
||||||
LLValue *thisvar = irFunc->thisArg;
|
LLValue *thisvar = irFunc->thisArg;
|
||||||
assert(thisvar);
|
assert(thisvar);
|
||||||
|
@ -893,46 +944,14 @@ void DtoDefineFunction(FuncDeclaration *fd) {
|
||||||
gIR->DBuilder.EmitLocalVariable(thismem, fd->vthis, nullptr, true);
|
gIR->DBuilder.EmitLocalVariable(thismem, fd->vthis, nullptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// give the 'nestArg' storage
|
// give the 'nestArg' parameter (an lvalue) storage
|
||||||
if (irFty.arg_nest) {
|
if (irFty.arg_nest) {
|
||||||
irFunc->nestArg = DtoAllocaDump(irFunc->nestArg, 0, "nestedFrame");
|
irFunc->nestArg = DtoAllocaDump(irFunc->nestArg, 0, "nestedFrame");
|
||||||
}
|
}
|
||||||
|
|
||||||
// give arguments storage and debug info
|
// define all explicit parameters
|
||||||
if (fd->parameters) {
|
if (fd->parameters)
|
||||||
// Not all arguments are necessarily passed on the LLVM level
|
defineParameters(irFty, *fd->parameters);
|
||||||
// (e.g. zero-member structs), so we need to keep track of the
|
|
||||||
// index in the IrFuncTy args array separately.
|
|
||||||
size_t llArgIdx = 0;
|
|
||||||
for (size_t i = 0; i < fd->parameters->dim; ++i) {
|
|
||||||
auto *const vd = (*fd->parameters)[i];
|
|
||||||
|
|
||||||
IrParameter *irparam = getIrParameter(vd);
|
|
||||||
Type *debugInfoType = vd->type;
|
|
||||||
if (!irparam) {
|
|
||||||
// This is a parameter that is not passed on the LLVM level.
|
|
||||||
// Create the param here and set it to a "dummy" alloca that
|
|
||||||
// we do not store to here.
|
|
||||||
irparam = getIrParameter(vd, true);
|
|
||||||
irparam->value = DtoAlloca(vd, vd->ident->toChars());
|
|
||||||
} else {
|
|
||||||
if (!irparam->arg->byref) {
|
|
||||||
// let the abi transform the argument back first
|
|
||||||
LLValue *mem = irFty.getParamLVal(irparam->arg->type, llArgIdx, irparam->value);
|
|
||||||
mem->setName(vd->ident->toChars());
|
|
||||||
|
|
||||||
// set the arg var value to the alloca
|
|
||||||
irparam->value = mem;
|
|
||||||
|
|
||||||
debugInfoType = irparam->arg->type;
|
|
||||||
}
|
|
||||||
++llArgIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (global.params.symdebug)
|
|
||||||
gIR->DBuilder.EmitLocalVariable(irparam->value, vd, debugInfoType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ScopeStack scopeStack(gIR);
|
ScopeStack scopeStack(gIR);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue