mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 09:31:03 +03:00
Merge branch 'master' into merge-2.064
Conflicts: dmd2/root/rmem.c
This commit is contained in:
commit
731f2a8fdf
10 changed files with 17 additions and 565 deletions
|
@ -260,8 +260,6 @@ if(MSVC)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
# disable dmd gc
|
|
||||||
list(REMOVE_ITEM FE_SRC ${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/root/dmgcmem.c)
|
|
||||||
set(LDC_SOURCE_FILES
|
set(LDC_SOURCE_FILES
|
||||||
${LDC_GENERATED}
|
${LDC_GENERATED}
|
||||||
${FE_SRC}
|
${FE_SRC}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
|
||||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
#if __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -604,7 +604,7 @@ int tryMain(size_t argc, char *argv[])
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
inifilename = inifile(argv[0], "sc.ini", "Environment");
|
inifilename = inifile(argv[0], "sc.ini", "Environment");
|
||||||
#elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
#elif __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
||||||
inifilename = inifile(argv[0], "dmd.conf", "Environment");
|
inifilename = inifile(argv[0], "dmd.conf", "Environment");
|
||||||
#else
|
#else
|
||||||
#error "fix this"
|
#error "fix this"
|
||||||
|
@ -1023,7 +1023,7 @@ Language changes listed by -transition=id:\n\
|
||||||
browse("http://dlang.org/dmd-windows.html");
|
browse("http://dlang.org/dmd-windows.html");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if linux
|
#if __linux__
|
||||||
#if DMDV1
|
#if DMDV1
|
||||||
browse("http://www.digitalmars.com/d/1.0/dmd-linux.html");
|
browse("http://www.digitalmars.com/d/1.0/dmd-linux.html");
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -119,7 +119,7 @@ unsigned __stdcall startthread(void *p)
|
||||||
return EXIT_SUCCESS; // if skidding
|
return EXIT_SUCCESS; // if skidding
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif linux // Posix
|
#elif __linux__ // Posix
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
|
@ -1,499 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
// Copyright (c) 2000-2011 by Digital Mars
|
|
||||||
// All Rights Reserved
|
|
||||||
// written by Walter Bright
|
|
||||||
// http://www.digitalmars.com
|
|
||||||
// License for redistribution is by either the Artistic License
|
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
|
||||||
// See the included readme.txt for details.
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "rmem.h"
|
|
||||||
#include "gc/gc.h"
|
|
||||||
//#include "printf.h"
|
|
||||||
|
|
||||||
/* This implementation of the storage allocator uses the Digital Mars gc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Mem mem;
|
|
||||||
|
|
||||||
//static int nuncollectable;
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
void gc_init();
|
|
||||||
GC *gc_get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mem::init()
|
|
||||||
{
|
|
||||||
gc_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
char *Mem::strdup(const char *s)
|
|
||||||
{
|
|
||||||
return gc_get()->strdup(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Mem::malloc(size_t size)
|
|
||||||
{
|
|
||||||
if (gc) // if cached allocator
|
|
||||||
{
|
|
||||||
// PRINTF("Using cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
|
|
||||||
// GC::file = NULL;
|
|
||||||
// GC::line = 0;
|
|
||||||
return ((GC *)gc)->malloc(size);
|
|
||||||
}
|
|
||||||
if (this == &mem) // don't cache global mem
|
|
||||||
{
|
|
||||||
// PRINTF("Using global gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
|
|
||||||
// GC::file = NULL;
|
|
||||||
// GC::line = 0;
|
|
||||||
return gc_get()->malloc(size);
|
|
||||||
}
|
|
||||||
// PRINTF("Generating cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
|
|
||||||
gc = gc_get();
|
|
||||||
return gc->malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Mem::malloc_uncollectable(size_t size)
|
|
||||||
{ void *p;
|
|
||||||
|
|
||||||
p = ::malloc(size);
|
|
||||||
if (!p)
|
|
||||||
error();
|
|
||||||
addroots((char *)p, (char *)p + size);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
++nuncollectable;
|
|
||||||
WPRINTF(L"malloc_uncollectable(%u) = %x, n=%d\n", size, p, nuncollectable);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Mem::calloc(size_t size, size_t n)
|
|
||||||
{
|
|
||||||
return gc_get()->calloc(size, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Mem::realloc(void *p, size_t size)
|
|
||||||
{
|
|
||||||
return gc_get()->realloc(p, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mem::free(void *p)
|
|
||||||
{
|
|
||||||
gc_get()->free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mem::free_uncollectable(void *p)
|
|
||||||
{
|
|
||||||
if (p)
|
|
||||||
{ removeroots((char *)p);
|
|
||||||
::free(p);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
--nuncollectable;
|
|
||||||
WPRINTF(L"free_uncollectable(%x) n=%d\n", p, nuncollectable);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
gc_get()->fullcollect();
|
|
||||||
|
|
||||||
GCStats stats;
|
|
||||||
|
|
||||||
getStats(&stats);
|
|
||||||
WPRINTF(L"poolsize = %x, usedsize = %x, freelistsize = %x\n",
|
|
||||||
stats.poolsize, stats.usedsize, stats.freelistsize);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Mem::mallocdup(void *o, size_t size)
|
|
||||||
{
|
|
||||||
return gc_get()->mallocdup(o, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mem::check(void *p)
|
|
||||||
{
|
|
||||||
if (gc)
|
|
||||||
gc->check(p);
|
|
||||||
else
|
|
||||||
gc_get()->check(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mem::error()
|
|
||||||
{
|
|
||||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
|
||||||
assert(0);
|
|
||||||
#endif
|
|
||||||
printf("Error: out of memory\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mem::fullcollect()
|
|
||||||
{
|
|
||||||
gc_get()->fullcollect();
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
{
|
|
||||||
GCStats stats;
|
|
||||||
|
|
||||||
gc_get()->getStats(&stats);
|
|
||||||
WPRINTF(L"Thread %x ", Thread::getId());
|
|
||||||
WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n",
|
|
||||||
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Mem::fullcollectNoStack()
|
|
||||||
{
|
|
||||||
gc_get()->fullcollectNoStack();
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
{
|
|
||||||
GCStats stats;
|
|
||||||
|
|
||||||
gc_get()->getStats(&stats);
|
|
||||||
WPRINTF(L"Thread %x ", Thread::getId());
|
|
||||||
WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n",
|
|
||||||
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Mem::mark(void *pointer)
|
|
||||||
{
|
|
||||||
(void) pointer; // for VC /W4 compatibility
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Mem::addroots(char* pStart, char* pEnd)
|
|
||||||
{
|
|
||||||
gc_get()->addRange(pStart, pEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Mem::removeroots(char* pStart)
|
|
||||||
{
|
|
||||||
gc_get()->removeRange(pStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Mem::setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData)
|
|
||||||
{
|
|
||||||
(void)pClientData;
|
|
||||||
gc_get()->setFinalizer(pObj, pFn);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Mem::setStackBottom(void *stackbottom)
|
|
||||||
{
|
|
||||||
gc_get()->setStackBottom(stackbottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GC *Mem::getThreadGC()
|
|
||||||
{
|
|
||||||
return gc_get();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* =================================================== */
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
void * operator new(size_t m_size)
|
|
||||||
{
|
|
||||||
//PRINTF("Call to global operator new(%d), file = '%s', line = %d\n", m_size, GC::file ? GC::file : "(null)", GC::line);
|
|
||||||
GC::file = NULL;
|
|
||||||
GC::line = 0;
|
|
||||||
return mem.malloc(m_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator delete(void *p)
|
|
||||||
{
|
|
||||||
//WPRINTF(L"Call to global operator delete\n");
|
|
||||||
mem.free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* operator new[](size_t size)
|
|
||||||
{
|
|
||||||
return operator new(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator delete[](void *pv)
|
|
||||||
{
|
|
||||||
operator delete(pv);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void * Mem::operator new(size_t m_size)
|
|
||||||
{ void *p;
|
|
||||||
|
|
||||||
p = gc_get()->malloc(m_size);
|
|
||||||
//printf("Mem::operator new(%d) = %p\n", m_size, p);
|
|
||||||
if (!p)
|
|
||||||
mem.error();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void * Mem::operator new(size_t m_size, Mem *mem)
|
|
||||||
{ void *p;
|
|
||||||
|
|
||||||
p = mem->malloc(m_size);
|
|
||||||
//printf("Mem::operator new(%d) = %p\n", m_size, p);
|
|
||||||
if (!p)
|
|
||||||
::mem.error();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void * Mem::operator new(size_t m_size, GC *gc)
|
|
||||||
{ void *p;
|
|
||||||
|
|
||||||
// if (!gc)
|
|
||||||
// WPRINTF(L"gc is NULL\n");
|
|
||||||
p = gc->malloc(m_size);
|
|
||||||
//printf("Mem::operator new(%d) = %p\n", m_size, p);
|
|
||||||
if (!p)
|
|
||||||
::mem.error();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mem::operator delete(void *p)
|
|
||||||
{
|
|
||||||
// printf("Mem::operator delete(%p)\n", p);
|
|
||||||
gc_get()->free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================ */
|
|
||||||
|
|
||||||
/* The following section of code exists to find the right
|
|
||||||
* garbage collector for this thread. There is one independent instance
|
|
||||||
* of the collector per thread.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ===================== linux ================================ */
|
|
||||||
|
|
||||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#define LOG 0 // log thread creation / destruction
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
|
|
||||||
// Key identifying the thread-specific data
|
|
||||||
static pthread_key_t gc_key;
|
|
||||||
|
|
||||||
/* "Once" variable ensuring that the key for gc_alloc will be allocated
|
|
||||||
* exactly once.
|
|
||||||
*/
|
|
||||||
static pthread_once_t gc_alloc_key_once = PTHREAD_ONCE_INIT;
|
|
||||||
|
|
||||||
/* Forward functions */
|
|
||||||
static void gc_alloc_key();
|
|
||||||
static void gc_alloc_destroy_gc(void * accu);
|
|
||||||
|
|
||||||
|
|
||||||
void gc_init()
|
|
||||||
{
|
|
||||||
#if LOG
|
|
||||||
WPRINTF(L"Thread %lx: gc_init()\n", pthread_self());
|
|
||||||
#endif
|
|
||||||
pthread_once(&gc_alloc_key_once, gc_alloc_key);
|
|
||||||
#if LOG
|
|
||||||
WPRINTF(L"Thread %lx: gc_init() return\n", pthread_self());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
GC *gc_get()
|
|
||||||
{
|
|
||||||
GC *gc;
|
|
||||||
|
|
||||||
// Get the thread-specific data associated with the key
|
|
||||||
gc = (GC *) pthread_getspecific(gc_key);
|
|
||||||
|
|
||||||
// It's initially NULL, meaning that we must allocate the buffer first.
|
|
||||||
if (gc == NULL)
|
|
||||||
{
|
|
||||||
GC_LOG();
|
|
||||||
gc = new GC();
|
|
||||||
gc->init();
|
|
||||||
|
|
||||||
// Store the buffer pointer in the thread-specific data.
|
|
||||||
pthread_setspecific(gc_key, (void *) gc);
|
|
||||||
#if LOG
|
|
||||||
WPRINTF(L"Thread %lx: allocating gc at %x\n", pthread_self(), gc);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return gc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to allocate the key for gc_alloc thread-specific data.
|
|
||||||
|
|
||||||
static void gc_alloc_key()
|
|
||||||
{
|
|
||||||
pthread_key_create(&gc_key, gc_alloc_destroy_gc);
|
|
||||||
#if LOG
|
|
||||||
WPRINTF(L"Thread %lx: allocated gc key %d\n", pthread_self(), gc_key);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to free the buffer when the thread exits.
|
|
||||||
// Called only when the thread-specific data is not NULL.
|
|
||||||
|
|
||||||
static void gc_alloc_destroy_gc(void *gc)
|
|
||||||
{
|
|
||||||
#if LOG
|
|
||||||
WPRINTF(L"Thread %x: freeing gc at %x\n", pthread_self(), gc);
|
|
||||||
#endif
|
|
||||||
delete (GC *)gc;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ===================== win32 ================================ */
|
|
||||||
|
|
||||||
#if !defined(linux) && defined(_WIN32)
|
|
||||||
|
|
||||||
#if 1 // single threaded version
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
|
|
||||||
static GC *gc;
|
|
||||||
|
|
||||||
void gc_init()
|
|
||||||
{
|
|
||||||
if (!gc)
|
|
||||||
{ gc = (GC *)::malloc(sizeof(GC));
|
|
||||||
gc->init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GC *gc_get()
|
|
||||||
{
|
|
||||||
return gc;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // multi threaded version
|
|
||||||
|
|
||||||
#include "mutex.h"
|
|
||||||
#include "thread.h"
|
|
||||||
|
|
||||||
/* This is the win32 version. It suffers from the bug that
|
|
||||||
* when the thread exits the data structure is not cleared,
|
|
||||||
* but the memory pool it points to is free'd.
|
|
||||||
* Thus, if a new thread comes along with the same thread id,
|
|
||||||
* the data will look initialized, but will point to garbage.
|
|
||||||
*
|
|
||||||
* What needs to happen is when a thread exits, the associated
|
|
||||||
* GC_context data struct is cleared.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct GC_context
|
|
||||||
{
|
|
||||||
ThreadId threadid; // identifier of current thread
|
|
||||||
GC *gc;
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutex gc_mutex;
|
|
||||||
|
|
||||||
static GC_context array[64];
|
|
||||||
|
|
||||||
// Array of pointers to GC_context objects, one per threadid
|
|
||||||
GC_context *gccontext = array;
|
|
||||||
unsigned gccontext_allocdim = 64;
|
|
||||||
unsigned gccontext_dim;
|
|
||||||
|
|
||||||
ThreadId gc_cache_ti;
|
|
||||||
GC_context *gc_cache_cc;
|
|
||||||
|
|
||||||
extern "C" void gc_init()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" GC *gc_get()
|
|
||||||
{
|
|
||||||
/* This works by creating an array of GC_context's, one
|
|
||||||
* for each thread. We match up by thread id.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ThreadId ti;
|
|
||||||
GC_context *cc;
|
|
||||||
|
|
||||||
//PRINTF("gc_get()\n");
|
|
||||||
|
|
||||||
ti = Thread::getId();
|
|
||||||
gc_mutex.acquire();
|
|
||||||
|
|
||||||
// Used cached version if we can
|
|
||||||
if (ti == gc_cache_ti)
|
|
||||||
{
|
|
||||||
cc = gc_cache_cc;
|
|
||||||
//exception(L"getGC_context(): cache x%x", ti);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This does a linear search through gccontext[].
|
|
||||||
// A hash table might be faster if there are more
|
|
||||||
// than a dozen threads.
|
|
||||||
GC_context *ccp;
|
|
||||||
GC_context *ccptop = &gccontext[gccontext_dim];
|
|
||||||
for (ccp = gccontext; ccp < ccptop; ccp++)
|
|
||||||
{
|
|
||||||
cc = ccp;
|
|
||||||
if (cc->threadid == ti)
|
|
||||||
{
|
|
||||||
WPRINTF(L"getGC_context(): existing x%x", ti);
|
|
||||||
goto Lret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not allocate with garbage collector, as this must reside
|
|
||||||
// global to all threads.
|
|
||||||
|
|
||||||
assert(gccontext_dim < gccontext_allocdim);
|
|
||||||
cc = ccp;
|
|
||||||
memset(cc, 0, sizeof(*cc));
|
|
||||||
cc->threadid = ti;
|
|
||||||
cc->gc = new GC();
|
|
||||||
cc->gc->init();
|
|
||||||
|
|
||||||
gccontext_dim++;
|
|
||||||
WPRINTF(L"getGC_context(): new x%x\n", ti);
|
|
||||||
|
|
||||||
Lret:
|
|
||||||
// Cache for next time
|
|
||||||
gc_cache_ti = ti;
|
|
||||||
gc_cache_cc = cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
gc_mutex.release();
|
|
||||||
return cc->gc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -26,7 +26,7 @@ void browse(const char *url)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if linux || __FreeBSD__ || __OpenBSD__ || __sun
|
#if __linux__ || __FreeBSD__ || __OpenBSD__ || __sun
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
|
@ -624,10 +624,10 @@ longdouble Port::strtold(const char *p, char **endp)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__
|
#if __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __HAIKU__
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#if linux
|
#if __linux__
|
||||||
#include <bits/nan.h>
|
#include <bits/nan.h>
|
||||||
#include <bits/mathdef.h>
|
#include <bits/mathdef.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
#ifndef POSIX
|
#ifndef POSIX
|
||||||
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun)
|
#define POSIX (__linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -880,11 +880,11 @@ void FileName::ensurePathToNameExists(const char *name)
|
||||||
*/
|
*/
|
||||||
const char *FileName::canonicalName(const char *name)
|
const char *FileName::canonicalName(const char *name)
|
||||||
{
|
{
|
||||||
#if linux
|
#if __linux__
|
||||||
// Lovely glibc extension to do it for us
|
// Lovely glibc extension to do it for us
|
||||||
return canonicalize_file_name(name);
|
return canonicalize_file_name(name);
|
||||||
#elif POSIX
|
#elif POSIX
|
||||||
#if _POSIX_VERSION >= 200809L || defined (linux)
|
#if _POSIX_VERSION >= 200809L || defined (__linux__)
|
||||||
// NULL destination buffer is allowed and preferred
|
// NULL destination buffer is allowed and preferred
|
||||||
return realpath(name, NULL);
|
return realpath(name, NULL);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -1003,7 +1003,7 @@ int main(int argc, char *argv[])
|
||||||
std::string ldcPath = locateBinary(LDC_EXE_NAME, argv[0]);
|
std::string ldcPath = locateBinary(LDC_EXE_NAME, argv[0]);
|
||||||
if (ldcPath.empty())
|
if (ldcPath.empty())
|
||||||
{
|
{
|
||||||
error("Could not locate "LDC_EXE_NAME" executable.");
|
error("Could not locate " LDC_EXE_NAME " executable.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to manually set up argv[0] and the terminating NULL.
|
// We need to manually set up argv[0] and the terminating NULL.
|
||||||
|
|
|
@ -379,25 +379,23 @@ LLFunction* DtoInlineIRFunction(FuncDeclaration* fdecl)
|
||||||
static llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
|
static llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl)
|
||||||
{
|
{
|
||||||
IrFuncTy &irFty = fdecl->irFty;
|
IrFuncTy &irFty = fdecl->irFty;
|
||||||
LLFunctionType* type = 0;
|
if (irFty.funcType) return irFty.funcType;
|
||||||
|
|
||||||
// create new ir funcTy
|
|
||||||
irFty.reset();
|
|
||||||
irFty.ret = new IrFuncTyArg(Type::tvoid, false);
|
irFty.ret = new IrFuncTyArg(Type::tvoid, false);
|
||||||
|
|
||||||
irFty.args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
|
irFty.args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
|
||||||
|
|
||||||
if (fdecl->llvmInternal == LLVMva_start)
|
if (fdecl->llvmInternal == LLVMva_start)
|
||||||
type = GET_INTRINSIC_DECL(vastart)->getFunctionType();
|
irFty.funcType = GET_INTRINSIC_DECL(vastart)->getFunctionType();
|
||||||
else if (fdecl->llvmInternal == LLVMva_copy) {
|
else if (fdecl->llvmInternal == LLVMva_copy) {
|
||||||
type = GET_INTRINSIC_DECL(vacopy)->getFunctionType();
|
irFty.funcType = GET_INTRINSIC_DECL(vacopy)->getFunctionType();
|
||||||
irFty.args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
|
irFty.args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
|
||||||
}
|
}
|
||||||
else if (fdecl->llvmInternal == LLVMva_end)
|
else if (fdecl->llvmInternal == LLVMva_end)
|
||||||
type = GET_INTRINSIC_DECL(vaend)->getFunctionType();
|
irFty.funcType = GET_INTRINSIC_DECL(vaend)->getFunctionType();
|
||||||
assert(type);
|
assert(irFty.funcType);
|
||||||
|
|
||||||
return type;
|
return irFty.funcType;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -127,51 +127,6 @@ struct IrFuncTy
|
||||||
reverseParams(false)
|
reverseParams(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
// Copy constructor and operator= seems to be required for MSC
|
|
||||||
|
|
||||||
IrFuncTy(const IrFuncTy& rhs)
|
|
||||||
: funcType(rhs.funcType),
|
|
||||||
ret(rhs.ret),
|
|
||||||
args(IrFuncTy::ArgList(rhs.args)),
|
|
||||||
arg_sret(rhs.arg_sret),
|
|
||||||
arg_this(rhs.arg_this),
|
|
||||||
arg_nest(rhs.arg_nest),
|
|
||||||
arg_arguments(rhs.arg_arguments),
|
|
||||||
arg_argptr(rhs.arg_argptr),
|
|
||||||
c_vararg(rhs.c_vararg),
|
|
||||||
reverseParams(rhs.reverseParams)
|
|
||||||
{}
|
|
||||||
|
|
||||||
IrFuncTy& operator=(const IrFuncTy& rhs)
|
|
||||||
{
|
|
||||||
funcType = rhs.funcType;
|
|
||||||
ret = rhs.ret;
|
|
||||||
args = IrFuncTy::ArgList(rhs.args);
|
|
||||||
arg_sret = rhs.arg_sret;
|
|
||||||
arg_this = rhs.arg_this;
|
|
||||||
arg_nest = rhs.arg_nest;
|
|
||||||
arg_arguments = rhs.arg_arguments;
|
|
||||||
arg_argptr = rhs.arg_argptr;
|
|
||||||
c_vararg = rhs.c_vararg;
|
|
||||||
reverseParams = rhs.reverseParams;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
funcType = 0;
|
|
||||||
ret = NULL;
|
|
||||||
arg_sret = arg_this = arg_nest = arg_arguments = arg_argptr = NULL;
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
args = IrFuncTy::ArgList();
|
|
||||||
#else
|
|
||||||
args.clear();
|
|
||||||
#endif
|
|
||||||
c_vararg = false;
|
|
||||||
reverseParams = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::Value* putRet(Type* dty, DValue* dval);
|
llvm::Value* putRet(Type* dty, DValue* dval);
|
||||||
llvm::Value* getRet(Type* dty, DValue* dval);
|
llvm::Value* getRet(Type* dty, DValue* dval);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue