[llvm-commits] [dragonegg] r138229 - /dragonegg/trunk/src/Types.cpp
Duncan Sands
baldrick at free.fr
Sun Aug 21 23:57:36 PDT 2011
Author: baldrick
Date: Mon Aug 22 01:57:36 2011
New Revision: 138229
URL: http://llvm.org/viewvc/llvm-project?rev=138229&view=rev
Log:
Handle the case in which an array type has an alignment less than
the element type. The gcc-4.5 optimizers sometimes produce this;
the gcc-4.6 optimizers don't seem to, so it's probably a gcc-4.5
bug. Turn on the check that LLVM types have alignment equal to
or less than the alignment of the corresponding GCC type.
Modified:
dragonegg/trunk/src/Types.cpp
Modified: dragonegg/trunk/src/Types.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Types.cpp?rev=138229&r1=138228&r2=138229&view=diff
==============================================================================
--- dragonegg/trunk/src/Types.cpp (original)
+++ dragonegg/trunk/src/Types.cpp Mon Aug 22 01:57:36 2011
@@ -321,11 +321,20 @@
return GetUnitType(C)->getPointerTo(AddrSpace);
}
+/// isSized - Return true if the GCC type has a size, perhaps variable. Note
+/// that this returns false for function types, for which the GCC type size
+/// doesn't represent anything useful for us.
+static bool isSized(tree type) {
+ if (TREE_CODE(type) == FUNCTION_TYPE || TREE_CODE(type) == METHOD_TYPE)
+ return false;
+ return TYPE_SIZE(type);
+}
+
/// isSizeCompatible - Return true if the specified gcc type is guaranteed to be
/// turned by ConvertType into an LLVM type of the same size (i.e. TYPE_SIZE the
/// same as getTypeAllocSizeInBits).
bool isSizeCompatible(tree type) {
- if (TREE_CODE(type) == FUNCTION_TYPE || TREE_CODE(type) == METHOD_TYPE)
+ if (!isSized(type))
return false;
return isInt64(TYPE_SIZE(type), true);
}
@@ -335,52 +344,54 @@
// Matching LLVM types with GCC trees
//===----------------------------------------------------------------------===//
-// llvm_set_type - Associate an LLVM type with each TREE type.
-// These are lazily computed by ConvertType.
-
-static Type *llvm_set_type(tree Tr, Type *Ty) {
- assert(TYPE_P(Tr) && "Expected a gcc type!");
-
+static Type *CheckTypeConversion(tree type, Type *Ty) {
#ifndef NDEBUG
bool Mismatch = false;
+ // If the GCC type has a size, check that the LLVM type does too. Note that
+ // the LLVM type may have a size when the GCC type does not. For example a
+ // C variable length array int[] may be converted into [0 x i32].
+ if (isSized(type) && !Ty->isSized()) {
+ Mismatch = true;
+ errs() << "The GCC type has a size but the LLVM type does not!\n";
+ }
// Check that the LLVM and GCC types really do have the same size when we say
// they do.
- if (isSizeCompatible(Tr)) {
- if (!Ty->isSized()) {
+ if (isSizeCompatible(type) && Ty->isSized()) {
+ uint64_t GCCSize = getInt64(TYPE_SIZE(type), true);
+ uint64_t LLVMSize = getTargetData().getTypeAllocSizeInBits(Ty);
+ if (LLVMSize != GCCSize) {
Mismatch = true;
- errs() << "No size\n";
- } else {
- uint64_t GCCSize = getInt64(TYPE_SIZE(Tr), true);
- uint64_t LLVMSize = getTargetData().getTypeAllocSizeInBits(Ty);
- if (LLVMSize != GCCSize) {
- errs() << "GCC size: " << GCCSize << "; LLVM size: " << LLVMSize
- << "\n";
- Mismatch = true;
- }
+ errs() << "GCC size: " << GCCSize << "; LLVM size: " << LLVMSize
+ << "!\n";
}
}
// Check that the LLVM type has the same alignment or less than the GCC type.
-// FIXME: Reduce LLVM array alignment when the GCC array has a small alignment
-// (due to an alignment clause?), then turn this back on.
-// if (Ty->isSized()) {
-// unsigned GCCAlign = TYPE_ALIGN(Tr);
-// unsigned LLVMAlign = getTargetData().getABITypeAlignment(Ty) * 8;
-// if (LLVMAlign > GCCAlign) {
-// errs() << "GCC align: " << GCCAlign << "; LLVM align: " << LLVMAlign
-// << "\n";
-// Mismatch = true;
-// }
-// }
+ if (Ty->isSized()) {
+ unsigned GCCAlign = TYPE_ALIGN(type);
+ unsigned LLVMAlign = getTargetData().getABITypeAlignment(Ty) * 8;
+ if (LLVMAlign > GCCAlign) {
+ Mismatch = true;
+ errs() << "GCC align: " << GCCAlign << "; LLVM align: " << LLVMAlign
+ << "\n";
+ }
+ }
if (Mismatch) {
errs() << "GCC: ";
- debug_tree(Tr);
+ debug_tree(type);
errs() << "LLVM: ";
Ty->print(errs());
DieAbjectly("\nLLVM type doesn't represent GCC type!");
}
#endif
- setCachedType(Tr, Ty);
+ return Ty;
+}
+
+// RememberTypeConversion - Associate an LLVM type with a GCC type.
+// These are lazily computed by ConvertType.
+static Type *RememberTypeConversion(tree type, Type *Ty) {
+ CheckTypeConversion(type, Ty);
+ setCachedType(type, Ty);
return Ty;
}
@@ -486,6 +497,10 @@
// Create the array type.
Type *Ty = ArrayType::get(ElementTy, NumElements);
+ // If the array is underaligned, wrap it in a packed struct.
+ if (TYPE_ALIGN(type) < getTargetData().getABITypeAlignment(Ty) * 8)
+ Ty = StructType::get(Context, Ty, /*isPacked*/ true);
+
// If the user increased the alignment of the array element type, then the
// size of the array is rounded up by that alignment even though the size
// of the array element type is not (!). Correct for this if necessary by
@@ -1295,25 +1310,25 @@
DieAbjectly("Unexpected type!", type);
case ARRAY_TYPE:
- return llvm_set_type(type, ConvertArrayTypeRecursive(type));
+ return RememberTypeConversion(type, ConvertArrayTypeRecursive(type));
case FUNCTION_TYPE:
case METHOD_TYPE: {
CallingConv::ID CallingConv;
AttrListPtr PAL;
// No declaration to pass through, passing NULL.
- return llvm_set_type(type, ConvertFunctionType(type, NULL, NULL,
- CallingConv, PAL));
+ return RememberTypeConversion(type, ConvertFunctionType(type, NULL, NULL,
+ CallingConv, PAL));
}
case POINTER_TYPE:
case REFERENCE_TYPE:
- return llvm_set_type(type, ConvertPointerTypeRecursive(type));
+ return RememberTypeConversion(type, ConvertPointerTypeRecursive(type));
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
- return llvm_set_type(type, ConvertRecordTypeRecursive(type));
+ return RememberTypeConversion(type, ConvertRecordTypeRecursive(type));
}
}
@@ -1336,47 +1351,49 @@
// converted and we can safely return the result of the previous conversion.
Type *Ty = getCachedType(type);
assert(Ty && "Type not already converted!");
- return Ty;
+ return CheckTypeConversion(type, Ty);
}
case ENUMERAL_TYPE:
// If the enum is incomplete return a placeholder type.
if (!TYPE_SIZE(type))
- return Type::getInt32Ty(Context);
+ return CheckTypeConversion(type, GetUnitType(Context));
// Otherwise fall through.
case BOOLEAN_TYPE:
case INTEGER_TYPE: {
uint64_t Size = getInt64(TYPE_SIZE(type), true);
- return IntegerType::get(Context, Size); // Not worth caching.
+ // Caching the type conversion is not worth it.
+ return CheckTypeConversion(type, IntegerType::get(Context, Size));
}
case COMPLEX_TYPE: {
if (Type *Ty = getCachedType(type)) return Ty;
Type *Ty = ConvertTypeNonRecursive(TYPE_MAIN_VARIANT(TREE_TYPE(type)));
Ty = StructType::get(Ty, Ty, NULL);
- return llvm_set_type(type, Ty);
+ return RememberTypeConversion(type, Ty);
}
case OFFSET_TYPE:
// Handle OFFSET_TYPE specially. This is used for pointers to members,
// which are really just integer offsets. Return the appropriate integer
// type directly.
- return getTargetData().getIntPtrType(Context); // Not worth caching.
+ // Caching the type conversion is not worth it.
+ return CheckTypeConversion(type, getTargetData().getIntPtrType(Context));
case REAL_TYPE:
- // It is not worth caching the result of this type conversion.
+ // Caching the type conversion is not worth it.
switch (TYPE_PRECISION(type)) {
default:
DieAbjectly("Unknown FP type!", type);
- case 32: return Type::getFloatTy(Context);
- case 64: return Type::getDoubleTy(Context);
- case 80: return Type::getX86_FP80Ty(Context);
+ case 32: return CheckTypeConversion(type, Type::getFloatTy(Context));
+ case 64: return CheckTypeConversion(type, Type::getDoubleTy(Context));
+ case 80: return CheckTypeConversion(type, Type::getX86_FP80Ty(Context));
case 128:
#ifdef TARGET_POWERPC
- return Type::getPPC_FP128Ty(Context);
+ return CheckTypeConversion(type, Type::getPPC_FP128Ty(Context));
#else
// IEEE quad precision.
- return Type::getFP128Ty(Context);
+ return CheckTypeConversion(type, Type::getFP128Ty(Context));
#endif
}
@@ -1384,12 +1401,14 @@
case QUAL_UNION_TYPE:
case UNION_TYPE:
// If the type was already converted then return the already computed type.
- if (Type *Ty = getCachedType(type)) return Ty;
+ if (Type *Ty = getCachedType(type))
+ return CheckTypeConversion(type, Ty);
// Otherwise this must be an incomplete type - return an opaque struct.
assert(!TYPE_SIZE(type) && "Expected an incomplete type!");
- return llvm_set_type(type, StructType::create(Context,
- getDescriptiveName(type)));
+ return RememberTypeConversion(type,
+ StructType::create(Context,
+ getDescriptiveName(type)));
case VECTOR_TYPE: {
if (Type *Ty = getCachedType(type)) return Ty;
@@ -1401,11 +1420,12 @@
else
Ty = ConvertTypeNonRecursive(TYPE_MAIN_VARIANT(TREE_TYPE(type)));
Ty = VectorType::get(Ty, TYPE_VECTOR_SUBPARTS(type));
- return llvm_set_type(type, Ty);
+ return RememberTypeConversion(type, Ty);
}
case VOID_TYPE:
- return Type::getVoidTy(Context); // Not worth caching.
+ // Caching the type conversion is not worth it.
+ return CheckTypeConversion(type, Type::getVoidTy(Context));
}
}
@@ -1584,7 +1604,7 @@
// SCC as the pointer (since the SCC contains more than one type).
Type *PointeeTy = getCachedType(pointee);
assert(PointeeTy && "Pointee not converted!");
- llvm_set_type(some_type, PointeeTy->getPointerTo());
+ RememberTypeConversion(some_type, PointeeTy->getPointerTo());
}
}
}
More information about the llvm-commits
mailing list