Intrinsics shouldn't see struct padding, so use a special TargetABI for them

that removes it.
This unbreaks the `llvm_*_with_overflow` intrinsics.
This commit is contained in:
Frits van Bommel
2009-05-16 13:06:49 +02:00
parent 62e8384da0
commit 541f3723cd
7 changed files with 219 additions and 60 deletions

View File

@@ -10,6 +10,7 @@
#include "gen/abi.h"
#include "gen/logger.h"
#include "gen/dvalue.h"
#include "gen/abi-generic.h"
#include "ir/irfunction.h"
@@ -311,3 +312,79 @@ TargetABI * TargetABI::getTarget()
return new UnknownTargetABI;
}
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// A simple ABI for LLVM intrinsics.
struct IntrinsicABI : TargetABI
{
RemoveStructPadding remove_padding;
bool returnInArg(TypeFunction* tf)
{
return false;
}
bool passByVal(Type* t)
{
return false;
}
void fixup(IrFuncTyArg& arg) {
assert(arg.type->ty == Tstruct);
// TODO: Check that no unions are passed in or returned.
LLType* abiTy = DtoUnpaddedStructType(arg.type);
if (abiTy && abiTy != arg.ltype) {
arg.ltype = abiTy;
arg.rewrite = &remove_padding;
}
}
void rewriteFunctionType(TypeFunction* tf)
{
assert(tf->linkage == LINKintrinsic);
IrFuncTy& fty = tf->fty;
if (!fty.arg_sret) {
Type* rt = fty.ret->type->toBasetype();
if (rt->ty == Tstruct) {
Logger::println("Intrinsic ABI: Transforming return type");
fixup(*fty.ret);
}
}
Logger::println("Intrinsic ABI: Transforming arguments");
LOG_SCOPE;
for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) {
IrFuncTyArg& arg = **I;
if (Logger::enabled())
Logger::cout() << "Arg: " << arg.type->toChars() << '\n';
// Arguments that are in memory are of no interest to us.
if (arg.byref)
continue;
Type* ty = arg.type->toBasetype();
if (ty->ty == Tstruct)
fixup(arg);
if (Logger::enabled())
Logger::cout() << "New arg type: " << *arg.ltype << '\n';
}
}
};
TargetABI * TargetABI::getIntrinsic()
{
static IntrinsicABI iabi;
return &iabi;
}