mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-19 06:13:14 +01:00
Merge branch 'merge-2.064' into merge-2.065
This commit is contained in:
@@ -236,9 +236,15 @@ public:
|
||||
virtual elem *toElem(IRState *irs);
|
||||
elem *toElemDtor(IRState *irs);
|
||||
#if IN_LLVM
|
||||
/// Emits an LLVM constant corresponding to the expression.
|
||||
///
|
||||
/// Due to the current implementation of AssocArrayLiteralExp::toElem,the
|
||||
/// implementations have to be able to handle being called on expressions
|
||||
/// that are not actually constant. In such a case, an LLVM undef of the
|
||||
/// expected type should be returned (_not_ null).
|
||||
virtual llvm::Constant *toConstElem(IRState *irs);
|
||||
virtual void cacheLvalue(IRState* irs);
|
||||
|
||||
virtual void cacheLvalue(IRState* irs);
|
||||
llvm::Value* cachedLvalue;
|
||||
|
||||
virtual AssignExp* isAssignExp() { return NULL; }
|
||||
|
||||
@@ -121,9 +121,6 @@ LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// helper function that adds zero bytes to a vector of constants
|
||||
extern size_t add_zeros(std::vector<LLConstant*>& values, size_t diff);
|
||||
|
||||
/// Return the type returned by DtoUnpaddedStruct called on a value of the
|
||||
/// specified type.
|
||||
/// Union types will get expanded into a struct, with a type for each member.
|
||||
|
||||
69
gen/toir.cpp
69
gen/toir.cpp
@@ -652,8 +652,8 @@ LLConstant* AddExp::toConstElem(IRState* p)
|
||||
}
|
||||
|
||||
error("expression '%s' is not a constant", toChars());
|
||||
fatal();
|
||||
return NULL;
|
||||
if (!global.gag) fatal();
|
||||
return llvm::UndefValue::get(DtoType(type));
|
||||
}
|
||||
|
||||
/// Tries to remove a MulExp by a constant value of baseSize from e. Returns
|
||||
@@ -766,8 +766,8 @@ LLConstant* MinExp::toConstElem(IRState* p)
|
||||
}
|
||||
|
||||
error("expression '%s' is not a constant", toChars());
|
||||
fatal();
|
||||
return NULL;
|
||||
if (!global.gag) fatal();
|
||||
return llvm::UndefValue::get(DtoType(type));
|
||||
}
|
||||
|
||||
DValue* MinExp::toElem(IRState* p)
|
||||
@@ -1231,7 +1231,7 @@ Lerr:
|
||||
error("cannot cast %s to %s at compile time", e1->type->toChars(), type->toChars());
|
||||
if (!global.gag)
|
||||
fatal();
|
||||
return NULL;
|
||||
return llvm::UndefValue::get(DtoType(type));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1290,11 +1290,7 @@ llvm::Constant* SymOffExp::toConstElem(IRState* p)
|
||||
IF_LOG Logger::println("SymOffExp::toConstElem: %s @ %s", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// We might get null here due to the hackish implementation of
|
||||
// AssocArrayLiteralExp::toElem.
|
||||
llvm::Constant* base = DtoConstSymbolAddress(loc, var);
|
||||
if (!base) return 0;
|
||||
|
||||
llvm::Constant* result;
|
||||
if (offset == 0)
|
||||
{
|
||||
@@ -1462,7 +1458,8 @@ LLConstant* AddrExp::toConstElem(IRState* p)
|
||||
else if (e1->op == TOKslice)
|
||||
{
|
||||
error("non-constant expression '%s'", toChars());
|
||||
fatal();
|
||||
if (!global.gag) fatal();
|
||||
return llvm::UndefValue::get(DtoType(type));
|
||||
}
|
||||
// not yet supported
|
||||
else
|
||||
@@ -2872,7 +2869,8 @@ LLConstant* FuncExp::toConstElem(IRState* p)
|
||||
{
|
||||
assert(fd->tok == TOKdelegate || fd->tok == TOKreserved);
|
||||
error("delegate literals as constant expressions are not yet allowed");
|
||||
return 0;
|
||||
if (!global.gag) fatal();
|
||||
return llvm::UndefValue::get(DtoType(type));
|
||||
}
|
||||
|
||||
// We need to actually codegen the function here, as literals are not added
|
||||
@@ -3302,6 +3300,36 @@ DValue* RemoveExp::toElem(IRState* p)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Constructs an array initializer constant with the given constants as its
|
||||
/// elements. If the element types differ (unions, …), an anonymous struct
|
||||
/// literal is emitted (as for array constant initializers).
|
||||
static llvm::Constant* arrayConst(std::vector<llvm::Constant*>& vals,
|
||||
Type* nominalElemType)
|
||||
{
|
||||
if (vals.size() == 0)
|
||||
{
|
||||
llvm::ArrayType* type = llvm::ArrayType::get(DtoType(nominalElemType), 0);
|
||||
return llvm::ConstantArray::get(type, vals);
|
||||
}
|
||||
|
||||
llvm::Type* elementType = NULL;
|
||||
bool differentTypes = false;
|
||||
for (std::vector<llvm::Constant*>::iterator i = vals.begin(), end = vals.end();
|
||||
i != end; ++i)
|
||||
{
|
||||
if (!elementType)
|
||||
elementType = (*i)->getType();
|
||||
else
|
||||
differentTypes |= (elementType != (*i)->getType());
|
||||
}
|
||||
|
||||
if (differentTypes)
|
||||
return llvm::ConstantStruct::getAnon(vals, true);
|
||||
|
||||
llvm::ArrayType *t = llvm::ArrayType::get(elementType, vals.size());
|
||||
return llvm::ConstantArray::get(t, vals);
|
||||
}
|
||||
|
||||
DValue* AssocArrayLiteralExp::toElem(IRState* p)
|
||||
{
|
||||
Logger::print("AssocArrayLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars());
|
||||
@@ -3356,16 +3384,16 @@ DValue* AssocArrayLiteralExp::toElem(IRState* p)
|
||||
|
||||
LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
|
||||
|
||||
LLArrayType* arrtype = LLArrayType::get(DtoType(indexType), keys->dim);
|
||||
LLConstant* initval = LLConstantArray::get(arrtype, keysInits);
|
||||
LLConstant* globalstore = new LLGlobalVariable(*gIR->module, arrtype, false, LLGlobalValue::InternalLinkage, initval, ".aaKeysStorage");
|
||||
LLConstant* initval = arrayConst(keysInits, indexType);
|
||||
LLConstant* globalstore = new LLGlobalVariable(*gIR->module, initval->getType(),
|
||||
false, LLGlobalValue::InternalLinkage, initval, ".aaKeysStorage");
|
||||
LLConstant* slice = llvm::ConstantExpr::getGetElementPtr(globalstore, idxs, true);
|
||||
slice = DtoConstSlice(DtoConstSize_t(keys->dim), slice);
|
||||
LLValue* keysArray = DtoAggrPaint(slice, funcTy->getParamType(1));
|
||||
|
||||
arrtype = LLArrayType::get(DtoType(vtype), values->dim);
|
||||
initval = LLConstantArray::get(arrtype, valuesInits);
|
||||
globalstore = new LLGlobalVariable(*gIR->module, arrtype, false, LLGlobalValue::InternalLinkage, initval, ".aaValuesStorage");
|
||||
initval = arrayConst(valuesInits, vtype);
|
||||
globalstore = new LLGlobalVariable(*gIR->module, initval->getType(),
|
||||
false, LLGlobalValue::InternalLinkage, initval, ".aaValuesStorage");
|
||||
slice = llvm::ConstantExpr::getGetElementPtr(globalstore, idxs, true);
|
||||
slice = DtoConstSlice(DtoConstSize_t(keys->dim), slice);
|
||||
LLValue* valuesArray = DtoAggrPaint(slice, funcTy->getParamType(2));
|
||||
@@ -3527,5 +3555,10 @@ llvm::Constant* Expression::toConstElem(IRState * p)
|
||||
error("expression '%s' is not a constant", toChars());
|
||||
if (!global.gag)
|
||||
fatal();
|
||||
return NULL;
|
||||
|
||||
// Do not return null here, as AssocArrayLiteralExp::toElem determines
|
||||
// whether it can allocate the needed arrays statically by just invoking
|
||||
// toConstElem on its key/value expressions, and handling the null value
|
||||
// consequently would require error-prone adaptions in all other code.
|
||||
return llvm::UndefValue::get(DtoType(type));
|
||||
}
|
||||
|
||||
@@ -382,6 +382,10 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
|
||||
llvm_unreachable("not global/function");
|
||||
}
|
||||
|
||||
// The logic here should be sound in theory, but as long as the frontend
|
||||
// keeps inserting templates into wrong modules, this yields to linking
|
||||
// errors (see e.g. GitHub issue #558).
|
||||
#if 0
|
||||
// Check if sym is a nested function and we can declare it as internal.
|
||||
//
|
||||
// Nested naked functions and the implicitly generated __require/__ensure
|
||||
@@ -427,7 +431,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
// default to external linkage
|
||||
return llvm::GlobalValue::ExternalLinkage;
|
||||
}
|
||||
|
||||
@@ -87,34 +87,50 @@ llvm::Constant * IrAggr::getDefaultInit()
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool isAligned(llvm::Type* type, size_t offset) {
|
||||
return gDataLayout->getABITypeAlignment(type) % offset == 0;
|
||||
}
|
||||
|
||||
// helper function that adds zero bytes to a vector of constants
|
||||
size_t add_zeros(llvm::SmallVectorImpl<llvm::Constant*>& constants, size_t diff)
|
||||
size_t add_zeros(llvm::SmallVectorImpl<llvm::Constant*>& constants,
|
||||
size_t startOffset, size_t endOffset)
|
||||
{
|
||||
size_t n = constants.size();
|
||||
while (diff)
|
||||
size_t const oldLength = constants.size();
|
||||
|
||||
llvm::Type* const eightByte = llvm::Type::getInt64Ty(gIR->context());
|
||||
llvm::Type* const fourByte = llvm::Type::getInt32Ty(gIR->context());
|
||||
llvm::Type* const twoByte = llvm::Type::getInt16Ty(gIR->context());
|
||||
|
||||
assert(startOffset <= endOffset);
|
||||
size_t paddingLeft = endOffset - startOffset;
|
||||
while (paddingLeft)
|
||||
{
|
||||
if (global.params.is64bit && diff % 8 == 0)
|
||||
if (global.params.is64bit && paddingLeft >= 8 && isAligned(eightByte, startOffset))
|
||||
{
|
||||
constants.push_back(LLConstant::getNullValue(llvm::Type::getInt64Ty(gIR->context())));
|
||||
diff -= 8;
|
||||
constants.push_back(llvm::Constant::getNullValue(eightByte));
|
||||
startOffset += 8;
|
||||
}
|
||||
else if (diff % 4 == 0)
|
||||
else if (paddingLeft >= 4 && isAligned(fourByte, startOffset))
|
||||
{
|
||||
constants.push_back(LLConstant::getNullValue(llvm::Type::getInt32Ty(gIR->context())));
|
||||
diff -= 4;
|
||||
constants.push_back(llvm::Constant::getNullValue(fourByte));
|
||||
startOffset += 4;
|
||||
}
|
||||
else if (diff % 2 == 0)
|
||||
else if (paddingLeft >= 2 && isAligned(twoByte, startOffset))
|
||||
{
|
||||
constants.push_back(LLConstant::getNullValue(llvm::Type::getInt16Ty(gIR->context())));
|
||||
diff -= 2;
|
||||
constants.push_back(llvm::Constant::getNullValue(twoByte));
|
||||
startOffset += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
constants.push_back(LLConstant::getNullValue(llvm::Type::getInt8Ty(gIR->context())));
|
||||
diff -= 1;
|
||||
constants.push_back(llvm::Constant::getNullValue(
|
||||
llvm::Type::getInt8Ty(gIR->context())));
|
||||
startOffset += 1;
|
||||
}
|
||||
|
||||
paddingLeft = endOffset - startOffset;
|
||||
}
|
||||
return constants.size() - n;
|
||||
|
||||
return constants.size() - oldLength;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -201,9 +217,7 @@ llvm::Constant* IrAggr::createInitializerConstant(
|
||||
const size_t structsize = type->size();
|
||||
if (offset < structsize)
|
||||
{
|
||||
size_t diff = structsize - offset;
|
||||
IF_LOG Logger::println("adding %zu bytes zero padding", diff);
|
||||
add_zeros(constants, diff);
|
||||
add_zeros(constants, offset, structsize);
|
||||
}
|
||||
|
||||
// get initializer type
|
||||
@@ -324,9 +338,7 @@ void IrAggr::addFieldInitializers(
|
||||
// insert explicit padding?
|
||||
if (alignedoffset < vd->offset)
|
||||
{
|
||||
size_t diff = vd->offset - alignedoffset;
|
||||
IF_LOG Logger::println("adding %zu bytes zero padding", diff);
|
||||
add_zeros(constants, diff);
|
||||
add_zeros(constants, alignedoffset, vd->offset);
|
||||
}
|
||||
|
||||
IF_LOG Logger::println("adding field %s", vd->toChars());
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init);
|
||||
extern size_t add_zeros(std::vector<llvm::Constant*>& constants, size_t diff);
|
||||
|
||||
extern LLConstant* DtoDefineClassInfo(ClassDeclaration* cd);
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ struct IrFuncTy
|
||||
// Copy constructor and operator= seems to be required for MSC
|
||||
|
||||
IrFuncTy(const IrFuncTy& rhs)
|
||||
: funcType(ths.funcType),
|
||||
: funcType(rhs.funcType),
|
||||
ret(rhs.ret),
|
||||
args(IrFuncTy::ArgList(rhs.args)),
|
||||
arg_sret(rhs.arg_sret),
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern size_t add_zeros(std::vector<llvm::Type*>& defaultTypes, size_t diff);
|
||||
extern size_t add_zeros(std::vector<llvm::Type*>& defaultTypes,
|
||||
size_t startOffset, size_t endOffset);
|
||||
extern bool var_offset_sort_cb(const VarDeclaration* v1, const VarDeclaration* v2);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -167,7 +168,7 @@ void IrTypeClass::addBaseClassData(
|
||||
// insert explicit padding?
|
||||
if (alignedoffset < vd->offset)
|
||||
{
|
||||
field_index += add_zeros(defaultTypes, vd->offset - alignedoffset);
|
||||
field_index += add_zeros(defaultTypes, alignedoffset, vd->offset);
|
||||
}
|
||||
|
||||
// add default type
|
||||
@@ -220,7 +221,7 @@ void IrTypeClass::addBaseClassData(
|
||||
// tail padding?
|
||||
if (offset < base->structsize)
|
||||
{
|
||||
field_index += add_zeros(defaultTypes, base->structsize - offset);
|
||||
field_index += add_zeros(defaultTypes, offset, base->structsize);
|
||||
offset = base->structsize;
|
||||
}
|
||||
#endif
|
||||
@@ -268,7 +269,7 @@ IrTypeClass* IrTypeClass::get(ClassDeclaration* cd)
|
||||
// tail padding?
|
||||
if (offset < cd->structsize)
|
||||
{
|
||||
field_index += add_zeros(defaultTypes, cd->structsize - offset);
|
||||
field_index += add_zeros(defaultTypes, offset, cd->structsize);
|
||||
offset = cd->structsize;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -38,35 +38,51 @@ IrTypeStruct::IrTypeStruct(StructDeclaration * sd)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t add_zeros(std::vector<llvm::Type*>& defaultTypes, size_t diff)
|
||||
static bool isAligned(llvm::Type* type, size_t offset) {
|
||||
return gDataLayout->getABITypeAlignment(type) % offset == 0;
|
||||
}
|
||||
|
||||
size_t add_zeros(std::vector<llvm::Type*>& defaultTypes,
|
||||
size_t startOffset, size_t endOffset)
|
||||
{
|
||||
size_t n = defaultTypes.size();
|
||||
while (diff)
|
||||
size_t const oldLength = defaultTypes.size();
|
||||
|
||||
llvm::Type* const eightByte = llvm::Type::getInt64Ty(gIR->context());
|
||||
llvm::Type* const fourByte = llvm::Type::getInt32Ty(gIR->context());
|
||||
llvm::Type* const twoByte = llvm::Type::getInt16Ty(gIR->context());
|
||||
|
||||
assert(startOffset <= endOffset);
|
||||
size_t paddingLeft = endOffset - startOffset;
|
||||
while (paddingLeft)
|
||||
{
|
||||
if (global.params.is64bit && diff % 8 == 0)
|
||||
if (global.params.is64bit && paddingLeft >= 8 && isAligned(eightByte, startOffset))
|
||||
{
|
||||
defaultTypes.push_back(llvm::Type::getInt64Ty(gIR->context()));
|
||||
diff -= 8;
|
||||
defaultTypes.push_back(eightByte);
|
||||
startOffset += 8;
|
||||
}
|
||||
else if (diff % 4 == 0)
|
||||
else if (paddingLeft >= 4 && isAligned(fourByte, startOffset))
|
||||
{
|
||||
defaultTypes.push_back(llvm::Type::getInt32Ty(gIR->context()));
|
||||
diff -= 4;
|
||||
defaultTypes.push_back(fourByte);
|
||||
startOffset += 4;
|
||||
}
|
||||
else if (diff % 2 == 0)
|
||||
else if (paddingLeft >= 2 && isAligned(twoByte, startOffset))
|
||||
{
|
||||
defaultTypes.push_back(llvm::Type::getInt16Ty(gIR->context()));
|
||||
diff -= 2;
|
||||
defaultTypes.push_back(twoByte);
|
||||
startOffset += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultTypes.push_back(llvm::Type::getInt8Ty(gIR->context()));
|
||||
diff -= 1;
|
||||
startOffset += 1;
|
||||
}
|
||||
|
||||
paddingLeft = endOffset - startOffset;
|
||||
}
|
||||
return defaultTypes.size() - n;
|
||||
|
||||
return defaultTypes.size() - oldLength;
|
||||
}
|
||||
|
||||
|
||||
bool var_offset_sort_cb(const VarDeclaration* v1, const VarDeclaration* v2)
|
||||
{
|
||||
if (v1 && v2)
|
||||
@@ -209,7 +225,7 @@ IrTypeStruct* IrTypeStruct::get(StructDeclaration* sd)
|
||||
// insert explicit padding?
|
||||
if (alignedoffset < vd->offset)
|
||||
{
|
||||
field_index += add_zeros(defaultTypes, vd->offset - alignedoffset);
|
||||
field_index += add_zeros(defaultTypes, alignedoffset, vd->offset);
|
||||
}
|
||||
|
||||
// add default type
|
||||
@@ -225,7 +241,7 @@ IrTypeStruct* IrTypeStruct::get(StructDeclaration* sd)
|
||||
// tail padding?
|
||||
if (offset < sd->structsize)
|
||||
{
|
||||
add_zeros(defaultTypes, sd->structsize - offset);
|
||||
add_zeros(defaultTypes, offset, sd->structsize);
|
||||
}
|
||||
|
||||
// set struct body
|
||||
|
||||
Submodule tests/d2/dmd-testsuite updated: 2834b34907...fa4a570db2
Reference in New Issue
Block a user