forked from OSchip/llvm-project
parent
67829f6493
commit
1726aaa4fc
|
@ -467,188 +467,12 @@ public:
|
|||
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) {
|
||||
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) {
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue