I use Nelua programming language that emits C code by default as a
source-to-source compiler and I have just noticed a rather weird behavior.

When I run a certain `thread` example code with either GCC or clang, it worked
just fine...but with TCC, at random times, I get

/usr/lib/x86_64-linux-gnu/crt1.o: error: section type conflict: .note.GNU-stack
01 <> 07

I decided to take the generated C code and compile it first and run it with TCC
to validate my finding.

The following example command

tcc "/home/stefanos/.cache/nelua/threads.c" -w -g -lpthread
-o "/home/stefanos/.cache/nelua/threads"

throws an error like I already have shared above, but to my surprise if I take
the aforementioned command and tweak it to run the source code immediately, it
works!

tcc -run "/home/stefanos/.cache/nelua/threads.c" -w -g -lpthread

Can anyone tell me what's going on?

Am I doing something wrong here?

Cheers.

P.S.: Here's the generated C code, for reference

/* Generated by Nelua 0.2.0-dev */
/* Compile command: tcc "/home/stefanos/.cache/nelua/threads.c" -w -g -lpthread
-o "/home/stefanos/.cache/nelua/threads" */ /* Compile hash:
35qxLvpCsJZ8pVFPXh2fNjGNxzXA */ /* ------------------------------ DIRECTIVES
-------------------------------- */ /* Disable some warnings that the generated
code can trigger. */ #if defined(__clang__) && __clang_major__ >= 3
  #pragma clang diagnostic ignored "-Wtype-limits"
  #pragma clang diagnostic ignored "-Wwrite-strings"
  #pragma clang diagnostic ignored "-Wunused"
  #pragma clang diagnostic ignored "-Wunused-parameter"
  #pragma clang diagnostic ignored "-Wmissing-field-initializers"
  #pragma clang diagnostic ignored "-Wparentheses-equality"
  #pragma clang diagnostic ignored "-Wtautological-compare"
  #pragma clang diagnostic ignored "-Wmissing-braces"
  #ifndef __cplusplus
    #pragma clang diagnostic ignored "-Wincompatible-pointer-types"
    #pragma clang diagnostic error   "-Wimplicit-function-declaration"
    #pragma clang diagnostic error   "-Wimplicit-int"
  #else
    #pragma clang diagnostic ignored "-Wnarrowing"
    #pragma clang diagnostic ignored "-Wc99-designator"
  #endif
#elif defined(__GNUC__) && __GNUC__ >= 5
  #pragma GCC diagnostic ignored "-Wtype-limits"
  #pragma GCC diagnostic ignored "-Wwrite-strings"
  #pragma GCC diagnostic ignored "-Wunused-parameter"
  #pragma GCC diagnostic ignored "-Wunused-value"
  #pragma GCC diagnostic ignored "-Wunused-variable"
  #pragma GCC diagnostic ignored "-Wunused-function"
  #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
  #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
  #ifndef __cplusplus
    #pragma GCC diagnostic ignored "-Wmissing-braces"
    #pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
    #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
    #pragma GCC diagnostic error   "-Wimplicit-function-declaration"
    #pragma GCC diagnostic error   "-Wimplicit-int"
  #else
    #pragma GCC diagnostic ignored "-Wnarrowing"
  #endif
#endif
#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)
  #define _CRT_SECURE_NO_WARNINGS
#endif
/* Macro used to perform compile-time checks. */
#if __STDC_VERSION__ >= 201112L
  #define NELUA_STATIC_ASSERT _Static_assert
#elif __cplusplus >= 201103L
  #define NELUA_STATIC_ASSERT static_assert
#else
  #define NELUA_STATIC_ASSERT(x, y)
#endif
/* Macro used to get alignment of a type. */
#if __STDC_VERSION__ >= 201112L
  #define NELUA_ALIGNOF _Alignof
#elif __cplusplus >= 201103L
  #define NELUA_ALIGNOF alignof
#elif defined(__GNUC__)
  #define NELUA_ALIGNOF __alignof__
#elif defined(_MSC_VER)
  #define NELUA_ALIGNOF __alignof
