From a4e4f34a342ccbd734467f2a75e8c9297edc534b Mon Sep 17 00:00:00 2001 From: Tomas Lindquist Olsen Date: Sun, 13 Jul 2008 04:11:08 +0200 Subject: [PATCH] [svn r365] Implemented raw struct equality comparison, uses C memcmp. Renamed DtoDelegateCompare to DtoDelegateEquals, for consistency with the other equality helpers. --- gen/structs.cpp | 23 +++++++++++++++++++++++ gen/structs.h | 5 +++++ gen/toir.cpp | 10 ++++++++-- gen/tollvm.cpp | 27 +++++++++++++++++++++++++-- gen/tollvm.h | 7 ++++++- llvmdc.kdevelop.filelist | 2 ++ 6 files changed, 69 insertions(+), 5 deletions(-) diff --git a/gen/structs.cpp b/gen/structs.cpp index b44fe82c..565c4bff 100644 --- a/gen/structs.cpp +++ b/gen/structs.cpp @@ -13,6 +13,7 @@ #include "gen/arrays.h" #include "gen/logger.h" #include "gen/structs.h" +#include "gen/dvalue.h" #include "ir/irstruct.h" @@ -377,6 +378,28 @@ void DtoDefineStruct(StructDeclaration* sd) sd->ir.DModule = gIR->dmodule; } +////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////// D STRUCT UTILITIES //////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// + +LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs) +{ + Type* t = lhs->getType()->toBasetype(); + assert(t->ty == Tstruct); + + // set predicate + llvm::ICmpInst::Predicate cmpop; + if (op == TOKequal) + cmpop = llvm::ICmpInst::ICMP_EQ; + else + cmpop = llvm::ICmpInst::ICMP_NE; + + // call memcmp + size_t sz = getABITypeSize(DtoType(t)); + LLValue* val = DtoMemCmp(lhs->getRVal(), rhs->getRVal(), DtoConstSize_t(sz)); + return gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false), "tmp"); +} + ////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////// D UNION HELPER CLASS //////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/structs.h b/gen/structs.h index ed676bf6..3cb30ba0 100644 --- a/gen/structs.h +++ b/gen/structs.h @@ -25,6 +25,11 @@ void DtoConstInitStruct(StructDeclaration* sd); */ void DtoDefineStruct(StructDeclaration* sd); +/** + * Returns a boolean=true if the two structs are equal + */ +LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs); + typedef LLSmallVector DStructIndexVector; LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, DStructIndexVector& idxs); diff --git a/gen/toir.cpp b/gen/toir.cpp index deed6653..1bfdc193 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1747,7 +1747,13 @@ DValue* EqualExp::toElem(IRState* p) else if (t->ty == Tdelegate) { Logger::println("delegate"); - eval = DtoDelegateCompare(op,l->getRVal(),r->getRVal()); + eval = DtoDelegateEquals(op,l->getRVal(),r->getRVal()); + } + else if (t->ty == Tstruct) + { + Logger::println("struct"); + // when this is reached it means there is no opEquals overload. + eval = DtoStructEquals(op,l,r); } else { @@ -2266,7 +2272,7 @@ DValue* IdentityExp::toElem(IRState* p) else { assert(l->getType() == r->getType()); } - eval = DtoDelegateCompare(op,l,r); + eval = DtoDelegateEquals(op,l,r); } else if (t1->isfloating()) { diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 336398c3..582a5208 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -186,9 +186,9 @@ const LLStructType* DtoDelegateType(Type* t) ////////////////////////////////////////////////////////////////////////////////////////// -LLValue* DtoDelegateCompare(TOK op, LLValue* lhs, LLValue* rhs) +LLValue* DtoDelegateEquals(TOK op, LLValue* lhs, LLValue* rhs) { - Logger::println("Doing delegate compare"); + Logger::println("Doing delegate equality"); llvm::ICmpInst::Predicate pred = (op == TOKequal || op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE; llvm::Value *b1, *b2; if (rhs == NULL) @@ -444,6 +444,29 @@ void DtoMemCpy(LLValue* dst, LLValue* src, LLValue* nbytes) ////////////////////////////////////////////////////////////////////////////////////////// +LLValue* DtoMemCmp(LLValue* lhs, LLValue* rhs, LLValue* nbytes) +{ + // int memcmp ( const void * ptr1, const void * ptr2, size_t num ); + + LLFunction* fn = gIR->module->getFunction("memcmp"); + if (!fn) + { + std::vector params(3); + params[0] = getVoidPtrType(); + params[1] = getVoidPtrType(); + params[2] = DtoSize_t(); + const LLFunctionType* fty = LLFunctionType::get(LLType::Int32Ty, params, false); + fn = LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, "memcmp", gIR->module); + } + + lhs = DtoBitCast(lhs,getVoidPtrType()); + rhs = DtoBitCast(rhs,getVoidPtrType()); + + return gIR->ir->CreateCall3(fn, lhs, rhs, nbytes, "tmp"); +} + +////////////////////////////////////////////////////////////////////////////////////////// + void DtoAggrZeroInit(LLValue* v) { uint64_t n = getTypeStoreSize(v->getType()->getContainedType(0)); diff --git a/gen/tollvm.h b/gen/tollvm.h index d97e9648..0fce4ae7 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -27,7 +27,7 @@ Type* DtoDType(Type* t); // delegate helpers const LLStructType* DtoDelegateType(Type* t); -LLValue* DtoDelegateCompare(TOK op, LLValue* lhs, LLValue* rhs); +LLValue* DtoDelegateEquals(TOK op, LLValue* lhs, LLValue* rhs); // return linkage type for symbol using the current ir state for context LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym); @@ -113,6 +113,11 @@ void DtoMemSetZero(LLValue* dst, LLValue* nbytes); */ void DtoMemCpy(LLValue* dst, LLValue* src, LLValue* nbytes); +/** + * Generates a call to C memcmp. + */ +LLValue* DtoMemCmp(LLValue* lhs, LLValue* rhs, LLValue* nbytes); + /** * The same as DtoMemSetZero but figures out the size itself by "dereferencing" the v pointer once. * @param v Destination memory. diff --git a/llvmdc.kdevelop.filelist b/llvmdc.kdevelop.filelist index 8cf0303d..0250200b 100644 --- a/llvmdc.kdevelop.filelist +++ b/llvmdc.kdevelop.filelist @@ -58,6 +58,8 @@ dmd/macro.h dmd/mangle.c dmd/mars.c dmd/mars.h +dmd/md5.c +dmd/md5.h dmd/mem.c dmd/mem.h dmd/module.c