mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-26 01:23:13 +01:00
[svn r289] Fixed: right shift >> was broken for unsigned types.
Fixed: debug info for classes now started.
This commit is contained in:
128
dmd/mem.c
128
dmd/mem.c
@@ -2,19 +2,27 @@
|
||||
/* Copyright (c) 2000 Digital Mars */
|
||||
/* All Rights Reserved */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// I needed to perfix the dir after upgrading to gc 7.0
|
||||
#include "gc/gc.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
#define USE_BOEHM_GC 0
|
||||
|
||||
#if USE_BOEHM_GC
|
||||
// I needed to perfix the dir after upgrading to gc 7.0
|
||||
#include "gc/gc.h"
|
||||
#endif
|
||||
|
||||
/* This implementation of the storage allocator uses the standard C allocation package.
|
||||
*/
|
||||
|
||||
Mem mem;
|
||||
|
||||
#if USE_BOEHM_GC
|
||||
|
||||
static bool gc_was_init = false;
|
||||
|
||||
void Mem::init()
|
||||
@@ -148,4 +156,112 @@ void operator delete(void *p)
|
||||
GC_free(p);
|
||||
}
|
||||
|
||||
#elif !USE_BOEHM_GC
|
||||
|
||||
void Mem::init()
|
||||
{
|
||||
}
|
||||
|
||||
char *Mem::strdup(const char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (s)
|
||||
{
|
||||
p = ::strdup(s);
|
||||
if (p)
|
||||
return p;
|
||||
error();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *Mem::malloc(size_t size)
|
||||
{ void *p;
|
||||
|
||||
if (!size)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = ::malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *Mem::calloc(size_t size, size_t n)
|
||||
{ void *p;
|
||||
|
||||
if (!size || !n)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = ::malloc(size * n);
|
||||
if (!p)
|
||||
error();
|
||||
memset(p, 0, size * n);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *Mem::realloc(void *p, size_t size)
|
||||
{
|
||||
if (!size)
|
||||
{ if (p)
|
||||
{ ::free(p);
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
else if (!p)
|
||||
{
|
||||
p = ::malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
else
|
||||
{
|
||||
p = ::realloc(p, size);
|
||||
if (!p)
|
||||
error();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void Mem::free(void *p)
|
||||
{
|
||||
if (p)
|
||||
::free(p);
|
||||
}
|
||||
|
||||
void *Mem::mallocdup(void *o, size_t size)
|
||||
{ void *p;
|
||||
|
||||
if (!size)
|
||||
p = NULL;
|
||||
else
|
||||
{
|
||||
p = ::malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
else
|
||||
memcpy(p,o,size);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void Mem::error()
|
||||
{
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void Mem::fullcollect()
|
||||
{
|
||||
}
|
||||
|
||||
void Mem::mark(void *pointer)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // USE_BOEHM_GC
|
||||
|
||||
@@ -1327,6 +1327,7 @@ static LLConstant* build_offti_array(ClassDeclaration* cd, LLConstant* init)
|
||||
|
||||
static LLConstant* build_class_dtor(ClassDeclaration* cd)
|
||||
{
|
||||
#if 0
|
||||
// construct the function
|
||||
std::vector<const LLType*> paramTypes;
|
||||
paramTypes.push_back(getPtrToType(cd->type->ir.type->get()));
|
||||
@@ -1364,6 +1365,17 @@ static LLConstant* build_class_dtor(ClassDeclaration* cd)
|
||||
builder.CreateRetVoid();
|
||||
|
||||
return llvm::ConstantExpr::getBitCast(func, getPtrToType(LLType::Int8Ty));
|
||||
#else
|
||||
|
||||
FuncDeclaration* dtor = cd->dtor;
|
||||
|
||||
// if no destructor emit a null
|
||||
if (!dtor)
|
||||
return getNullPtr(getVoidPtrType());
|
||||
|
||||
DtoForceDeclareDsymbol(dtor);
|
||||
return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::Int8Ty));
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint build_classinfo_flags(ClassDeclaration* cd)
|
||||
|
||||
@@ -176,6 +176,9 @@ void IfStatement::toIR(IRState* p)
|
||||
Logger::println("IfStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
if (match)
|
||||
{
|
||||
LLValue* allocainst = new llvm::AllocaInst(DtoType(match->type), "._tmp_if_var", p->topallocapoint());
|
||||
@@ -203,7 +206,8 @@ void IfStatement::toIR(IRState* p)
|
||||
gIR->scope() = IRScope(ifbb,elsebb);
|
||||
|
||||
// do scoped statements
|
||||
ifbody->toIR(p);
|
||||
if (ifbody)
|
||||
ifbody->toIR(p);
|
||||
if (!gIR->scopereturned()) {
|
||||
llvm::BranchInst::Create(endbb,gIR->scopebb());
|
||||
}
|
||||
@@ -264,6 +268,9 @@ void WhileStatement::toIR(IRState* p)
|
||||
Logger::println("WhileStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
// create while blocks
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* whilebb = llvm::BasicBlock::Create("whilecond", gIR->topfunc(), oldend);
|
||||
@@ -308,6 +315,9 @@ void DoStatement::toIR(IRState* p)
|
||||
Logger::println("DoStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
// create while blocks
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* dowhilebb = llvm::BasicBlock::Create("dowhile", gIR->topfunc(), oldend);
|
||||
@@ -344,6 +354,9 @@ void ForStatement::toIR(IRState* p)
|
||||
Logger::println("ForStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
// create for blocks
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* forbb = llvm::BasicBlock::Create("forcond", gIR->topfunc(), oldend);
|
||||
@@ -412,6 +425,9 @@ void BreakStatement::toIR(IRState* p)
|
||||
if (p->scopereturned())
|
||||
return;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
if (ident != 0) {
|
||||
Logger::println("ident = %s", ident->toChars());
|
||||
|
||||
@@ -446,6 +462,9 @@ void ContinueStatement::toIR(IRState* p)
|
||||
Logger::println("ContinueStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
if (ident != 0) {
|
||||
Logger::println("ident = %s", ident->toChars());
|
||||
|
||||
@@ -491,6 +510,9 @@ void TryFinallyStatement::toIR(IRState* p)
|
||||
Logger::println("TryFinallyStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
// create basic blocks
|
||||
llvm::BasicBlock* oldend = p->scopeend();
|
||||
|
||||
@@ -535,6 +557,9 @@ void TryCatchStatement::toIR(IRState* p)
|
||||
|
||||
Logger::attention(loc, "try-catch is not yet fully implemented");
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
// create basic blocks
|
||||
llvm::BasicBlock* oldend = p->scopeend();
|
||||
|
||||
@@ -577,6 +602,9 @@ void ThrowStatement::toIR(IRState* p)
|
||||
|
||||
Logger::attention(loc, "throw is not yet fully implemented");
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
assert(exp);
|
||||
DValue* e = exp->toElem(p);
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_throw_exception");
|
||||
@@ -654,6 +682,9 @@ void SwitchStatement::toIR(IRState* p)
|
||||
Logger::println("SwitchStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
|
||||
// clear data from previous passes... :/
|
||||
@@ -822,6 +853,9 @@ void UnrolledLoopStatement::toIR(IRState* p)
|
||||
Logger::println("UnrolledLoopStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* endbb = llvm::BasicBlock::Create("unrolledend", p->topfunc(), oldend);
|
||||
|
||||
@@ -847,6 +881,9 @@ void ForeachStatement::toIR(IRState* p)
|
||||
Logger::println("ForeachStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
//assert(arguments->dim == 1);
|
||||
assert(value != 0);
|
||||
assert(body != 0);
|
||||
@@ -1047,6 +1084,9 @@ void GotoStatement::toIR(IRState* p)
|
||||
Logger::println("GotoStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
assert(tf == NULL);
|
||||
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
@@ -1080,6 +1120,9 @@ void GotoDefaultStatement::toIR(IRState* p)
|
||||
Logger::println("GotoDefaultStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergotodefault", p->topfunc(), oldend);
|
||||
|
||||
@@ -1099,6 +1142,9 @@ void GotoCaseStatement::toIR(IRState* p)
|
||||
Logger::println("GotoCaseStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergotocase", p->topfunc(), oldend);
|
||||
|
||||
@@ -1121,6 +1167,9 @@ void WithStatement::toIR(IRState* p)
|
||||
Logger::println("WithStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
assert(exp);
|
||||
assert(body);
|
||||
|
||||
@@ -1141,6 +1190,9 @@ void SynchronizedStatement::toIR(IRState* p)
|
||||
|
||||
Logger::attention(loc, "synchronized is currently ignored. only the body will be emitted");
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
body->toIR(p);
|
||||
}
|
||||
|
||||
@@ -1186,6 +1238,9 @@ void VolatileStatement::toIR(IRState* p)
|
||||
Logger::println("VolatileStatement::toIR(): %s", loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
// mark in-volatile
|
||||
bool old = gIR->func()->inVolatile;
|
||||
gIR->func()->inVolatile = true;
|
||||
|
||||
243
gen/todebug.cpp
243
gen/todebug.cpp
@@ -129,20 +129,20 @@ static const llvm::StructType* getDwarfGlobalVariableType() {
|
||||
|
||||
static LLGlobalVariable* dwarfCompileUnit(Module* m)
|
||||
{
|
||||
std::vector<LLConstant*> vals;
|
||||
vals.push_back(DBG_TAG(DW_TAG_compile_unit));
|
||||
vals.push_back(DBG_CAST(getDwarfAnchor(DW_TAG_compile_unit)));
|
||||
std::vector<LLConstant*> vals(6);
|
||||
vals[0] = DBG_TAG(DW_TAG_compile_unit);
|
||||
vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_compile_unit));
|
||||
|
||||
vals.push_back(DtoConstUint(DW_LANG_C));// _D)); // doesn't seem to work
|
||||
vals.push_back(DtoConstStringPtr(m->srcfile->name->toChars(), "llvm.metadata"));
|
||||
vals[2] = DtoConstUint(DW_LANG_C);// _D)); // doesn't seem to work
|
||||
vals[3] = DtoConstStringPtr(m->srcfile->name->toChars(), "llvm.metadata");
|
||||
std::string srcpath(FileName::path(m->srcfile->name->toChars()));
|
||||
if (srcpath.empty()) {
|
||||
const char* str = get_current_dir_name();
|
||||
assert(str != NULL);
|
||||
srcpath = str;
|
||||
}
|
||||
vals.push_back(DtoConstStringPtr(srcpath.c_str(), "llvm.metadata"));
|
||||
vals.push_back(DtoConstStringPtr("LLVMDC (http://www.dsource.org/projects/llvmdc)", "llvm.metadata"));
|
||||
vals[4] = DtoConstStringPtr(srcpath.c_str(), "llvm.metadata");
|
||||
vals[5] = DtoConstStringPtr("LLVMDC (http://www.dsource.org/projects/llvmdc)", "llvm.metadata");
|
||||
|
||||
LLGlobalVariable* gv = emitDwarfGlobal(getDwarfCompileUnitType(), vals, "llvm.dbg.compile_unit");
|
||||
m->ir.irModule->dwarfCompileUnit = gv;
|
||||
@@ -153,25 +153,28 @@ static LLGlobalVariable* dwarfCompileUnit(Module* m)
|
||||
|
||||
static LLGlobalVariable* dwarfSubProgram(FuncDeclaration* fd, llvm::GlobalVariable* compileUnit)
|
||||
{
|
||||
std::vector<LLConstant*> vals;
|
||||
vals.push_back(DBG_TAG(DW_TAG_subprogram));
|
||||
vals.push_back(DBG_CAST(getDwarfAnchor(DW_TAG_subprogram)));
|
||||
std::vector<LLConstant*> vals(11);
|
||||
vals[0] = DBG_TAG(DW_TAG_subprogram);
|
||||
vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_subprogram));
|
||||
|
||||
vals.push_back(DBG_CAST(compileUnit));
|
||||
vals.push_back(DtoConstStringPtr(fd->toPrettyChars(), "llvm.metadata"));
|
||||
vals.push_back(vals.back());
|
||||
vals.push_back(DtoConstStringPtr(fd->mangle(), "llvm.metadata"));
|
||||
vals.push_back(DBG_CAST( DtoDwarfCompileUnit(fd->getModule()) ));
|
||||
vals.push_back(DtoConstUint(fd->loc.linnum));
|
||||
vals.push_back(DBG_NULL);
|
||||
vals.push_back(DtoConstBool(fd->protection == PROTprivate));
|
||||
vals.push_back(DtoConstBool(fd->getModule() == gIR->dmodule));
|
||||
vals[2] = DBG_CAST(compileUnit);
|
||||
vals[3] = DtoConstStringPtr(fd->toPrettyChars(), "llvm.metadata");
|
||||
vals[4] = vals[3];
|
||||
vals[5] = DtoConstStringPtr(fd->mangle(), "llvm.metadata");
|
||||
vals[6] = DBG_CAST( DtoDwarfCompileUnit(fd->getModule()) );
|
||||
vals[7] = DtoConstUint(fd->loc.linnum);
|
||||
vals[8] = DBG_NULL;
|
||||
vals[9] = DtoConstBool(fd->protection == PROTprivate);
|
||||
vals[10] = DtoConstBool(fd->getModule() == gIR->dmodule);
|
||||
|
||||
Logger::println("emitting subprogram global");
|
||||
|
||||
return emitDwarfGlobal(getDwarfSubProgramType(), vals, "llvm.dbg.subprogram");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static LLGlobalVariable* dwarfTypeDescription_impl(Type* type, LLGlobalVariable* cu, const char* c_name);
|
||||
static LLGlobalVariable* dwarfTypeDescription(Type* type, LLGlobalVariable* cu, const char* c_name);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -182,34 +185,34 @@ static LLGlobalVariable* dwarfBasicType(Type* type, llvm::GlobalVariable* compil
|
||||
|
||||
const LLType* T = DtoType(type);
|
||||
|
||||
std::vector<LLConstant*> vals;
|
||||
std::vector<LLConstant*> vals(10);
|
||||
|
||||
// tag
|
||||
vals.push_back(DBG_TAG(DW_TAG_base_type));
|
||||
vals[0] = DBG_TAG(DW_TAG_base_type);
|
||||
|
||||
// context
|
||||
vals.push_back(DBG_CAST(compileUnit));
|
||||
vals[1] = DBG_CAST(compileUnit);
|
||||
|
||||
// name
|
||||
vals.push_back(DtoConstStringPtr(type->toChars(), "llvm.metadata"));
|
||||
vals[2] = DtoConstStringPtr(type->toChars(), "llvm.metadata");
|
||||
|
||||
// compile unit where defined
|
||||
vals.push_back(DBG_NULL);
|
||||
vals[3] = DBG_NULL;
|
||||
|
||||
// line number where defined
|
||||
vals.push_back(DtoConstInt(0));
|
||||
vals[4] = DtoConstInt(0);
|
||||
|
||||
// size in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false));
|
||||
vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);
|
||||
|
||||
// alignment in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false));
|
||||
vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);
|
||||
|
||||
// offset in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, 0, false));
|
||||
vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false);
|
||||
|
||||
// FIXME: dont know what this is
|
||||
vals.push_back(DtoConstUint(0));
|
||||
vals[8] = DtoConstUint(0);
|
||||
|
||||
// dwarf type
|
||||
unsigned id;
|
||||
@@ -228,7 +231,7 @@ static LLGlobalVariable* dwarfBasicType(Type* type, llvm::GlobalVariable* compil
|
||||
{
|
||||
assert(0 && "unsupported basictype for debug info");
|
||||
}
|
||||
vals.push_back(DtoConstUint(id));
|
||||
vals[9] = DtoConstUint(id);
|
||||
|
||||
return emitDwarfGlobal(getDwarfBasicTypeType(), vals, "llvm.dbg.basictype");
|
||||
}
|
||||
@@ -254,42 +257,42 @@ static LLGlobalVariable* dwarfDerivedType(Type* type, llvm::GlobalVariable* comp
|
||||
assert(0 && "unsupported derivedtype for debug info");
|
||||
}
|
||||
|
||||
std::vector<LLConstant*> vals;
|
||||
std::vector<LLConstant*> vals(10);
|
||||
|
||||
// tag
|
||||
vals.push_back(DBG_TAG(tag));
|
||||
vals[0] = DBG_TAG(tag);
|
||||
|
||||
// context
|
||||
vals.push_back(DBG_CAST(compileUnit));
|
||||
vals[1] = DBG_CAST(compileUnit);
|
||||
|
||||
// name
|
||||
vals.push_back(name);
|
||||
vals[2] = name;
|
||||
|
||||
// compile unit where defined
|
||||
vals.push_back(DBG_NULL);
|
||||
vals[3] = DBG_NULL;
|
||||
|
||||
// line number where defined
|
||||
vals.push_back(DtoConstInt(0));
|
||||
vals[4] = DtoConstInt(0);
|
||||
|
||||
// size in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false));
|
||||
vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);
|
||||
|
||||
// alignment in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false));
|
||||
vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);
|
||||
|
||||
// offset in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, 0, false));
|
||||
vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false);
|
||||
|
||||
// FIXME: dont know what this is
|
||||
vals.push_back(DtoConstUint(0));
|
||||
vals[8] = DtoConstUint(0);
|
||||
|
||||
// base type
|
||||
Type* nt = t->nextOf();
|
||||
LLGlobalVariable* nTD = dwarfTypeDescription(nt, compileUnit, NULL);
|
||||
LLGlobalVariable* nTD = dwarfTypeDescription_impl(nt, compileUnit, NULL);
|
||||
if (nt->ty == Tvoid || !nTD)
|
||||
vals.push_back(DBG_NULL);
|
||||
vals[9] = DBG_NULL;
|
||||
else
|
||||
vals.push_back(DBG_CAST(nTD));
|
||||
vals[9] = DBG_CAST(nTD);
|
||||
|
||||
return emitDwarfGlobal(getDwarfDerivedTypeType(), vals, "llvm.dbg.derivedtype");
|
||||
}
|
||||
@@ -308,44 +311,44 @@ static LLGlobalVariable* dwarfMemberType(unsigned linnum, Type* type, LLGlobalVa
|
||||
else
|
||||
name = getNullPtr(getVoidPtrType());
|
||||
|
||||
std::vector<LLConstant*> vals;
|
||||
std::vector<LLConstant*> vals(10);
|
||||
|
||||
// tag
|
||||
vals.push_back(DBG_TAG(DW_TAG_member));
|
||||
vals[0] = DBG_TAG(DW_TAG_member);
|
||||
|
||||
// context
|
||||
vals.push_back(DBG_CAST(compileUnit));
|
||||
vals[1] = DBG_CAST(compileUnit);
|
||||
|
||||
// name
|
||||
vals.push_back(name);
|
||||
vals[2] = name;
|
||||
|
||||
// compile unit where defined
|
||||
if (definedCU)
|
||||
vals.push_back(DBG_CAST(definedCU));
|
||||
vals[3] = DBG_CAST(definedCU);
|
||||
else
|
||||
vals.push_back(DBG_NULL);
|
||||
vals[3] = DBG_NULL;
|
||||
|
||||
// line number where defined
|
||||
vals.push_back(DtoConstInt(linnum));
|
||||
vals[4] = DtoConstInt(linnum);
|
||||
|
||||
// size in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false));
|
||||
vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);
|
||||
|
||||
// alignment in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false));
|
||||
vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);
|
||||
|
||||
// offset in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, offset*8, false));
|
||||
vals[7] = LLConstantInt::get(LLType::Int64Ty, offset*8, false);
|
||||
|
||||
// FIXME: dont know what this is
|
||||
vals.push_back(DtoConstUint(0));
|
||||
vals[8] = DtoConstUint(0);
|
||||
|
||||
// base type
|
||||
LLGlobalVariable* nTD = dwarfTypeDescription(t, compileUnit, NULL);
|
||||
if (t->ty == Tvoid || !nTD)
|
||||
vals.push_back(DBG_NULL);
|
||||
vals[9] = DBG_NULL;
|
||||
else
|
||||
vals.push_back(DBG_CAST(nTD));
|
||||
vals[9] = DBG_CAST(nTD);
|
||||
|
||||
return emitDwarfGlobal(getDwarfDerivedTypeType(), vals, "llvm.dbg.derivedtype");
|
||||
}
|
||||
@@ -381,9 +384,9 @@ static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* co
|
||||
|
||||
const LLArrayType* at = LLArrayType::get(DBG_TYPE, 2);
|
||||
|
||||
std::vector<LLConstant*> elems;
|
||||
elems.push_back(DBG_CAST(len));
|
||||
elems.push_back(DBG_CAST(ptr));
|
||||
std::vector<LLConstant*> elems(2);
|
||||
elems[0] = DBG_CAST(len);
|
||||
elems[1] = DBG_CAST(ptr);
|
||||
|
||||
LLConstant* ca = LLConstantArray::get(at, elems);
|
||||
members = new LLGlobalVariable(ca->getType(), true, LLGlobalValue::InternalLinkage, ca, ".array", gIR->module);
|
||||
@@ -392,11 +395,20 @@ static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* co
|
||||
name = DtoConstStringPtr(t->toChars(), "llvm.metadata");
|
||||
}
|
||||
|
||||
// struct
|
||||
else if (t->ty == Tstruct)
|
||||
// struct/class
|
||||
else if (t->ty == Tstruct || t->ty == Tclass)
|
||||
{
|
||||
TypeStruct* ts = (TypeStruct*)t;
|
||||
StructDeclaration* sd = ts->sym;
|
||||
AggregateDeclaration* sd;
|
||||
if (t->ty == Tstruct)
|
||||
{
|
||||
TypeStruct* ts = (TypeStruct*)t;
|
||||
sd = ts->sym;
|
||||
}
|
||||
else
|
||||
{
|
||||
TypeClass* tc = (TypeClass*)t;
|
||||
sd = tc->sym;
|
||||
}
|
||||
assert(sd);
|
||||
|
||||
IrStruct* ir = sd->ir.irStruct;
|
||||
@@ -415,6 +427,7 @@ static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* co
|
||||
definedCU = DtoDwarfCompileUnit(sd->getModule());
|
||||
|
||||
std::vector<LLConstant*> elems;
|
||||
elems.reserve(ir->offsets.size());
|
||||
for (IrStruct::OffsetMap::iterator i=ir->offsets.begin(); i!=ir->offsets.end(); ++i)
|
||||
{
|
||||
unsigned offset = i->first;
|
||||
@@ -436,46 +449,46 @@ static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* co
|
||||
assert(0 && "unsupported compositetype for debug info");
|
||||
}
|
||||
|
||||
std::vector<LLConstant*> vals;
|
||||
std::vector<LLConstant*> vals(11);
|
||||
|
||||
// tag
|
||||
vals.push_back(DBG_TAG(tag));
|
||||
vals[0] = DBG_TAG(tag);
|
||||
|
||||
// context
|
||||
vals.push_back(DBG_CAST(compileUnit));
|
||||
vals[1] = DBG_CAST(compileUnit);
|
||||
|
||||
// name
|
||||
vals.push_back(name);
|
||||
vals[2] = name;
|
||||
|
||||
// compile unit where defined
|
||||
if (definedCU)
|
||||
vals.push_back(DBG_CAST(definedCU));
|
||||
vals[3] = DBG_CAST(definedCU);
|
||||
else
|
||||
vals.push_back(DBG_NULL);
|
||||
vals[3] = DBG_NULL;
|
||||
|
||||
// line number where defined
|
||||
vals.push_back(DtoConstInt(linnum));
|
||||
vals[4] = DtoConstInt(linnum);
|
||||
|
||||
// size in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false));
|
||||
vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);
|
||||
|
||||
// alignment in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false));
|
||||
vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);
|
||||
|
||||
// offset in bits
|
||||
vals.push_back(LLConstantInt::get(LLType::Int64Ty, 0, false));
|
||||
vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false);
|
||||
|
||||
// FIXME: dont know what this is
|
||||
vals.push_back(DtoConstUint(0));
|
||||
vals[8] = DtoConstUint(0);
|
||||
|
||||
// FIXME: ditto
|
||||
vals.push_back(DBG_NULL);
|
||||
vals[9] = DBG_NULL;
|
||||
|
||||
// members array
|
||||
if (members)
|
||||
vals.push_back(DBG_CAST(members));
|
||||
vals[10] = DBG_CAST(members);
|
||||
else
|
||||
vals.push_back(DBG_NULL);
|
||||
vals[10] = DBG_NULL;
|
||||
|
||||
// set initializer
|
||||
if (!gv)
|
||||
@@ -493,25 +506,25 @@ static LLGlobalVariable* dwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaratio
|
||||
assert(vd->isDataseg());
|
||||
LLGlobalVariable* compileUnit = DtoDwarfCompileUnit(gIR->dmodule);
|
||||
|
||||
std::vector<LLConstant*> vals;
|
||||
vals.push_back(DBG_TAG(DW_TAG_variable));
|
||||
vals.push_back(DBG_CAST(getDwarfAnchor(DW_TAG_variable)));
|
||||
std::vector<LLConstant*> vals(12);
|
||||
vals[0] = DBG_TAG(DW_TAG_variable);
|
||||
vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_variable));
|
||||
|
||||
vals.push_back(DBG_CAST(compileUnit));
|
||||
vals[2] = DBG_CAST(compileUnit);
|
||||
|
||||
vals.push_back(DtoConstStringPtr(vd->mangle(), "llvm.metadata"));
|
||||
vals.push_back(DtoConstStringPtr(vd->toPrettyChars(), "llvm.metadata"));
|
||||
vals.push_back(DtoConstStringPtr(vd->toChars(), "llvm.metadata"));
|
||||
vals[3] = DtoConstStringPtr(vd->mangle(), "llvm.metadata");
|
||||
vals[4] = DtoConstStringPtr(vd->toPrettyChars(), "llvm.metadata");
|
||||
vals[5] = DtoConstStringPtr(vd->toChars(), "llvm.metadata");
|
||||
|
||||
vals.push_back(DBG_CAST(DtoDwarfCompileUnit(vd->getModule())));
|
||||
vals.push_back(DtoConstUint(vd->loc.linnum));
|
||||
vals[6] = DBG_CAST(DtoDwarfCompileUnit(vd->getModule()));
|
||||
vals[7] = DtoConstUint(vd->loc.linnum);
|
||||
|
||||
LLGlobalVariable* TY = dwarfTypeDescription(vd->type, compileUnit, NULL);
|
||||
vals.push_back(TY ? DBG_CAST(TY) : DBG_NULL);
|
||||
vals.push_back(DtoConstBool(vd->protection == PROTprivate));
|
||||
vals.push_back(DtoConstBool(vd->getModule() == gIR->dmodule));
|
||||
LLGlobalVariable* TY = dwarfTypeDescription_impl(vd->type, compileUnit, NULL);
|
||||
vals[8] = TY ? DBG_CAST(TY) : DBG_NULL;
|
||||
vals[9] = DtoConstBool(vd->protection == PROTprivate);
|
||||
vals[10] = DtoConstBool(vd->getModule() == gIR->dmodule);
|
||||
|
||||
vals.push_back(DBG_CAST(ll));
|
||||
vals[11] = DBG_CAST(ll);
|
||||
|
||||
return emitDwarfGlobal(getDwarfGlobalVariableType(), vals, "llvm.dbg.global_variable");
|
||||
}
|
||||
@@ -549,15 +562,15 @@ static LLGlobalVariable* dwarfVariable(VarDeclaration* vd, LLGlobalVariable* typ
|
||||
|
||||
static void dwarfDeclare(LLValue* var, LLGlobalVariable* varDescr)
|
||||
{
|
||||
LLSmallVector<LLValue*,2> args;
|
||||
args.push_back(DtoBitCast(var, DBG_TYPE));
|
||||
args.push_back(DBG_CAST(varDescr));
|
||||
LLSmallVector<LLValue*,2> args(2);
|
||||
args[0] = DtoBitCast(var, DBG_TYPE);
|
||||
args[1] = DBG_CAST(varDescr);
|
||||
gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.declare"), args.begin(), args.end());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static LLGlobalVariable* dwarfTypeDescription(Type* type, LLGlobalVariable* cu, const char* c_name)
|
||||
static LLGlobalVariable* dwarfTypeDescription_impl(Type* type, LLGlobalVariable* cu, const char* c_name)
|
||||
{
|
||||
Type* t = type->toBasetype();
|
||||
if (t->ty == Tvoid)
|
||||
@@ -566,16 +579,28 @@ static LLGlobalVariable* dwarfTypeDescription(Type* type, LLGlobalVariable* cu,
|
||||
return dwarfBasicType(type, cu);
|
||||
else if (t->ty == Tpointer)
|
||||
return dwarfDerivedType(type, cu);
|
||||
else if (t->ty == Tarray || t->ty == Tstruct)
|
||||
else if (t->ty == Tarray || t->ty == Tstruct || t->ty == Tclass)
|
||||
return dwarfCompositeType(type, cu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LLGlobalVariable* dwarfTypeDescription(Type* type, LLGlobalVariable* cu, const char* c_name)
|
||||
{
|
||||
Type* t = type->toBasetype();
|
||||
if (t->ty == Tclass)
|
||||
return dwarfTypeDescription_impl(type->pointerTo(), cu, c_name);
|
||||
else
|
||||
return dwarfTypeDescription_impl(type, cu, c_name);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd)
|
||||
{
|
||||
Logger::println("D to dwarf local variable");
|
||||
LOG_SCOPE;
|
||||
|
||||
// get compile units
|
||||
LLGlobalVariable* thisCU = DtoDwarfCompileUnit(gIR->dmodule);
|
||||
LLGlobalVariable* varCU = thisCU;
|
||||
@@ -600,6 +625,9 @@ void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd)
|
||||
|
||||
LLGlobalVariable* DtoDwarfCompileUnit(Module* m)
|
||||
{
|
||||
Logger::println("D to dwarf compile_unit");
|
||||
LOG_SCOPE;
|
||||
|
||||
// we might be generating for an import
|
||||
if (!m->ir.irModule)
|
||||
m->ir.irModule = new IrModule(m);
|
||||
@@ -618,6 +646,9 @@ LLGlobalVariable* DtoDwarfCompileUnit(Module* m)
|
||||
|
||||
LLGlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd)
|
||||
{
|
||||
Logger::println("D to dwarf subprogram");
|
||||
LOG_SCOPE;
|
||||
|
||||
// FIXME: duplicates ?
|
||||
return dwarfSubProgram(fd, DtoDwarfCompileUnit(gIR->dmodule));
|
||||
}
|
||||
@@ -626,6 +657,9 @@ LLGlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd)
|
||||
|
||||
LLGlobalVariable* DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd)
|
||||
{
|
||||
Logger::println("D to dwarf global_variable");
|
||||
LOG_SCOPE;
|
||||
|
||||
// FIXME: duplicates ?
|
||||
return dwarfGlobalVariable(ll, vd);
|
||||
}
|
||||
@@ -634,6 +668,9 @@ LLGlobalVariable* DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* v
|
||||
|
||||
void DtoDwarfFuncStart(FuncDeclaration* fd)
|
||||
{
|
||||
Logger::println("D to dwarf funcstart");
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(fd->ir.irFunc->dwarfSubProg);
|
||||
gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(fd->ir.irFunc->dwarfSubProg));
|
||||
}
|
||||
@@ -642,6 +679,9 @@ void DtoDwarfFuncStart(FuncDeclaration* fd)
|
||||
|
||||
void DtoDwarfFuncEnd(FuncDeclaration* fd)
|
||||
{
|
||||
Logger::println("D to dwarf funcend");
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(fd->ir.irFunc->dwarfSubProg);
|
||||
gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(fd->ir.irFunc->dwarfSubProg));
|
||||
}
|
||||
@@ -650,10 +690,13 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd)
|
||||
|
||||
void DtoDwarfStopPoint(unsigned ln)
|
||||
{
|
||||
LLSmallVector<LLValue*,3> args;
|
||||
args.push_back(DtoConstUint(ln));
|
||||
args.push_back(DtoConstUint(0));
|
||||
Logger::println("D to dwarf stoppoint at line %u", ln);
|
||||
LOG_SCOPE;
|
||||
|
||||
LLSmallVector<LLValue*,3> args(3);
|
||||
args[0] = DtoConstUint(ln);
|
||||
args[1] = DtoConstUint(0);
|
||||
FuncDeclaration* fd = gIR->func()->decl;
|
||||
args.push_back(DBG_CAST(DtoDwarfCompileUnit(fd->getModule())));
|
||||
args[2] = DBG_CAST(DtoDwarfCompileUnit(fd->getModule()));
|
||||
gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.stoppoint"), args.begin(), args.end());
|
||||
}
|
||||
|
||||
36
gen/toir.cpp
36
gen/toir.cpp
@@ -2191,9 +2191,43 @@ BinBitExp(And,And);
|
||||
BinBitExp(Or,Or);
|
||||
BinBitExp(Xor,Xor);
|
||||
BinBitExp(Shl,Shl);
|
||||
BinBitExp(Shr,AShr);
|
||||
//BinBitExp(Shr,AShr);
|
||||
BinBitExp(Ushr,LShr);
|
||||
|
||||
DValue* ShrExp::toElem(IRState* p)
|
||||
{
|
||||
Logger::print("ShrExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
DValue* u = e1->toElem(p);
|
||||
DValue* v = e2->toElem(p);
|
||||
LLValue* x;
|
||||
if (e1->type->isunsigned())
|
||||
x = p->ir->CreateLShr(u->getRVal(), v->getRVal(), "tmp");
|
||||
else
|
||||
x = p->ir->CreateAShr(u->getRVal(), v->getRVal(), "tmp");
|
||||
return new DImValue(type, x);
|
||||
}
|
||||
|
||||
DValue* ShrAssignExp::toElem(IRState* p)
|
||||
{
|
||||
Logger::print("ShrAssignExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
p->exps.push_back(IRExp(e1,e2,NULL));
|
||||
DValue* u = e1->toElem(p);
|
||||
p->topexp()->v = u;
|
||||
DValue* v = e2->toElem(p);
|
||||
p->exps.pop_back();
|
||||
LLValue* uval = u->getRVal();
|
||||
LLValue* vval = v->getRVal();
|
||||
LLValue* tmp;
|
||||
if (e1->type->isunsigned())
|
||||
tmp = p->ir->CreateLShr(uval, vval, "tmp");
|
||||
else
|
||||
tmp = p->ir->CreateAShr(uval, vval, "tmp");
|
||||
DtoStore(DtoPointedType(u->getLVal(), tmp), u->getLVal());
|
||||
return u;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue* HaltExp::toElem(IRState* p)
|
||||
|
||||
14
premake.lua
14
premake.lua
@@ -1,5 +1,10 @@
|
||||
project.name = llvmdc
|
||||
|
||||
-- options
|
||||
OPAQUE_VTBLS = 1
|
||||
USE_BOEHM_GC = 1
|
||||
|
||||
-- idgen
|
||||
package = newpackage()
|
||||
package.name = "idgen"
|
||||
package.kind = "exe"
|
||||
@@ -8,6 +13,7 @@ package.files = { "dmd/idgen.c" }
|
||||
package.buildoptions = { "-x c++" }
|
||||
package.postbuildcommands = { "./idgen", "mv -f id.c id.h dmd" }
|
||||
|
||||
-- impcnvgen
|
||||
package = newpackage()
|
||||
package.name = "impcnvgen"
|
||||
package.kind = "exe"
|
||||
@@ -16,6 +22,7 @@ package.files = { "dmd/impcnvgen.c" }
|
||||
package.buildoptions = { "-x c++" }
|
||||
package.postbuildcommands = { "./impcnvgen", "mv -f impcnvtab.c dmd" }
|
||||
|
||||
-- llvmdc
|
||||
package = newpackage()
|
||||
package.bindir = "bin"
|
||||
package.name = "llvmdc"
|
||||
@@ -32,11 +39,14 @@ package.linkoptions = {
|
||||
package.defines = {
|
||||
"IN_LLVM",
|
||||
"_DH",
|
||||
"OPAQUE_VTBLS=1",
|
||||
"OPAQUE_VTBLS="..OPAQUE_VTBLS,
|
||||
"USE_BOEHM_GC="..USE_BOEHM_GC,
|
||||
}
|
||||
package.config.Release.defines = { "LLVMD_NO_LOGGER" }
|
||||
package.config.Debug.buildoptions = { "-g -O0" }
|
||||
--package.targetprefix = "llvm"
|
||||
package.includepaths = { ".", "dmd" }
|
||||
--package.postbuildcommands = { "cd runtime; ./build.sh; cd .." }
|
||||
package.links = { "gc" }
|
||||
if USE_BOEHM_GC == 1 then
|
||||
package.links = { "gc" }
|
||||
end
|
||||
|
||||
@@ -480,6 +480,7 @@ extern (C) void rt_finalize(void* p, bool det = true)
|
||||
{
|
||||
if (c.destructor)
|
||||
{
|
||||
debug(PRINTF) printf("calling dtor of %.*s\n", c.name.length, c.name.ptr);
|
||||
fp_t fp = cast(fp_t)c.destructor;
|
||||
(*fp)(cast(Object)p); // call destructor
|
||||
}
|
||||
|
||||
@@ -53,7 +53,8 @@ private import gcalloc;
|
||||
private import cstdlib = tango.stdc.stdlib : calloc, free, malloc, realloc;
|
||||
private import cstring = tango.stdc.string : memcpy, memmove, memset;
|
||||
|
||||
debug private import tango.stdc.stdio;
|
||||
private import tango.stdc.stdio;
|
||||
private import tango.stdc.posix.pthread;
|
||||
|
||||
version (GNU)
|
||||
{
|
||||
|
||||
33
tangotests/debug11.d
Normal file
33
tangotests/debug11.d
Normal file
@@ -0,0 +1,33 @@
|
||||
module tangotests.debug11;
|
||||
|
||||
class C
|
||||
{
|
||||
}
|
||||
|
||||
class D : C
|
||||
{
|
||||
int i = 42;
|
||||
}
|
||||
|
||||
class E : D
|
||||
{
|
||||
float fp = 3.14f;
|
||||
}
|
||||
|
||||
class F : E
|
||||
{
|
||||
F f;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
auto c = new C;
|
||||
auto d = new D;
|
||||
auto e = new E;
|
||||
auto f = new F;
|
||||
|
||||
auto ci = c.classinfo;
|
||||
|
||||
int* fail;
|
||||
*fail = 0;
|
||||
}
|
||||
@@ -143,7 +143,12 @@ void print(TypeInfo ti, void* arg)
|
||||
else if (ti == typeid(double))
|
||||
printf("%f", *cast(double*)arg);
|
||||
else if (ti == typeid(real)) // FIXME: 80bit?
|
||||
printf("%f", *cast(real*)arg);
|
||||
{
|
||||
version(LLVM_X86_FP80)
|
||||
printf("%llf", *cast(real*)arg);
|
||||
else
|
||||
printf("%f", *cast(real*)arg);
|
||||
}
|
||||
|
||||
else if (ti == typeid(char))
|
||||
printf("%.*s", 1, arg);
|
||||
|
||||
Reference in New Issue
Block a user