#else
  #define NELUA_ALIGNOF(x)
#endif
/* Checks if Nelua and C agrees on pointer size. */
NELUA_STATIC_ASSERT(sizeof(void*) == 8 && NELUA_ALIGNOF(void*) == 8, "Nelua and
C disagree on pointer size or alignment"); /* Enable 64 bit offsets for stdio
APIs. */ #if !defined(_FILE_OFFSET_BITS) && __SIZEOF_LONG__ >= 8
  #define _FILE_OFFSET_BITS 64
#endif
/* Enable POSIX APIs in included headers. */
#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) &&
!defined(_GNU_SOURCE) && !defined(_DEFAULT_SOURCE) #if defined(__gnu_linux__)
    #define _GNU_SOURCE
  #else
    #define _XOPEN_SOURCE 600
  #endif
#endif
#define NELUA_NIL (nlniltype){}
#include <stdio.h>
#include <time.h>
#ifndef _THREADS_H
#define _THREADS_H
#include <time.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <sched.h>
#include <stdint.h>
#if !(defined(__linux__) || defined(_WIN32) || defined(__CYGWIN__))
  #define C11THREADS_NO_TIMED_MUTEX
#endif
#ifdef C11THREADS_NO_TIMED_MUTEX
  #include <sys/time.h>
  #define PTHREAD_MUTEX_TIMED_NP PTHREAD_MUTEX_NORMAL
#endif
#define ONCE_FLAG_INIT  PTHREAD_ONCE_INIT
#define TSS_DTOR_ITERATIONS 4
typedef pthread_t thrd_t;
typedef pthread_mutex_t mtx_t;
typedef pthread_cond_t cnd_t;
typedef pthread_key_t tss_t;
typedef pthread_once_t once_flag;
typedef int (*thrd_start_t)(void*);
typedef void (*tss_dtor_t)(void*);
enum {
  mtx_plain = 0,
  mtx_recursive = 1,
  mtx_timed = 2,
};
enum {
  thrd_success,
  thrd_timedout,
  thrd_busy,
  thrd_error,
  thrd_nomem
};
static inline int thrd_err_map(int errcode) {
  switch(errcode) {
    case 0:
      return thrd_success;
    case ENOMEM:
      return thrd_nomem;
    case ETIMEDOUT:
      return thrd_timedout;
    case EBUSY:
      return thrd_busy;
  }
  return thrd_error;
}
static inline int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) {
  return thrd_err_map(pthread_create(thr, 0, (void*(*)(void*))(void*)func,
arg)); }
static inline int thrd_equal(thrd_t a, thrd_t b) {
  return pthread_equal(a, b);
}
static inline thrd_t thrd_current(void) {
  return pthread_self();
}
static inline int thrd_sleep(const struct timespec *ts_in, struct timespec
*rem_out) { #ifdef _POSIX_TIMERS
  return nanosleep(ts_in, rem_out) == 0 ? 0 : (errno == EINTR ? -1 : -2);
#else
  if(rem_out) {
    rem_out.tv_sec = 0;
    rem_out.tv_nsec = 0;
  }
  return usleep(ts_in.tv_sec*1000000 + ts_in.tv_nsec/1000) == 0 ? 0 : (errno ==
EINTR ? -1 : -2); #endif
}
static inline void thrd_exit(int res) {
  pthread_exit((void*)(uintptr_t)res);
}
static inline int thrd_detach(thrd_t thr) {
  return thrd_err_map(pthread_detach(thr));
}
static inline int thrd_join(thrd_t thr, int *res) {
  void *retval;
  int errcode = pthread_join(thr, &retval);
  if(res) {
    *res = (int)(uintptr_t)retval;
  }
  return thrd_err_map(errcode);
}
static inline void thrd_yield(void) {
  sched_yield();
}
static inline int mtx_init(mtx_t *mtx, int type) {
  int errcode;
  pthread_mutexattr_t attr;
  errcode = pthread_mutexattr_init(&attr);
  if(type & mtx_timed) {
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_TIMED_NP);
  }
  if(type & mtx_recursive) {
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  }
  errcode = pthread_mutex_init(mtx, &attr);
  pthread_mutexattr_destroy(&attr);
  return thrd_err_map(errcode);
}
static inline int mtx_lock(mtx_t *mtx) {
  return thrd_err_map(pthread_mutex_lock(mtx));
}
static inline int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) {
  int errcode;
#ifdef C11THREADS_NO_TIMED_MUTEX
  struct timeval now;
  struct timespec sleeptime;
  sleeptime.tv_sec = 0;
  sleeptime.tv_nsec = 5000000;
  while((errcode = pthread_mutex_trylock(mtx)) == EBUSY) {
    gettimeofday(&now, NULL);
    if(now.tv_sec > ts->tv_sec || (now.tv_sec == ts->tv_sec && (now.tv_usec *
1000) >= ts->tv_nsec)) { return thrd_timedout;
    }
    nanosleep(&sleeptime, NULL);
  }
#else
  errcode = pthread_mutex_timedlock(mtx, ts);
#endif
  return thrd_err_map(errcode);
}
static inline int mtx_trylock(mtx_t *mtx) {
  return thrd_err_map(pthread_mutex_trylock(mtx));
}
static inline int mtx_unlock(mtx_t *mtx) {
  return thrd_err_map(pthread_mutex_unlock(mtx));
}
static inline void mtx_destroy(mtx_t *mtx) {
  pthread_mutex_destroy(mtx);
}
static inline int cnd_init(cnd_t *cond) {
  return thrd_err_map(pthread_cond_init(cond, 0));
}
static inline int cnd_signal(cnd_t *cond) {
  return thrd_err_map(pthread_cond_signal(cond));
}
static inline int cnd_broadcast(cnd_t *cond) {
  return thrd_err_map(pthread_cond_broadcast(cond));
}
static inline int cnd_wait(cnd_t *cond, mtx_t *mtx) {
  return thrd_err_map(pthread_cond_wait(cond, mtx));
}
static inline int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec
*ts) { return thrd_err_map(pthread_cond_timedwait(cond, mtx, ts));
}
static inline void cnd_destroy(cnd_t *cond) {
  pthread_cond_destroy(cond);
}
static inline int tss_create(tss_t *key, tss_dtor_t dtor) {
  return thrd_err_map(pthread_key_create(key, dtor));
}
static inline void *tss_get(tss_t key) {
  return pthread_getspecific(key);
}
static inline int tss_set(tss_t key, void *val){
  return thrd_err_map(pthread_setspecific(key, val));
}
static inline void tss_delete(tss_t key) {
  pthread_key_delete(key);
}
static inline void call_once(once_flag *flag, void (*func)(void)) {
  pthread_once(flag, func);
}
#endif
#include <stdint.h>
#include <stdbool.h>
/* Macro used to force inlining a function. */
#ifdef __GNUC__
  #define NELUA_INLINE __attribute__((always_inline)) inline
