blob: 0c7091696e4adfd2717bdf3c9d852224ed1cf499 [file] [log] [blame]
Chris Lattnercf3056d2003-10-13 03:32:08 +00001//===- SimpleStructMutation.cpp - Swap structure elements around ----------===//
John Criswellb576c942003-10-20 19:43:21 +00002//
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.
7//
8//===----------------------------------------------------------------------===//
Chris Lattner7546c212001-11-10 07:28:25 +00009//
10// This pass does a simple transformation that swaps all of the elements of the
11// struct types in the program around.
12//
13//===----------------------------------------------------------------------===//
14
Chris Lattner568ddab2002-07-24 17:12:05 +000015#include "llvm/Transforms/IPO.h"
Chris Lattnere6aa3732002-11-19 20:49:40 +000016#include "llvm/Transforms/MutateStructTypes.h"
Chris Lattner7546c212001-11-10 07:28:25 +000017#include "llvm/Analysis/FindUsedTypes.h"
18#include "llvm/Analysis/FindUnsafePointerTypes.h"
Chris Lattner497c60c2002-05-07 18:12:18 +000019#include "llvm/Target/TargetData.h"
20#include "llvm/DerivedTypes.h"
Chris Lattner12739d92001-11-26 16:59:10 +000021#include <algorithm>
Chris Lattner697954c2002-01-20 22:54:45 +000022using std::vector;
23using std::set;
24using std::pair;
Chris Lattner7546c212001-11-10 07:28:25 +000025
Brian Gaeked0fde302003-11-11 22:41:34 +000026namespace llvm {
27
Chris Lattnerbd0ef772002-02-26 21:46:54 +000028namespace {
Chris Lattner96c466b2002-04-29 14:57:45 +000029 struct SimpleStructMutation : public MutateStructTypes {
Chris Lattnere9754ef2002-07-23 18:03:11 +000030 enum Transform { SwapElements, SortElements };
Chris Lattnerbd0ef772002-02-26 21:46:54 +000031
Chris Lattnere9754ef2002-07-23 18:03:11 +000032 virtual bool run(Module &M) = 0;
33
Chris Lattnerf57b8452002-04-27 06:56:12 +000034 // getAnalysisUsage - This function needs the results of the
Chris Lattnerbd0ef772002-02-26 21:46:54 +000035 // FindUsedTypes and FindUnsafePointerTypes analysis passes...
36 //
Chris Lattnerf57b8452002-04-27 06:56:12 +000037 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
Chris Lattner3a15d702002-09-26 00:17:21 +000038 AU.addRequired<TargetData>();
Chris Lattner5f0eb8d2002-08-08 19:01:30 +000039 AU.addRequired<FindUsedTypes>();
40 AU.addRequired<FindUnsafePointerTypes>();
Chris Lattnerf57b8452002-04-27 06:56:12 +000041 MutateStructTypes::getAnalysisUsage(AU);
Chris Lattnerbd0ef772002-02-26 21:46:54 +000042 }
43
Chris Lattnere9754ef2002-07-23 18:03:11 +000044 protected:
Chris Lattner0b12b5f2002-06-25 16:13:21 +000045 TransformsType getTransforms(Module &M, enum Transform);
Chris Lattnerbd0ef772002-02-26 21:46:54 +000046 };
Chris Lattnere9754ef2002-07-23 18:03:11 +000047
48 struct SwapStructElements : public SimpleStructMutation {
Chris Lattnere9754ef2002-07-23 18:03:11 +000049 virtual bool run(Module &M) {
50 setTransforms(getTransforms(M, SwapElements));
51 bool Changed = MutateStructTypes::run(M);
52 clearTransforms();
53 return Changed;
54 }
55 };
56
57 struct SortStructElements : public SimpleStructMutation {
Chris Lattnere9754ef2002-07-23 18:03:11 +000058 virtual bool run(Module &M) {
59 setTransforms(getTransforms(M, SortElements));
60 bool Changed = MutateStructTypes::run(M);
61 clearTransforms();
62 return Changed;
63 }
64 };
Chris Lattner3a15d702002-09-26 00:17:21 +000065
66 RegisterOpt<SwapStructElements> X("swapstructs",
67 "Swap structure types around");
68 RegisterOpt<SortStructElements> Y("sortstructs",
69 "Sort structure elements by size");
Chris Lattnerbd0ef772002-02-26 21:46:54 +000070} // end anonymous namespace
71
Chris Lattner3a15d702002-09-26 00:17:21 +000072Pass *createSwapElementsPass() { return new SwapStructElements(); }
73Pass *createSortElementsPass() { return new SortStructElements(); }
Chris Lattnerbd0ef772002-02-26 21:46:54 +000074
Chris Lattner697954c2002-01-20 22:54:45 +000075
Chris Lattner7546c212001-11-10 07:28:25 +000076// PruneTypes - Given a type Ty, make sure that neither it, or one of its
77// subtypes, occur in TypesToModify.
78//
79static void PruneTypes(const Type *Ty, set<const StructType*> &TypesToModify,
80 set<const Type*> &ProcessedTypes) {
81 if (ProcessedTypes.count(Ty)) return; // Already been checked
82 ProcessedTypes.insert(Ty);
83
84 // If the element is in TypesToModify, remove it now...
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000085 if (const StructType *ST = dyn_cast<StructType>(Ty)) {
Chris Lattner7546c212001-11-10 07:28:25 +000086 TypesToModify.erase(ST); // This doesn't fail if the element isn't present
Chris Lattner697954c2002-01-20 22:54:45 +000087 std::cerr << "Unable to swap type: " << ST << "\n";
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000088 }
Chris Lattner7546c212001-11-10 07:28:25 +000089
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000090 // Remove all types that this type contains as well... do not remove types
91 // that are referenced only through pointers, because we depend on the size of
92 // the pointer, not on what the structure points to.
Chris Lattner7546c212001-11-10 07:28:25 +000093 //
94 for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000095 I != E; ++I) {
96 if (!isa<PointerType>(*I))
97 PruneTypes(*I, TypesToModify, ProcessedTypes);
98 }
Chris Lattner7546c212001-11-10 07:28:25 +000099}
100
Chris Lattner12739d92001-11-26 16:59:10 +0000101static bool FirstLess(const pair<unsigned, unsigned> &LHS,
102 const pair<unsigned, unsigned> &RHS) {
103 return LHS.second < RHS.second;
104}
Chris Lattner7546c212001-11-10 07:28:25 +0000105
Chris Lattner12739d92001-11-26 16:59:10 +0000106static unsigned getIndex(const vector<pair<unsigned, unsigned> > &Vec,
107 unsigned Field) {
108 for (unsigned i = 0; ; ++i)
109 if (Vec[i].first == Field) return i;
110}
111
Chris Lattnere9754ef2002-07-23 18:03:11 +0000112static inline void GetTransformation(const TargetData &TD, const StructType *ST,
Chris Lattner12739d92001-11-26 16:59:10 +0000113 vector<int> &Transform,
Chris Lattner497c60c2002-05-07 18:12:18 +0000114 enum SimpleStructMutation::Transform XForm) {
Chris Lattner12739d92001-11-26 16:59:10 +0000115 unsigned NumElements = ST->getElementTypes().size();
116 Transform.reserve(NumElements);
117
118 switch (XForm) {
Chris Lattnerf4de63f2002-01-21 07:31:50 +0000119 case SimpleStructMutation::SwapElements:
Chris Lattner12739d92001-11-26 16:59:10 +0000120 // The transformation to do is: just simply swap the elements
121 for (unsigned i = 0; i < NumElements; ++i)
122 Transform.push_back(NumElements-i-1);
123 break;
124
Chris Lattnerf4de63f2002-01-21 07:31:50 +0000125 case SimpleStructMutation::SortElements: {
Chris Lattner12739d92001-11-26 16:59:10 +0000126 vector<pair<unsigned, unsigned> > ElList;
127
128 // Build mapping from index to size
129 for (unsigned i = 0; i < NumElements; ++i)
Chris Lattner697954c2002-01-20 22:54:45 +0000130 ElList.push_back(
131 std::make_pair(i, TD.getTypeSize(ST->getElementTypes()[i])));
Chris Lattner12739d92001-11-26 16:59:10 +0000132
133 sort(ElList.begin(), ElList.end(), ptr_fun(FirstLess));
134
135 for (unsigned i = 0; i < NumElements; ++i)
136 Transform.push_back(getIndex(ElList, i));
137
138 break;
139 }
140 }
141}
Chris Lattner7546c212001-11-10 07:28:25 +0000142
Chris Lattnerbd0ef772002-02-26 21:46:54 +0000143
Chris Lattnerf4de63f2002-01-21 07:31:50 +0000144SimpleStructMutation::TransformsType
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000145 SimpleStructMutation::getTransforms(Module &, enum Transform XForm) {
Chris Lattner7546c212001-11-10 07:28:25 +0000146 // We need to know which types to modify, and which types we CAN'T modify
Chris Lattner793c6b82002-01-31 00:45:11 +0000147 // TODO: Do symbol tables as well
Chris Lattner7546c212001-11-10 07:28:25 +0000148
149 // Get the results out of the analyzers...
Chris Lattner793c6b82002-01-31 00:45:11 +0000150 FindUsedTypes &FUT = getAnalysis<FindUsedTypes>();
151 const set<const Type *> &UsedTypes = FUT.getTypes();
152
153 FindUnsafePointerTypes &FUPT = getAnalysis<FindUnsafePointerTypes>();
154 const set<PointerType*> &UnsafePTys = FUPT.getUnsafeTypes();
155
Chris Lattner7546c212001-11-10 07:28:25 +0000156
157
Chris Lattnerd5b48ca2001-11-14 11:02:49 +0000158 // Combine the two sets, weeding out non structure types. Closures in C++
159 // sure would be nice.
Chris Lattner7546c212001-11-10 07:28:25 +0000160 set<const StructType*> TypesToModify;
161 for (set<const Type *>::const_iterator I = UsedTypes.begin(),
162 E = UsedTypes.end(); I != E; ++I)
163 if (const StructType *ST = dyn_cast<StructType>(*I))
164 TypesToModify.insert(ST);
165
166
167 // Go through the Unsafe types and remove all types from TypesToModify that we
168 // are not allowed to modify, because that would be unsafe.
169 //
170 set<const Type*> ProcessedTypes;
171 for (set<PointerType*>::const_iterator I = UnsafePTys.begin(),
Chris Lattnerd5b48ca2001-11-14 11:02:49 +0000172 E = UnsafePTys.end(); I != E; ++I) {
Chris Lattner697954c2002-01-20 22:54:45 +0000173 //cerr << "Pruning type: " << *I << "\n";
Chris Lattner7546c212001-11-10 07:28:25 +0000174 PruneTypes(*I, TypesToModify, ProcessedTypes);
Chris Lattnerd5b48ca2001-11-14 11:02:49 +0000175 }
Chris Lattner7546c212001-11-10 07:28:25 +0000176
177
178 // Build up a set of structure types that we are going to modify, and
179 // information describing how to modify them.
Chris Lattner697954c2002-01-20 22:54:45 +0000180 std::map<const StructType*, vector<int> > Transforms;
Chris Lattner3a15d702002-09-26 00:17:21 +0000181 TargetData &TD = getAnalysis<TargetData>();
Chris Lattner7546c212001-11-10 07:28:25 +0000182
183 for (set<const StructType*>::iterator I = TypesToModify.begin(),
184 E = TypesToModify.end(); I != E; ++I) {
185 const StructType *ST = *I;
Chris Lattner7546c212001-11-10 07:28:25 +0000186
187 vector<int> &Transform = Transforms[ST]; // Fill in the map directly
Chris Lattnere9754ef2002-07-23 18:03:11 +0000188 GetTransformation(TD, ST, Transform, XForm);
Chris Lattner7546c212001-11-10 07:28:25 +0000189 }
190
Chris Lattner12739d92001-11-26 16:59:10 +0000191 return Transforms;
Chris Lattner7546c212001-11-10 07:28:25 +0000192}
Brian Gaeked0fde302003-11-11 22:41:34 +0000193
194} // End llvm namespace