Store bools as i8.

I really hope we can refactor this to use a less leaky
abstraction later – it should at least be possible to merge
voidToI8 and i1ToI8.
This commit is contained in:
David Nadlinger
2013-06-06 21:14:46 +02:00
parent 7e92984ebe
commit 848dee32d4
16 changed files with 105 additions and 60 deletions

View File

@@ -74,7 +74,7 @@ DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue)
}
// cast return value
LLType* targettype = getPtrToType(DtoType(type));
LLType* targettype = getPtrToType(i1ToI8(DtoType(type)));
if (ret->getType() != targettype)
ret = DtoBitCast(ret, targettype);

View File

@@ -64,9 +64,7 @@ static LLValue *DtoSlicePtr(DValue *dval)
LLStructType* DtoArrayType(Type* arrayTy)
{
assert(arrayTy->nextOf());
LLType* elemty = DtoType(arrayTy->nextOf());
if (elemty == LLType::getVoidTy(gIR->context()))
elemty = LLType::getInt8Ty(gIR->context());
LLType* elemty = i1ToI8(voidToI8(DtoType(arrayTy->nextOf())));
llvm::Type *elems[] = { DtoSize_t(), getPtrToType(elemty) };
return llvm::StructType::get(gIR->context(), elems, false);
@@ -87,10 +85,7 @@ LLArrayType* DtoStaticArrayType(Type* t)
TypeSArray* tsa = static_cast<TypeSArray*>(t);
Type* tnext = tsa->nextOf();
LLType* elemty = DtoType(tnext);
if (elemty == LLType::getVoidTy(gIR->context()))
elemty = LLType::getInt8Ty(gIR->context());
LLType* elemty = i1ToI8(voidToI8(DtoType(tnext)));
return LLArrayType::get(elemty, tsa->dim->toUInteger());
}
@@ -291,7 +286,7 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
// get elem type
Type* elemty = arrty->nextOf();
LLType* llelemty = DtoTypeNotVoid(elemty);
LLType* llelemty = i1ToI8(voidToI8(DtoType(elemty)));
// true if array elements differ in type, can happen with array of unions
bool mismatch = false;
@@ -424,7 +419,7 @@ void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
LLValue* dstarr = get_slice_ptr(dst,sz1);
LLValue* srcarr = DtoBitCast(DtoArrayPtr(src), getVoidPtrType());
LLType* arrayelemty = DtoTypeNotVoid(src->getType()->nextOf()->toBasetype());
LLType* arrayelemty = voidToI8(DtoType(src->getType()->nextOf()->toBasetype()));
LLValue* sz2 = gIR->ir->CreateMul(DtoConstSize_t(getTypePaddedSize(arrayelemty)), DtoArrayLen(src), "tmp");
copySlice(dstarr, sz1, srcarr, sz2);
@@ -939,7 +934,7 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
Logger::cout() << "to array" << '\n';
LLType* ptrty = DtoArrayType(totype)->getContainedType(1);
LLType* ety = DtoTypeNotVoid(fromtype->nextOf());
LLType* ety = voidToI8(DtoType(fromtype->nextOf()));
if (fromtype->ty == Tsarray) {
LLValue* uval = u->getRVal();

View File

@@ -497,7 +497,7 @@ LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
}
// cast it to the right type
val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
val = DtoBitCast(val, getPtrToType(i1ToI8(DtoType(vd->type))));
if (Logger::enabled())
Logger::cout() << "value: " << *val << '\n';

View File

@@ -172,7 +172,7 @@ void VarDeclaration::codegen(Ir* p)
// this->ir.irGlobal->value!), and in case we also do an initializer
// with a different type later, swap it out and replace any existing
// uses with bitcasts to the previous type.
llvm::GlobalVariable* gvar = createGlobal(DtoType(type), isLLConst,
llvm::GlobalVariable* gvar = createGlobal(i1ToI8(DtoType(type)), isLLConst,
llLinkage, llName, isThreadlocal());
this->ir.irGlobal->value = gvar;
@@ -206,7 +206,7 @@ void VarDeclaration::codegen(Ir* p)
ir.irGlobal->constInit = initVal;
gvar->setInitializer(initVal);
// Also set up the debug info.
// Also set up the edbug info.
DtoDwarfGlobalVariable(gvar, this);
}

