mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 02:43:14 +01:00
Automated merge with http://hg.dsource.org/projects/ldc
This commit is contained in:
13
dmd/func.c
13
dmd/func.c
@@ -1266,12 +1266,17 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
}
|
||||
else
|
||||
{ // Call invariant virtually
|
||||
ThisExp *v = new ThisExp(0);
|
||||
v->type = vthis->type;
|
||||
e = new AssertExp(loc, v, NULL);
|
||||
// LDC: unless this is a struct without invariant
|
||||
StructDeclaration* sd = ad->isStructDeclaration();
|
||||
if (!sd || sd->inv)
|
||||
{
|
||||
ThisExp *v = new ThisExp(0);
|
||||
v->type = vthis->type;
|
||||
e = new AssertExp(loc, v, NULL);
|
||||
}
|
||||
|
||||
// LDC: check for null this
|
||||
v = new ThisExp(0);
|
||||
ThisExp* v = new ThisExp(0);
|
||||
v->type = vthis->type;
|
||||
v->var = vthis;
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#if __sun && __SVR4
|
||||
#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more, LDC#313
|
||||
#endif
|
||||
|
||||
#if IN_LLVM
|
||||
#include <cmath>
|
||||
#endif
|
||||
|
||||
@@ -677,6 +677,13 @@ void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) {
|
||||
}
|
||||
}
|
||||
|
||||
if (fty.arg_this) {
|
||||
fty.arg_this->attrs |= llvm::Attribute::Nest;
|
||||
}
|
||||
if (fty.arg_nest) {
|
||||
fty.arg_nest->attrs |= llvm::Attribute::Nest;
|
||||
}
|
||||
|
||||
Logger::println("x86-64 D ABI: Transforming arguments");
|
||||
LOG_SCOPE;
|
||||
|
||||
|
||||
12
gen/abi.cpp
12
gen/abi.cpp
@@ -132,7 +132,7 @@ struct X86_struct_to_register : ABIRewrite
|
||||
assert(dv->isLVal());
|
||||
LLValue* mem = dv->getLVal();
|
||||
const LLType* t = LLIntegerType::get(dty->size()*8);
|
||||
DtoLoad(DtoBitCast(mem, getPtrToType(t)));
|
||||
return DtoLoad(DtoBitCast(mem, getPtrToType(t)));
|
||||
}
|
||||
const LLType* type(Type* t, const LLType*)
|
||||
{
|
||||
@@ -196,8 +196,16 @@ struct X86TargetABI : TargetABI
|
||||
Logger::println("Putting context ptr in register");
|
||||
fty.arg_nest->attrs = llvm::Attribute::InReg;
|
||||
}
|
||||
else if (IrFuncTyArg* sret = fty.arg_sret)
|
||||
{
|
||||
Logger::println("Putting sret ptr in register");
|
||||
// sret and inreg are incompatible, but the ABI requires the
|
||||
// sret parameter to be in EAX in this situation...
|
||||
sret->attrs = (sret->attrs | llvm::Attribute::InReg)
|
||||
& ~llvm::Attribute::StructRet;
|
||||
}
|
||||
// otherwise try to mark the last param inreg
|
||||
else if (!fty.arg_sret && !fty.args.empty())
|
||||
else if (!fty.args.empty())
|
||||
{
|
||||
// The last parameter is passed in EAX rather than being pushed on the stack if the following conditions are met:
|
||||
// * It fits in EAX.
|
||||
|
||||
@@ -894,7 +894,10 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
|
||||
|
||||
Type* totype = to->toBasetype();
|
||||
Type* fromtype = u->getType()->toBasetype();
|
||||
assert(fromtype->ty == Tarray || fromtype->ty == Tsarray);
|
||||
if (fromtype->ty != Tarray && fromtype->ty != Tsarray) {
|
||||
error(loc, "can't cast %s to %s", u->getType()->toChars(), to->toChars());
|
||||
fatal();
|
||||
}
|
||||
|
||||
LLValue* rval;
|
||||
LLValue* rval2;
|
||||
|
||||
@@ -1528,9 +1528,8 @@ namespace AsmParserx8632
|
||||
}
|
||||
|
||||
// osx needs an extra underscore
|
||||
if ( global.params.os == OSMacOSX )
|
||||
insnTemplate << "_";
|
||||
|
||||
if ( global.params.os == OSMacOSX || global.params.os == OSWindows )
|
||||
insnTemplate << "_";
|
||||
// print out the mangle
|
||||
insnTemplate << vd->mangle();
|
||||
vd->nakedUse = true;
|
||||
|
||||
@@ -514,7 +514,7 @@ LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
|
||||
LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl, char* name)
|
||||
{
|
||||
// sanity checks
|
||||
assert(fdecl->isVirtual());
|
||||
@@ -533,7 +533,9 @@ LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
|
||||
// load vtbl ptr
|
||||
funcval = DtoLoad(funcval);
|
||||
// index vtbl
|
||||
funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toChars());
|
||||
std::string vtblname = name;
|
||||
vtblname.append("@vtbl");
|
||||
funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, vtblname.c_str());
|
||||
// load funcptr
|
||||
funcval = DtoAlignedLoad(funcval);
|
||||
|
||||
@@ -542,6 +544,10 @@ LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
|
||||
|
||||
// cast to final funcptr type
|
||||
funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
|
||||
|
||||
// postpone naming until after casting to get the name in call instructions
|
||||
funcval->setName(name);
|
||||
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "funcval casted: " << *funcval << '\n';
|
||||
|
||||
|
||||
@@ -32,6 +32,6 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* to);
|
||||
|
||||
LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* sd, VarDeclaration* vd);
|
||||
|
||||
LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl);
|
||||
LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl, char* name);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -410,7 +410,7 @@ LLValue* DtoComplexEquals(Loc& loc, TOK op, DValue* lhs, DValue* rhs)
|
||||
DValue* DtoCastComplex(Loc& loc, DValue* val, Type* _to)
|
||||
{
|
||||
Type* to = _to->toBasetype();
|
||||
Type* vty = val->getType();
|
||||
Type* vty = val->getType()->toBasetype();
|
||||
if (to->iscomplex()) {
|
||||
if (vty->size() == to->size())
|
||||
return val;
|
||||
@@ -438,17 +438,25 @@ DValue* DtoCastComplex(Loc& loc, DValue* val, Type* _to)
|
||||
DImValue* im = new DImValue(to, impart);
|
||||
return DtoCastFloat(loc, im, to);
|
||||
}
|
||||
else if (to->isfloating()) {
|
||||
// FIXME: this loads both values, even when we only need one
|
||||
LLValue* v = val->getRVal();
|
||||
LLValue* repart = gIR->ir->CreateExtractValue(v, 0, ".re_part");
|
||||
DImValue* re = new DImValue(to, repart);
|
||||
return DtoCastFloat(loc, re, to);
|
||||
}
|
||||
else if (to->ty == Tbool) {
|
||||
return new DImValue(_to, DtoComplexEquals(loc, TOKnotequal, val, DtoNullValue(vty)));
|
||||
}
|
||||
else if (to->isfloating() || to->isintegral()) {
|
||||
// FIXME: this loads both values, even when we only need one
|
||||
LLValue* v = val->getRVal();
|
||||
LLValue* repart = gIR->ir->CreateExtractValue(v, 0, ".re_part");
|
||||
Type *extractty;
|
||||
if (vty->ty == Tcomplex32) {
|
||||
extractty = Type::tfloat32;
|
||||
} else if (vty->ty == Tcomplex64) {
|
||||
extractty = Type::tfloat64;
|
||||
} else if (vty->ty == Tcomplex80) {
|
||||
extractty = Type::tfloat80;
|
||||
}
|
||||
DImValue* re = new DImValue(extractty, repart);
|
||||
return DtoCastFloat(loc, re, to);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
error(loc, "Don't know how to cast %s to %s", vty->toChars(), to->toChars());
|
||||
}
|
||||
|
||||
|
||||
@@ -369,7 +369,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (global.params.objname && files.dim > 1)
|
||||
if (global.params.objname && files.dim > 1 && !singleObj)
|
||||
{
|
||||
error("multiple source files, but only one .obj name");
|
||||
fatal();
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
#include "llvm/Analysis/CaptureTracking.h"
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
@@ -43,24 +44,40 @@ STATISTIC(NumGcToStack, "Number of calls promoted to constant-size allocas");
|
||||
STATISTIC(NumToDynSize, "Number of calls promoted to dynamically-sized allocas");
|
||||
STATISTIC(NumDeleted, "Number of GC calls deleted because the return value was unused");
|
||||
|
||||
|
||||
namespace {
|
||||
struct Analysis {
|
||||
TargetData& TD;
|
||||
const Module& M;
|
||||
CallGraph* CG;
|
||||
CallGraphNode* CGNode;
|
||||
|
||||
const Type* getTypeFor(Value* typeinfo) const;
|
||||
};
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Helper functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void EmitMemSet(IRBuilder<>& B, Value* Dst, Value* Val, Value* Len) {
|
||||
void EmitMemSet(IRBuilder<>& B, Value* Dst, Value* Val, Value* Len,
|
||||
const Analysis& A) {
|
||||
Dst = B.CreateBitCast(Dst, PointerType::getUnqual(Type::Int8Ty));
|
||||
|
||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||
const Type* Tys[1];
|
||||
Tys[0] = Len->getType();
|
||||
Value *MemSet = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys, 1);
|
||||
Function *MemSet = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys, 1);
|
||||
Value *Align = ConstantInt::get(Type::Int32Ty, 1);
|
||||
|
||||
B.CreateCall4(MemSet, Dst, Val, Len, Align);
|
||||
CallSite CS = B.CreateCall4(MemSet, Dst, Val, Len, Align);
|
||||
if (A.CGNode)
|
||||
A.CGNode->addCalledFunction(CS, A.CG->getOrInsertFunction(MemSet));
|
||||
}
|
||||
|
||||
static void EmitMemZero(IRBuilder<>& B, Value* Dst, Value* Len) {
|
||||
EmitMemSet(B, Dst, ConstantInt::get(Type::Int8Ty, 0), Len);
|
||||
static void EmitMemZero(IRBuilder<>& B, Value* Dst, Value* Len,
|
||||
const Analysis& A) {
|
||||
EmitMemSet(B, Dst, ConstantInt::get(Type::Int8Ty, 0), Len, A);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,13 +86,6 @@ static void EmitMemZero(IRBuilder<>& B, Value* Dst, Value* Len) {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
struct Analysis {
|
||||
TargetData& TD;
|
||||
const Module& M;
|
||||
|
||||
const Type* getTypeFor(Value* typeinfo) const;
|
||||
};
|
||||
|
||||
class FunctionInfo {
|
||||
protected:
|
||||
const Type* Ty;
|
||||
@@ -174,7 +184,7 @@ namespace {
|
||||
// Use the original B to put initialization at the
|
||||
// allocation site.
|
||||
Value* Size = B.CreateMul(TypeSize, arrSize);
|
||||
EmitMemZero(B, alloca, Size);
|
||||
EmitMemZero(B, alloca, Size, A);
|
||||
}
|
||||
|
||||
return alloca;
|
||||
@@ -252,6 +262,7 @@ namespace {
|
||||
|
||||
bool doInitialization(Module &M) {
|
||||
this->M = &M;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool runOnFunction(Function &F);
|
||||
@@ -259,6 +270,7 @@ namespace {
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<TargetData>();
|
||||
AU.addRequired<LoopInfo>();
|
||||
AU.addPreserved<CallGraph>();
|
||||
}
|
||||
};
|
||||
char GarbageCollect2Stack::ID = 0;
|
||||
@@ -284,8 +296,9 @@ GarbageCollect2Stack::GarbageCollect2Stack()
|
||||
KnownFunctions["_d_allocclass"] = &AllocClass;
|
||||
}
|
||||
|
||||
static void RemoveCall(Instruction* Inst) {
|
||||
if (InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst)) {
|
||||
static void RemoveCall(CallSite CS, const Analysis& A) {
|
||||
if (CS.isInvoke()) {
|
||||
InvokeInst* Invoke = cast<InvokeInst>(CS.getInstruction());
|
||||
// If this was an invoke instruction, we need to do some extra
|
||||
// work to preserve the control flow.
|
||||
|
||||
@@ -296,7 +309,9 @@ static void RemoveCall(Instruction* Inst) {
|
||||
BranchInst::Create(Invoke->getNormalDest(), Invoke->getParent());
|
||||
}
|
||||
// Remove the runtime call.
|
||||
Inst->eraseFromParent();
|
||||
if (A.CGNode)
|
||||
A.CGNode->removeCallEdgeFor(CS);
|
||||
CS.getInstruction()->eraseFromParent();
|
||||
}
|
||||
|
||||
/// runOnFunction - Top level algorithm.
|
||||
@@ -306,8 +321,10 @@ bool GarbageCollect2Stack::runOnFunction(Function &F) {
|
||||
|
||||
TargetData &TD = getAnalysis<TargetData>();
|
||||
const LoopInfo &LI = getAnalysis<LoopInfo>();
|
||||
CallGraph* CG = getAnalysisIfAvailable<CallGraph>();
|
||||
CallGraphNode* CGNode = CG ? (*CG)[&F] : NULL;
|
||||
|
||||
Analysis A = { TD, *M };
|
||||
Analysis A = { TD, *M, CG, CGNode };
|
||||
|
||||
BasicBlock& Entry = F.getEntryBlock();
|
||||
|
||||
@@ -351,7 +368,7 @@ bool GarbageCollect2Stack::runOnFunction(Function &F) {
|
||||
if (Inst->use_empty() && info->SafeToDelete) {
|
||||
Changed = true;
|
||||
NumDeleted++;
|
||||
RemoveCall(Inst);
|
||||
RemoveCall(CS, A);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -374,7 +391,7 @@ bool GarbageCollect2Stack::runOnFunction(Function &F) {
|
||||
newVal = Builder.CreateBitCast(newVal, Inst->getType());
|
||||
Inst->replaceAllUsesWith(newVal);
|
||||
|
||||
RemoveCall(Inst);
|
||||
RemoveCall(CS, A);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ void RTTIBuilder::push_void_array(uint64_t dim, llvm::Constant* ptr)
|
||||
void RTTIBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* mangle_sym)
|
||||
{
|
||||
std::string initname(mangle_sym->mangle());
|
||||
initname.append(".rtti.void[].data");
|
||||
initname.append(".rtti.voidarr.data");
|
||||
|
||||
LLGlobalVariable* G = new llvm::GlobalVariable(
|
||||
CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname, gIR->module);
|
||||
@@ -87,9 +87,14 @@ void RTTIBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* ma
|
||||
|
||||
void RTTIBuilder::push_array(llvm::Constant * CI, uint64_t dim, Type* valtype, Dsymbol * mangle_sym)
|
||||
{
|
||||
std::string initname(mangle_sym?mangle_sym->mangle():".ldc");
|
||||
std::string tmpStr(valtype->arrayOf()->toChars());
|
||||
tmpStr.erase( remove( tmpStr.begin(), tmpStr.end(), '[' ), tmpStr.end() );
|
||||
tmpStr.erase( remove( tmpStr.begin(), tmpStr.end(), ']' ), tmpStr.end() );
|
||||
tmpStr.append("arr");
|
||||
|
||||
std::string initname(mangle_sym?mangle_sym->mangle():".ldc");
|
||||
initname.append(".rtti.");
|
||||
initname.append(valtype->arrayOf()->toChars());
|
||||
initname.append(tmpStr);
|
||||
initname.append(".data");
|
||||
|
||||
LLGlobalVariable* G = new llvm::GlobalVariable(
|
||||
|
||||
@@ -322,7 +322,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||
// add attrs for hidden ptr
|
||||
Attr.Index = 1;
|
||||
Attr.Attrs = tf->fty.arg_sret->attrs;
|
||||
assert((Attr.Attrs & llvm::Attribute::StructRet) && "Sret arg not sret?");
|
||||
assert((Attr.Attrs & (llvm::Attribute::StructRet | llvm::Attribute::InReg))
|
||||
&& "Sret arg not sret or inreg?");
|
||||
attrs.push_back(Attr);
|
||||
}
|
||||
|
||||
|
||||
20
gen/toir.cpp
20
gen/toir.cpp
@@ -1134,22 +1134,8 @@ DValue* DotVarExp::toElem(IRState* p)
|
||||
assert(funcval);
|
||||
}
|
||||
else {
|
||||
assert(fdecl->vtblIndex > 0);
|
||||
assert(e1type->ty == Tclass);
|
||||
|
||||
LLValue* zero = DtoConstUint(0);
|
||||
size_t vtblidx = fdecl->vtblIndex;
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "vthis: " << *vthis << '\n';
|
||||
funcval = DtoGEP(vthis, zero, zero);
|
||||
funcval = DtoLoad(funcval);
|
||||
Logger::println("vtblidx = %lu", vtblidx);
|
||||
funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars());
|
||||
funcval = DtoLoad(funcval);
|
||||
|
||||
funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "funcval casted: " << *funcval << '\n';
|
||||
DImValue vthis3(e1type, vthis);
|
||||
funcval = DtoVirtualFunctionPointer(&vthis3, fdecl, toChars());
|
||||
}
|
||||
|
||||
return new DFuncValue(fdecl, funcval, vthis2);
|
||||
@@ -2031,7 +2017,7 @@ DValue* DelegateExp::toElem(IRState* p)
|
||||
|
||||
LLValue* castfptr;
|
||||
if (func->isVirtual() && !func->isFinal())
|
||||
castfptr = DtoVirtualFunctionPointer(u, func);
|
||||
castfptr = DtoVirtualFunctionPointer(u, func, toChars());
|
||||
else if (func->isAbstract())
|
||||
assert(0 && "TODO delegate to abstract method");
|
||||
else if (func->toParent()->isInterfaceDeclaration())
|
||||
|
||||
@@ -152,8 +152,8 @@ class ClassInfo : Object
|
||||
void*[] vtbl; /// virtual function pointer table
|
||||
Interface[] interfaces; /// interfaces this class implements
|
||||
ClassInfo base; /// base class
|
||||
void* destructor;
|
||||
void function(Object) classInvariant;
|
||||
void* destructor; // Only use as delegate.funcptr!
|
||||
void* classInvariant; // Only use as delegate.funcptr!
|
||||
uint flags;
|
||||
// 1: // IUnknown
|
||||
// 2: // has no possible pointers into GC memory
|
||||
@@ -162,7 +162,7 @@ class ClassInfo : Object
|
||||
// 32: // has typeinfo
|
||||
void* deallocator;
|
||||
OffsetTypeInfo[] offTi;
|
||||
void* defaultConstructor; // default Constructor
|
||||
void* defaultConstructor; // default Constructor. Only use as delegate.funcptr!
|
||||
TypeInfo typeinfo;
|
||||
|
||||
/**
|
||||
@@ -198,8 +198,10 @@ class ClassInfo : Object
|
||||
|
||||
if (flags & 8 && defaultConstructor)
|
||||
{
|
||||
auto ctor = cast(Object function(Object))defaultConstructor;
|
||||
return ctor(o);
|
||||
Object delegate() ctor;
|
||||
ctor.ptr = cast(void*)o;
|
||||
ctor.funcptr = cast(Object function())defaultConstructor;
|
||||
return ctor();
|
||||
}
|
||||
return o;
|
||||
}
|
||||
@@ -762,7 +764,10 @@ class TypeInfo_Struct : TypeInfo
|
||||
assert(p);
|
||||
if (xtoHash)
|
||||
{ debug(PRINTF) printf("getHash() using xtoHash\n");
|
||||
h = (*xtoHash)(p);
|
||||
hash_t delegate() toHash;
|
||||
toHash.ptr = p;
|
||||
toHash.funcptr = xtoHash;
|
||||
h = toHash();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -785,9 +790,12 @@ class TypeInfo_Struct : TypeInfo
|
||||
c = 1;
|
||||
else if (!p1 || !p2)
|
||||
c = 0;
|
||||
else if (xopEquals)
|
||||
c = (*xopEquals)(p1, p2);
|
||||
else
|
||||
else if (xopEquals) {
|
||||
int delegate(void*) opEquals;
|
||||
opEquals.ptr = p1;
|
||||
opEquals.funcptr = xopEquals;
|
||||
c = opEquals(p2);
|
||||
} else
|
||||
// BUG: relies on the GC not moving objects
|
||||
c = (memcmp(p1, p2, m_init.length) == 0);
|
||||
return c;
|
||||
@@ -803,13 +811,12 @@ class TypeInfo_Struct : TypeInfo
|
||||
if (p1)
|
||||
{ if (!p2)
|
||||
c = 1;
|
||||
else if (xopCmp)
|
||||
// the x86 D calling conv requires the this arg to be last here
|
||||
version(X86)
|
||||
c = (*xopCmp)(p2, p1);
|
||||
else
|
||||
c = (*xopCmp)(p1, p2);
|
||||
else
|
||||
else if (xopCmp) {
|
||||
int delegate(void*) opCmp;
|
||||
opCmp.ptr = p1;
|
||||
opCmp.funcptr = xopCmp;
|
||||
c = opCmp(p2);
|
||||
} else
|
||||
// BUG: relies on the GC not moving objects
|
||||
c = memcmp(p1, p2, m_init.length);
|
||||
}
|
||||
@@ -831,10 +838,11 @@ class TypeInfo_Struct : TypeInfo
|
||||
char[] name;
|
||||
void[] m_init; // initializer; never null
|
||||
|
||||
hash_t function(void*) xtoHash;
|
||||
int function(void*,void*) xopEquals;
|
||||
int function(void*,void*) xopCmp;
|
||||
char[] function(void*) xtoString;
|
||||
// These are ONLY for use as a delegate.funcptr!
|
||||
hash_t function() xtoHash;
|
||||
int function(void*) xopEquals;
|
||||
int function(void*) xopCmp;
|
||||
char[] function() xtoString;
|
||||
|
||||
uint m_flags;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,10 @@ extern(C) void _d_invariant(Object o)
|
||||
{
|
||||
if (c.classInvariant)
|
||||
{
|
||||
(*c.classInvariant)(o);
|
||||
void delegate() inv;
|
||||
inv.ptr = cast(void*) o;
|
||||
inv.funcptr = c.classInvariant;
|
||||
inv();
|
||||
}
|
||||
c = c.base;
|
||||
} while (c);
|
||||
|
||||
@@ -560,8 +560,10 @@ 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
|
||||
void delegate() dg;
|
||||
dg.ptr = p;
|
||||
dg.funcptr = cast(void function()) c.destructor;
|
||||
dg(); // call destructor
|
||||
}
|
||||
c = c.base;
|
||||
} while (c);
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
Index: object.di
|
||||
===================================================================
|
||||
--- object.di (revision 4655)
|
||||
--- object.di (revision 4578)
|
||||
+++ object.di (working copy)
|
||||
@@ -41,9 +41,11 @@
|
||||
@@ -35,15 +35,17 @@
|
||||
Interface[] interfaces;
|
||||
ClassInfo base;
|
||||
void* destructor;
|
||||
- void(*classInvariant)(Object);
|
||||
+ void* classInvariant;
|
||||
uint flags;
|
||||
// 1: // IUnknown
|
||||
// 2: // has no possible pointers into GC memory
|
||||
// 4: // has offTi[] member
|
||||
// 8: // has constructors
|
||||
@@ -14,9 +21,25 @@ Index: object.di
|
||||
|
||||
static ClassInfo find(char[] classname);
|
||||
Object create();
|
||||
@@ -127,10 +129,11 @@
|
||||
char[] name;
|
||||
void[] m_init;
|
||||
|
||||
- uint function(void*) xtoHash;
|
||||
- int function(void*,void*) xopEquals;
|
||||
- int function(void*,void*) xopCmp;
|
||||
- char[] function(void*) xtoString;
|
||||
+ // These are ONLY for use as a delegate.funcptr!
|
||||
+ hash_t function() xtoHash;
|
||||
+ int function(void*) xopEquals;
|
||||
+ int function(void*) xopCmp;
|
||||
+ char[] function() xtoString;
|
||||
|
||||
uint m_flags;
|
||||
}
|
||||
Index: lib/common/tango/core/Thread.d
|
||||
===================================================================
|
||||
--- lib/common/tango/core/Thread.d (revision 4655)
|
||||
--- lib/common/tango/core/Thread.d (revision 4578)
|
||||
+++ lib/common/tango/core/Thread.d (working copy)
|
||||
@@ -295,7 +295,7 @@
|
||||
}
|
||||
@@ -38,7 +61,7 @@ Index: lib/common/tango/core/Thread.d
|
||||
movq r12[RBP], R12 ;
|
||||
Index: lib/gc/basic/gcx.d
|
||||
===================================================================
|
||||
--- lib/gc/basic/gcx.d (revision 4655)
|
||||
--- lib/gc/basic/gcx.d (revision 4578)
|
||||
+++ lib/gc/basic/gcx.d (working copy)
|
||||
@@ -2198,7 +2198,7 @@
|
||||
}
|
||||
@@ -58,9 +81,28 @@ Index: lib/gc/basic/gcx.d
|
||||
movq r10[RBP], R10 ;
|
||||
movq r11[RBP], R11 ;
|
||||
movq r12[RBP], R12 ;
|
||||
Index: tango/text/convert/Layout.d
|
||||
===================================================================
|
||||
--- tango/text/convert/Layout.d (revision 4578)
|
||||
+++ tango/text/convert/Layout.d (working copy)
|
||||
@@ -660,8 +660,12 @@
|
||||
|
||||
case TypeCode.STRUCT:
|
||||
auto s = cast(TypeInfo_Struct) type;
|
||||
- if (s.xtoString)
|
||||
- return Utf.fromString8 (s.xtoString(p), result);
|
||||
+ if (s.xtoString) {
|
||||
+ char[] delegate() toString;
|
||||
+ toString.ptr = p;
|
||||
+ toString.funcptr = cast(char[] function()) s.xtoString;
|
||||
+ return Utf.fromString8 (toString(), result);
|
||||
+ }
|
||||
goto default;
|
||||
|
||||
case TypeCode.INTERFACE:
|
||||
Index: tango/net/Socket.d
|
||||
===================================================================
|
||||
--- tango/net/Socket.d (revision 4655)
|
||||
--- tango/net/Socket.d (revision 4578)
|
||||
+++ tango/net/Socket.d (working copy)
|
||||
@@ -1545,10 +1545,10 @@
|
||||
|
||||
|
||||
@@ -15,15 +15,32 @@ void main()
|
||||
|
||||
version(D_InlineAsm_X86)
|
||||
{
|
||||
asm
|
||||
{
|
||||
mov EAX, [a];
|
||||
push EAX;
|
||||
mov EAX, [b];
|
||||
push EAX;
|
||||
call foo;
|
||||
fstp c;
|
||||
}
|
||||
version(Windows)
|
||||
{
|
||||
asm
|
||||
{
|
||||
movss XMM0, [a];
|
||||
movss XMM1, [b];
|
||||
movss [ESP], XMM1;
|
||||
movss [ESP]+4, XMM0;
|
||||
call foo;
|
||||
fstp [c]-4;
|
||||
movss XMM0, [c]-4;
|
||||
movss [c], XMM0;
|
||||
}
|
||||
} else
|
||||
{
|
||||
|
||||
asm
|
||||
{
|
||||
mov EAX, [a];
|
||||
push EAX;
|
||||
mov EAX, [b];
|
||||
push EAX;
|
||||
call foo;
|
||||
fstp c;
|
||||
}
|
||||
}
|
||||
}
|
||||
else version(D_InlineAsm_X86_64)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,9 @@ extern(C):
|
||||
version(darwin) {
|
||||
int* __error();
|
||||
alias __error __errno_location;
|
||||
} else version (Windows) {
|
||||
int* strerror();
|
||||
alias strerror __errno_location;
|
||||
} else {
|
||||
int* __errno_location();
|
||||
}
|
||||
|
||||
@@ -3,9 +3,17 @@ int foo(int op)(int a, int b)
|
||||
version(X86)
|
||||
{
|
||||
const OP = (op == '+') ? "add" : "sub";
|
||||
asm { naked; }
|
||||
mixin("asm{"~OP~" EAX, [ESP+4];}");
|
||||
asm { ret 4; }
|
||||
version (Windows)
|
||||
{
|
||||
asm { naked; }
|
||||
mixin("asm{push EBP;mov EBP,ESP;sub ESP,8;mov ECX,[EBP+8];"~OP~" EAX, ECX;add ESP,8;pop EBP;}");
|
||||
asm { ret; }
|
||||
} else
|
||||
{
|
||||
asm { naked; }
|
||||
mixin("asm{"~OP~" EAX, [ESP+4];}");
|
||||
asm { ret 4; }
|
||||
}
|
||||
}
|
||||
else version(X86_64)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ module mini.norun_debug1;
|
||||
|
||||
void main()
|
||||
{
|
||||
int* ptr;
|
||||
int* ptr = cast(int*) 1;
|
||||
|
||||
// all these should be inspectable
|
||||
int i = 1;
|
||||
|
||||
@@ -16,6 +16,6 @@ void main()
|
||||
|
||||
void func(Vec2 v2, ref Vec2 rv2, char[] str, out int i, ref float f)
|
||||
{
|
||||
int* fail;
|
||||
int* fail = cast(int*) 1;
|
||||
*fail = 0;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ void main()
|
||||
scope c = new C;
|
||||
I i = c;
|
||||
|
||||
int* fail;
|
||||
int* fail = cast(int*) 1;
|
||||
*fail = 0;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ void main()
|
||||
while (iter < 25)
|
||||
{
|
||||
if (rand() % 20 == 10)
|
||||
*cast(int*)null = 0;
|
||||
*cast(int*)1 = 0;
|
||||
++iter;
|
||||
}
|
||||
assert(0);
|
||||
|
||||
@@ -5,6 +5,6 @@ void main()
|
||||
int i = 42;
|
||||
int* ip = &i;
|
||||
|
||||
int* fail;
|
||||
int* fail = cast(int*) 1;
|
||||
*fail = 0;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ void main()
|
||||
wchar wc = 'w';
|
||||
dchar dc = 'd';
|
||||
|
||||
int* fail;
|
||||
int* fail = cast(int*) 1;
|
||||
*fail = 32;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,6 @@ void main()
|
||||
|
||||
void func(int i, real r, real* p)
|
||||
{
|
||||
int* fail;
|
||||
int* fail = cast(int*) 1;
|
||||
*fail = 666;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ void main()
|
||||
{
|
||||
char[] str = "hello world :)";
|
||||
|
||||
int* fail;
|
||||
int* fail = cast(int*) 1;
|
||||
*fail = 32;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ int gi;
|
||||
|
||||
void main()
|
||||
{
|
||||
int* fail;
|
||||
int* fail = cast(int*) 1;
|
||||
*fail = 0;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,6 @@ void main()
|
||||
foo.bar.y = 3.1415;
|
||||
foo.bar.foo = &foo;
|
||||
|
||||
int* fail;
|
||||
int* fail = cast(int*) 1;
|
||||
*fail = 0;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ struct Foo
|
||||
|
||||
void func()
|
||||
{
|
||||
int* fail;
|
||||
int* fail = cast(int*) 1;
|
||||
*fail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import std.stdio;
|
||||
class Foo {}
|
||||
void func3()
|
||||
{
|
||||
Foo[1] test=[new Foo];
|
||||
writefln(test);
|
||||
}
|
||||
void main() {
|
||||
func3();
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
module bug58;
|
||||
import std.stdio;
|
||||
void main()
|
||||
{
|
||||
int[16] arr = [1,16,2,15,3,14,4,13,5,12,6,11,7,10,8,9];
|
||||
writefln("arr = ",arr);
|
||||
arr.sort;
|
||||
writefln("arr.sort = ",arr);
|
||||
assert(arr == [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
module bug66;
|
||||
import std.stdio;
|
||||
class Scene { string name() { return "Scene"; } }
|
||||
class Group : Scene { this () { } }
|
||||
void main() { writefln((new Group).name); }
|
||||
@@ -1,20 +0,0 @@
|
||||
module bug71;
|
||||
|
||||
void main()
|
||||
{
|
||||
static TypeInfo skipCI(TypeInfo valti)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (valti.classinfo.name.length == 18 &&
|
||||
valti.classinfo.name[9..18] == "Invariant")
|
||||
valti = (cast(TypeInfo_Invariant)valti).next;
|
||||
else if (valti.classinfo.name.length == 14 &&
|
||||
valti.classinfo.name[9..14] == "Const")
|
||||
valti = (cast(TypeInfo_Const)valti).next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return valti;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
module bug79;
|
||||
import std.c.linux.linux;
|
||||
void main()
|
||||
{
|
||||
timespec ts;
|
||||
ts.tv_nsec -= 1;
|
||||
//auto t = ts.tv_nsec - 1;
|
||||
//t -= 1;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
module imports2;
|
||||
import std.stdio;
|
||||
|
||||
void main() {
|
||||
writefln("Hello world!"[]);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
module stdiotest;
|
||||
|
||||
import std.stdio;
|
||||
|
||||
T typed(T)(T x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
/*char[] str = "hello";
|
||||
writefln(str);
|
||||
|
||||
writefln("hello world");*/
|
||||
|
||||
char[] fmt = "%s";
|
||||
writefln(2.0f);
|
||||
|
||||
/*{writefln(typed!(byte)(1));}
|
||||
{writefln(typed!(short)(2));}
|
||||
{writefln(typed!(int)(3));}
|
||||
{writefln(typed!(long)(-4));}
|
||||
{writefln(typed!(ulong)(5));}
|
||||
{writefln("%f", typed!(float)(6));}
|
||||
{writefln("%f", typed!(double)(7));}
|
||||
{writefln("%f", typed!(real)(8));}*/
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
module stdiotest2;
|
||||
import std.stdio;
|
||||
void main()
|
||||
{
|
||||
int[4] v = [1,2,3,4];
|
||||
{
|
||||
writefln("%s", v);
|
||||
{
|
||||
int[] dv = v;
|
||||
{writefln("%s", dv);}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
writefln(v);
|
||||
{
|
||||
//int[] dv = v;
|
||||
//{writefln(dv);}
|
||||
}
|
||||
}
|
||||
//writefln(1,2,3,4.56,"hello",v);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
module strings2;
|
||||
|
||||
import std.string;
|
||||
import std.stdio;
|
||||
|
||||
void main()
|
||||
{
|
||||
int i = 32;
|
||||
auto str = format(i);
|
||||
writefln(str);
|
||||
|
||||
long l = 123123;
|
||||
str = format(l);
|
||||
writefln(str);
|
||||
}
|
||||
@@ -58,7 +58,10 @@ void main()
|
||||
assert(ti.compare(&v,&u) > 0);
|
||||
{
|
||||
auto tis = cast(TypeInfo_Struct)ti;
|
||||
assert(tis.xtoString(&s) == s.toString());
|
||||
char[] delegate() structToString;
|
||||
structToString.ptr = &s;
|
||||
structToString.funcptr = tis.xtoString;
|
||||
assert(structToString() == s.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// tries to implement a fairly complete variadic print function
|
||||
module tangotests.vararg3;
|
||||
module tangotests.vararg6;
|
||||
|
||||
extern(C) int printf(char*, ...);
|
||||
|
||||
@@ -179,7 +179,10 @@ void print(TypeInfo ti, void* arg)
|
||||
{
|
||||
if (sti.xtoString !is null)
|
||||
{
|
||||
char[] str = sti.xtoString(arg);
|
||||
char[] delegate() toString;
|
||||
toString.ptr = arg;
|
||||
toString.funcptr = sti.xtoString;
|
||||
char[] str = toString();
|
||||
printf("%.*s", str.length, str.ptr);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -69,7 +69,7 @@ int main(char[][] args)
|
||||
compilefailed ~= c.toString;
|
||||
}
|
||||
else if (cl == RUN || cl == NORUN) {
|
||||
if (system(toStringz("obj/" ~ testname)) != 0) {
|
||||
if (system(toStringz(Path.native("obj/" ~ testname))) != 0) {
|
||||
if (cl == RUN)
|
||||
runfailed ~= c.toString;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user