src/builtin.lisp, src/codegen-proto.lisp: Improve slot initialization.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 21 Oct 2015 23:46:28 +0000 (00:46 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 7 Nov 2015 14:23:54 +0000 (14:23 +0000)
The fundamental difficulty is that actually we're not initializing an
instance's slots: we're assigning values to them.

Previously, we tried to distinguish scalar from aggregate initializers.
The former got converted into

sod__obj->nick.slot = EXPR;

while the latter ended up as

sod__obj->nick.slot = (TYPE) { COMPOUND-INIT };

There are two problems with this.  The first is easy: aggregate
literals, such are used in the latter case, are shiny and new in C99.
The second is more subtle: we distinguish aggregate from scalar
initializers from whether they're wrapped up in braces -- but in fact
they needn't be if they've been concealed in a macro, e.g.,
`PTHREAD_MUTEX_INITIALIZER', or `DSTR_INIT'.  Under the previous rules,
you'd have to write something like

pthread_mutex_t slot = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;

as your slot definition in order to get the right effect, and that's
just annoying.  (It would be a disservice to users to insert the cast
unconditionally, of course, since that would eliminate useful type
checking.)

Change all of this.  Instead, actually initialize an object of the right
type (we know that type that is, of course), and then assign it to the
slot.  A decent compiler will turn this into exactly the same object
code (yes, I tested this), and it means that our heuristic is no longer
needed for anything important.  I've preserved the distinction anyway,
because we can format compound initializers slightly more prettily, but
it no longer makes any semantic difference, and the dependency on C99
has been eliminated.

src/builtin.lisp
src/codegen-proto.lisp

index 5aad5f5..7bb38e5 100644 (file)
@@ -140,19 +140,22 @@ static void *~A__init(void *p)~%{~%" class)
                               "  struct ~A *sod__obj = ~A__imprint(p);~2%"
                               (ilayout-struct-tag class) class)
                       (setf used t))
-                    (format stream "  ~A.~A =" isl
-                            (sod-slot-name dslot))
+                    (format stream "  {~%    ~A ~A ="
+                            (sod-slot-type dslot)
+                            *sod-tmp-val*)
                     (ecase (sod-initializer-value-kind init)
                       (:simple (write (sod-initializer-value-form init)
                                       :stream stream
                                       :pretty nil :escape nil)
                                (format stream ";~%"))
-                      (:compound (format stream " (~A) {"
-                                         (sod-slot-type dslot))
+                      (:compound (format stream " {")
                                  (write (sod-initializer-value-form init)
                                         :stream stream
                                         :pretty nil :escape nil)
-                                 (format stream "};~%"))))))))))))
+                                 (format stream "    };~%")))
+                    (format stream "    ~A.~A = ~A;~%  }~%"
+                            isl (sod-slot-name dslot)
+                            *sod-tmp-val*))))))))))
     (unless used
       (format stream "  ~A__imprint(p);~%" class))
     (format stream "~&~:
index 42175a5..6dc6dc1 100644 (file)
@@ -64,6 +64,8 @@
   (make-instance 'temporary-name :tag "sod__master_ap"))
 (defparameter *sod-tmp-ap*
   (make-instance 'temporary-name :tag "sod__tmp_ap"))
+(defparameter *sod-tmp-val*
+  (make-instance 'temporary-name :tag "sod__t"))
 
 ;;;--------------------------------------------------------------------------
 ;;; Instructions.