#elif defined(_MSC_VER)
  #define NELUA_INLINE __forceinline
#elif __STDC_VERSION__ >= 199901L
  #define NELUA_INLINE inline
#else
  #define NELUA_INLINE
#endif
#include <stdlib.h>
/* Macro used to import/export extern C functions. */
#ifdef __cplusplus
  #define NELUA_EXTERN extern "C"
#else
  #define NELUA_EXTERN extern
#endif
/* Macro used to generate traceback on aborts when sanitizing. */
#if defined(__clang__) && defined(__has_feature)
  #if __has_feature(undefined_behavior_sanitizer)
    #define NELUA_UBSAN_UNREACHABLE __builtin_unreachable
  #endif
#elif defined(__gnu_linux__) && defined(__GNUC__) && __GNUC__ >= 5
  NELUA_EXTERN void __ubsan_handle_builtin_unreachable(void*)
__attribute__((weak)); #define NELUA_UBSAN_UNREACHABLE()
{if(&__ubsan_handle_builtin_unreachable) __builtin_unreachable();} #endif
#ifndef NELUA_UBSAN_UNREACHABLE
  #define NELUA_UBSAN_UNREACHABLE()
#endif
/* Macro used to specify a function that never returns. */
#if __STDC_VERSION__ >= 201112L
  #define NELUA_NORETURN _Noreturn
