1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25 
26 
27 #include "trace_writer.hpp"
28 #include "trace_format.hpp"
29 
30 
31 namespace trace {
32 
33 
34 class ModelWriter : public Visitor
35 {
36 protected:
37     Writer &writer;
38 
39 public:
ModelWriter(Writer & _writer)40     ModelWriter(Writer &_writer) :
41         writer(_writer) {
42     }
43 
visit(Null *)44     void visit(Null *) override {
45         writer.writeNull();
46     }
47 
visit(Bool * node)48     void visit(Bool *node) override {
49         writer.writeBool(node->value);
50     }
51 
visit(SInt * node)52     void visit(SInt *node) override {
53         writer.writeSInt(node->value);
54     }
55 
visit(UInt * node)56     void visit(UInt *node) override {
57         writer.writeUInt(node->value);
58     }
59 
visit(Float * node)60     void visit(Float *node) override {
61         writer.writeFloat(node->value);
62     }
63 
visit(Double * node)64     void visit(Double *node) override {
65         writer.writeDouble(node->value);
66     }
67 
visit(String * node)68     void visit(String *node) override {
69         writer.writeString(node->value);
70     }
71 
visit(WString * node)72     void visit(WString *node) override {
73         writer.writeWString(node->value);
74     }
75 
visit(Enum * node)76     void visit(Enum *node) override {
77         writer.writeEnum(node->sig, node->value);
78     }
79 
visit(Bitmask * node)80     void visit(Bitmask *node) override {
81         writer.writeBitmask(node->sig, node->value);
82     }
83 
visit(Struct * node)84     void visit(Struct *node) override {
85         writer.beginStruct(node->sig);
86         for (unsigned i = 0; i < node->sig->num_members; ++i) {
87             _visit(node->members[i]);
88         }
89         writer.endStruct();
90     }
91 
visit(Array * node)92     void visit(Array *node) override {
93         writer.beginArray(node->values.size());
94         for (auto & value : node->values) {
95             _visit(value);
96         }
97         writer.endArray();
98     }
99 
visit(Blob * node)100     void visit(Blob *node) override {
101         writer.writeBlob(node->buf, node->size);
102     }
103 
visit(Pointer * node)104     void visit(Pointer *node) override {
105         writer.writePointer(node->value);
106     }
107 
visit(Repr * node)108     void visit(Repr *node) override {
109         writer.beginRepr();
110         _visit(node->humanValue);
111         _visit(node->machineValue);
112         writer.endRepr();
113     }
114 
visit(Call * call)115     void visit(Call *call) {
116         unsigned call_no = writer.beginEnter(call->sig, call->thread_id);
117         if (call->flags & CALL_FLAG_FAKE) {
118             writer.writeFlags(FLAG_FAKE);
119         }
120         if (call->backtrace != NULL) {
121             writer.beginBacktrace(call->backtrace->size());
122             for (auto & frame : *call->backtrace) {
123                 writer.writeStackFrame(frame);
124             }
125             writer.endBacktrace();
126         }
127         for (unsigned i = 0; i < call->args.size(); ++i) {
128             if (call->args[i].value) {
129                 writer.beginArg(i);
130                 _visit(call->args[i].value);
131                 writer.endArg();
132             }
133         }
134         writer.endEnter();
135         writer.beginLeave(call_no);
136         if (call->ret) {
137             writer.beginReturn();
138             _visit(call->ret);
139             writer.endReturn();
140         }
141         writer.endLeave();
142     }
143 };
144 
145 
writeCall(Call * call)146 void Writer::writeCall(Call *call) {
147     ModelWriter visitor(*this);
148     visitor.visit(call);
149 }
150 
151 
152 } /* namespace trace */
153 
154