diff gen/abi.cpp @ 1359:34f2fd925de3

Intrinsics shouldn't see struct padding, so use a special TargetABI for them that removes it. This unbreaks the `llvm_*_with_overflow` intrinsics.
author Frits van Bommel <fvbommel wxs.nl>
date Sat, 16 May 2009 13:06:49 +0200
parents 15e9762bb620
children c363d131c1ef
line wrap: on
line diff
--- a/gen/abi.cpp	Fri May 15 17:17:20 2009 +0200
+++ b/gen/abi.cpp	Sat May 16 13:06:49 2009 +0200
@@ -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 @@
         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;
+}