I implemented constructors and destructors. This was the one thing I was missing for my own project.

See the attachment.

Can I push it?

    Herman

diff --git a/tcc.h b/tcc.h
index c48b45b..7fd4dda 100644
--- a/tcc.h
+++ b/tcc.h
@@ -468,7 +468,9 @@ struct SymAttr {
     dllexport   : 1,
     nodecorate  : 1,
     dllimport   : 1,
-    unused      : 4;
+    constructor : 1,
+    destructor  : 1,
+    unused      : 2;
 };
 
 /* function attributes or temporary attributes for parsing */
@@ -1433,7 +1435,7 @@ ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
 ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
 ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
 ST_FUNC void section_reserve(Section *sec, unsigned long size);
-ST_FUNC Section *find_section(TCCState *s1, const char *name);
+ST_FUNC Section *find_section(TCCState *s1, const char *name, int create);
 ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
 
 ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
@@ -1443,6 +1445,11 @@ ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);
 #endif
 ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
 
+#ifndef TCC_TARGET_PE
+ST_FUNC void add_init_array (TCCState *s1, Sym *sym);
+ST_FUNC void add_fini_array (TCCState *s1, Sym *sym);
+#endif
+
 ST_FUNC int put_elf_str(Section *s, const char *sym);
 ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
 ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
diff --git a/tccasm.c b/tccasm.c
index a8412f4..77b8056 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -430,13 +430,13 @@ static void use_section1(TCCState *s1, Section *sec)
 static void use_section(TCCState *s1, const char *name)
 {
     Section *sec;
-    sec = find_section(s1, name);
+    sec = find_section(s1, name, 1);
     use_section1(s1, sec);
 }
 
 static void push_section(TCCState *s1, const char *name)
 {
-    Section *sec = find_section(s1, name);
+    Section *sec = find_section(s1, name, 1);
     sec->prev = cur_text_section;
     use_section1(s1, sec);
 }
diff --git a/tccelf.c b/tccelf.c
index 213ef9c..cbceac5 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -340,8 +340,8 @@ ST_FUNC void section_reserve(Section *sec, unsigned long size)
 }
 
 /* return a reference to a section, and create it if it does not
-   exists */
-ST_FUNC Section *find_section(TCCState *s1, const char *name)
+   exists and create != 0 */
+ST_FUNC Section *find_section(TCCState *s1, const char *name, int create)
 {
     Section *sec;
     int i;
@@ -351,7 +351,7 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name)
             return sec;
     }
     /* sections are created as PROGBITS */
-    return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
+    return create ? new_section(s1, name, SHT_PROGBITS, SHF_ALLOC) : NULL;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -1410,7 +1410,7 @@ static void add_init_array_defines(TCCState *s1, const char *section_name)
     snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
     snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
 
-    s = find_section(s1, section_name);
+    s = find_section(s1, section_name, 1);
     if (!s) {
         end_offset = 0;
         s = data_section;
@@ -1434,6 +1434,34 @@ static int tcc_add_support(TCCState *s1, const char *filename)
     snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
     return tcc_add_file(s1, buf);
 }
+
+ST_FUNC void add_init_array (TCCState *s1, Sym *sym)
+{
+    Section *s;
+    unsigned char *ptr;
+
+    s = find_section(s1, ".init_array", 1);
+    if (s) {
+       s->sh_flags |= SHF_WRITE;
+       ptr = section_ptr_add(s, PTR_SIZE);
+       memset (ptr, 0, PTR_SIZE);
+       put_elf_reloc (s1->symtab, s, ptr - s->data, R_DATA_PTR, sym->c);
+    }
+}
+
+ST_FUNC void add_fini_array (TCCState *s1, Sym *sym)
+{
+    Section *s;
+    unsigned char *ptr;
+
+    s = find_section(s1, ".fini_array", 1);
+    if (s) {
+       s->sh_flags |= SHF_WRITE;
+       ptr = section_ptr_add(s, PTR_SIZE);
+       memset (ptr, 0, PTR_SIZE);
+       put_elf_reloc (s1->symtab, s, ptr - s->data, R_DATA_PTR, sym->c);
+    }
+}
 #endif
 
 ST_FUNC void tcc_add_bcheck(TCCState *s1)
@@ -1456,7 +1484,7 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1)
                 SHN_UNDEF, "__bound_init");
     if (s1->output_type != TCC_OUTPUT_MEMORY) {
         /* add 'call __bound_init()' in .init section */
-        Section *init_section = find_section(s1, ".init");
+        Section *init_section = find_section(s1, ".init", 1);
         unsigned char *pinit = section_ptr_add(init_section, 5);
         pinit[0] = 0xe8;
         write32le(pinit + 1, -4);
@@ -2081,6 +2109,7 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
 static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
 {
     Section *dynamic = dyninf->dynamic;
+    Section *s;
 
     /* put dynamic section entries */
     put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
@@ -2109,6 +2138,29 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
     put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
     put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
     put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);
+    s = find_section (s1, ".preinit_array", 0);
+    if (s) {
+        put_dt(dynamic, DT_PREINIT_ARRAY, s->sh_addr);
+        put_dt(dynamic, DT_PREINIT_ARRAYSZ, s->data_offset);
+    }
+    s = find_section (s1, ".init_array", 0);
+    if (s) {
+        put_dt(dynamic, DT_INIT_ARRAY, s->sh_addr);
+        put_dt(dynamic, DT_INIT_ARRAYSZ, s->data_offset);
+    }
+    s = find_section (s1, ".fini_array", 0);
+    if (s) {
+        put_dt(dynamic, DT_FINI_ARRAY, s->sh_addr);
+        put_dt(dynamic, DT_FINI_ARRAYSZ, s->data_offset);
+    }
+    s = find_section (s1, ".init", 0);
+    if (s) {
+        put_dt(dynamic, DT_INIT, s->sh_addr);
+    }
+    s = find_section (s1, ".fini", 0);
+    if (s) {
+        put_dt(dynamic, DT_FINI, s->sh_addr);
+    }
     if (s1->do_debug)
         put_dt(dynamic, DT_DEBUG, 0);
     put_dt(dynamic, DT_NULL, 0);
diff --git a/tccgen.c b/tccgen.c
index 5b56b74..7f434d8 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -3578,11 +3578,19 @@ redo:
             skip(')');
 	    break;
 	}
