summaryrefslogtreecommitdiff
path: root/lib/VMCore/iMemory.cpp
blob: 9c52da3abdedc00bca3fa5c7f5ae976bfbeb492a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//===-- iMemory.cpp - Implement Memory instructions --------------*- C++ -*--=//
//
// This file implements the various memory related classes defined in iMemory.h
//
//===----------------------------------------------------------------------===//

#include "llvm/iMemory.h"
#include "llvm/ConstPoolVals.h"

//===----------------------------------------------------------------------===//
//                        MemAccessInst Implementation
//===----------------------------------------------------------------------===//

// getIndexedType - Returns the type of the element that would be loaded with
// a load instruction with the specified parameters.
//
// A null type is returned if the indices are invalid for the specified 
// pointer type.
//
/* static */
const Type* MemAccessInst::getIndexedType(const Type *Ptr, 
					const vector<ConstPoolVal*> &Idx,
					bool AllowStructLeaf = false) {
  if (!Ptr->isPointerType()) return 0;   // Type isn't a pointer type!
 
  // Get the type pointed to...
  Ptr = ((const PointerType*)Ptr)->getValueType();
  
  if (Ptr->isStructType()) {
    unsigned CurIDX = 0;
    while (Ptr->isStructType()) {
      if (Idx.size() == CurIDX) 
	return AllowStructLeaf ? Ptr : 0;   // Can't load a whole structure!?!?
      if (Idx[CurIDX]->getType() != Type::UByteTy) return 0; // Illegal idx
      unsigned NextIdx = ((ConstPoolUInt*)Idx[CurIDX++])->getValue();
      
      const StructType *ST = (const StructType *)Ptr;
      Ptr = ST->getElementTypes()[NextIdx];
    }
    return Ptr;
  } else if (Ptr->isArrayType()) {
    assert(0 && "Loading from arrays not implemented yet!");
  } else {
    return (Idx.size() == 0) ? Ptr : 0;  // Load directly through ptr
  }
}

/* static */
unsigned int
MemAccessInst::getIndexedOfsetForTarget(const Type *Ptr, 
					const vector<ConstPoolVal*> &Idx,
					const TargetMachine& targetMachine)
{
  if (!Ptr->isPointerType())
    return 0;				// Type isn't a pointer type!
 
  unsigned int curOffset = 0;
  
  // Get the type pointed to...
  Ptr = ((const PointerType*) Ptr)->getValueType();
  
  if (Ptr->isStructType()) {
    unsigned CurIDX = 0;		// which element of Idx vector
    while (Ptr->isStructType()) {
      const StructType * SPtr = (StructType *) Ptr;
      
      if (Idx.size() == CurIDX) 
	break;
      
      assert (Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
      unsigned NextIdx = ((ConstPoolUInt*)Idx[CurIDX++])->getValue();
      
      // add the offset for the current element
      curOffset += SPtr->getElementOffset(NextIdx, targetMachine);
      
      // and update Ptr to refer to current element
      Ptr = SPtr->getElementTypes()[NextIdx];
    }
    return curOffset;
  } else if (Ptr->isArrayType()) {
    assert(0 && "Loading from arrays not implemented yet!");
  } else {
    assert (Idx.size() == 0 && "Indexing type that is not struct or array?");
    return 0;				// Load directly through ptr
  }
}
  

//===----------------------------------------------------------------------===//
//                           LoadInst Implementation
//===----------------------------------------------------------------------===//

LoadInst::LoadInst(Value *Ptr, const vector<ConstPoolVal*> &Idx,
		   const string &Name = "")
  : MemAccessInst(getIndexedType(Ptr->getType(), Idx), Load, Idx, Name)
{
  assert(getIndexedType(Ptr->getType(), Idx) && "Load operands invalid!");
  Operands.reserve(1+Idx.size());
  Operands.push_back(Use(Ptr, this));
  
  for (unsigned i = 0, E = Idx.size(); i != E; ++i)
    Operands.push_back(Use(Idx[i], this));
  
}


//===----------------------------------------------------------------------===//
//                           StoreInst Implementation
//===----------------------------------------------------------------------===//

StoreInst::StoreInst(Value *Val, Value *Ptr, const vector<ConstPoolVal*> &Idx,
		     const string &Name = "")
  : MemAccessInst(Type::VoidTy, Store, Idx, Name) {
  assert(getIndexedType(Ptr->getType(), Idx) && "Store operands invalid!");
  
  Operands.reserve(2+Idx.size());
  Operands.push_back(Use(Val, this));
  Operands.push_back(Use(Ptr, this));

  for (unsigned i = 0, E = Idx.size(); i != E; ++i)
    Operands.push_back(Use(Idx[i], this));
}


//===----------------------------------------------------------------------===//
//                       GetElementPtrInst Implementation
//===----------------------------------------------------------------------===//

GetElementPtrInst::GetElementPtrInst(Value *Ptr, 
				     const vector<ConstPoolVal*> &Idx,
				     const string &Name = "")
  : MemAccessInst(PointerType::getPointerType(getIndexedType(Ptr->getType(),
							     Idx, true)),
		  GetElementPtr, Idx, Name) {
  assert(getIndexedType(Ptr->getType(), Idx, true) && "gep operands invalid!");
  Operands.reserve(1+Idx.size());
  Operands.push_back(Use(Ptr, this));

  for (unsigned i = 0, E = Idx.size(); i != E; ++i)
    Operands.push_back(Use(Idx[i], this));
}

bool GetElementPtrInst::isStructSelector() const {
  return ((PointerType*)Operands[0]->getType())->getValueType()->isStructType();
}