View File

@@ -18,18 +18,36 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
static bool checkVarValueType(LLType* t, bool extraDeref)
{
if (extraDeref)
{
llvm::PointerType* pt = llvm::dyn_cast<llvm::PointerType>(t);
if (!pt) return false;
t = pt->getElementType();
}
llvm::PointerType* pt = llvm::dyn_cast<llvm::PointerType>(t);
if (!pt) return false;
// bools should not be stored as i1 any longer.
if (pt->getElementType() == llvm::Type::getInt1Ty(gIR->context()))
return false;
return true;
}
DVarValue::DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue)
: DValue(t), var(vd), val(llvmValue)
{
assert(isaPointer(llvmValue));
assert(!isSpecialRefVar(vd) ||
isaPointer(isaPointer(llvmValue)->getElementType()));
assert(checkVarValueType(llvmValue->getType(), isSpecialRefVar(vd)));
}
DVarValue::DVarValue(Type* t, LLValue* llvmValue)
: DValue(t), var(0), val(llvmValue)
{
assert(isaPointer(llvmValue));
assert(checkVarValueType(llvmValue->getType(), false));
}
LLValue* DVarValue::getLVal()
@@ -50,7 +68,17 @@ LLValue* DVarValue::getRVal()
if (DtoIsPassedByRef(type->toBasetype()))
return storage;
return DtoLoad(storage);
llvm::Value* rawValue = DtoLoad(storage);
if (type->toBasetype()->ty == Tbool)
{
assert(rawValue->getType() == llvm::Type::getInt8Ty(gIR->context()));
return gIR->ir->CreateTrunc(rawValue,
llvm::Type::getInt1Ty(gIR->context()));
}
return rawValue;
}
LLValue* DVarValue::getRefStorage()

View File

@@ -1059,7 +1059,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
if (lazy)
argt = irparam->value->getType();
else
argt = DtoType(vd->type);
argt = i1ToI8(DtoType(vd->type));
LLValue* mem = DtoRawAlloca(argt, 0, vd->ident->toChars());
// let the abi transform the argument back first

View File

