Implemented proper support for naked asm using llvm module level asm. Still not 100% complete, but already 1000 times better that what we had before. Don's BignumX86 implementation from Tango (when turned into a standalone unittest) seems to fully work with no changes, and great performance :)

Fixed align N; in asm blocks.

Fixed inreg parameter passing on x86 for ref/out params.

Removed support for lazy initialization of function local static variables, I have no idea why I ever implemented this, it's not in the D spec, and DMD doesn't support it :P

Some of the global variable related changes might cause minor regressions, but they should be easily fixable.
This commit is contained in:
Tomas Lindquist Olsen 2009-02-03 08:54:57 +01:00
parent 8ab98dad49
commit dc5944df99
28 changed files with 491 additions and 153 deletions

View file

@ -836,36 +836,6 @@ bool DtoIsTemplateInstance(Dsymbol* s)
return false;
}
/****************************************************************************************/
/*////////////////////////////////////////////////////////////////////////////////////////
// LAZY STATIC INIT HELPER
////////////////////////////////////////////////////////////////////////////////////////*/
void DtoLazyStaticInit(bool istempl, LLValue* gvar, Initializer* init, Type* t)
{
// create a flag to make sure initialization only happens once
llvm::GlobalValue::LinkageTypes gflaglink = istempl ? TEMPLATE_LINKAGE_TYPE : llvm::GlobalValue::InternalLinkage;
std::string gflagname(gvar->getName());
gflagname.append("__initflag");
llvm::GlobalVariable* gflag = new llvm::GlobalVariable(LLType::Int1Ty,false,gflaglink,DtoConstBool(false),gflagname,gIR->module);
// check flag and do init if not already done
llvm::BasicBlock* oldend = gIR->scopeend();
llvm::BasicBlock* initbb = llvm::BasicBlock::Create("ifnotinit",gIR->topfunc(),oldend);
llvm::BasicBlock* endinitbb = llvm::BasicBlock::Create("ifnotinitend",gIR->topfunc(),oldend);
LLValue* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false));
gIR->ir->CreateCondBr(cond, initbb, endinitbb);
gIR->scope() = IRScope(initbb,endinitbb);
DValue* ie = DtoInitializer(gvar, init);
DVarValue dst(t, gvar);
DtoAssign(init->loc, &dst, ie);
gIR->ir->CreateStore(DtoConstBool(true), gflag);
gIR->ir->CreateBr(endinitbb);
gIR->scope() = IRScope(endinitbb,oldend);
}
/****************************************************************************************/
/*////////////////////////////////////////////////////////////////////////////////////////
// PROCESSING QUEUE HELPERS
@ -946,7 +916,7 @@ void DtoDefineDsymbol(Dsymbol* dsym)
DtoDefineClass(cd);
}
else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
DtoDefineFunc(fd);
DtoDefineFunction(fd);
}
else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) {
DtoDefineTypeInfo(fd);
@ -967,36 +937,10 @@ void DtoConstInitGlobal(VarDeclaration* vd)
Logger::println("DtoConstInitGlobal(%s) @ %s", vd->toChars(), vd->locToChars());
LOG_SCOPE;
// if the variable is a function local static variable with a runtime initializer
// we must do lazy initialization, which involves a boolean flag to make sure it happens only once
// FIXME: I don't think it's thread safe ...
bool doLazyInit = false;
Dsymbol* par = vd->toParent();
if (par && par->isFuncDeclaration() && vd->init)
{
if (ExpInitializer* einit = vd->init->isExpInitializer())
{
if (!einit->exp->isConst())
{
// mark as needing lazy now
doLazyInit = true;
}
}
}
// if we do lazy init, we start out with an undefined initializer
LLConstant* initVal;
if (doLazyInit)
{
initVal = llvm::UndefValue::get(DtoType(vd->type));
}
// otherwise we build it
else
{
initVal = DtoConstInitializer(vd->loc, vd->type, vd->init);
}
// build the initializer
LLConstant* initVal = DtoConstInitializer(vd->loc, vd->type, vd->init);
// set the initializer if appropriate
IrGlobal* glob = vd->ir.irGlobal;
@ -1035,9 +979,6 @@ void DtoConstInitGlobal(VarDeclaration* vd)
gIR->usedArray.push_back(llvm::ConstantExpr::getBitCast(gv, getVoidPtrType()));
}
}
if (doLazyInit)
DtoLazyStaticInit(istempl, gvar, vd->init, vd->type);
}
//////////////////////////////////////////////////////////////////////////////////////////