blob: c8f8896766f9e50cb12eab327b84c94a24f4320d [file] [log] [blame]
Chris Lattner7546c212001-11-10 07:28:25 +00001//===- SwapStructContents.cpp - Swap structure elements around ---*- C++ -*--=//
2//
3// This pass does a simple transformation that swaps all of the elements of the
4// struct types in the program around.
5//
6//===----------------------------------------------------------------------===//
7
8
9#include "llvm/Transforms/SwapStructContents.h"
10#include "llvm/Transforms/MutateStructTypes.h"
11#include "llvm/Analysis/FindUsedTypes.h"
12#include "llvm/Analysis/FindUnsafePointerTypes.h"
13#include "llvm/DerivedTypes.h"
14
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000015#include "llvm/Assembly/Writer.h"
16
Chris Lattner7546c212001-11-10 07:28:25 +000017// PruneTypes - Given a type Ty, make sure that neither it, or one of its
18// subtypes, occur in TypesToModify.
19//
20static void PruneTypes(const Type *Ty, set<const StructType*> &TypesToModify,
21 set<const Type*> &ProcessedTypes) {
22 if (ProcessedTypes.count(Ty)) return; // Already been checked
23 ProcessedTypes.insert(Ty);
24
25 // If the element is in TypesToModify, remove it now...
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000026 if (const StructType *ST = dyn_cast<StructType>(Ty)) {
Chris Lattner7546c212001-11-10 07:28:25 +000027 TypesToModify.erase(ST); // This doesn't fail if the element isn't present
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000028 cerr << "Unable to swap type: " << ST << endl;
29 }
Chris Lattner7546c212001-11-10 07:28:25 +000030
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000031 // Remove all types that this type contains as well... do not remove types
32 // that are referenced only through pointers, because we depend on the size of
33 // the pointer, not on what the structure points to.
Chris Lattner7546c212001-11-10 07:28:25 +000034 //
35 for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000036 I != E; ++I) {
37 if (!isa<PointerType>(*I))
38 PruneTypes(*I, TypesToModify, ProcessedTypes);
39 }
Chris Lattner7546c212001-11-10 07:28:25 +000040}
41
42
43
44// doPassInitialization - This does all of the work of the pass
45//
46bool SwapStructContents::doPassInitialization(Module *M) {
47 // We need to know which types to modify, and which types we CAN'T modify
48 FindUsedTypes FUT/*(true)*/; // TODO: Do symbol tables as well
49 FindUnsafePointerTypes FUPT;
50
51 // Simutaneously find all of the types used, and all of the types that aren't
52 // safe.
53 //
54 vector<Pass*> Analyses;
55 Analyses.push_back(&FUT);
56 Analyses.push_back(&FUPT);
57 Pass::runAllPasses(M, Analyses); // Do analyses
58
59
60 // Get the results out of the analyzers...
61 const set<PointerType*> &UnsafePTys = FUPT.getUnsafeTypes();
62 const set<const Type *> &UsedTypes = FUT.getTypes();
63
64
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000065 // Combine the two sets, weeding out non structure types. Closures in C++
66 // sure would be nice.
Chris Lattner7546c212001-11-10 07:28:25 +000067 set<const StructType*> TypesToModify;
68 for (set<const Type *>::const_iterator I = UsedTypes.begin(),
69 E = UsedTypes.end(); I != E; ++I)
70 if (const StructType *ST = dyn_cast<StructType>(*I))
71 TypesToModify.insert(ST);
72
73
74 // Go through the Unsafe types and remove all types from TypesToModify that we
75 // are not allowed to modify, because that would be unsafe.
76 //
77 set<const Type*> ProcessedTypes;
78 for (set<PointerType*>::const_iterator I = UnsafePTys.begin(),
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000079 E = UnsafePTys.end(); I != E; ++I) {
80 cerr << "Pruning type: " << *I << endl;
Chris Lattner7546c212001-11-10 07:28:25 +000081 PruneTypes(*I, TypesToModify, ProcessedTypes);
Chris Lattnerd5b48ca2001-11-14 11:02:49 +000082 }
Chris Lattner7546c212001-11-10 07:28:25 +000083
84
85 // Build up a set of structure types that we are going to modify, and
86 // information describing how to modify them.
87 map<const StructType*, vector<int> > Transforms;
88
89 for (set<const StructType*>::iterator I = TypesToModify.begin(),
90 E = TypesToModify.end(); I != E; ++I) {
91 const StructType *ST = *I;
92 unsigned NumElements = ST->getElementTypes().size();
93
94 vector<int> &Transform = Transforms[ST]; // Fill in the map directly
95 Transform.reserve(NumElements);
96
97 // The transformation to do is: just simply swap the elements
98 for (unsigned i = 0; i < NumElements; ++i)
99 Transform.push_back(NumElements-i-1);
100 }
101
102 // Create the Worker to do our stuff for us...
103 StructMutator = new MutateStructTypes(Transforms);
104
105 // Do initial work.
106 return StructMutator->doPassInitialization(M);
107}
108