+	case TOK_CONSTRUCTOR1:
+	case TOK_CONSTRUCTOR2:
+            ad->a.constructor = 1;
+            break;
+	case TOK_DESTRUCTOR1:
+	case TOK_DESTRUCTOR2:
+            ad->a.destructor = 1;
+            break;
         case TOK_SECTION1:
         case TOK_SECTION2:
             skip('(');
 	    parse_mult_str(&astr, "section name");
-            ad->section = find_section(tcc_state, (char *)astr.data);
+            ad->section = find_section(tcc_state, (char *)astr.data, 1);
             skip(')');
 	    cstr_free(&astr);
             break;
@@ -7560,7 +7568,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
 
 /* parse a function defined by symbol 'sym' and generate its code in
    'cur_text_section' */
-static void gen_function(Sym *sym)
+static void gen_function(Sym *sym, AttributeDef *ad)
 {
     /* Initialize VLA state */
     struct scope f = { 0 };
@@ -7576,6 +7584,15 @@ static void gen_function(Sym *sym)
     /* NOTE: we patch the symbol size later */
     put_extern_sym(sym, cur_text_section, ind, 0);
 
+#ifndef TCC_TARGET_PE
+    if (ad && ad->a.constructor) {
+        add_init_array (tcc_state, sym);
+    }
+    if (ad && ad->a.destructor) {
+        add_fini_array (tcc_state, sym);
+    }
+#endif
+
     funcname = get_tok_str(sym->v, NULL);
     func_ind = ind;
 
@@ -7634,7 +7651,7 @@ static void gen_inline_functions(TCCState *s)
                 begin_macro(fn->func_str, 1);
                 next();
                 cur_text_section = text_section;
-                gen_function(sym);
+                gen_function(sym, NULL);
                 end_macro();
 
                 inline_generated = 1;
@@ -7814,7 +7831,7 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
                     cur_text_section = ad.section;
                     if (!cur_text_section)
                         cur_text_section = text_section;
-                    gen_function(sym);
+                    gen_function(sym, &ad);
                 }
                 break;
             } else {
diff --git a/tcctok.h b/tcctok.h
index 7be0d4f..22f1583 100644
--- a/tcctok.h
+++ b/tcctok.h
@@ -127,6 +127,12 @@
      DEF(TOK_REGPARM2, "__regparm__")
      DEF(TOK_CLEANUP1, "cleanup")
      DEF(TOK_CLEANUP2, "__cleanup__")
+#if !defined TCC_TARGET_PE
+     DEF(TOK_CONSTRUCTOR1, "constructor")
+     DEF(TOK_CONSTRUCTOR2, "__constructor__")
+     DEF(TOK_DESTRUCTOR1, "destructor")
+     DEF(TOK_DESTRUCTOR2, "__destructor__")
+#endif
 
      DEF(TOK_MODE, "__mode__")
      DEF(TOK_MODE_QI, "__QI__")
diff --git a/tests/tests2/108_constructor.c b/tests/tests2/108_constructor.c
new file mode 100644
index 0000000..145d0da
--- /dev/null
+++ b/tests/tests2/108_constructor.c
@@ -0,0 +1,20 @@
+extern int write (int fd, void *buf, int len);
+
+static void __attribute__ ((constructor))
+testc (void)
+{
+  write (1, "constructor\n", 12);
+}
+
+static void __attribute__ ((destructor))
+testd (void)
+{
+  write (1, "destructor\n", 11);
+}
+
+int
+main (void)
+{
+  write (1, "main\n", 5);
+  return 0;
+}
diff --git a/tests/tests2/108_constructor.expect b/tests/tests2/108_constructor.expect
new file mode 100644
index 0000000..167ca51
--- /dev/null
+++ b/tests/tests2/108_constructor.expect
@@ -0,0 +1,3 @@
+constructor
+main
+destructor
diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile
index a452d84..cec5b50 100644
--- a/tests/tests2/Makefile
+++ b/tests/tests2/Makefile
@@ -67,6 +67,9 @@ GEN-ALWAYS =
 106_pthread.test: FLAGS += -pthread
 106_pthread.test: NORUN = true
 
+# constructor/destructor
+108_constructor.test: NORUN = true
+
 # Filter source directory in warnings/errors (out-of-tree builds)
 FILTER = 2>&1 | sed 's,$(SRC)/,,g'
 # Filter some always-warning
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to