On 1/25/21 7:34 PM, Herman ten Brugge wrote:
On 1/25/21 6:55 PM, grischka wrote:
Herman ten Brugge via Tinycc-devel wrote:
The problem is that packed structeres should probably always use
single_byte code.
For example:
-----
struct __attribute__((packed)) {
  char a;
  int b;
} s;

int
main(void)
{
  s.b = 3;
}
-----
Also fails to run on arm32 (openbsd).
I do not have a solution. But maybe Grischka can solve this?

Don't know, maybe look what gcc does?
gcc uses load/store bytes for packed structs. A packed struct can
also start at any address (see below) so this is the only thing that works.

However, with your example, for example, one could take the address
    int *p = &s.b;
and pass that to other functions, as well.  There is not much
that the compiler could do.
yes this would not work. But this also does not work with all other compilers.

For the 96_nodata_wanted test using 'packed' or not probably would
not make much difference, at least on ARM.  Maybe it was supposed
to test single-byte access under code suppression.  But why shouldn't
it work anyway.
The stack is adjusted with 7 bytes (size of the struct =7 and align=1). The code in struct_layout expects the struct is aligned but this is not the case for packed structs.

I implemented load/store bytes for packed structs in tcc (see attachment).
Can I push it to mob?

    Herman

diff --git a/tcc.h b/tcc.h
index 3f8647d..eeeb01c 100644
--- a/tcc.h
+++ b/tcc.h
@@ -1036,7 +1036,8 @@ struct filespec {
 #define VT_STATIC  0x00002000  /* static variable */
 #define VT_TYPEDEF 0x00004000  /* typedef definition */
 #define VT_INLINE  0x00008000  /* inline definition */
-/* currently unused: 0x000[1248]0000  */
+#define VT_PACKED  0x00010000  /* packed struct */
+/* currently unused: 0x000[248]0000  */
 
 #define VT_STRUCT_SHIFT 20     /* shift for bitfield shift values (32 - 2*6) */
 #define VT_STRUCT_MASK (((1U << (6+6)) - 1) << VT_STRUCT_SHIFT | VT_BITFIELD)
diff --git a/tccgen.c b/tccgen.c
index 33a91f8..39bb682 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -2316,11 +2316,18 @@ ST_FUNC int gv(int rc)
     int bit_pos, bit_size, size, align;
 
     /* NOTE: get_reg can modify vstack[] */
-    if (vtop->type.t & VT_BITFIELD) {
+    if (vtop->type.t & (VT_BITFIELD | VT_PACKED)) {
         CType type;
 
-        bit_pos = BIT_POS(vtop->type.t);
-        bit_size = BIT_SIZE(vtop->type.t);
+       if (vtop->type.t & VT_BITFIELD) {
+            bit_pos = BIT_POS(vtop->type.t);
+            bit_size = BIT_SIZE(vtop->type.t);
+       }
+       else {
+            size = type_size(&vtop->type, &align);
+            bit_pos = 0;
+            bit_size = size * 8;
+       }
         /* remove bit field info to avoid loops */
         vtop->type.t &= ~VT_STRUCT_MASK;
 
@@ -2329,12 +2336,17 @@ ST_FUNC int gv(int rc)
         if ((vtop->type.t & VT_BTYPE) == VT_BOOL)
             type.t |= VT_UNSIGNED;
 
-        r = adjust_bf(vtop, bit_pos, bit_size);
-
-        if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
-            type.t |= VT_LLONG;
-        else
-            type.t |= VT_INT;
+        if (vtop->type.t & VT_PACKED) {
+            type.t |= VT_BYTE;
+           r = VT_STRUCT;
+       }
+       else {
+            r = adjust_bf(vtop, bit_pos, bit_size);
+             if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
+                type.t |= VT_LLONG;
+            else
+                type.t |= VT_INT;
+       }
 
         if (r == VT_STRUCT) {
             load_packed_bf(&type, bit_pos, bit_size);
@@ -2528,7 +2540,7 @@ static void gv_dup(void)
     t = vtop->type.t;
 #if PTR_SIZE == 4
     if ((t & VT_BTYPE) == VT_LLONG) {
-        if (t & VT_BITFIELD) {
+        if (t & (VT_BITFIELD | VT_PACKED)) {
             gv(RC_INT);
             t = vtop->type.t;
         }
@@ -3679,7 +3691,7 @@ static void gen_cast(CType *type)
         force_charshort_cast();
 
     /* bitfields first get cast to ints */
-    if (vtop->type.t & VT_BITFIELD)
+    if (vtop->type.t & (VT_BITFIELD | VT_PACKED))
         gv(RC_INT);
 
     dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
@@ -4151,14 +4163,21 @@ ST_FUNC void vstore(void)
             gfunc_call(3);
         /* leave source on stack */
 
-    } else if (ft & VT_BITFIELD) {
+    } else if (ft & (VT_BITFIELD | VT_PACKED)) {
         /* bitfield store handling */
 
         /* save lvalue as expression result (example: s.b = s.a = n;) */
         vdup(), vtop[-1] = vtop[-2];
 
-        bit_pos = BIT_POS(ft);
-        bit_size = BIT_SIZE(ft);
+       if (ft & VT_BITFIELD) {
+            bit_pos = BIT_POS(ft);
+            bit_size = BIT_SIZE(ft);
+       }
+       else {
+            size = type_size(&vtop[-1].type, &align);
+            bit_pos = 0;
+            bit_size = size * 8;
+       }
         /* remove bit field info to avoid loops */
         vtop[-1].type.t = ft & ~VT_STRUCT_MASK;
 
@@ -4166,11 +4185,17 @@ ST_FUNC void vstore(void)
             gen_cast(&vtop[-1].type);
             vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | 
VT_UNSIGNED);
         }
-        r = adjust_bf(vtop - 1, bit_pos, bit_size);
+        r = ft & VT_PACKED ? VT_STRUCT : adjust_bf(vtop - 1, bit_pos, 
bit_size);
         if (dbt != VT_BOOL) {
             gen_cast(&vtop[-1].type);
             dbt = vtop[-1].type.t & VT_BTYPE;
-        }
+       }
+
+       if (ft & VT_PACKED) {
+            vtop->type.t = vtop->type.t & ~VT_PACKED;
+            vtop[-1].type.t = (vtop[-1].type.t & ~(VT_BTYPE | VT_PACKED)) | 
VT_BYTE;
+       }
+
         if (r == VT_STRUCT) {
             store_packed_bf(bit_pos, bit_size);
         } else {
@@ -4603,6 +4628,10 @@ static void struct_layout(CType *type, AttributeDef *ad)
                 if (pcc && pragma_pack < a)
                     a = 0;
             }
+#ifdef TCC_TARGET_ARM
+           if (packed)
+               f->type.t |= VT_PACKED;
+#endif
         }
         /* some individual align was specified */
         if (a)
diff --git a/tests/tests2/96_nodata_wanted.c b/tests/tests2/96_nodata_wanted.c
index 1a4cd33..4e95603 100644
--- a/tests/tests2/96_nodata_wanted.c
+++ b/tests/tests2/96_nodata_wanted.c
@@ -58,10 +58,7 @@ ts1:;
         void *p = (void*)&main;
         char cc[] = "static string";
         double d = 8.0;
-        struct
-#ifndef __arm__
-        __attribute__((packed))
-#endif
+        struct __attribute__((packed))
         {
             unsigned x : 12;
             unsigned char y : 7;
_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to