mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-13 03:13:13 +01:00
merge
This commit is contained in:
@@ -265,7 +265,7 @@ int main(int argc, char *argv[])
|
||||
global.params.argv0 = argv[0];
|
||||
#endif
|
||||
global.params.link = 1;
|
||||
global.params.useAssert = 0;
|
||||
global.params.useAssert = 1;
|
||||
global.params.useInvariants = 1;
|
||||
global.params.useIn = 1;
|
||||
global.params.useOut = 1;
|
||||
|
||||
@@ -883,4 +883,17 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// void _d_invariant(Object o)
|
||||
{
|
||||
std::string fname("_d_invariant");
|
||||
std::vector<const LLType*> types;
|
||||
types.push_back(objectTy);
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,8 +113,11 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args, llvm::PAListPtr& palist, T
|
||||
int begin = tf->parameters->dim;
|
||||
Logger::println("num non vararg params = %d", begin);
|
||||
|
||||
// get n args in arguments list
|
||||
size_t n_arguments = arguments ? arguments->dim : 0;
|
||||
|
||||
// build struct with argument types (non variadic args)
|
||||
for (int i=begin; i<arguments->dim; i++)
|
||||
for (int i=begin; i<n_arguments; i++)
|
||||
{
|
||||
Expression* argexp = (Expression*)arguments->data[i];
|
||||
vtypes.push_back(DtoType(argexp->type));
|
||||
@@ -127,7 +130,7 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args, llvm::PAListPtr& palist, T
|
||||
LLValue* mem = DtoAlloca(vtype,"_argptr_storage");
|
||||
|
||||
// store arguments in the struct
|
||||
for (int i=begin,k=0; i<arguments->dim; i++,k++)
|
||||
for (int i=begin,k=0; i<n_arguments; i++,k++)
|
||||
{
|
||||
Expression* argexp = (Expression*)arguments->data[i];
|
||||
if (global.params.llvmAnnotate)
|
||||
@@ -147,7 +150,7 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args, llvm::PAListPtr& palist, T
|
||||
Logger::cout() << "_arguments storage: " << *typeinfomem << '\n';
|
||||
|
||||
std::vector<LLConstant*> vtypeinfos;
|
||||
for (int i=begin,k=0; i<arguments->dim; i++,k++)
|
||||
for (int i=begin,k=0; i<n_arguments; i++,k++)
|
||||
{
|
||||
Expression* argexp = (Expression*)arguments->data[i];
|
||||
vtypeinfos.push_back(DtoTypeInfoOf(argexp->type));
|
||||
@@ -219,6 +222,9 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||
const LLFunctionType* callableTy = DtoExtractFunctionType(callable->getType());
|
||||
assert(callableTy);
|
||||
|
||||
// get n arguments
|
||||
size_t n_arguments = arguments ? arguments->dim : 0;
|
||||
|
||||
// get llvm argument iterator, for types
|
||||
LLFunctionType::param_iterator argbegin = callableTy->param_begin();
|
||||
LLFunctionType::param_iterator argiter = argbegin;
|
||||
@@ -280,8 +286,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||
// variadic instrinsics need some custom casts
|
||||
if (va_intrinsic)
|
||||
{
|
||||
size_t n = arguments->dim;
|
||||
for (int i=0; i<n; i++)
|
||||
for (int i=0; i<n_arguments; i++)
|
||||
{
|
||||
Expression* exp = (Expression*)arguments->data[i];
|
||||
DValue* expelem = exp->toElem(gIR);
|
||||
@@ -302,7 +307,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||
else
|
||||
{
|
||||
Logger::println("doing normal arguments");
|
||||
for (int i=0; i<arguments->dim; i++) {
|
||||
for (int i=0; i<n_arguments; i++) {
|
||||
int j = argiter-argbegin;
|
||||
Argument* fnarg = Argument::getNth(tf->parameters, i);
|
||||
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
|
||||
|
||||
58
gen/toir.cpp
58
gen/toir.cpp
@@ -1569,30 +1569,56 @@ DValue* AssertExp::toElem(IRState* p)
|
||||
Logger::print("AssertExp::toElem: %s\n", toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if(!global.params.useAssert)
|
||||
return NULL;
|
||||
|
||||
// condition
|
||||
DValue* cond = e1->toElem(p);
|
||||
Type* condty = e1->type->toBasetype();
|
||||
|
||||
// create basic blocks
|
||||
llvm::BasicBlock* oldend = p->scopeend();
|
||||
llvm::BasicBlock* assertbb = llvm::BasicBlock::Create("assert", p->topfunc(), oldend);
|
||||
llvm::BasicBlock* endbb = llvm::BasicBlock::Create("noassert", p->topfunc(), oldend);
|
||||
InvariantDeclaration* invdecl;
|
||||
|
||||
// test condition
|
||||
LLValue* condval = DtoBoolean(loc, cond);
|
||||
// class invariants
|
||||
if(
|
||||
global.params.useInvariants &&
|
||||
condty->ty == Tclass &&
|
||||
!((TypeClass*)condty)->sym->isInterfaceDeclaration())
|
||||
{
|
||||
Logger::print("calling class invariant");
|
||||
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_invariant");
|
||||
LLValue* arg = DtoBitCast(cond->getRVal(), fn->getFunctionType()->getParamType(0));
|
||||
gIR->CreateCallOrInvoke(fn, arg);
|
||||
}
|
||||
// struct invariants
|
||||
else if(
|
||||
global.params.useInvariants &&
|
||||
condty->ty == Tpointer && condty->next->ty == Tstruct &&
|
||||
(invdecl = ((TypeStruct*)condty->next)->sym->inv) != NULL)
|
||||
{
|
||||
Logger::print("calling struct invariant");
|
||||
DFuncValue invfunc(invdecl, invdecl->ir.irFunc->func, cond->getRVal());
|
||||
DtoCallFunction(loc, NULL, &invfunc, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create basic blocks
|
||||
llvm::BasicBlock* oldend = p->scopeend();
|
||||
llvm::BasicBlock* assertbb = llvm::BasicBlock::Create("assert", p->topfunc(), oldend);
|
||||
llvm::BasicBlock* endbb = llvm::BasicBlock::Create("noassert", p->topfunc(), oldend);
|
||||
|
||||
// branch
|
||||
llvm::BranchInst::Create(endbb, assertbb, condval, p->scopebb());
|
||||
// test condition
|
||||
LLValue* condval = DtoBoolean(loc, cond);
|
||||
|
||||
// call assert runtime functions
|
||||
p->scope() = IRScope(assertbb,endbb);
|
||||
DtoAssert(&loc, msg ? msg->toElem(p) : NULL);
|
||||
// branch
|
||||
llvm::BranchInst::Create(endbb, assertbb, condval, p->scopebb());
|
||||
|
||||
// assert inserts unreachable terminator
|
||||
// if (!gIR->scopereturned())
|
||||
// llvm::BranchInst::Create(endbb, p->scopebb());
|
||||
// call assert runtime functions
|
||||
p->scope() = IRScope(assertbb,endbb);
|
||||
DtoAssert(&loc, msg ? msg->toElem(p) : NULL);
|
||||
|
||||
// rewrite the scope
|
||||
p->scope() = IRScope(endbb,oldend);
|
||||
// rewrite the scope
|
||||
p->scope() = IRScope(endbb,oldend);
|
||||
}
|
||||
|
||||
// no meaningful return value
|
||||
return NULL;
|
||||
|
||||
25
runtime/internal/invariant.d
Normal file
25
runtime/internal/invariant.d
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
extern(C) void _d_invariant(Object o)
|
||||
{ ClassInfo c;
|
||||
|
||||
//printf("__d_invariant(%p)\n", o);
|
||||
|
||||
// BUG: needs to be filename/line of caller, not library routine
|
||||
assert(o !is null); // just do null check, not invariant check
|
||||
|
||||
c = o.classinfo;
|
||||
do
|
||||
{
|
||||
if (c.classInvariant)
|
||||
{
|
||||
(*c.classInvariant)(o);
|
||||
}
|
||||
c = c.base;
|
||||
} while (c);
|
||||
}
|
||||
@@ -83,6 +83,7 @@ OBJ_BASE= \
|
||||
memory.bc \
|
||||
qsort2.bc \
|
||||
switch.bc \
|
||||
invariant.bc \
|
||||
|
||||
OBJ_UTIL= \
|
||||
util/console.bc \
|
||||
|
||||
Reference in New Issue
Block a user