diff options
| -rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 7 | ||||
| -rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 16 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 24 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/TargetData.cpp | 25 | 
5 files changed, 73 insertions, 4 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index a32883720be..b9453c90b58 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -293,6 +293,8 @@ void BitcodeReaderValueList::ResolveConstantForwardRefs() {        } else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) {          NewC = ConstantStruct::get(Context, &NewOps[0], NewOps.size(),                                           UserCS->getType()->isPacked()); +      } else if (ConstantUnion *UserCU = dyn_cast<ConstantUnion>(UserC)) { +        NewC = ConstantUnion::get(UserCU->getType(), NewOps[0]);        } else if (isa<ConstantVector>(UserC)) {          NewC = ConstantVector::get(&NewOps[0], NewOps.size());        } else { @@ -1015,6 +1017,11 @@ bool BitcodeReader::ParseConstants() {            Elts.push_back(ValueList.getConstantFwdRef(Record[i],                                                       STy->getElementType(i)));          V = ConstantStruct::get(STy, Elts); +      } else if (const UnionType *UnTy = dyn_cast<UnionType>(CurTy)) { +        uint64_t Index = Record[0]; +        Constant *Val = ValueList.getConstantFwdRef(Record[1], +                                        UnTy->getElementType(Index)); +        V = ConstantUnion::get(UnTy, Val);        } else if (const ArrayType *ATy = dyn_cast<ArrayType>(CurTy)) {          const Type *EltTy = ATy->getElementType();          for (unsigned i = 0; i != Size; ++i) diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 82e73b5cff2..3ab27266674 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -808,11 +808,25 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,        else if (isCStr7)          AbbrevToUse = CString7Abbrev;      } else if (isa<ConstantArray>(C) || isa<ConstantStruct>(V) || -               isa<ConstantUnion>(C) || isa<ConstantVector>(V)) { +               isa<ConstantVector>(V)) {        Code = bitc::CST_CODE_AGGREGATE;        for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)          Record.push_back(VE.getValueID(C->getOperand(i)));        AbbrevToUse = AggregateAbbrev; +    } else if (isa<ConstantUnion>(C)) { +      Code = bitc::CST_CODE_AGGREGATE; + +      // Unions only have one entry but we must send type along with it. +      const Type *EntryKind = C->getOperand(0)->getType(); + +      const UnionType *UnTy = cast<UnionType>(C->getType()); +      int UnionIndex = UnTy->getElementTypeIndex(EntryKind); +      assert(UnionIndex != -1 && "Constant union contains invalid entry"); + +      Record.push_back(UnionIndex); +      Record.push_back(VE.getValueID(C->getOperand(0))); + +      AbbrevToUse = AggregateAbbrev;      } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {        switch (CE->getOpcode()) {        default: diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 2636e2c4017..1d4f7f7ae68 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1138,6 +1138,21 @@ static void EmitGlobalConstantStruct(const ConstantStruct *CS,           "Layout of constant struct may be incorrect!");  } +static void EmitGlobalConstantUnion(const ConstantUnion *CU,  +                                    unsigned AddrSpace, AsmPrinter &AP) { +  const TargetData *TD = AP.TM.getTargetData(); +  unsigned Size = TD->getTypeAllocSize(CU->getType()); + +  const Constant *Contents = CU->getOperand(0); +  unsigned FilledSize = TD->getTypeAllocSize(Contents->getType()); +     +  // Print the actually filled part +  AP.EmitGlobalConstant(Contents, AddrSpace); + +  // And pad with enough zeroes +  AP.OutStreamer.EmitZeros(Size-FilledSize, AddrSpace); +} +  static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace,                                   AsmPrinter &AP) {    // FP Constants are printed as integer constants to avoid losing @@ -1257,9 +1272,6 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) {    if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))      return EmitGlobalConstantFP(CFP, AddrSpace, *this); -   -  if (const ConstantVector *V = dyn_cast<ConstantVector>(CV)) -    return EmitGlobalConstantVector(V, AddrSpace, *this);    if (isa<ConstantPointerNull>(CV)) {      unsigned Size = TM.getTargetData()->getTypeAllocSize(CV->getType()); @@ -1267,6 +1279,12 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) {      return;    } +  if (const ConstantUnion *CVU = dyn_cast<ConstantUnion>(CV)) +    return EmitGlobalConstantUnion(CVU, AddrSpace, *this); +   +  if (const ConstantVector *V = dyn_cast<ConstantVector>(CV)) +    return EmitGlobalConstantVector(V, AddrSpace, *this); +      // Otherwise, it must be a ConstantExpr.  Lower it to an MCExpr, then emit it    // thread the streamer with EmitValue.    OutStreamer.EmitValue(LowerConstant(CV, *this), diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 3d9a4d523b6..11293e47f64 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2592,6 +2592,11 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) {        }        Ty = StTy->getElementType(Field); +    } else if (const UnionType *UnTy = dyn_cast<UnionType>(Ty)) { +      unsigned Field = cast<ConstantInt>(Idx)->getZExtValue(); +       +      // Offset canonically 0 for unions, but type changes +      Ty = UnTy->getElementType(Field);      } else {        Ty = cast<SequentialType>(Ty)->getElementType(); diff --git a/llvm/lib/Target/TargetData.cpp b/llvm/lib/Target/TargetData.cpp index 9a168087aed..643b3977461 100644 --- a/llvm/lib/Target/TargetData.cpp +++ b/llvm/lib/Target/TargetData.cpp @@ -460,6 +460,15 @@ uint64_t TargetData::getTypeSizeInBits(const Type *Ty) const {    case Type::StructTyID:      // Get the layout annotation... which is lazily created on demand.      return getStructLayout(cast<StructType>(Ty))->getSizeInBits(); +  case Type::UnionTyID: { +    const UnionType *UnTy = cast<UnionType>(Ty); +    uint64_t Size = 0; +    for (UnionType::element_iterator i = UnTy->element_begin(), +             e = UnTy->element_end(); i != e; ++i) { +      Size = std::max(Size, getTypeSizeInBits(*i)); +    } +    return Size; +  }    case Type::IntegerTyID:      return cast<IntegerType>(Ty)->getBitWidth();    case Type::VoidTyID: @@ -516,6 +525,17 @@ unsigned char TargetData::getAlignment(const Type *Ty, bool abi_or_pref) const {      unsigned Align = getAlignmentInfo(AGGREGATE_ALIGN, 0, abi_or_pref, Ty);      return std::max(Align, (unsigned)Layout->getAlignment());    } +  case Type::UnionTyID: { +    const UnionType *UnTy = cast<UnionType>(Ty); +    unsigned Align = 1; + +    // Unions need the maximum alignment of all their entries +    for (UnionType::element_iterator i = UnTy->element_begin(),  +             e = UnTy->element_end(); i != e; ++i) { +      Align = std::max(Align, (unsigned)getAlignment(*i, abi_or_pref)); +    } +    return Align; +  }    case Type::IntegerTyID:    case Type::VoidTyID:      AlignType = INTEGER_ALIGN; @@ -600,6 +620,11 @@ uint64_t TargetData::getIndexedOffset(const Type *ptrTy, Value* const* Indices,        // Update Ty to refer to current element        Ty = STy->getElementType(FieldNo); +    } else if (const UnionType *UnTy = dyn_cast<UnionType>(*TI)) { +        unsigned FieldNo = cast<ConstantInt>(Indices[CurIDX])->getZExtValue(); + +        // Offset into union is canonically 0, but type changes +        Ty = UnTy->getElementType(FieldNo);      } else {        // Update Ty to refer to current element        Ty = cast<SequentialType>(Ty)->getElementType();  | 

