[cfe-commits] r51763 - /cfe/trunk/lib/CodeGen/CGExprConstant.cpp
Eli Friedman
eli.friedman at gmail.com
Fri May 30 03:24:49 PDT 2008
Author: efriedma
Date: Fri May 30 05:24:46 2008
New Revision: 51763
URL: http://llvm.org/viewvc/llvm-project?rev=51763&view=rev
Log:
Some additions to constant initializer generation code. Adds
bit-field initialization; ugly code, X86-only, but it works, at least
for basic stuff. Separates/adds union initialization; currently disabled,
though, because the struct/array code needs modifications to support
elements of the wrong type.
Fixes PR2381 and PR2309 with the bit-field initialization. And NetHack
compiles and appears to work with a few tweaks (to work around the lack
of transparent_union support, and clang being a bit strict about
conflicting declarations).
Modified:
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=51763&r1=51762&r2=51763&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Fri May 30 05:24:46 2008
@@ -18,6 +18,7 @@
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
@@ -73,9 +74,10 @@
return Visit(DAE->getExpr());
}
- llvm::Constant *EmitArrayInitialization(InitListExpr *ILE,
- const llvm::ArrayType *AType) {
+ llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
std::vector<llvm::Constant*> Elts;
+ const llvm::ArrayType *AType =
+ cast<llvm::ArrayType>(ConvertType(ILE->getType()));
unsigned NumInitElements = ILE->getNumInits();
// FIXME: Check for wide strings
if (NumInitElements > 0 && isa<StringLiteral>(ILE->getInit(0)) &&
@@ -92,7 +94,6 @@
unsigned i = 0;
for (; i < NumInitableElts; ++i) {
llvm::Constant *C = Visit(ILE->getInit(i));
- assert (C && "Failed to create initializer expression");
Elts.push_back(C);
}
@@ -103,9 +104,56 @@
return llvm::ConstantArray::get(AType, Elts);
}
- llvm::Constant *EmitStructInitialization(InitListExpr *ILE,
- const llvm::StructType *SType) {
-
+ void InsertBitfieldIntoStruct(std::vector<llvm::Constant*>& Elts,
+ FieldDecl* Field, Expr* E) {
+ // Calculate the value to insert
+ llvm::Constant *C = Visit(E);
+ llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C);
+ if (!CI) {
+ CGM.WarnUnsupported(E, "bitfield initialization");
+ return;
+ }
+ llvm::APInt V = CI->getValue();
+
+ // Calculate information about the relevant field
+ const llvm::Type* Ty = CI->getType();
+ unsigned size = CGM.getTypes().getTargetData().getTypeStoreSizeInBits(Ty);
+ unsigned fieldOffset = CGM.getTypes().getLLVMFieldNo(Field) * size;
+ CodeGenTypes::BitFieldInfo bitFieldInfo =
+ CGM.getTypes().getBitFieldInfo(Field);
+ fieldOffset += bitFieldInfo.Begin;
+
+ // Find where to start the insertion
+ // FIXME: This is O(n^2) in the number of bit-fields!
+ // FIXME: This won't work if the struct isn't completely packed!
+ unsigned offset = 0, i = 0;
+ while (offset < (fieldOffset & -8))
+ offset += CGM.getTypes().getTargetData().getTypeStoreSizeInBits(Elts[i++]->getType());
+
+ // Insert the bits into the struct
+ // FIXME: This algorthm is only correct on X86!
+ // FIXME: THis algorthm assumes bit-fields only have byte-size elements!
+ unsigned bitsToInsert = bitFieldInfo.Size;
+ unsigned curBits = std::min(8 - (fieldOffset & 7), bitsToInsert);
+ unsigned byte = V.getLoBits(curBits).getZExtValue() << (fieldOffset & 7);
+ do {
+ llvm::Constant* byteC = llvm::ConstantInt::get(llvm::Type::Int8Ty, byte);
+ Elts[i] = llvm::ConstantExpr::getOr(Elts[i], byteC);
+ ++i;
+ V = V.lshr(curBits);
+ bitsToInsert -= curBits;
+
+ if (!bitsToInsert)
+ break;
+
+ curBits = bitsToInsert > 8 ? 8 : bitsToInsert;
+ byte = V.getLoBits(curBits).getZExtValue();
+ } while (true);
+ }
+
+ llvm::Constant *EmitStructInitialization(InitListExpr *ILE) {
+ const llvm::StructType *SType =
+ cast<llvm::StructType>(ConvertType(ILE->getType()));
RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl();
std::vector<llvm::Constant*> Elts;
@@ -124,13 +172,11 @@
if (!curField->getIdentifier())
continue;
- llvm::Constant *C = Visit(ILE->getInit(EltNo));
- assert (C && "Failed to create initializer expression");
-
if (curField->isBitField()) {
- CGM.WarnUnsupported(ILE->getInit(EltNo), "bitfield initialization");
+ InsertBitfieldIntoStruct(Elts, curField, ILE->getInit(EltNo));
} else {
- Elts[CGM.getTypes().getLLVMFieldNo(curField)] = C;
+ Elts[CGM.getTypes().getLLVMFieldNo(curField)] =
+ Visit(ILE->getInit(EltNo));
}
EltNo++;
}
@@ -138,20 +184,75 @@
return llvm::ConstantStruct::get(SType, Elts);
}
- llvm::Constant *EmitVectorInitialization(InitListExpr *ILE,
- const llvm::VectorType *VType) {
+ llvm::Constant *EmitUnionInitialization(InitListExpr *ILE) {
+ // FIXME: Need to make this work correctly for unions in structs/arrays
+ CGM.WarnUnsupported(ILE, "bitfield initialization");
+ return llvm::UndefValue::get(CGM.getTypes().ConvertType(ILE->getType()));
+
+ // Following is a partial implementation; it doesn't work correctly
+ // because the parent struct/arrays don't adapt their type yet, though
+ RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl();
+ const llvm::Type *Ty = ConvertType(ILE->getType());
+
+ // Find the field decl we're initializing, if any
+ int FieldNo = 0; // Field no in RecordDecl
+ FieldDecl* curField;
+ do {
+ curField = RD->getMember(FieldNo);
+ FieldNo++;
+ } while (!curField->getIdentifier() && FieldNo < RD->getNumMembers());
+
+ if (ILE->getNumInits() == 0 || !curField->getIdentifier())
+ return llvm::Constant::getNullValue(Ty);
+
+ if (curField->isBitField()) {
+ // Create a dummy struct for bit-field insertion
+ unsigned NumElts = CGM.getTargetData().getABITypeSize(Ty) / 8;
+ llvm::Constant* NV = llvm::Constant::getNullValue(llvm::Type::Int8Ty);
+ std::vector<llvm::Constant*> Elts(NumElts, NV);
+
+ InsertBitfieldIntoStruct(Elts, curField, ILE->getInit(0));
+ const llvm::ArrayType *RetTy =
+ llvm::ArrayType::get(NV->getType(), NumElts);
+ return llvm::ConstantArray::get(RetTy, Elts);
+ }
+
+ llvm::Constant *C = Visit(ILE->getInit(0));
+ // Build a struct with the union sub-element as the first member,
+ // and padded to the appropriate size
+ std::vector<llvm::Constant*> Elts;
+ std::vector<const llvm::Type*> Types;
+ Elts.push_back(C);
+ Types.push_back(C->getType());
+ unsigned CurSize = CGM.getTargetData().getTypeStoreSize(C->getType());
+ unsigned TotalSize = CGM.getTargetData().getTypeStoreSize(Ty);
+ while (CurSize < TotalSize) {
+ Elts.push_back(llvm::Constant::getNullValue(llvm::Type::Int8Ty));
+ Types.push_back(llvm::Type::Int8Ty);
+ CurSize++;
+ }
+
+ // This always generates a packed struct
+ // FIXME: Try to generate an unpacked struct when we can
+ llvm::StructType* STy = llvm::StructType::get(Types, true);
+ return llvm::ConstantStruct::get(STy, Elts);
+ }
+
+ llvm::Constant *EmitVectorInitialization(InitListExpr *ILE) {
+ const llvm::VectorType *VType =
+ cast<llvm::VectorType>(ConvertType(ILE->getType()));
std::vector<llvm::Constant*> Elts;
unsigned NumInitElements = ILE->getNumInits();
unsigned NumElements = VType->getNumElements();
+ // FIXME: Handle case in assertion correctly
assert (NumInitElements == NumElements
&& "Unsufficient vector init elelments");
// Copy initializer elements.
unsigned i = 0;
for (; i < NumElements; ++i) {
llvm::Constant *C = Visit(ILE->getInit(i));
- assert (C && "Failed to create initializer expression");
Elts.push_back(C);
}
@@ -159,24 +260,27 @@
}
llvm::Constant *VisitInitListExpr(InitListExpr *ILE) {
- const llvm::CompositeType *CType =
- dyn_cast<llvm::CompositeType>(ConvertType(ILE->getType()));
-
- if (!CType) {
- // We have a scalar in braces. Just use the first element.
+ if (ILE->getType()->isScalarType()) {
+ // We have a scalar in braces. Just use the first element.
+ if (ILE->getNumInits() > 0)
return Visit(ILE->getInit(0));
+
+ const llvm::Type* RetTy = CGM.getTypes().ConvertType(ILE->getType());
+ return llvm::Constant::getNullValue(RetTy);
}
-
- if (const llvm::ArrayType *AType = dyn_cast<llvm::ArrayType>(CType))
- return EmitArrayInitialization(ILE, AType);
- if (const llvm::StructType *SType = dyn_cast<llvm::StructType>(CType))
- return EmitStructInitialization(ILE, SType);
+ if (ILE->getType()->isArrayType())
+ return EmitArrayInitialization(ILE);
+
+ if (ILE->getType()->isStructureType())
+ return EmitStructInitialization(ILE);
+
+ if (ILE->getType()->isUnionType())
+ return EmitUnionInitialization(ILE);
+
+ if (ILE->getType()->isVectorType())
+ return EmitVectorInitialization(ILE);
- if (const llvm::VectorType *VType = dyn_cast<llvm::VectorType>(CType))
- return EmitVectorInitialization(ILE, VType);
-
- // Make sure we have an array at this point
assert(0 && "Unable to handle InitListExpr");
// Get rid of control reaches end of void function warning.
// Not reached.
More information about the cfe-commits
mailing list