Mercurial > projects > ldc
changeset 1001:7a0238db1962
Implement support for intrinsics returning struct types
(such as llvm.*.with.overflow)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Thu, 26 Feb 2009 22:47:06 +0100 |
parents | d6895f24dc8f |
children | c749648ed2b8 |
files | gen/functions.cpp gen/tocall.cpp runtime/import/ldc/intrinsics.di |
diffstat | 3 files changed, 77 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/gen/functions.cpp Thu Feb 26 18:43:25 2009 +0100 +++ b/gen/functions.cpp Thu Feb 26 22:47:06 2009 +0100 @@ -70,23 +70,33 @@ else { assert(rt); - if (gABI->returnInArg(rt)) + if (f->linkage == LINKintrinsic) { - rettype = getPtrToType(DtoType(rt)); - actualRettype = LLType::VoidTy; - f->retInPtr = retinptr = true; + // Intrinsics don't care about ABI + Logger::cout() << "Intrinsic returning " << rt->toChars() << '\n'; + actualRettype = rettype = DtoType(rt); + Logger::cout() << " (LLVM type: " << *rettype << ")\n"; } else { - rettype = DtoType(rt); - // do abi specific transformations - actualRettype = gABI->getRetType(f, rettype); - } + if (gABI->returnInArg(rt)) + { + rettype = getPtrToType(DtoType(rt)); + actualRettype = LLType::VoidTy; + f->retInPtr = retinptr = true; + } + else + { + rettype = DtoType(rt); + // do abi specific transformations + actualRettype = gABI->getRetType(f, rettype); + } - // FIXME: should probably be part of the abi - if (unsigned ea = DtoShouldExtend(rt)) - { - f->retAttrs |= ea; + // FIXME: should probably be part of the abi + if (unsigned ea = DtoShouldExtend(rt)) + { + f->retAttrs |= ea; + } } }
--- a/gen/tocall.cpp Thu Feb 26 18:43:25 2009 +0100 +++ b/gen/tocall.cpp Thu Feb 26 22:47:06 2009 +0100 @@ -464,8 +464,22 @@ // get return value LLValue* retllval = (retinptr) ? args[0] : call->get(); - // do abi specific return value fixups - retllval = gABI->getRet(tf, retllval); + if (tf->linkage == LINKintrinsic) + { + // Ignore ABI for intrinsics + Type* rettype = tf->next; + if (rettype->ty == Tstruct) { + // LDC assumes structs are in memory, so put it there. + LLValue* mem = DtoAlloca(retllval->getType()); + DtoStore(retllval, mem); + retllval = mem; + } + } + else + { + // do abi specific return value fixups + retllval = gABI->getRet(tf, retllval); + } // repaint the type if necessary if (resulttype)
--- a/runtime/import/ldc/intrinsics.di Thu Feb 26 18:43:25 2009 +0100 +++ b/runtime/import/ldc/intrinsics.di Thu Feb 26 22:47:06 2009 +0100 @@ -332,6 +332,45 @@ pragma(intrinsic, "llvm.atomic.load.umin.i#.p0i#") T llvm_atomic_load_umin(T)(T* ptr, T val); + +// +// ARITHMETIC-WITH-OVERFLOW INTRINSICS +// + +struct OverflowRet(T) { + static assert(is(T : int), T.stringof ~ " is not an integer type!"); + T result; + bool overflow; +} + +// Signed and unsigned addition +pragma(intrinsic, "llvm.sadd.with.overflow.i#") + OverflowRet!(T) llvm_sadd_with_overflow(T)(T lhs, T rhs); + +pragma(intrinsic, "llvm.uadd.with.overflow.i#") + OverflowRet!(T) llvm_uadd_with_overflow(T)(T lhs, T rhs); + +// Signed and unsigned subtraction +pragma(intrinsic, "llvm.ssub.with.overflow.i#") + OverflowRet!(T) llvm_ssub_with_overflow(T)(T lhs, T rhs); + +pragma(intrinsic, "llvm.usub.with.overflow.i#") + OverflowRet!(T) llvm_usub_with_overflow(T)(T lhs, T rhs); + +// Signed and unsigned multiplication +pragma(intrinsic, "llvm.smul.with.overflow.i#") + OverflowRet!(T) llvm_smul_with_overflow(T)(T lhs, T rhs); + +/* Note: LLVM documentations says: + * Warning: 'llvm.umul.with.overflow' is badly broken. + * It is actively being fixed, but it should not currently be used! + * + * See: http://llvm.org/docs/LangRef.html#int_umul_overflow + */ +pragma(intrinsic, "llvm.umul.with.overflow.i#") + OverflowRet!(T) llvm_umul_with_overflow(T)(T lhs, T rhs); + + // // GENERAL INTRINSICS //