Computer Laboratory

State.cpp
Go to the documentation of this file.
1 
2 /*
3  * Copyright (c) 2013 Jonathan Anderson
4  * All rights reserved.
5  *
6  * This software was developed by SRI International and the University of
7  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
8  * ("CTSRD"), as part of the DARPA CRASH research programme.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include "State.h"
33 #include "Transition.h"
34 #include "tesla.pb.h"
35 
36 #include <llvm/ADT/Twine.h>
37 #include <sstream>
38 
39 using namespace llvm;
40 using std::string;
41 
42 namespace tesla {
43 
44 State* State::Builder::Build() {
45  llvm::OwningPtr<State> New(new State(States.size(), Start, Accept, Name));
46  States.push_back(New.get());
47 
48  if (RefCount >= 0) {
49  auto& Refs = New->VariableReferences;
50  Refs.reset(new const Argument*[RefCount]);
51  bzero(Refs.get(), RefCount * sizeof(Refs[0]));
52 
53  New->Refs = MutableReferenceVector(Refs.get(), RefCount);
54  }
55 
56  return New.take();
57 }
58 
59 State::~State() {
60  for (Transition *T : Transitions) delete T;
61 }
62 
63 void State::AddTransition(OwningPtr<Transition>& T)
64 {
65  Transitions.push_back(T.take());
66 }
67 
68 void State::UpdateReferences(const Transition& T)
69 {
70  if (VariableReferences && !T.InScope())
71  return;
72 
73  OwningArrayPtr<const Argument*> Args;
74  ReferenceVector NewRefs;
75  T.ReferencesThusFar(Args, NewRefs);
76 
77  assert(!VariableReferences
78  || (NewRefs.size() == 0)
79  || (Refs.size() == NewRefs.size()));
80  const size_t Len = NewRefs.size();
81  assert(Len < 8 * sizeof(Mask()));
82 
83  if (!VariableReferences) {
84  // If we don't have any bound variables, just copy NewRefs.
85  VariableReferences.reset(new const Argument*[Len]);
86  memcpy(VariableReferences.get(), NewRefs.data(), Len * sizeof(Refs[0]));
87 
88  Refs = MutableReferenceVector(VariableReferences.get(), Len);
89  return;
90  }
91 
92 #ifndef NDEBUG
93  if (T.InScope()) {
94  for (auto *Arg : NewRefs) {
95  if (Arg == NULL)
96  continue;
97 
98  assert(Arg->type() == Argument::Variable);
99  assert(((size_t) Arg->index()) <= Len);
100  }
101 
102  uint32_t NewMask = 0;
103  for (size_t i = 0; i < Len; i++) {
104  if ((NewRefs[i] != NULL) && (NewRefs[i]->type() == Argument::Constant))
105  NewMask |= (1 << i);
106  }
107 
108  assert((Mask() & NewMask) == NewMask);
109  }
110 #endif
111 }
112 
113 uint32_t State::Mask() const {
114  uint32_t Mask = 0;
115  ReferenceVector Refs = References();
116 
117  for (size_t i = 0; i < Refs.size(); i++) {
118  if (Refs[i] && Refs[i]->type() == Argument::Variable)
119  Mask |= (1 << i);
120  }
121 
122 
123  return Mask;
124 }
125 
126 string State::Name(bool QuoteNonNumeric) const {
127  std::stringstream ss;
128  if (name.empty()) {
129  ss << ID();
130  } else {
131  auto Quote = (QuoteNonNumeric ? "'" : "");
132  ss << Quote << name << Quote;
133  }
134 
135  return ss.str();
136 }
137 
138 
139 string State::String() const {
140  assert(VariableReferences);
141 
142  std::stringstream ss;
143  ss << "state " << Name(true) << " " << InstanceName(Refs, true) << ":";
144 
145  for (const auto& I : Transitions) {
146  const Transition& T = *I;
147  ss << " " << T.String();
148  }
149 
150  return ss.str();
151 }
152 
153 string State::Dot() const {
154  assert(VariableReferences);
155  string NameExtra = name.empty() ? "" : ("\\n\\\"" + name + "\\\"");
156 
157  return (
158  Twine(ID())
159  + " [ label = \""
160  + "state " + Twine(ID())
161  + NameExtra
162  + "\\n" + InstanceName(Refs, false) + "\""
163  + (IsAcceptingState() ? ", shape = doublecircle" : "")
164  + " ];"
165  ).str();
166 }
167 
168 } // namespace tesla