diff --git a/ctx.cpp b/ctx.cpp index d13ba852..1f85df8e 100644 --- a/ctx.cpp +++ b/ctx.cpp @@ -1516,29 +1516,18 @@ FunctionEmitContext::maskedStore(llvm::Value *rvalue, llvm::Value *lvalue, assert(llvm::isa(lvalue->getType())); - const StructType *structType = dynamic_cast(rvalueType); - if (structType != NULL) { - // Assigning a structure - for (int i = 0; i < structType->GetElementCount(); ++i) { + const CollectionType *collectionType = + dynamic_cast(rvalueType); + if (collectionType != NULL) { + // Assigning a structure / array / vector. Handle each element + // individually with what turns into a recursive call to + // makedStore() + for (int i = 0; i < collectionType->GetElementCount(); ++i) { llvm::Value *eltValue = ExtractInst(rvalue, i, "rvalue_member"); llvm::Value *eltLValue = GetElementPtrInst(lvalue, 0, i, "struct_lvalue_ptr"); StoreInst(eltValue, eltLValue, storeMask, - structType->GetElementType(i)); - } - return; - } - - const SequentialType *sequentialType = - dynamic_cast(rvalueType); - if (sequentialType != NULL) { - // Assigning arrays and vectors. Handle each element individually - // with what turns into a recursive call to makedStore() - for (int i = 0; i < sequentialType->GetElementCount(); ++i) { - llvm::Value *eltLValue = GetElementPtrInst(lvalue, 0, i, "lval_i_ptr"); - llvm::Value *eltValue = ExtractInst(rvalue, i, "array_i_val"); - StoreInst(eltValue, eltLValue, storeMask, - sequentialType->GetElementType()); + collectionType->GetElementType(i)); } return; } diff --git a/expr.cpp b/expr.cpp index dc2669df..269fcee5 100644 --- a/expr.cpp +++ b/expr.cpp @@ -2489,71 +2489,57 @@ ExprList::TypeCheck() { llvm::Constant * ExprList::GetConstant(const Type *type) const { - const StructType *structType = dynamic_cast(type); - const SequentialType *sequentialType = - dynamic_cast(type); + const CollectionType *collectionType = + dynamic_cast(type); + if (collectionType == NULL) + return NULL; - if (structType != NULL) { - // We can potentially return an llvm::ConstantStruct if we have the - // same number of elements in the ExprList as the struct has - // members (and the various elements line up with the shape of the - // corresponding struct elements). - if ((int)exprs.size() != structType->GetElementCount()) { - Error(pos, "Initializer list for struct \"%s\" must have %d " - "elements (has %d).", structType->GetString().c_str(), - (int)exprs.size(), structType->GetElementCount()); + std::string name = NULL; + if (dynamic_cast(type) != NULL) + name = "struct"; + else if (dynamic_cast(type) != NULL) + name = "array"; + else if (dynamic_cast(type) != NULL) + name = "vector"; + else + FATAL("Unexpected CollectionType in ExprList::GetConstant()"); + + if ((int)exprs.size() != collectionType->GetElementCount()) { + Error(pos, "Initializer list for %s \"%s\" must have %d elements " + "(has %d).", name.c_str(), collectionType->GetString().c_str(), + collectionType->GetElementCount(), (int)exprs.size()); + return NULL; + } + + std::vector cv; + for (unsigned int i = 0; i < exprs.size(); ++i) { + if (exprs[i] == NULL) return NULL; - } - - std::vector cv; - for (unsigned int i = 0; i < exprs.size(); ++i) { - if (exprs[i] == NULL) - return NULL; - const Type *elementType = structType->GetElementType(i); - llvm::Constant *c = exprs[i]->GetConstant(elementType); - if (c == NULL) - // If this list element couldn't convert to the right - // constant type for the corresponding struct member, then - // give up - return NULL; - cv.push_back(c); - } + const Type *elementType = collectionType->GetElementType(i); + llvm::Constant *c = exprs[i]->GetConstant(elementType); + if (c == NULL) + // If this list element couldn't convert to the right constant + // type for the corresponding collection member, then give up. + return NULL; + cv.push_back(c); + } + if (dynamic_cast(type) != NULL) { #if defined(LLVM_2_8) || defined(LLVM_2_9) return llvm::ConstantStruct::get(*g->ctx, cv, false); #else const llvm::StructType *llvmStructType = - llvm::dyn_cast(structType->LLVMType(g->ctx)); + llvm::dyn_cast(collectionType->LLVMType(g->ctx)); assert(llvmStructType != NULL); return llvm::ConstantStruct::get(llvmStructType, cv); #endif } - else if (sequentialType) { - // Similarly, if we have an array or vector type, we may be able to - // return the corresponding llvm constant value. - if ((int)exprs.size() != sequentialType->GetElementCount()) { - bool isArray = (dynamic_cast(type) != NULL); - Error(pos, "Initializer list for %s \"%s\" must have %d elements (has %d).", - isArray ? "array" : "vector", sequentialType->GetString().c_str(), - (int)exprs.size(), sequentialType->GetElementCount()); - return NULL; - } - - std::vector cv; - for (unsigned int i = 0; i < exprs.size(); ++i) { - if (exprs[i] == NULL) - return NULL; - const Type *elementType = sequentialType->GetElementType(); - llvm::Constant *c = exprs[i]->GetConstant(elementType); - if (c == NULL) - return NULL; - cv.push_back(c); - } - + else { const llvm::Type *lt = type->LLVMType(g->ctx); const llvm::ArrayType *lat = llvm::dyn_cast(lt); // FIXME: should the assert below validly fail for uniform vectors - // now? + // now? Need a test case to reproduce it and then to be sure we + // have the right fix; leave the assert until we can hit it... assert(lat != NULL); return llvm::ConstantArray::get(lat, cv); } @@ -3900,25 +3886,13 @@ lUniformValueToVarying(FunctionEmitContext *ctx, llvm::Value *value, const llvm::Type *llvmType = type->GetAsVaryingType()->LLVMType(g->ctx); llvm::Value *retValue = llvm::UndefValue::get(llvmType); - // for structs, just recursively make their elements varying (if - // needed) and populate the return struct - const StructType *structType = dynamic_cast(type); - if (structType != NULL) { - for (int i = 0; i < structType->GetElementCount(); ++i) { - llvm::Value *v = ctx->ExtractInst(value, i, "struct_element"); - v = lUniformValueToVarying(ctx, v, structType->GetElementType(i)); - retValue = ctx->InsertInst(retValue, v, i, "set_struct_element"); - } - return retValue; - } - - // And similarly do the elements of arrays and vectors individually - const SequentialType *sequentialType = - dynamic_cast(type); - if (sequentialType != NULL) { - for (int i = 0; i < sequentialType->GetElementCount(); ++i) { + // for structs/arrays/vectors, just recursively make their elements + // varying (if needed) and populate the return value. + const CollectionType *collectionType = dynamic_cast(type); + if (collectionType != NULL) { + for (int i = 0; i < collectionType->GetElementCount(); ++i) { llvm::Value *v = ctx->ExtractInst(value, i, "get_element"); - v = lUniformValueToVarying(ctx, v, sequentialType->GetElementType()); + v = lUniformValueToVarying(ctx, v, collectionType->GetElementType(i)); retValue = ctx->InsertInst(retValue, v, i, "set_element"); } return retValue;