Stop using dynamic_cast for Types.

We now have a set of template functions CastType<AtomicType>, etc., that in
turn use a new typeId field in each Type instance, allowing them to be inlined
and to be quite efficient.

This improves front-end performance for a particular large program by 28%.
This commit is contained in:
Matt Pharr
2012-05-04 11:12:33 -07:00
parent c756c855ea
commit 944c53bff1
11 changed files with 539 additions and 425 deletions

12
ast.cpp
View File

@@ -356,10 +356,10 @@ lCheckAllOffSafety(ASTNode *node, void *data) {
return false;
const Type *type = fce->func->GetType();
const PointerType *pt = dynamic_cast<const PointerType *>(type);
const PointerType *pt = CastType<PointerType>(type);
if (pt != NULL)
type = pt->GetBaseType();
const FunctionType *ftype = dynamic_cast<const FunctionType *>(type);
const FunctionType *ftype = CastType<FunctionType>(type);
Assert(ftype != NULL);
if (ftype->isSafe == false) {
@@ -405,7 +405,7 @@ lCheckAllOffSafety(ASTNode *node, void *data) {
const Type *type = ie->baseExpr->GetType();
if (type == NULL)
return true;
if (dynamic_cast<const ReferenceType *>(type) != NULL)
if (CastType<ReferenceType>(type) != NULL)
type = type->GetReferenceTarget();
ConstExpr *ce = dynamic_cast<ConstExpr *>(ie->index);
@@ -415,16 +415,14 @@ lCheckAllOffSafety(ASTNode *node, void *data) {
return false;
}
const PointerType *pointerType =
dynamic_cast<const PointerType *>(type);
const PointerType *pointerType = CastType<PointerType>(type);
if (pointerType != NULL) {
// pointer[index] -> can't be sure -> not safe
*okPtr = false;
return false;
}
const SequentialType *seqType =
dynamic_cast<const SequentialType *>(type);
const SequentialType *seqType = CastType<SequentialType>(type);
Assert(seqType != NULL);
int nElements = seqType->GetElementCount();
if (nElements == 0) {

72
ctx.cpp
View File

@@ -1194,7 +1194,7 @@ FunctionEmitContext::CurrentLanesReturned(Expr *expr, bool doCoherenceCheck) {
llvm::Value *retVal = expr->GetValue(this);
if (retVal != NULL) {
if (returnType->IsUniformType() ||
dynamic_cast<const ReferenceType *>(returnType) != NULL)
CastType<ReferenceType>(returnType) != NULL)
StoreInst(retVal, returnValuePtr);
else {
// Use a masked store to store the value of the expression
@@ -2063,10 +2063,10 @@ FunctionEmitContext::GetElementPtrInst(llvm::Value *basePtr, llvm::Value *index,
// Regularize to a standard pointer type for basePtr's type
const PointerType *ptrType;
if (dynamic_cast<const ReferenceType *>(ptrRefType) != NULL)
if (CastType<ReferenceType>(ptrRefType) != NULL)
ptrType = PointerType::GetUniform(ptrRefType->GetReferenceTarget());
else {
ptrType = dynamic_cast<const PointerType *>(ptrRefType);
ptrType = CastType<PointerType>(ptrRefType);
Assert(ptrType != NULL);
}
@@ -2133,10 +2133,10 @@ FunctionEmitContext::GetElementPtrInst(llvm::Value *basePtr, llvm::Value *index0
// Regaularize the pointer type for basePtr
const PointerType *ptrType = NULL;
if (dynamic_cast<const ReferenceType *>(ptrRefType) != NULL)
if (CastType<ReferenceType>(ptrRefType) != NULL)
ptrType = PointerType::GetUniform(ptrRefType->GetReferenceTarget());
else {
ptrType = dynamic_cast<const PointerType *>(ptrRefType);
ptrType = CastType<PointerType>(ptrRefType);
Assert(ptrType != NULL);
}
@@ -2184,7 +2184,7 @@ FunctionEmitContext::GetElementPtrInst(llvm::Value *basePtr, llvm::Value *index0
// Now index into the second dimension with index1. First figure
// out the type of ptr0.
const Type *baseType = ptrType->GetBaseType();
const SequentialType *st = dynamic_cast<const SequentialType *>(baseType);
const SequentialType *st = CastType<SequentialType>(baseType);
Assert(st != NULL);
bool ptr0IsUniform =
@@ -2211,10 +2211,10 @@ FunctionEmitContext::AddElementOffset(llvm::Value *fullBasePtr, int elementNum,
const PointerType *ptrType = NULL;
if (ptrRefType != NULL) {
// Normalize references to uniform pointers
if (dynamic_cast<const ReferenceType *>(ptrRefType) != NULL)
if (CastType<ReferenceType>(ptrRefType) != NULL)
ptrType = PointerType::GetUniform(ptrRefType->GetReferenceTarget());
else
ptrType = dynamic_cast<const PointerType *>(ptrRefType);
ptrType = CastType<PointerType>(ptrRefType);
Assert(ptrType != NULL);
}
@@ -2240,8 +2240,8 @@ FunctionEmitContext::AddElementOffset(llvm::Value *fullBasePtr, int elementNum,
// want it.
if (resultPtrType != NULL) {
Assert(ptrType != NULL);
const CollectionType *ct =
dynamic_cast<const CollectionType *>(ptrType->GetBaseType());
const CollectionType *ct =
CastType<CollectionType>(ptrType->GetBaseType());
Assert(ct != NULL);
*resultPtrType = new PointerType(ct->GetElementType(elementNum),
ptrType->GetVariability(),
@@ -2261,8 +2261,7 @@ FunctionEmitContext::AddElementOffset(llvm::Value *fullBasePtr, int elementNum,
else {
// Otherwise do the math to find the offset and add it to the given
// varying pointers
const StructType *st =
dynamic_cast<const StructType *>(ptrType->GetBaseType());
const StructType *st = CastType<StructType>(ptrType->GetBaseType());
llvm::Value *offset = NULL;
if (st != NULL)
// If the pointer is to a structure, Target::StructOffset() gives
@@ -2273,8 +2272,8 @@ FunctionEmitContext::AddElementOffset(llvm::Value *fullBasePtr, int elementNum,
// Otherwise we should have a vector or array here and the offset
// is given by the element number times the size of the element
// type of the vector.
const SequentialType *st =
dynamic_cast<const SequentialType *>(ptrType->GetBaseType());
const SequentialType *st =
CastType<SequentialType>(ptrType->GetBaseType());
Assert(st != NULL);
llvm::Value *size =
g->target.SizeOf(st->GetElementType()->LLVMType(g->ctx), bblock);
@@ -2340,7 +2339,7 @@ FunctionEmitContext::LoadInst(llvm::Value *ptr, const char *name) {
static llvm::Value *
lFinalSliceOffset(FunctionEmitContext *ctx, llvm::Value *ptr,
const PointerType **ptrType) {
Assert(dynamic_cast<const PointerType *>(*ptrType) != NULL);
Assert(CastType<PointerType>(*ptrType) != NULL);
llvm::Value *slicePtr = ctx->ExtractInst(ptr, 0, LLVMGetName(ptr, "_ptr"));
llvm::Value *sliceOffset = ctx->ExtractInst(ptr, 1, LLVMGetName(ptr, "_offset"));
@@ -2377,8 +2376,7 @@ FunctionEmitContext::loadUniformFromSOA(llvm::Value *ptr, llvm::Value *mask,
const char *name) {
const Type *unifType = ptrType->GetBaseType()->GetAsUniformType();
const CollectionType *ct =
dynamic_cast<const CollectionType *>(ptrType->GetBaseType());
const CollectionType *ct = CastType<CollectionType>(ptrType->GetBaseType());
if (ct != NULL) {
// If we have a struct/array, we need to decompose it into
// individual element loads to fill in the result structure since
@@ -2420,10 +2418,10 @@ FunctionEmitContext::LoadInst(llvm::Value *ptr, llvm::Value *mask,
name = LLVMGetName(ptr, "_load");
const PointerType *ptrType;
if (dynamic_cast<const ReferenceType *>(ptrRefType) != NULL)
if (CastType<ReferenceType>(ptrRefType) != NULL)
ptrType = PointerType::GetUniform(ptrRefType->GetReferenceTarget());
else {
ptrType = dynamic_cast<const PointerType *>(ptrRefType);
ptrType = CastType<PointerType>(ptrRefType);
Assert(ptrType != NULL);
}
@@ -2440,8 +2438,8 @@ FunctionEmitContext::LoadInst(llvm::Value *ptr, llvm::Value *mask,
// atomic types, we need to make sure that the compiler emits
// unaligned vector loads, so we specify a reduced alignment here.
int align = 0;
const AtomicType *atomicType =
dynamic_cast<const AtomicType *>(ptrType->GetBaseType());
const AtomicType *atomicType =
CastType<AtomicType>(ptrType->GetBaseType());
if (atomicType != NULL && atomicType->IsVaryingType())
// We actually just want to align to the vector element
// alignment, but can't easily get that here, so just tell LLVM
@@ -2473,7 +2471,7 @@ FunctionEmitContext::gather(llvm::Value *ptr, const PointerType *ptrType,
llvm::Type *llvmReturnType = returnType->LLVMType(g->ctx);
const CollectionType *collectionType =
dynamic_cast<const CollectionType *>(ptrType->GetBaseType());
CastType<CollectionType>(ptrType->GetBaseType());
if (collectionType != NULL) {
// For collections, recursively gather element wise to find the
// result.
@@ -2508,7 +2506,7 @@ FunctionEmitContext::gather(llvm::Value *ptr, const PointerType *ptrType,
// Figure out which gather function to call based on the size of
// the elements.
const PointerType *pt = dynamic_cast<const PointerType *>(returnType);
const PointerType *pt = CastType<PointerType>(returnType);
const char *funcName = NULL;
if (pt != NULL)
funcName = g->target.is32Bit ? "__pseudo_gather32_32" :
@@ -2631,12 +2629,11 @@ FunctionEmitContext::maskedStore(llvm::Value *value, llvm::Value *ptr,
return;
}
Assert(dynamic_cast<const PointerType *>(ptrType) != NULL);
Assert(CastType<PointerType>(ptrType) != NULL);
Assert(ptrType->IsUniformType());
const Type *valueType = ptrType->GetBaseType();
const CollectionType *collectionType =
dynamic_cast<const CollectionType *>(valueType);
const CollectionType *collectionType = CastType<CollectionType>(valueType);
if (collectionType != NULL) {
// Assigning a structure / array / vector. Handle each element
// individually with what turns into a recursive call to
@@ -2660,7 +2657,7 @@ FunctionEmitContext::maskedStore(llvm::Value *value, llvm::Value *ptr,
// Figure out if we need a 8, 16, 32 or 64-bit masked store.
llvm::Function *maskedStoreFunc = NULL;
const PointerType *pt = dynamic_cast<const PointerType *>(valueType);
const PointerType *pt = CastType<PointerType>(valueType);
if (pt != NULL) {
if (pt->IsSlice()) {
// Masked store of (varying) slice pointer.
@@ -2714,7 +2711,7 @@ FunctionEmitContext::maskedStore(llvm::Value *value, llvm::Value *ptr,
Type::Equal(valueType, AtomicType::VaryingBool) ||
Type::Equal(valueType, AtomicType::VaryingInt32) ||
Type::Equal(valueType, AtomicType::VaryingUInt32) ||
dynamic_cast<const EnumType *>(valueType) != NULL) {
CastType<EnumType>(valueType) != NULL) {
maskedStoreFunc = m->module->getFunction("__pseudo_masked_store_32");
ptr = BitCastInst(ptr, LLVMTypes::Int32VectorPointerType,
LLVMGetName(ptr, "_to_int32vecptr"));
@@ -2755,12 +2752,12 @@ void
FunctionEmitContext::scatter(llvm::Value *value, llvm::Value *ptr,
const Type *valueType, const Type *origPt,
llvm::Value *mask) {
const PointerType *ptrType = dynamic_cast<const PointerType *>(origPt);
const PointerType *ptrType = CastType<PointerType>(origPt);
Assert(ptrType != NULL);
Assert(ptrType->IsVaryingType());
const CollectionType *srcCollectionType =
dynamic_cast<const CollectionType *>(valueType);
CastType<CollectionType>(valueType);
if (srcCollectionType != NULL) {
// We're scattering a collection type--we need to keep track of the
// source type (the type of the data values to be stored) and the
@@ -2771,7 +2768,7 @@ FunctionEmitContext::scatter(llvm::Value *value, llvm::Value *ptr,
// same struct type, versus scattering into an array of varying
// instances of the struct type, etc.
const CollectionType *dstCollectionType =
dynamic_cast<const CollectionType *>(ptrType->GetBaseType());
CastType<CollectionType>(ptrType->GetBaseType());
Assert(dstCollectionType != NULL);
// Scatter the collection elements individually
@@ -2816,11 +2813,10 @@ FunctionEmitContext::scatter(llvm::Value *value, llvm::Value *ptr,
ptr = lFinalSliceOffset(this, ptr, &ptrType);
}
const PointerType *pt = dynamic_cast<const PointerType *>(valueType);
const PointerType *pt = CastType<PointerType>(valueType);
// And everything should be a pointer or atomic from here on out...
Assert(pt != NULL ||
dynamic_cast<const AtomicType *>(valueType) != NULL);
Assert(pt != NULL || CastType<AtomicType>(valueType) != NULL);
llvm::Type *type = value->getType();
const char *funcName = NULL;
@@ -2896,10 +2892,10 @@ FunctionEmitContext::StoreInst(llvm::Value *value, llvm::Value *ptr,
}
const PointerType *ptrType;
if (dynamic_cast<const ReferenceType *>(ptrRefType) != NULL)
if (CastType<ReferenceType>(ptrRefType) != NULL)
ptrType = PointerType::GetUniform(ptrRefType->GetReferenceTarget());
else {
ptrType = dynamic_cast<const PointerType *>(ptrRefType);
ptrType = CastType<PointerType>(ptrRefType);
Assert(ptrType != NULL);
}
@@ -2936,7 +2932,7 @@ FunctionEmitContext::storeUniformToSOA(llvm::Value *value, llvm::Value *ptr,
Assert(Type::EqualIgnoringConst(ptrType->GetBaseType()->GetAsUniformType(),
valueType));
const CollectionType *ct = dynamic_cast<const CollectionType *>(valueType);
const CollectionType *ct = CastType<CollectionType>(valueType);
if (ct != NULL) {
// Handle collections element wise...
for (int i = 0; i < ct->GetElementCount(); ++i) {
@@ -3418,7 +3414,7 @@ llvm::Value *
FunctionEmitContext::addVaryingOffsetsIfNeeded(llvm::Value *ptr,
const Type *ptrType) {
// This should only be called for varying pointers
const PointerType *pt = dynamic_cast<const PointerType *>(ptrType);
const PointerType *pt = CastType<PointerType>(ptrType);
Assert(pt && pt->IsVaryingType());
const Type *baseType = ptrType->GetBaseType();

View File

@@ -136,7 +136,7 @@ DeclSpecs::GetBaseType(SourcePos pos) const {
}
if (vectorSize > 0) {
const AtomicType *atomicType = dynamic_cast<const AtomicType *>(retType);
const AtomicType *atomicType = CastType<AtomicType>(retType);
if (atomicType == NULL) {
Error(pos, "Only atomic types (int, float, ...) are legal for vector "
"types.");
@@ -148,7 +148,7 @@ DeclSpecs::GetBaseType(SourcePos pos) const {
retType = lApplyTypeQualifiers(typeQualifiers, retType, pos);
if (soaWidth > 0) {
const StructType *st = dynamic_cast<const StructType *>(retType);
const StructType *st = CastType<StructType>(retType);
if (st == NULL) {
Error(pos, "Illegal to provide soa<%d> qualifier with non-struct "
@@ -238,7 +238,7 @@ Declarator::InitFromDeclSpecs(DeclSpecs *ds) {
storageClass = ds->storageClass;
if (ds->declSpecList.size() > 0 &&
dynamic_cast<const FunctionType *>(type) == NULL) {
CastType<FunctionType>(type) == NULL) {
Error(pos, "__declspec specifiers for non-function type \"%s\" are "
"not used.", type->GetString().c_str());
}
@@ -351,7 +351,7 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
return;
}
// The parser should disallow this already, but double check.
if (dynamic_cast<const ReferenceType *>(baseType) != NULL) {
if (CastType<ReferenceType>(baseType) != NULL) {
Error(pos, "References to references are illegal.");
return;
}
@@ -370,7 +370,7 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
Error(pos, "Arrays of \"void\" type are illegal.");
return;
}
if (dynamic_cast<const ReferenceType *>(baseType)) {
if (CastType<ReferenceType>(baseType)) {
Error(pos, "Arrays of references (type \"%s\") are illegal.",
baseType->GetString().c_str());
return;
@@ -434,7 +434,7 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
decl->type = NULL;
}
const ArrayType *at = dynamic_cast<const ArrayType *>(decl->type);
const ArrayType *at = CastType<ArrayType>(decl->type);
if (at != NULL) {
// As in C, arrays are passed to functions as pointers to
// their element type. We'll just immediately make this
@@ -454,13 +454,13 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
// Make sure there are no unsized arrays (other than the
// first dimension) in function parameter lists.
at = dynamic_cast<const ArrayType *>(targetType);
at = CastType<ArrayType>(targetType);
while (at != NULL) {
if (at->GetElementCount() == 0)
Error(decl->pos, "Arrays with unsized dimensions in "
"dimensions after the first one are illegal in "
"function parameter lists.");
at = dynamic_cast<const ArrayType *>(at->GetElementType());
at = CastType<ArrayType>(at->GetElementType());
}
}
@@ -497,7 +497,7 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
return;
}
if (dynamic_cast<const FunctionType *>(returnType) != NULL) {
if (CastType<FunctionType>(returnType) != NULL) {
Error(pos, "Illegal to return function type from function.");
return;
}
@@ -596,7 +596,7 @@ Declaration::GetVariableDeclarations() const {
if (Type::Equal(decl->type, AtomicType::Void))
Error(decl->pos, "\"void\" type variable illegal in declaration.");
else if (dynamic_cast<const FunctionType *>(decl->type) == NULL) {
else if (CastType<FunctionType>(decl->type) == NULL) {
decl->type = decl->type->ResolveUnboundVariability(Variability::Varying);
Symbol *sym = new Symbol(decl->name, decl->pos, decl->type,
decl->storageClass);
@@ -621,8 +621,7 @@ Declaration::DeclareFunctions() {
continue;
}
const FunctionType *ftype =
dynamic_cast<const FunctionType *>(decl->type);
const FunctionType *ftype = CastType<FunctionType>(decl->type);
if (ftype == NULL)
continue;
@@ -690,8 +689,7 @@ GetStructTypesNamesPositions(const std::vector<StructDeclaration *> &sd,
}
for (int i = 0; i < (int)elementTypes->size() - 1; ++i) {
const ArrayType *arrayType =
dynamic_cast<const ArrayType *>((*elementTypes)[i]);
const ArrayType *arrayType = CastType<ArrayType>((*elementTypes)[i]);
if (arrayType != NULL && arrayType->GetElementCount() == 0)
Error((*elementPositions)[i], "Unsized arrays aren't allowed except "

482
expr.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -100,7 +100,7 @@ Function::Function(Symbol *s, Stmt *c) {
printf("\n\n\n");
}
const FunctionType *type = dynamic_cast<const FunctionType *>(sym->type);
const FunctionType *type = CastType<FunctionType>(sym->type);
Assert(type != NULL);
for (int i = 0; i < type->GetNumParameters(); ++i) {
@@ -111,7 +111,7 @@ Function::Function(Symbol *s, Stmt *c) {
args.push_back(sym);
const Type *t = type->GetParameterType(i);
if (sym != NULL && dynamic_cast<const ReferenceType *>(t) == NULL)
if (sym != NULL && CastType<ReferenceType>(t) == NULL)
sym->parentFunction = this;
}
@@ -132,7 +132,7 @@ Function::Function(Symbol *s, Stmt *c) {
const Type *
Function::GetReturnType() const {
const FunctionType *type = dynamic_cast<const FunctionType *>(sym->type);
const FunctionType *type = CastType<FunctionType>(sym->type);
Assert(type != NULL);
return type->GetReturnType();
}
@@ -140,7 +140,7 @@ Function::GetReturnType() const {
const FunctionType *
Function::GetType() const {
const FunctionType *type = dynamic_cast<const FunctionType *>(sym->type);
const FunctionType *type = CastType<FunctionType>(sym->type);
Assert(type != NULL);
return type;
}
@@ -205,7 +205,7 @@ Function::emitCode(FunctionEmitContext *ctx, llvm::Function *function,
#if 0
llvm::BasicBlock *entryBBlock = ctx->GetCurrentBasicBlock();
#endif
const FunctionType *type = dynamic_cast<const FunctionType *>(sym->type);
const FunctionType *type = CastType<FunctionType>(sym->type);
Assert(type != NULL);
if (type->isTask == true) {
// For tasks, we there should always be three parmeters: the
@@ -431,7 +431,7 @@ Function::GenerateIR() {
// If the function is 'export'-qualified, emit a second version of
// it without a mask parameter and without name mangling so that
// the application can call it
const FunctionType *type = dynamic_cast<const FunctionType *>(sym->type);
const FunctionType *type = CastType<FunctionType>(sym->type);
Assert(type != NULL);
if (type->isExported) {
if (!type->isTask) {

View File

@@ -368,7 +368,7 @@ Module::AddGlobalVariable(const std::string &name, const Type *type, Expr *initE
if (type == NULL)
return;
const ArrayType *at = dynamic_cast<const ArrayType *>(type);
const ArrayType *at = CastType<ArrayType>(type);
if (at != NULL && at->TotalElementCount() == 0) {
Error(pos, "Illegal to declare a global variable with unsized "
"array dimensions that aren't set with an initializer "
@@ -517,7 +517,7 @@ Module::AddGlobalVariable(const std::string &name, const Type *type, Expr *initE
*/
static bool
lRecursiveCheckValidParamType(const Type *t) {
const StructType *st = dynamic_cast<const StructType *>(t);
const StructType *st = CastType<StructType>(t);
if (st != NULL) {
for (int i = 0; i < st->GetElementCount(); ++i)
if (lRecursiveCheckValidParamType(st->GetElementType(i)))
@@ -525,11 +525,11 @@ lRecursiveCheckValidParamType(const Type *t) {
return false;
}
const SequentialType *seqt = dynamic_cast<const SequentialType *>(t);
const SequentialType *seqt = CastType<SequentialType>(t);
if (seqt != NULL)
return lRecursiveCheckValidParamType(seqt->GetElementType());
const PointerType *pt = dynamic_cast<const PointerType *>(t);
const PointerType *pt = CastType<PointerType>(t);
if (pt != NULL) {
if (pt->IsSlice() || pt->IsVaryingType())
return true;
@@ -550,7 +550,7 @@ lCheckForVaryingParameter(const Type *type, const std::string &name,
SourcePos pos) {
if (lRecursiveCheckValidParamType(type)) {
const Type *t = type->GetBaseType();
if (dynamic_cast<const StructType *>(t))
if (CastType<StructType>(t))
Error(pos, "Struct parameter \"%s\" with varying member(s) is illegal "
"in an exported function.", name.c_str());
else
@@ -568,7 +568,7 @@ static void
lCheckForStructParameters(const FunctionType *ftype, SourcePos pos) {
for (int i = 0; i < ftype->GetNumParameters(); ++i) {
const Type *type = ftype->GetParameterType(i);
if (dynamic_cast<const StructType *>(type) != NULL) {
if (CastType<StructType>(type) != NULL) {
Error(pos, "Passing structs to/from application functions is "
"currently broken. Use a pointer or const pointer to the "
"struct instead for now.");
@@ -615,7 +615,7 @@ Module::AddFunctionDeclaration(const std::string &name,
// different, return an error--overloading by return type isn't
// allowed.
const FunctionType *ofType =
dynamic_cast<const FunctionType *>(overloadFunc->type);
CastType<FunctionType>(overloadFunc->type);
Assert(ofType != NULL);
if (ofType->GetNumParameters() == functionType->GetNumParameters()) {
int i;
@@ -737,9 +737,9 @@ Module::AddFunctionDeclaration(const std::string &name,
// default.) Set parameter attributes accordingly. (Only for
// uniform pointers, since varying pointers are int vectors...)
if (!functionType->isTask &&
((dynamic_cast<const PointerType *>(argType) != NULL &&
((CastType<PointerType>(argType) != NULL &&
argType->IsUniformType()) ||
dynamic_cast<const ReferenceType *>(argType) != NULL)) {
CastType<ReferenceType>(argType) != NULL)) {
// NOTE: LLVM indexes function parameters starting from 1.
// This is unintuitive.
@@ -962,7 +962,7 @@ lEmitStructDecl(const StructType *st, std::vector<const StructType *> *emittedSt
// Otherwise first make sure any contained structs have been declared.
for (int i = 0; i < st->GetElementCount(); ++i) {
const StructType *elementStructType =
dynamic_cast<const StructType *>(st->GetElementType(i));
CastType<StructType>(st->GetElementType(i));
if (elementStructType != NULL)
lEmitStructDecl(elementStructType, emittedStructs, file);
}
@@ -1084,7 +1084,7 @@ lAddTypeIfNew(const Type *type, std::vector<const T *> *exportedTypes) {
if (Type::Equal((*exportedTypes)[i], type))
return;
const T *castType = dynamic_cast<const T *>(type);
const T *castType = CastType<T>(type);
Assert(castType != NULL);
exportedTypes->push_back(castType);
}
@@ -1099,13 +1099,13 @@ lGetExportedTypes(const Type *type,
std::vector<const StructType *> *exportedStructTypes,
std::vector<const EnumType *> *exportedEnumTypes,
std::vector<const VectorType *> *exportedVectorTypes) {
const ArrayType *arrayType = dynamic_cast<const ArrayType *>(type);
const StructType *structType = dynamic_cast<const StructType *>(type);
const ArrayType *arrayType = CastType<ArrayType>(type);
const StructType *structType = CastType<StructType>(type);
if (dynamic_cast<const ReferenceType *>(type) != NULL)
if (CastType<ReferenceType>(type) != NULL)
lGetExportedTypes(type->GetReferenceTarget(), exportedStructTypes,
exportedEnumTypes, exportedVectorTypes);
else if (dynamic_cast<const PointerType *>(type) != NULL)
else if (CastType<PointerType>(type) != NULL)
lGetExportedTypes(type->GetBaseType(), exportedStructTypes,
exportedEnumTypes, exportedVectorTypes);
else if (arrayType != NULL)
@@ -1117,12 +1117,12 @@ lGetExportedTypes(const Type *type,
lGetExportedTypes(structType->GetElementType(i), exportedStructTypes,
exportedEnumTypes, exportedVectorTypes);
}
else if (dynamic_cast<const EnumType *>(type) != NULL)
else if (CastType<EnumType>(type) != NULL)
lAddTypeIfNew(type, exportedEnumTypes);
else if (dynamic_cast<const VectorType *>(type) != NULL)
else if (CastType<VectorType>(type) != NULL)
lAddTypeIfNew(type, exportedVectorTypes);
else
Assert(dynamic_cast<const AtomicType *>(type) != NULL);
Assert(CastType<AtomicType>(type) != NULL);
}
@@ -1135,7 +1135,7 @@ lGetExportedParamTypes(const std::vector<Symbol *> &funcs,
std::vector<const EnumType *> *exportedEnumTypes,
std::vector<const VectorType *> *exportedVectorTypes) {
for (unsigned int i = 0; i < funcs.size(); ++i) {
const FunctionType *ftype = dynamic_cast<const FunctionType *>(funcs[i]->type);
const FunctionType *ftype = CastType<FunctionType>(funcs[i]->type);
// Handle the return type
lGetExportedTypes(ftype->GetReturnType(), exportedStructTypes,
exportedEnumTypes, exportedVectorTypes);
@@ -1152,7 +1152,7 @@ static void
lPrintFunctionDeclarations(FILE *file, const std::vector<Symbol *> &funcs) {
fprintf(file, "#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n");
for (unsigned int i = 0; i < funcs.size(); ++i) {
const FunctionType *ftype = dynamic_cast<const FunctionType *>(funcs[i]->type);
const FunctionType *ftype = CastType<FunctionType>(funcs[i]->type);
Assert(ftype);
std::string decl = ftype->GetCDeclaration(funcs[i]->name);
fprintf(file, " extern %s;\n", decl.c_str());
@@ -1163,7 +1163,7 @@ lPrintFunctionDeclarations(FILE *file, const std::vector<Symbol *> &funcs) {
static bool
lIsExported(const Symbol *sym) {
const FunctionType *ft = dynamic_cast<const FunctionType *>(sym->type);
const FunctionType *ft = CastType<FunctionType>(sym->type);
Assert(ft);
return ft->isExported;
}
@@ -1171,7 +1171,7 @@ lIsExported(const Symbol *sym) {
static bool
lIsExternC(const Symbol *sym) {
const FunctionType *ft = dynamic_cast<const FunctionType *>(sym->type);
const FunctionType *ft = CastType<FunctionType>(sym->type);
Assert(ft);
return ft->isExternC;
}

View File

@@ -550,7 +550,7 @@ rate_qualified_type_specifier
$$ = NULL;
else {
int soaWidth = (int)$1;
const StructType *st = dynamic_cast<const StructType *>($2);
const StructType *st = CastType<StructType>($2);
if (st == NULL) {
Error(@1, "\"soa\" qualifier is illegal with non-struct type \"%s\".",
$2->GetString().c_str());
@@ -895,7 +895,7 @@ struct_or_union_specifier
st = new UndefinedStructType($2, Variability::Unbound, false, @2);
m->symbolTable->AddType($2, st, @2);
}
else if (dynamic_cast<const StructType *>(st) == NULL)
else if (CastType<StructType>(st) == NULL)
Error(@2, "Type \"%s\" is not a struct type! (%s)", $2,
st->GetString().c_str());
$$ = st;
@@ -1060,7 +1060,7 @@ enum_specifier
$$ = NULL;
}
else {
const EnumType *enumType = dynamic_cast<const EnumType *>(type);
const EnumType *enumType = CastType<EnumType>(type);
if (enumType == NULL) {
Error(@2, "Type \"%s\" is not an enum type (%s).", $2,
type->GetString().c_str());
@@ -1858,8 +1858,7 @@ function_definition
{
if ($2 != NULL) {
$2->InitFromDeclSpecs($1);
const FunctionType *funcType =
dynamic_cast<const FunctionType *>($2->type);
const FunctionType *funcType = CastType<FunctionType>($2->type);
if (funcType == NULL)
Assert(m->errorCount > 0);
else {
@@ -1987,7 +1986,7 @@ lAddDeclaration(DeclSpecs *ds, Declarator *decl) {
decl->type = decl->type->ResolveUnboundVariability(Variability::Varying);
const FunctionType *ft = dynamic_cast<const FunctionType *>(decl->type);
const FunctionType *ft = CastType<FunctionType>(decl->type);
if (ft != NULL) {
bool isInline = (ds->typeQualifiers & TYPEQUAL_INLINE);
m->AddFunctionDeclaration(decl->name, ft, ds->storageClass,

View File

@@ -122,7 +122,7 @@ DeclStmt::DeclStmt(const std::vector<VariableDeclaration> &v, SourcePos p)
static bool
lHasUnsizedArrays(const Type *type) {
const ArrayType *at = dynamic_cast<const ArrayType *>(type);
const ArrayType *at = CastType<ArrayType>(type);
if (at == NULL)
return false;
@@ -297,8 +297,8 @@ DeclStmt::TypeCheck() {
// the int->float type conversion is in there and we don't return
// an int as the constValue later...
const Type *type = vars[i].sym->type;
if (dynamic_cast<const AtomicType *>(type) != NULL ||
dynamic_cast<const EnumType *>(type) != NULL) {
if (CastType<AtomicType>(type) != NULL ||
CastType<EnumType>(type) != NULL) {
// If it's an expr list with an atomic type, we'll later issue
// an error. Need to leave vars[i].init as is in that case so
// it is in fact caught later, though.
@@ -2461,7 +2461,7 @@ lEncodeType(const Type *t) {
if (Type::Equal(t, AtomicType::VaryingUInt64)) return 'V';
if (Type::Equal(t, AtomicType::UniformDouble)) return 'd';
if (Type::Equal(t, AtomicType::VaryingDouble)) return 'D';
if (dynamic_cast<const PointerType *>(t) != NULL) {
if (CastType<PointerType>(t) != NULL) {
if (t->IsUniformType())
return 'p';
else
@@ -2481,7 +2481,7 @@ lProcessPrintArg(Expr *expr, FunctionEmitContext *ctx, std::string &argTypes) {
if (type == NULL)
return NULL;
if (dynamic_cast<const ReferenceType *>(type) != NULL) {
if (CastType<ReferenceType>(type) != NULL) {
expr = new RefDerefExpr(expr, expr->pos);
type = expr->GetType();
if (type == NULL)
@@ -2732,7 +2732,7 @@ DeleteStmt::EmitCode(FunctionEmitContext *ctx) const {
}
// Typechecking should catch this
Assert(dynamic_cast<const PointerType *>(exprType) != NULL);
Assert(CastType<PointerType>(exprType) != NULL);
if (exprType->IsUniformType()) {
// For deletion of a uniform pointer, we just need to cast the
@@ -2772,7 +2772,7 @@ DeleteStmt::TypeCheck() {
if (expr == NULL || ((exprType = expr->GetType()) == NULL))
return NULL;
if (dynamic_cast<const PointerType *>(exprType) == NULL) {
if (CastType<PointerType>(exprType) == NULL) {
Error(pos, "Illegal to delete non-pointer type \"%s\".",
exprType->GetString().c_str());
return NULL;

View File

@@ -136,7 +136,7 @@ SymbolTable::LookupVariable(const char *name) {
bool
SymbolTable::AddFunction(Symbol *symbol) {
const FunctionType *ft = dynamic_cast<const FunctionType *>(symbol->type);
const FunctionType *ft = CastType<FunctionType>(symbol->type);
Assert(ft != NULL);
if (LookupFunction(symbol->name.c_str(), ft) != NULL)
// A function of the same name and type has already been added to
@@ -182,7 +182,7 @@ SymbolTable::LookupFunction(const char *name, const FunctionType *type) {
bool
SymbolTable::AddType(const char *name, const Type *type, SourcePos pos) {
const Type *t = LookupType(name);
if (t != NULL && dynamic_cast<const UndefinedStructType *>(t) == NULL) {
if (t != NULL && CastType<UndefinedStructType>(t) == NULL) {
// If we have a previous declaration of anything other than an
// UndefinedStructType with this struct name, issue an error. If
// we have an UndefinedStructType, then we'll fall through to the
@@ -270,7 +270,7 @@ SymbolTable::closestTypeMatch(const char *str, bool structsVsEnums) const {
for (iter = types.begin(); iter != types.end(); ++iter) {
// Skip over either StructTypes or EnumTypes, depending on the
// value of the structsVsEnums parameter
bool isEnum = (dynamic_cast<const EnumType *>(iter->second) != NULL);
bool isEnum = (CastType<EnumType>(iter->second) != NULL);
if (isEnum && structsVsEnums)
continue;
else if (!isEnum && !structsVsEnums)

137
type.cpp
View File

@@ -184,7 +184,7 @@ const AtomicType *AtomicType::Void =
AtomicType::AtomicType(BasicType bt, Variability v, bool ic)
: basicType(bt), variability(v), isConst(ic) {
: Type(ATOMIC_TYPE), basicType(bt), variability(v), isConst(ic) {
}
@@ -532,7 +532,7 @@ AtomicType::GetDIType(llvm::DIDescriptor scope) const {
// EnumType
EnumType::EnumType(SourcePos p)
: pos(p) {
: Type(ENUM_TYPE), pos(p) {
// name = "/* (anonymous) */";
isConst = false;
variability = Variability(Variability::Unbound);
@@ -540,7 +540,7 @@ EnumType::EnumType(SourcePos p)
EnumType::EnumType(const char *n, SourcePos p)
: pos(p), name(n) {
: Type(ENUM_TYPE), pos(p), name(n) {
isConst = false;
variability = Variability(Variability::Unbound);
}
@@ -817,7 +817,7 @@ PointerType *PointerType::Void =
PointerType::PointerType(const Type *t, Variability v, bool ic, bool is,
bool fr)
: variability(v), isConst(ic), isSlice(is), isFrozen(fr) {
: Type(POINTER_TYPE), variability(v), isConst(ic), isSlice(is), isFrozen(fr) {
baseType = t;
}
@@ -1083,7 +1083,7 @@ PointerType::LLVMType(llvm::LLVMContext *ctx) const {
switch (variability.type) {
case Variability::Uniform: {
llvm::Type *ptype = NULL;
const FunctionType *ftype = dynamic_cast<const FunctionType *>(baseType);
const FunctionType *ftype = CastType<FunctionType>(baseType);
if (ftype != NULL)
// Get the type of the function variant that takes the mask as the
// last parameter--i.e. we don't allow taking function pointers of
@@ -1155,7 +1155,7 @@ const Type *SequentialType::GetElementType(int index) const {
// ArrayType
ArrayType::ArrayType(const Type *c, int a)
: child(c), numElements(a) {
: SequentialType(ARRAY_TYPE), child(c), numElements(a) {
// 0 -> unsized array.
Assert(numElements >= 0);
Assert(Type::Equal(c, AtomicType::Void) == false);
@@ -1217,11 +1217,11 @@ ArrayType::IsConstType() const {
const Type *
ArrayType::GetBaseType() const {
const Type *type = child;
const ArrayType *at = dynamic_cast<const ArrayType *>(type);
const ArrayType *at = CastType<ArrayType>(type);
// Keep walking until we reach a child that isn't itself an array
while (at) {
type = at->child;
at = dynamic_cast<const ArrayType *>(type);
at = CastType<ArrayType>(type);
}
return type;
}
@@ -1338,7 +1338,7 @@ ArrayType::GetString() const {
else
buf[0] = '\0';
s += std::string("[") + std::string(buf) + std::string("]");
at = dynamic_cast<const ArrayType *>(at->child);
at = CastType<ArrayType>(at->child);
}
return s;
}
@@ -1381,7 +1381,7 @@ ArrayType::GetCDeclaration(const std::string &name) const {
else
buf[0] = '\0';
s += std::string("[") + std::string(buf) + std::string("]");
at = dynamic_cast<const ArrayType *>(at->child);
at = CastType<ArrayType>(at->child);
}
if (soaWidth > 0) {
@@ -1396,7 +1396,7 @@ ArrayType::GetCDeclaration(const std::string &name) const {
int
ArrayType::TotalElementCount() const {
const ArrayType *ct = dynamic_cast<const ArrayType *>(child);
const ArrayType *ct = CastType<ArrayType>(child);
if (ct != NULL)
return numElements * ct->TotalElementCount();
else
@@ -1425,7 +1425,7 @@ ArrayType::GetSizedArray(int sz) const {
const Type *
ArrayType::SizeUnsizedArrays(const Type *type, Expr *initExpr) {
const ArrayType *at = dynamic_cast<const ArrayType *>(type);
const ArrayType *at = CastType<ArrayType>(type);
if (at == NULL)
return type;
@@ -1437,7 +1437,7 @@ ArrayType::SizeUnsizedArrays(const Type *type, Expr *initExpr) {
// length of the expression list
if (at->GetElementCount() == 0) {
type = at->GetSizedArray(exprList->exprs.size());
at = dynamic_cast<const ArrayType *>(type);
at = CastType<ArrayType>(type);
}
// Is there another nested level of expression lists? If not, bail out
@@ -1449,7 +1449,7 @@ ArrayType::SizeUnsizedArrays(const Type *type, Expr *initExpr) {
return type;
const Type *nextType = at->GetElementType();
const ArrayType *nextArrayType = dynamic_cast<const ArrayType *>(nextType);
const ArrayType *nextArrayType = CastType<ArrayType>(nextType);
if (nextArrayType != NULL && nextArrayType->GetElementCount() == 0) {
// If the recursive call to SizeUnsizedArrays at the bottom of the
// function is going to size an unsized dimension, make sure that
@@ -1485,7 +1485,7 @@ ArrayType::SizeUnsizedArrays(const Type *type, Expr *initExpr) {
// VectorType
VectorType::VectorType(const AtomicType *b, int a)
: base(b), numElements(a) {
: SequentialType(VECTOR_TYPE), base(b), numElements(a) {
Assert(numElements > 0);
Assert(base != NULL);
}
@@ -2111,8 +2111,7 @@ StructType::checkIfCanBeSOA(const StructType *st) {
bool ok = true;
for (int i = 0; i < (int)st->elementTypes.size(); ++i) {
const Type *eltType = st->elementTypes[i];
const StructType *childStructType =
dynamic_cast<const StructType *>(eltType);
const StructType *childStructType = CastType<StructType>(eltType);
if (childStructType != NULL)
ok &= checkIfCanBeSOA(childStructType);
@@ -2124,7 +2123,7 @@ StructType::checkIfCanBeSOA(const StructType *st) {
eltType->IsUniformType() ? "uniform" : "varying");
ok = false;
}
else if (dynamic_cast<const ReferenceType *>(eltType)) {
else if (CastType<ReferenceType>(eltType)) {
Error(st->elementPositions[i], "Unable to apply SOA conversion to "
"struct due to member \"%s\" with reference type \"%s\".",
st->elementNames[i].c_str(), eltType->GetString().c_str());
@@ -2141,7 +2140,7 @@ StructType::checkIfCanBeSOA(const StructType *st) {
UndefinedStructType::UndefinedStructType(const std::string &n,
const Variability var, bool ic,
SourcePos p)
: name(n), variability(var), isConst(ic), pos(p) {
: Type(UNDEFINED_STRUCT_TYPE), name(n), variability(var), isConst(ic), pos(p) {
Assert(name != "");
if (variability != Variability::Unbound) {
// Create a new opaque LLVM struct type for this struct name
@@ -2303,7 +2302,7 @@ UndefinedStructType::GetDIType(llvm::DIDescriptor scope) const {
// ReferenceType
ReferenceType::ReferenceType(const Type *t)
: targetType(t) {
: Type(REFERENCE_TYPE), targetType(t) {
}
@@ -2493,7 +2492,7 @@ ReferenceType::GetCDeclaration(const std::string &name) const {
return "";
}
const ArrayType *at = dynamic_cast<const ArrayType *>(targetType);
const ArrayType *at = CastType<ArrayType>(targetType);
if (at != NULL) {
if (at->GetElementCount() == 0) {
// emit unsized arrays as pointers to the base type..
@@ -2553,8 +2552,8 @@ ReferenceType::GetDIType(llvm::DIDescriptor scope) const {
FunctionType::FunctionType(const Type *r, const std::vector<const Type *> &a,
SourcePos p)
: isTask(false), isExported(false), isExternC(false), returnType(r),
paramTypes(a), paramNames(std::vector<std::string>(a.size(), "")),
: Type(FUNCTION_TYPE), isTask(false), isExported(false), isExternC(false),
returnType(r), paramTypes(a), paramNames(std::vector<std::string>(a.size(), "")),
paramDefaults(std::vector<Expr *>(a.size(), NULL)),
paramPositions(std::vector<SourcePos>(a.size(), p)) {
Assert(returnType != NULL);
@@ -2568,8 +2567,8 @@ FunctionType::FunctionType(const Type *r, const std::vector<const Type *> &a,
const std::vector<Expr *> &ad,
const std::vector<SourcePos> &ap,
bool it, bool is, bool ec)
: isTask(it), isExported(is), isExternC(ec), returnType(r), paramTypes(a),
paramNames(an), paramDefaults(ad), paramPositions(ap) {
: Type(FUNCTION_TYPE), isTask(it), isExported(is), isExternC(ec), returnType(r),
paramTypes(a), paramNames(an), paramDefaults(ad), paramPositions(ap) {
Assert(paramTypes.size() == paramNames.size() &&
paramNames.size() == paramDefaults.size() &&
paramDefaults.size() == paramPositions.size());
@@ -2733,9 +2732,9 @@ FunctionType::GetCDeclaration(const std::string &fname) const {
// Convert pointers to arrays to unsized arrays, which are more clear
// to print out for multidimensional arrays (i.e. "float foo[][4] "
// versus "float (foo *)[4]").
const PointerType *pt = dynamic_cast<const PointerType *>(type);
const PointerType *pt = CastType<PointerType>(type);
if (pt != NULL &&
dynamic_cast<const ArrayType *>(pt->GetBaseType()) != NULL) {
CastType<ArrayType>(pt->GetBaseType()) != NULL) {
type = new ArrayType(pt->GetBaseType(), 0);
}
@@ -2906,7 +2905,7 @@ Type::GetAsUnsignedType() const {
*/
static const Type *
lVectorConvert(const Type *type, SourcePos pos, const char *reason, int vecSize) {
const VectorType *vt = dynamic_cast<const VectorType *>(type);
const VectorType *vt = CastType<VectorType>(type);
if (vt) {
if (vt->GetElementCount() != vecSize) {
Error(pos, "Implicit conversion between from vector type "
@@ -2917,7 +2916,7 @@ lVectorConvert(const Type *type, SourcePos pos, const char *reason, int vecSize)
return vt;
}
else {
const AtomicType *at = dynamic_cast<const AtomicType *>(type);
const AtomicType *at = CastType<AtomicType>(type);
if (!at) {
Error(pos, "Non-atomic type \"%s\" can't be converted to vector type "
"for %s.", type->GetString().c_str(), reason);
@@ -2935,11 +2934,10 @@ Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char
// First, if one or both types are function types, convert them to
// pointer to function types and then try again.
if (dynamic_cast<const FunctionType *>(t0) ||
dynamic_cast<const FunctionType *>(t1)) {
if (dynamic_cast<const FunctionType *>(t0))
if (CastType<FunctionType>(t0) || CastType<FunctionType>(t1)) {
if (CastType<FunctionType>(t0))
t0 = PointerType::GetUniform(t0);
if (dynamic_cast<const FunctionType *>(t1))
if (CastType<FunctionType>(t1))
t1 = PointerType::GetUniform(t1);
return MoreGeneralType(t0, t1, pos, reason, forceVarying, vecSize);
}
@@ -2967,8 +2965,7 @@ Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char
// If they're function types, it's hopeless if they didn't match in the
// Type::Equal() call above. Fail here so that we don't get into
// trouble calling GetAsConstType()...
if (dynamic_cast<const FunctionType *>(t0) ||
dynamic_cast<const FunctionType *>(t1)) {
if (CastType<FunctionType>(t0) || CastType<FunctionType>(t1)) {
Error(pos, "Incompatible function types \"%s\" and \"%s\" in %s.",
t0->GetString().c_str(), t1->GetString().c_str(), reason);
return NULL;
@@ -2979,8 +2976,8 @@ Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char
if (Type::EqualIgnoringConst(t0, t1))
return t0->GetAsNonConstType();
const PointerType *pt0 = dynamic_cast<const PointerType *>(t0);
const PointerType *pt1 = dynamic_cast<const PointerType *>(t1);
const PointerType *pt0 = CastType<PointerType>(t0);
const PointerType *pt1 = CastType<PointerType>(t1);
if (pt0 != NULL && pt1 != NULL) {
if (PointerType::IsVoidPointer(pt0))
return pt1;
@@ -2994,8 +2991,8 @@ Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char
}
}
const VectorType *vt0 = dynamic_cast<const VectorType *>(t0);
const VectorType *vt1 = dynamic_cast<const VectorType *>(t1);
const VectorType *vt0 = CastType<VectorType>(t0);
const VectorType *vt1 = CastType<VectorType>(t1);
if (vt0 && vt1) {
// both are vectors; convert their base types and make a new vector
// type, as long as their lengths match
@@ -3012,7 +3009,7 @@ Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char
// The 'more general' version of the two vector element types must
// be an AtomicType (that's all that vectors can hold...)
const AtomicType *at = dynamic_cast<const AtomicType *>(t);
const AtomicType *at = CastType<AtomicType>(t);
Assert(at != NULL);
return new VectorType(at, vt0->GetElementCount());
@@ -3027,7 +3024,7 @@ Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char
if (!t)
return NULL;
const AtomicType *at = dynamic_cast<const AtomicType *>(t);
const AtomicType *at = CastType<AtomicType>(t);
Assert(at != NULL);
return new VectorType(at, vt0->GetElementCount());
}
@@ -3039,18 +3036,18 @@ Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char
if (!t)
return NULL;
const AtomicType *at = dynamic_cast<const AtomicType *>(t);
const AtomicType *at = CastType<AtomicType>(t);
Assert(at != NULL);
return new VectorType(at, vt1->GetElementCount());
}
// TODO: what do we need to do about references here, if anything??
const AtomicType *at0 = dynamic_cast<const AtomicType *>(t0->GetReferenceTarget());
const AtomicType *at1 = dynamic_cast<const AtomicType *>(t1->GetReferenceTarget());
const AtomicType *at0 = CastType<AtomicType>(t0->GetReferenceTarget());
const AtomicType *at1 = CastType<AtomicType>(t1->GetReferenceTarget());
const EnumType *et0 = dynamic_cast<const EnumType *>(t0->GetReferenceTarget());
const EnumType *et1 = dynamic_cast<const EnumType *>(t1->GetReferenceTarget());
const EnumType *et0 = CastType<EnumType>(t0->GetReferenceTarget());
const EnumType *et1 = CastType<EnumType>(t1->GetReferenceTarget());
if (et0 != NULL && et1 != NULL) {
// Two different enum types -> make them uint32s...
Assert(et0->IsVaryingType() == et1->IsVaryingType());
@@ -3098,9 +3095,9 @@ Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char
bool
Type::IsBasicType(const Type *type) {
return (dynamic_cast<const AtomicType *>(type) != NULL ||
dynamic_cast<const EnumType *>(type) != NULL ||
dynamic_cast<const PointerType *>(type) != NULL);
return (CastType<AtomicType>(type) != NULL ||
CastType<EnumType>(type) != NULL ||
CastType<PointerType>(type) != NULL);
}
@@ -3110,16 +3107,16 @@ lCheckTypeEquality(const Type *a, const Type *b, bool ignoreConst) {
return false;
if (ignoreConst == true) {
if (dynamic_cast<const FunctionType *>(a) == NULL)
if (CastType<FunctionType>(a) == NULL)
a = a->GetAsNonConstType();
if (dynamic_cast<const FunctionType *>(b) == NULL)
if (CastType<FunctionType>(b) == NULL)
b = b->GetAsNonConstType();
}
else if (a->IsConstType() != b->IsConstType())
return false;
const AtomicType *ata = dynamic_cast<const AtomicType *>(a);
const AtomicType *atb = dynamic_cast<const AtomicType *>(b);
const AtomicType *ata = CastType<AtomicType>(a);
const AtomicType *atb = CastType<AtomicType>(b);
if (ata != NULL && atb != NULL) {
return ((ata->basicType == atb->basicType) &&
(ata->GetVariability() == atb->GetVariability()));
@@ -3128,33 +3125,31 @@ lCheckTypeEquality(const Type *a, const Type *b, bool ignoreConst) {
// For all of the other types, we need to see if we have the same two
// general types. If so, then we dig into the details of the type and
// see if all of the relevant bits are equal...
const EnumType *eta = dynamic_cast<const EnumType *>(a);
const EnumType *etb = dynamic_cast<const EnumType *>(b);
const EnumType *eta = CastType<EnumType>(a);
const EnumType *etb = CastType<EnumType>(b);
if (eta != NULL && etb != NULL)
// Kind of goofy, but this sufficies to check
return (eta->pos == etb->pos &&
eta->GetVariability() == etb->GetVariability());
const ArrayType *arta = dynamic_cast<const ArrayType *>(a);
const ArrayType *artb = dynamic_cast<const ArrayType *>(b);
const ArrayType *arta = CastType<ArrayType>(a);
const ArrayType *artb = CastType<ArrayType>(b);
if (arta != NULL && artb != NULL)
return (arta->GetElementCount() == artb->GetElementCount() &&
lCheckTypeEquality(arta->GetElementType(), artb->GetElementType(),
ignoreConst));
const VectorType *vta = dynamic_cast<const VectorType *>(a);
const VectorType *vtb = dynamic_cast<const VectorType *>(b);
const VectorType *vta = CastType<VectorType>(a);
const VectorType *vtb = CastType<VectorType>(b);
if (vta != NULL && vtb != NULL)
return (vta->GetElementCount() == vtb->GetElementCount() &&
lCheckTypeEquality(vta->GetElementType(), vtb->GetElementType(),
ignoreConst));
const StructType *sta = dynamic_cast<const StructType *>(a);
const StructType *stb = dynamic_cast<const StructType *>(b);
const UndefinedStructType *usta =
dynamic_cast<const UndefinedStructType *>(a);
const UndefinedStructType *ustb =
dynamic_cast<const UndefinedStructType *>(b);
const StructType *sta = CastType<StructType>(a);
const StructType *stb = CastType<StructType>(b);
const UndefinedStructType *usta = CastType<UndefinedStructType>(a);
const UndefinedStructType *ustb = CastType<UndefinedStructType>(b);
if ((sta != NULL || usta != NULL) && (stb != NULL || ustb != NULL)) {
// Report both defuned and undefined structs as equal if their
// names are the same.
@@ -3166,8 +3161,8 @@ lCheckTypeEquality(const Type *a, const Type *b, bool ignoreConst) {
return (namea == nameb);
}
const PointerType *pta = dynamic_cast<const PointerType *>(a);
const PointerType *ptb = dynamic_cast<const PointerType *>(b);
const PointerType *pta = CastType<PointerType>(a);
const PointerType *ptb = CastType<PointerType>(b);
if (pta != NULL && ptb != NULL)
return (pta->IsUniformType() == ptb->IsUniformType() &&
pta->IsSlice() == ptb->IsSlice() &&
@@ -3175,14 +3170,14 @@ lCheckTypeEquality(const Type *a, const Type *b, bool ignoreConst) {
lCheckTypeEquality(pta->GetBaseType(), ptb->GetBaseType(),
ignoreConst));
const ReferenceType *rta = dynamic_cast<const ReferenceType *>(a);
const ReferenceType *rtb = dynamic_cast<const ReferenceType *>(b);
const ReferenceType *rta = CastType<ReferenceType>(a);
const ReferenceType *rtb = CastType<ReferenceType>(b);
if (rta != NULL && rtb != NULL)
return (lCheckTypeEquality(rta->GetReferenceTarget(),
rtb->GetReferenceTarget(), ignoreConst));
const FunctionType *fta = dynamic_cast<const FunctionType *>(a);
const FunctionType *ftb = dynamic_cast<const FunctionType *>(b);
const FunctionType *fta = CastType<FunctionType>(a);
const FunctionType *ftb = CastType<FunctionType>(b);
if (fta != NULL && ftb != NULL) {
// Both the return types and all of the argument types must match
// for function types to match

148
type.h
View File

@@ -72,6 +72,21 @@ struct Variability {
};
/** Enumerant that records each of the types that inherit from the Type
baseclass. */
enum TypeId {
ATOMIC_TYPE,
ENUM_TYPE,
POINTER_TYPE,
ARRAY_TYPE,
VECTOR_TYPE,
STRUCT_TYPE,
UNDEFINED_STRUCT_TYPE,
REFERENCE_TYPE,
FUNCTION_TYPE
};
/** @brief Interface class that defines the type abstraction.
Abstract base class that defines the interface that must be implemented
@@ -231,6 +246,14 @@ public:
(i.e. not an aggregation of multiple instances of a type or
types.) */
static bool IsBasicType(const Type *type);
/** Indicates which Type implementation this type is. This value can
be used to determine the actual type much more efficiently than
using dynamic_cast. */
const TypeId typeId;
protected:
Type(TypeId id) : typeId(id) { }
};
@@ -452,6 +475,9 @@ public:
index must be between 0 and GetElementCount()-1.
*/
virtual const Type *GetElementType(int index) const = 0;
protected:
CollectionType(TypeId id) : Type(id) { }
};
@@ -473,6 +499,9 @@ public:
the same type.
*/
const Type *GetElementType(int index) const;
protected:
SequentialType(TypeId id) : CollectionType(id) { }
};
@@ -686,6 +715,8 @@ private:
const Variability variability;
const bool isConst;
const SourcePos pos;
mutable const StructType *oppositeConstStructType;
};
@@ -732,8 +763,6 @@ private:
const Variability variability;
const bool isConst;
const SourcePos pos;
mutable const StructType *oppositeConstStructType;
};
@@ -875,8 +904,119 @@ private:
const std::vector<SourcePos> paramPositions;
};
inline bool IsReferenceType(const Type *t) {
return dynamic_cast<const ReferenceType *>(t) != NULL;
/* Efficient dynamic casting of Types. First, we specify a default
template function that returns NULL, indicating a failed cast, for
arbitrary types. */
template <typename T> inline const T *
CastType(const Type *type) {
return NULL;
}
/* Now we have template specializaitons for the Types implemented in this
file. Each one checks the Type::typeId member and then performs the
corresponding static cast if it's safe as per the typeId.
*/
template <> inline const AtomicType *
CastType(const Type *type) {
if (type != NULL && type->typeId == ATOMIC_TYPE)
return (const AtomicType *)type;
else
return NULL;
}
template <> inline const EnumType *
CastType(const Type *type) {
if (type != NULL && type->typeId == ENUM_TYPE)
return (const EnumType *)type;
else
return NULL;
}
template <> inline const PointerType *
CastType(const Type *type) {
if (type != NULL && type->typeId == POINTER_TYPE)
return (const PointerType *)type;
else
return NULL;
}
template <> inline const ArrayType *
CastType(const Type *type) {
if (type != NULL && type->typeId == ARRAY_TYPE)
return (const ArrayType *)type;
else
return NULL;
}
template <> inline const VectorType *
CastType(const Type *type) {
if (type != NULL && type->typeId == VECTOR_TYPE)
return (const VectorType *)type;
else
return NULL;
}
template <> inline const SequentialType *
CastType(const Type *type) {
// Note that this function must be updated if other sequential type
// implementations are added.
if (type != NULL &&
(type->typeId == ARRAY_TYPE || type->typeId == VECTOR_TYPE))
return (const SequentialType *)type;
else
return NULL;
}
template <> inline const CollectionType *
CastType(const Type *type) {
// Similarly a new collection type implementation requires updating
// this function.
if (type != NULL &&
(type->typeId == ARRAY_TYPE || type->typeId == VECTOR_TYPE ||
type->typeId == STRUCT_TYPE))
return (const CollectionType *)type;
else
return NULL;
}
template <> inline const StructType *
CastType(const Type *type) {
if (type != NULL && type->typeId == STRUCT_TYPE)
return (const StructType *)type;
else
return NULL;
}
template <> inline const UndefinedStructType *
CastType(const Type *type) {
if (type != NULL && type->typeId == UNDEFINED_STRUCT_TYPE)
return (const UndefinedStructType *)type;
else
return NULL;
}
template <> inline const ReferenceType *
CastType(const Type *type) {
if (type != NULL && type->typeId == REFERENCE_TYPE)
return (const ReferenceType *)type;
else
return NULL;
}
template <> inline const FunctionType *
CastType(const Type *type) {
if (type != NULL && type->typeId == FUNCTION_TYPE)
return (const FunctionType *)type;
else
return NULL;
}
inline bool IsReferenceType(const Type *t) {
return CastType<ReferenceType>(t) != NULL;
}
#endif // ISPC_TYPE_H