File: CompileContext.C

package info (click to toggle)
guavac 1.2-2
  • links: PTS
  • area: main
  • in suites: potato
  • size: 2,728 kB
  • ctags: 2,387
  • sloc: cpp: 20,367; yacc: 1,664; makefile: 504; lex: 348; ansic: 286; sh: 263
file content (194 lines) | stat: -rw-r--r-- 6,311 bytes parent folder | download | duplicates (2)
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// Copyright (c) 1996  David Engberg  All rights reserved
// $Id: CompileContext.C,v 1.4 1997/11/10 00:48:06 geppetto Exp $
#pragma implementation
#include "CompileContext.h"
#include "Compiler.h"
#include "IntermediateClass.h"
#include "IntermediateFunction.h"
#include <cassert>

//
//  Method name : CCompileContext
//  Description : Constructs a compile context that gloms together a group
//    of different attributes, each of with is provided as an argument.
//    It initially assumes that all local variables have not been initialized
//    and the current entry point is reachable.
//    All of the provided pointer arguments are assumed to be valid aliases
//    to these elements.
//
CCompileContext::CCompileContext(CCompiler* compiler,
				 const CIntermediateClass* inClass,
				 CJavaClassFile* classInfo,
				 const CIntermediateFunction* inMethod,
				 CJavaMethodInfo* methodInfo,
				 unsigned long localVariablesUsed)
  : fCompilerAlias(compiler),
    fIntermediateClassAlias(inClass),
    fClassAlias(classInfo),
    fIntermediateMethodAlias(inMethod),
    fMethodAlias(methodInfo),
    fLocalVariablesInitialized(localVariablesUsed),
    fReachable(true)
{
  assert(compiler != 0 && classInfo != 0 && methodInfo != 0);
}

//
//  Method name : CCompileContext
//  Description : Copy constructor.
//
CCompileContext::CCompileContext(const CCompileContext& source)
  : fCompilerAlias(source.fCompilerAlias),
    fIntermediateClassAlias(source.fIntermediateClassAlias),
    fClassAlias(source.fClassAlias),
    fIntermediateMethodAlias(source.fIntermediateMethodAlias),
    fMethodAlias(source.fMethodAlias),
    fLocalVariablesInitialized(source.fLocalVariablesInitialized),
    fReachable(source.fReachable),
    fThrowable(source.fThrowable)
{
}

//
//  Method name : ~CCompileContext
//  Description : Destructor
//
CCompileContext::~CCompileContext()
{
}

//
//  Method name : operator=
//  Description : Assignment operator.
//
CCompileContext&
CCompileContext::operator=(const CCompileContext& source)
{
  if (&source != this) {
    fCompilerAlias = source.fCompilerAlias;
    fClassAlias = source.fClassAlias;
    fMethodAlias = source.fMethodAlias;
    fLocalVariablesInitialized = source.fLocalVariablesInitialized;
    fReachable = source.fReachable;
    fThrowable = source.fThrowable;
  }
  return *this;
}

//
//  Method name : IsVariableInitialized
//  Description : Returns true if the local variable in the current compile
//    context at the provided index has already been initialized.
//
bool
CCompileContext::IsVariableInitialized(unsigned long index) const
{
  return fLocalVariablesInitialized.GetElement(index);
}

//
//  Method name : InitializeVariable
//  Description : Indicates to the compile context that the provided local
//    variable slot has been assigned to, and therefore initialized.
//
void
CCompileContext::InitializeVariable(unsigned long index)
{
  fLocalVariablesInitialized.SetElement(index);
}

//
//  Method name : Merge
//  Description : This operation takes two compile contexts and merges them
//    at the join node of a control-flow graph.  This is the type of operation
//    that happens, for example, after the 'then' and 'else' branches of
//    an 'if' statement are calculated and the results need to be merged.
//    This operation assumes the two compile contexts come from the same
//    root and tries to reflect the state of the control flow regardless which
//    branch may be taken at run-time.
//    This modifies the current compile context to take on the merged result,
//    but leaves the provided argument untouched.
//
void
CCompileContext::Merge(const CCompileContext& other)
{
  assert(fCompilerAlias == other.fCompilerAlias &&
	 fClassAlias == other.fClassAlias &&
	 fMethodAlias == other.fMethodAlias);
  if (other.fReachable) {
    if (fReachable) {
      fLocalVariablesInitialized &= other.fLocalVariablesInitialized;
    } else {
      fLocalVariablesInitialized = other.fLocalVariablesInitialized;
    }
  }
  fReachable |= other.fReachable;
  // don't do anything with fThrowable
}

//
//  Method name : Throwable
//  Description : Returns true if the provided type signature can be legally
//    thrown in this compile context.  This means that it is either declared
//    in the 'throws' clause for this method, handled by a surrounding
//    try/catch clause, or descends from Error or RuntimeException.
//
bool
CCompileContext::Throwable(const CJavaTypeSignature& type) const
{
  static const CJavaTypeSignature errorType(CCompiler::kErrorName);
  static const CJavaTypeSignature
    runtimeExceptionType(CCompiler::kRuntimeExceptionName);
  if (fCompilerAlias->SameType(type, errorType) ||
      fCompilerAlias->AssignableSubtype(type, errorType) ||
      fCompilerAlias->SameType(type, runtimeExceptionType) ||
      fCompilerAlias->AssignableSubtype(type, runtimeExceptionType)) {
    return true;
  }
  deque<CJavaTypeSignature>::const_iterator end = fThrowable.end();
  for (deque<CJavaTypeSignature>::const_iterator i = fThrowable.begin();
       !(i == end); ++i) {
    if (fCompilerAlias->SameType(type, *i) ||
	fCompilerAlias->AssignableSubtype(type, *i)) {
      return true;
    }
  }
  return false;
}

//
//  Method name : PushThrowable
//  Description : Specifies that values of the provided type can be thrown
//    within this context.  These throwable types are held in a LIFO, so
//    the last one pushed will be the first one popped.
//
void
CCompileContext::PushThrowable(const CJavaTypeSignature& type)
{
  fThrowable.push_back(type);
}

//
//  Method name : PopThrowable
//  Description : Removes the last-pushed type from this context's throwable
//    stack.
//
void
CCompileContext::PopThrowable()
{
  fThrowable.pop_back();
}

//
//  Method name : GetLocalVariableLocation
//  Description : The local variable offsets that are originally assigned
//    are later thrown off by the stupid synthetic constructor parameters
//    that need to be inserted to support access to outer final local
//    variables.  As a result, any access to a local variable slot needs
//    to call this to make sure its offset is correct.
//
unsigned short
CCompileContext::GetLocalVariableLocation(unsigned short from) const
{
  return fIntermediateMethodAlias->GetLocalVariableLocation(from);
}