@@ -49,7 +49,7 @@ LLValue* DtoNew(Type* newtype)
// call runtime allocator
LLValue* mem = gIR->CreateCallOrInvoke(fn, ti, ".gc_mem").getInstruction();
// cast
return DtoBitCast(mem, getPtrToType(DtoType(newtype)), ".gc_mem");
return DtoBitCast(mem, getPtrToType(i1ToI8(DtoType(newtype))), ".gc_mem");
}
void DtoDeleteMemory(LLValue* ptr)
@@ -113,7 +113,7 @@ void DtoDeleteArray(DValue* arr)
llvm::AllocaInst* DtoAlloca(Type* type, const char* name)
{
LLType* lltype = DtoType(type);
LLType* lltype = i1ToI8(DtoType(type));
llvm::AllocaInst* ai = new llvm::AllocaInst(lltype, name, gIR->topallocapoint());
ai->setAlignment(type->alignsize());
return ai;
@@ -375,7 +375,10 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op, bool canSkipPostblit)
assert(t->ty != Tvoid && "Cannot assign values of type void.");
if (t->ty == Tstruct) {
if (t->ty == Tbool) {
DtoStoreZextI8(rhs->getRVal(), lhs->getLVal());
}
else if (t->ty == Tstruct) {
llvm::Value* src = rhs->getRVal();
llvm::Value* dst = lhs->getLVal();
@@ -623,7 +626,10 @@ DValue* DtoCastPtr(Loc& loc, DValue* val, Type* to)
if (totype->ty == Tpointer || totype->ty == Tclass) {
LLValue* src = val->getRVal();
if (Logger::enabled())
Logger::cout() << "src: " << *src << "to type: " << *tolltype << '\n';
{
Logger::cout() << "src: " << *src << '\n';
Logger::cout() << "to type: " << *tolltype << '\n';
}
rval = DtoBitCast(src, tolltype);
}
else if (totype->ty == Tbool) {
@@ -1056,9 +1062,9 @@ void DtoVarDeclaration(VarDeclaration* vd)
}
Type* type = isSpecialRefVar(vd) ? vd->type->pointerTo() : vd->type;
LLType* lltype = DtoType(type);
llvm::Value* allocainst;
LLType* lltype = DtoType(type);
if(gDataLayout->getTypeSizeInBits(lltype) == 0)
allocainst = llvm::ConstantPointerNull::get(getPtrToType(lltype));
else
@@ -1298,7 +1304,7 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
else if (init->isVoidInitializer())
{
Logger::println("const void initializer");
LLType* ty = DtoTypeNotVoid(type);
LLType* ty = voidToI8(DtoType(type));
_init = LLConstant::getNullValue(ty);
}
else {
@@ -1366,14 +1372,14 @@ LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp)
Type* expBase = stripModifiers(exp->type->toBasetype())->merge();
Type* targetBase = stripModifiers(targetType->toBasetype())->merge();
if (expBase->equals(targetBase))
if (expBase->equals(targetBase) && targetBase->ty != Tbool)
{
Logger::println("Matching D types, nothing left to do.");
return val;
}
llvm::Type* llType = val->getType();
llvm::Type* targetLLType = DtoType(targetBase);
llvm::Type* targetLLType = i1ToI8(DtoType(targetBase));
if (llType == targetLLType)
{
Logger::println("Matching LLVM types, ignoring frontend glitch.");

View File

@@ -372,14 +372,14 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) {
if (lazy)
types.push_back(irparam->value->getType()->getContainedType(0));
else
types.push_back(DtoType(vd->type));
types.push_back(i1ToI8(DtoType(vd->type)));
} else {
types.push_back(irparam->value->getType());
}
} else if (isSpecialRefVar(vd)) {
types.push_back(DtoType(vd->type->pointerTo()));
} else {
types.push_back(DtoType(vd->type));
types.push_back(i1ToI8(DtoType(vd->type)));
}
if (Logger::enabled()) {
Logger::cout() << "Nested var '" << vd->toChars() <<

View File

@@ -138,7 +138,7 @@ LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
}
// cast it to the right type
val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
val = DtoBitCast(val, getPtrToType(i1ToI8(DtoType(vd->type))));
if (Logger::enabled())
Logger::cout() << "value: " << *val << '\n';

View File

@@ -246,7 +246,7 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args,
{
Expression* argexp = static_cast<Expression*>(arguments->data[i]);
LLValue* argdst = DtoGEPi(mem,0,k);
argdst = DtoBitCast(argdst, getPtrToType(DtoType(argexp->type)));
argdst = DtoBitCast(argdst, getPtrToType(i1ToI8(DtoType(argexp->type))));
DtoVariadicArgument(argexp, argdst);
}

View File

@@ -215,7 +215,7 @@ DValue* VarExp::toElem(IRState* p)
if (isGlobal)
{
llvm::Type* expectedType = DtoType(type->pointerTo());
llvm::Type* expectedType = llvm::PointerType::getUnqual(i1ToI8(DtoType(type)));
// The type of globals is determined by their initializer, so
// we might need to cast. Make sure that the type sizes fit -
// '==' instead of '<=' should probably work as well.
@@ -438,7 +438,7 @@ DValue* StringExp::toElem(IRState* p)
Type* dtype = type->toBasetype();
Type* cty = dtype->nextOf()->toBasetype();
LLType* ct = DtoTypeNotVoid(cty);
LLType* ct = voidToI8(DtoType(cty));
//printf("ct = %s\n", type->nextOf()->toChars());
LLArrayType* at = LLArrayType::get(ct,len+1);
@@ -496,7 +496,7 @@ LLConstant* StringExp::toConstElem(IRState* p)
bool nullterm = (t->ty != Tsarray);
size_t endlen = nullterm ? len+1 : len;
LLType* ct = DtoTypeNotVoid(cty);
LLType* ct = voidToI8(DtoType(cty));
LLArrayType* at = LLArrayType::get(ct,endlen);
LLConstant* _init;
@@ -2496,7 +2496,7 @@ DValue* CondExp::toElem(IRState* p)
LLValue* resval = DtoAlloca(dtype,"condtmp");
dvv = new DVarValue(type, resval);
} else {
dvv = new DConstValue(type, getNullValue(DtoTypeNotVoid(dtype)));
dvv = new DConstValue(type, getNullValue(voidToI8(DtoType(dtype))));
}
llvm::BasicBlock* oldend = p->scopeend();
@@ -2726,7 +2726,7 @@ DValue* ArrayLiteralExp::toElem(IRState* p)
Logger::cout() << (dyn?"dynamic":"static") << " array literal with length " << len << " of D type: '" << arrayType->toChars() << "' has llvm type: '" << *llType << "'\n";
// llvm storage type
LLType* llElemType = DtoTypeNotVoid(elemType);
LLType* llElemType = voidToI8(DtoType(elemType));
LLType* llStoType = LLArrayType::get(llElemType, len);
if (Logger::enabled())
Logger::cout() << "llvm storage type: '" << *llStoType << "'\n";
@@ -2785,7 +2785,7 @@ LLConstant* ArrayLiteralExp::toConstElem(IRState* p)
Type* elemt = bt->nextOf();
// build llvm array type
LLArrayType* arrtype = LLArrayType::get(DtoTypeNotVoid(elemt), elements->dim);
LLArrayType* arrtype = LLArrayType::get(i1ToI8(voidToI8(DtoType(elemt))), elements->dim);
// dynamic arrays can occur here as well ...
bool dyn = (bt->ty != Tsarray);
@@ -3190,7 +3190,7 @@ DValue* TupleExp::toElem(IRState *p)
for (size_t i = 0; i < exps->dim; i++)
{
Expression *el = static_cast<Expression *>(exps->data[i]);
types.push_back(DtoTypeNotVoid(el->type));
types.push_back(voidToI8(DtoType(el->type)));
}
LLValue *val = DtoRawAlloca(LLStructType::get(gIR->context(), types),0, "tuple");
for (size_t i = 0; i < exps->dim; i++)

View File

@@ -246,12 +246,20 @@ LLType* DtoStructTypeFromArguments(Arguments* arguments)
//////////////////////////////////////////////////////////////////////////////////////////
LLType* DtoTypeNotVoid(Type* t)
LLType* voidToI8(LLType* t)
{
LLType* lt = DtoType(t);
if (lt == LLType::getVoidTy(gIR->context()))
if (t == LLType::getVoidTy(gIR->context()))
return LLType::getInt8Ty(gIR->context());
return lt;
return t;
}
//////////////////////////////////////////////////////////////////////////////////////////
LLType* i1ToI8(LLType* t)
{
if (t == LLType::getInt1Ty(gIR->context()))
return LLType::getInt8Ty(gIR->context());
return t;
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -717,15 +725,27 @@ LLValue* DtoAlignedLoad(LLValue* src, const char* name)
void DtoStore(LLValue* src, LLValue* dst)
{
// if (Logger::enabled())
// Logger::cout() << "storing " << *src << " into " << *dst << '\n';
assert(src->getType() != llvm::Type::getInt1Ty(gIR->context()) &&
"Should store bools as i8 instead of i1.");
gIR->ir->CreateStore(src,dst);
//st->setVolatile(gIR->func()->inVolatile);
}
void DtoStoreZextI8(LLValue* src, LLValue* dst)
{
if (src->getType() == llvm::Type::getInt1Ty(gIR->context()))
{
llvm::Type* i8 = llvm::Type::getInt8Ty(gIR->context());
assert(dst->getType()->getContainedType(0) == i8);
src = gIR->ir->CreateZExt(src, i8);
}
gIR->ir->CreateStore(src, dst);
}
// Like DtoStore, but the pointer is guaranteed to be aligned appropriately for the type.
void DtoAlignedStore(LLValue* src, LLValue* dst)
{
assert(src->getType() != llvm::Type::getInt1Ty(gIR->context()) &&
"Should store bools as i8 instead of i1.");
llvm::StoreInst* st = gIR->ir->CreateStore(src,dst);
st->setAlignment(getABITypeAlign(src->getType()));
}

View File

@@ -25,9 +25,8 @@
// D->LLVM type handling stuff
LLType* DtoType(Type* t);
// same as DtoType except it converts 'void' to 'i8'
LLType* DtoTypeNotVoid(Type* t);
LLType* voidToI8(LLType* t);
LLType* i1ToI8(LLType* t);
// returns true is the type must be passed by pointer
bool DtoIsPassedByRef(Type* type);
@@ -82,6 +81,7 @@ LLConstant* DtoConstBool(bool);
LLValue* DtoLoad(LLValue* src, const char* name=0);
LLValue* DtoAlignedLoad(LLValue* src, const char* name=0);
void DtoStore(LLValue* src, LLValue* dst);
void DtoStoreZextI8(LLValue* src, LLValue* dst);
void DtoAlignedStore(LLValue* src, LLValue* dst);
LLValue* DtoBitCast(LLValue* v, LLType* t, const char* name=0);
LLConstant* DtoBitCast(LLConstant* v, LLType* t);

View File

@@ -96,5 +96,5 @@ void IrFuncTy::getParam(Type* dty, size_t idx, DValue* val, llvm::Value* lval)
return;
}
DtoStore(val->getRVal(), lval);
DtoStoreZextI8(val->getRVal(), lval);
}

