forked from OSchip/llvm-project
parent
67829f6493
commit
1726aaa4fc
|
@ -467,188 +467,12 @@ public:
|
||||||
return llvm::ConstantArray::get(AType, Elts);
|
return llvm::ConstantArray::get(AType, Elts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertBitfieldIntoStruct(std::vector<llvm::Constant*>& Elts,
|
|
||||||
FieldDecl* Field, Expr* E) {
|
|
||||||
// Calculate the value to insert
|
|
||||||
llvm::Constant *C = CGM.EmitConstantExpr(E, Field->getType(), CGF);
|
|
||||||
if (!C)
|
|
||||||
return;
|
|
||||||
|
|
||||||
llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C);
|
|
||||||
if (!CI) {
|
|
||||||
CGM.ErrorUnsupported(E, "bitfield initialization");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
llvm::APInt V = CI->getValue();
|
|
||||||
|
|
||||||
// Calculate information about the relevant field
|
|
||||||
const llvm::Type* Ty = CI->getType();
|
|
||||||
const llvm::TargetData &TD = CGM.getTypes().getTargetData();
|
|
||||||
unsigned size = TD.getTypeAllocSizeInBits(Ty);
|
|
||||||
CodeGenTypes::BitFieldInfo Info = CGM.getTypes().getBitFieldInfo(Field);
|
|
||||||
unsigned FieldOffset = Info.FieldNo * size;
|
|
||||||
|
|
||||||
FieldOffset += Info.Start;
|
|
||||||
|
|
||||||
// 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 += TD.getTypeAllocSizeInBits(Elts[i++]->getType());
|
|
||||||
|
|
||||||
// Advance over 0 sized elements (must terminate in bounds since
|
|
||||||
// the bitfield must have a size).
|
|
||||||
while (TD.getTypeAllocSizeInBits(Elts[i]->getType()) == 0)
|
|
||||||
++i;
|
|
||||||
|
|
||||||
// Promote the size of V if necessary
|
|
||||||
// FIXME: This should never occur, but currently it can because initializer
|
|
||||||
// constants are cast to bool, and because clang is not enforcing bitfield
|
|
||||||
// width limits.
|
|
||||||
if (Info.Size > V.getBitWidth())
|
|
||||||
V.zext(Info.Size);
|
|
||||||
|
|
||||||
// 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 = Info.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) {
|
llvm::Constant *EmitStructInitialization(InitListExpr *ILE) {
|
||||||
return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
|
return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
|
||||||
|
|
||||||
// FIXME: Remove the old struct builder once we're sure that the new one
|
|
||||||
// works well enough!
|
|
||||||
const llvm::StructType *SType =
|
|
||||||
cast<llvm::StructType>(ConvertType(ILE->getType()));
|
|
||||||
RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
|
|
||||||
std::vector<llvm::Constant*> Elts;
|
|
||||||
|
|
||||||
// Initialize the whole structure to zero.
|
|
||||||
// FIXME: This doesn't handle member pointers correctly!
|
|
||||||
for (unsigned i = 0; i < SType->getNumElements(); ++i) {
|
|
||||||
const llvm::Type *FieldTy = SType->getElementType(i);
|
|
||||||
Elts.push_back(llvm::Constant::getNullValue(FieldTy));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy initializer elements. Skip padding fields.
|
|
||||||
unsigned EltNo = 0; // Element no in ILE
|
|
||||||
bool RewriteType = false;
|
|
||||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
|
||||||
FieldEnd = RD->field_end();
|
|
||||||
EltNo < ILE->getNumInits() && Field != FieldEnd; ++Field) {
|
|
||||||
if (Field->isBitField()) {
|
|
||||||
if (!Field->getIdentifier())
|
|
||||||
continue;
|
|
||||||
InsertBitfieldIntoStruct(Elts, *Field, ILE->getInit(EltNo));
|
|
||||||
} else {
|
|
||||||
unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(*Field);
|
|
||||||
llvm::Constant *C = CGM.EmitConstantExpr(ILE->getInit(EltNo),
|
|
||||||
Field->getType(), CGF);
|
|
||||||
if (!C) return 0;
|
|
||||||
RewriteType |= (C->getType() != Elts[FieldNo]->getType());
|
|
||||||
Elts[FieldNo] = C;
|
|
||||||
}
|
|
||||||
EltNo++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RewriteType) {
|
|
||||||
// FIXME: Make this work for non-packed structs
|
|
||||||
assert(SType->isPacked() && "Cannot recreate unpacked structs");
|
|
||||||
std::vector<const llvm::Type*> Types;
|
|
||||||
for (unsigned i = 0; i < Elts.size(); ++i)
|
|
||||||
Types.push_back(Elts[i]->getType());
|
|
||||||
SType = llvm::StructType::get(Types, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return llvm::ConstantStruct::get(SType, Elts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Constant *EmitUnion(llvm::Constant *C, const llvm::Type *Ty) {
|
|
||||||
if (!C)
|
|
||||||
return 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().getTypeAllocSize(C->getType());
|
|
||||||
unsigned TotalSize = CGM.getTargetData().getTypeAllocSize(Ty);
|
|
||||||
|
|
||||||
assert(CurSize <= TotalSize && "Union size mismatch!");
|
|
||||||
if (unsigned NumPadBytes = TotalSize - CurSize) {
|
|
||||||
const llvm::Type *Ty = llvm::Type::Int8Ty;
|
|
||||||
if (NumPadBytes > 1)
|
|
||||||
Ty = llvm::ArrayType::get(Ty, NumPadBytes);
|
|
||||||
|
|
||||||
Elts.push_back(llvm::Constant::getNullValue(Ty));
|
|
||||||
Types.push_back(Ty);
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::StructType* STy = llvm::StructType::get(Types, false);
|
|
||||||
return llvm::ConstantStruct::get(STy, Elts);
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::Constant *EmitUnionInitialization(InitListExpr *ILE) {
|
llvm::Constant *EmitUnionInitialization(InitListExpr *ILE) {
|
||||||
return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
|
return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
|
||||||
|
|
||||||
const llvm::Type *Ty = ConvertType(ILE->getType());
|
|
||||||
|
|
||||||
FieldDecl* curField = ILE->getInitializedFieldInUnion();
|
|
||||||
if (!curField) {
|
|
||||||
// There's no field to initialize, so value-initialize the union.
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// Make sure that it's really an empty and not a failure of
|
|
||||||
// semantic analysis.
|
|
||||||
RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
|
|
||||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
|
||||||
FieldEnd = RD->field_end();
|
|
||||||
Field != FieldEnd; ++Field)
|
|
||||||
assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed");
|
|
||||||
#endif
|
|
||||||
return llvm::Constant::getNullValue(Ty);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curField->isBitField()) {
|
|
||||||
// Create a dummy struct for bit-field insertion
|
|
||||||
unsigned NumElts = CGM.getTargetData().getTypeAllocSize(Ty);
|
|
||||||
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 *InitElem;
|
|
||||||
if (ILE->getNumInits() > 0) {
|
|
||||||
Expr *Init = ILE->getInit(0);
|
|
||||||
InitElem = CGM.EmitConstantExpr(Init, Init->getType(), CGF);
|
|
||||||
} else {
|
|
||||||
InitElem = CGM.EmitNullConstant(curField->getType());
|
|
||||||
}
|
|
||||||
return EmitUnion(InitElem, Ty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Constant *EmitVectorInitialization(InitListExpr *ILE) {
|
llvm::Constant *EmitVectorInitialization(InitListExpr *ILE) {
|
||||||
|
|
Loading…
Reference in New Issue