#elif defined(__GNUC__)
  #define NELUA_NORETURN __attribute__((noreturn))
#elif defined(_MSC_VER)
  #define NELUA_NORETURN __declspec(noreturn)
#else
  #define NELUA_NORETURN
#endif
#include <string.h>
/* Macro used for branch prediction. */
#if defined(__GNUC__) || defined(__clang__)
  #define NELUA_UNLIKELY(x) __builtin_expect(x, 0)
#else
  #define NELUA_UNLIKELY(x) (x)
#endif
#include <stddef.h>
/* Macro used sign that a type punning cast may alias (related to strict
aliasing). */ #ifdef __GNUC__
  #define NELUA_MAYALIAS __attribute__((may_alias))
#else
  #define NELUA_MAYALIAS
#endif
/* ------------------------------ DECLARATIONS ------------------------------ */
typedef struct nlniltype {} nlniltype;
typedef struct nlniltype nltype;
static int threads_thread_function(void* arg);
static NELUA_INLINE void nelua_write_stderr(const char* msg, uintptr_t len,
bool flush); static NELUA_NORETURN void nelua_abort(void);
static NELUA_NORETURN void nelua_panic_cstring(const char* s);
static NELUA_INLINE void* nelua_assert_deref(void* p);
typedef int* nlcint_ptr;
typedef struct NELUA_MAYALIAS thrd_t_arr4 {thrd_t v[4];} thrd_t_arr4;
typedef union NELUA_MAYALIAS thrd_t_arr4_cast {thrd_t_arr4 a; thrd_t p[4];}
thrd_t_arr4_cast; static NELUA_INLINE intptr_t
nelua_assert_bounds_nlisize(intptr_t index, uintptr_t len); static int
nelua_main(int argc, char** argv); /* ------------------------------
DEFINITIONS ------------------------------- */ void nelua_write_stderr(const
char* msg, uintptr_t len, bool flush) { if(len > 0 && msg) {
    fwrite(msg, 1, len, stderr);
  }
  if(flush) {
    fwrite("\n", 1, 1, stderr);
    fflush(stderr);
  }
}
void nelua_abort(void) {
  NELUA_UBSAN_UNREACHABLE();
  abort();
}
void nelua_panic_cstring(const char* s) {
  if(s) {
    nelua_write_stderr(s, strlen(s), true);
  }
  nelua_abort();
}
void* nelua_assert_deref(void* p) {
  if(NELUA_UNLIKELY(p == NULL)) {
    nelua_panic_cstring("attempt to dereference a null pointer");
  }
  return p;
}
int threads_thread_function(void* arg) {
  int thread_num = (*(int*)nelua_assert_deref((nlcint_ptr)arg));
  printf((char*)"Hello from thread \033[1;%dm%d\033[0m\n", (34 + thread_num),
thread_num); return thread_num;
}
intptr_t nelua_assert_bounds_nlisize(intptr_t index, uintptr_t len) {
  if(NELUA_UNLIKELY((uintptr_t)index >= len || index < 0)) {
    nelua_panic_cstring("array index: position out of bounds");
  }
  return index;
}
int nelua_main(int argc, char** argv) {
  while(true) {
    thrd_t_arr4 threads = (thrd_t_arr4){0};
    for(intptr_t _it = 0; _it < 4; _it += 1) {
      intptr_t i = _it;
      if((thrd_create((&threads.v[nelua_assert_bounds_nlisize(i, 4)]),
threads_thread_function, (void*)(&i)) != thrd_success)) { printf((char*)"Error
creating thread \033[1;30m%ld\033[0m\n", i); return 0;
      }
      thrd_join(threads.v[nelua_assert_bounds_nlisize(i, 4)], (nlcint_ptr)NULL);
    }
  }
  return 0;
}
int main(int argc, char** argv) {
  return nelua_main(argc, argv);
}




_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to