View File

@@ -188,9 +188,9 @@ IrTypePointer* IrTypePointer::get(Type* dt)
}
}
elemType = DtoTypeNotVoid(dt->nextOf());
elemType = i1ToI8(voidToI8(DtoType(dt->nextOf())));
// DtoTypeNotVoid could have already created the same type, e.g. for
// DtoType could have already created the same type, e.g. for
// dt == Node* in struct Node { Node* n; }.
if (dt->irtype)
return dt->irtype->isPointer();
@@ -226,9 +226,7 @@ llvm::Type * IrTypeSArray::sarray2llvm(Type * t)
assert(t->ty == Tsarray && "not static array type");
TypeSArray* tsa = static_cast<TypeSArray*>(t);
uint64_t dim = static_cast<uint64_t>(tsa->dim->toUInteger());
LLType* elemType = DtoType(t->nextOf());
if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext()))
elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());
LLType* elemType = i1ToI8(voidToI8(DtoType(t->nextOf())));
return llvm::ArrayType::get(elemType, dim);
}
@@ -248,7 +246,7 @@ IrTypeArray* IrTypeArray::get(Type* dt)
assert(!dt->irtype);
assert(dt->ty == Tarray && "not dynamic array type");
LLType* elemType = DtoTypeNotVoid(dt->nextOf());
LLType* elemType = i1ToI8(voidToI8(DtoType(dt->nextOf())));
// Could have already built the type as part of a struct forward reference,
// just as for pointers.
@@ -289,9 +287,7 @@ llvm::Type* IrTypeVector::vector2llvm(Type* dt)
assert(tv->basetype->ty == Tsarray);
TypeSArray* tsa = static_cast<TypeSArray*>(tv->basetype);
uint64_t dim = static_cast<uint64_t>(tsa->dim->toUInteger());
LLType* elemType = DtoType(tsa->next);
if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext()))
elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());
LLType* elemType = voidToI8(DtoType(tsa->next));
return llvm::VectorType::get(elemType, dim);
}

View File

@@ -169,7 +169,7 @@ void IrTypeClass::addBaseClassData(
}
// add default type
defaultTypes.push_back(DtoType(vd->type));
defaultTypes.push_back(DtoType(vd->type)); // @@@ i1ToI8?!
// advance offset to right past this field
offset = vd->offset + vd->type->size();