Chris Lattner | cf3056d | 2003-10-13 03:32:08 +0000 | [diff] [blame] | 1 | //===- TransformInternals.cpp - Implement shared functions for transforms -===// |
Misha Brukman | fd93908 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 2 | // |
John Criswell | b576c94 | 2003-10-20 19:43:21 +0000 | [diff] [blame] | 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by the LLVM research group and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
Misha Brukman | fd93908 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 7 | // |
John Criswell | b576c94 | 2003-10-20 19:43:21 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// |
Chris Lattner | 59cd9f1 | 2001-11-04 23:24:06 +0000 | [diff] [blame] | 9 | // |
| 10 | // This file defines shared functions used by the different components of the |
| 11 | // Transforms library. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #include "TransformInternals.h" |
Chris Lattner | 59cd9f1 | 2001-11-04 23:24:06 +0000 | [diff] [blame] | 16 | #include "llvm/Type.h" |
Chris Lattner | 0ac5429 | 2002-04-09 19:08:28 +0000 | [diff] [blame] | 17 | #include "llvm/Function.h" |
Alkis Evlogimenos | eb62bc7 | 2004-07-29 12:17:34 +0000 | [diff] [blame] | 18 | #include "llvm/Instructions.h" |
Chris Lattner | 559d519 | 2004-01-09 05:53:38 +0000 | [diff] [blame] | 19 | using namespace llvm; |
Brian Gaeke | d0fde30 | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 20 | |
Chris Lattner | 8e2e5f7 | 2002-09-16 18:32:33 +0000 | [diff] [blame] | 21 | static const Type *getStructOffsetStep(const StructType *STy, uint64_t &Offset, |
Chris Lattner | 16125fb | 2003-04-24 18:25:27 +0000 | [diff] [blame] | 22 | std::vector<Value*> &Indices, |
| 23 | const TargetData &TD) { |
Chris Lattner | 9e77f7e | 2002-03-21 06:27:20 +0000 | [diff] [blame] | 24 | assert(Offset < TD.getTypeSize(STy) && "Offset not in composite!"); |
| 25 | const StructLayout *SL = TD.getStructLayout(STy); |
| 26 | |
| 27 | // This loop terminates always on a 0 <= i < MemberOffsets.size() |
| 28 | unsigned i; |
| 29 | for (i = 0; i < SL->MemberOffsets.size()-1; ++i) |
| 30 | if (Offset >= SL->MemberOffsets[i] && Offset < SL->MemberOffsets[i+1]) |
| 31 | break; |
Misha Brukman | fd93908 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 32 | |
Chris Lattner | 9e77f7e | 2002-03-21 06:27:20 +0000 | [diff] [blame] | 33 | assert(Offset >= SL->MemberOffsets[i] && |
| 34 | (i == SL->MemberOffsets.size()-1 || Offset < SL->MemberOffsets[i+1])); |
Misha Brukman | fd93908 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 35 | |
Chris Lattner | 9e77f7e | 2002-03-21 06:27:20 +0000 | [diff] [blame] | 36 | // Make sure to save the current index... |
Reid Spencer | c5b206b | 2006-12-31 05:48:39 +0000 | [diff] [blame^] | 37 | Indices.push_back(ConstantInt::get(Type::Int32Ty, i)); |
Chris Lattner | 9e77f7e | 2002-03-21 06:27:20 +0000 | [diff] [blame] | 38 | Offset = SL->MemberOffsets[i]; |
| 39 | return STy->getContainedType(i); |
| 40 | } |
| 41 | |
| 42 | |
Chris Lattner | c0b90e7 | 2001-11-08 20:19:56 +0000 | [diff] [blame] | 43 | // getStructOffsetType - Return a vector of offsets that are to be used to index |
| 44 | // into the specified struct type to get as close as possible to index as we |
| 45 | // can. Note that it is possible that we cannot get exactly to Offset, in which |
| 46 | // case we update offset to be the offset we actually obtained. The resultant |
| 47 | // leaf type is returned. |
| 48 | // |
| 49 | // If StopEarly is set to true (the default), the first object with the |
| 50 | // specified type is returned, even if it is a struct type itself. In this |
| 51 | // case, this routine will not drill down to the leaf type. Set StopEarly to |
| 52 | // false if you want a leaf |
| 53 | // |
Chris Lattner | 559d519 | 2004-01-09 05:53:38 +0000 | [diff] [blame] | 54 | const Type *llvm::getStructOffsetType(const Type *Ty, unsigned &Offset, |
| 55 | std::vector<Value*> &Indices, |
| 56 | const TargetData &TD, bool StopEarly) { |
Chris Lattner | 9e77f7e | 2002-03-21 06:27:20 +0000 | [diff] [blame] | 57 | if (Offset == 0 && StopEarly && !Indices.empty()) |
Chris Lattner | c0b90e7 | 2001-11-08 20:19:56 +0000 | [diff] [blame] | 58 | return Ty; // Return the leaf type |
Chris Lattner | c0b90e7 | 2001-11-08 20:19:56 +0000 | [diff] [blame] | 59 | |
Chris Lattner | 8e2e5f7 | 2002-09-16 18:32:33 +0000 | [diff] [blame] | 60 | uint64_t ThisOffset; |
Chris Lattner | 89a1c80 | 2001-11-26 16:59:47 +0000 | [diff] [blame] | 61 | const Type *NextType; |
| 62 | if (const StructType *STy = dyn_cast<StructType>(Ty)) { |
Chris Lattner | d21cd80 | 2004-02-09 04:37:31 +0000 | [diff] [blame] | 63 | if (STy->getNumElements()) { |
Chris Lattner | 9493101 | 2003-10-17 18:03:54 +0000 | [diff] [blame] | 64 | Offset = 0; |
| 65 | return STy; |
| 66 | } |
| 67 | |
Chris Lattner | 9e77f7e | 2002-03-21 06:27:20 +0000 | [diff] [blame] | 68 | ThisOffset = Offset; |
Chris Lattner | 16125fb | 2003-04-24 18:25:27 +0000 | [diff] [blame] | 69 | NextType = getStructOffsetStep(STy, ThisOffset, Indices, TD); |
Chris Lattner | 7991c28 | 2001-12-14 16:38:59 +0000 | [diff] [blame] | 70 | } else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { |
Chris Lattner | e32487e | 2003-06-07 21:45:42 +0000 | [diff] [blame] | 71 | assert(Offset == 0 || Offset < TD.getTypeSize(ATy) && |
| 72 | "Offset not in composite!"); |
Chris Lattner | c0b90e7 | 2001-11-08 20:19:56 +0000 | [diff] [blame] | 73 | |
Chris Lattner | 89a1c80 | 2001-11-26 16:59:47 +0000 | [diff] [blame] | 74 | NextType = ATy->getElementType(); |
Chris Lattner | 22bc934 | 2005-01-08 19:48:40 +0000 | [diff] [blame] | 75 | unsigned ChildSize = (unsigned)TD.getTypeSize(NextType); |
Reid Spencer | c5b206b | 2006-12-31 05:48:39 +0000 | [diff] [blame^] | 76 | if (ConstantInt::isValueValidForType(Type::Int32Ty, |
Reid Spencer | b83eb64 | 2006-10-20 07:07:24 +0000 | [diff] [blame] | 77 | uint64_t(Offset/ChildSize))) |
Reid Spencer | c5b206b | 2006-12-31 05:48:39 +0000 | [diff] [blame^] | 78 | Indices.push_back(ConstantInt::get(Type::Int32Ty, Offset/ChildSize)); |
Chris Lattner | 28977af | 2004-04-05 01:30:19 +0000 | [diff] [blame] | 79 | else |
Reid Spencer | c5b206b | 2006-12-31 05:48:39 +0000 | [diff] [blame^] | 80 | Indices.push_back(ConstantInt::get(Type::Int64Ty, Offset/ChildSize)); |
Chris Lattner | 89a1c80 | 2001-11-26 16:59:47 +0000 | [diff] [blame] | 81 | ThisOffset = (Offset/ChildSize)*ChildSize; |
Chris Lattner | 7991c28 | 2001-12-14 16:38:59 +0000 | [diff] [blame] | 82 | } else { |
Misha Brukman | cf00c4a | 2003-10-10 17:57:28 +0000 | [diff] [blame] | 83 | Offset = 0; // Return the offset that we were able to achieve |
Chris Lattner | 7991c28 | 2001-12-14 16:38:59 +0000 | [diff] [blame] | 84 | return Ty; // Return the leaf type |
Chris Lattner | 89a1c80 | 2001-11-26 16:59:47 +0000 | [diff] [blame] | 85 | } |
Chris Lattner | c0b90e7 | 2001-11-08 20:19:56 +0000 | [diff] [blame] | 86 | |
Chris Lattner | 22bc934 | 2005-01-08 19:48:40 +0000 | [diff] [blame] | 87 | unsigned SubOffs = unsigned(Offset - ThisOffset); |
Chris Lattner | 4736d06 | 2002-03-07 21:18:00 +0000 | [diff] [blame] | 88 | const Type *LeafTy = getStructOffsetType(NextType, SubOffs, |
Chris Lattner | 16125fb | 2003-04-24 18:25:27 +0000 | [diff] [blame] | 89 | Indices, TD, StopEarly); |
Chris Lattner | 22bc934 | 2005-01-08 19:48:40 +0000 | [diff] [blame] | 90 | Offset = unsigned(ThisOffset + SubOffs); |
Chris Lattner | c0b90e7 | 2001-11-08 20:19:56 +0000 | [diff] [blame] | 91 | return LeafTy; |
| 92 | } |