@@ -46,90 +46,22 @@ static cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
46
46
cl::desc(" Output file" ),
47
47
cl::sub(FromJSON));
48
48
49
- namespace {
50
- // A structural representation of the JSON input.
51
- struct DeserializableCtx {
52
- GlobalValue::GUID Guid = 0 ;
53
- std::vector<uint64_t > Counters;
54
- std::vector<std::vector<DeserializableCtx>> Callsites;
55
- };
56
-
57
- ctx_profile::ContextNode *
58
- createNode (std::vector<std::unique_ptr<char []>> &Nodes,
59
- const std::vector<DeserializableCtx> &DCList);
60
-
61
- // Convert a DeserializableCtx into a ContextNode, potentially linking it to
62
- // its sibling (e.g. callee at same callsite) "Next".
63
- ctx_profile::ContextNode *
64
- createNode (std::vector<std::unique_ptr<char []>> &Nodes,
65
- const DeserializableCtx &DC,
66
- ctx_profile::ContextNode *Next = nullptr ) {
67
- auto AllocSize = ctx_profile::ContextNode::getAllocSize (DC.Counters .size (),
68
- DC.Callsites .size ());
69
- auto *Mem = Nodes.emplace_back (std::make_unique<char []>(AllocSize)).get ();
70
- std::memset (Mem, 0 , AllocSize);
71
- auto *Ret = new (Mem) ctx_profile::ContextNode (DC.Guid , DC.Counters .size (),
72
- DC.Callsites .size (), Next);
73
- std::memcpy (Ret->counters (), DC.Counters .data (),
74
- sizeof (uint64_t ) * DC.Counters .size ());
75
- for (const auto &[I, DCList] : llvm::enumerate (DC.Callsites ))
76
- Ret->subContexts ()[I] = createNode (Nodes, DCList);
77
- return Ret;
78
- }
79
-
80
- // Convert a list of DeserializableCtx into a linked list of ContextNodes.
81
- ctx_profile::ContextNode *
82
- createNode (std::vector<std::unique_ptr<char []>> &Nodes,
83
- const std::vector<DeserializableCtx> &DCList) {
84
- ctx_profile::ContextNode *List = nullptr ;
85
- for (const auto &DC : DCList)
86
- List = createNode (Nodes, DC, List);
87
- return List;
88
- }
89
- } // namespace
90
-
91
- namespace llvm {
92
- namespace json {
93
- // Hook into the JSON deserialization.
94
- bool fromJSON (const Value &E, DeserializableCtx &R, Path P) {
95
- json::ObjectMapper Mapper (E, P);
96
- return Mapper && Mapper.map (" Guid" , R.Guid ) &&
97
- Mapper.map (" Counters" , R.Counters ) &&
98
- Mapper.mapOptional (" Callsites" , R.Callsites );
99
- }
100
- } // namespace json
101
- } // namespace llvm
102
-
103
49
// Save the bitstream profile from the JSON representation.
104
50
Error convertFromJSON () {
105
51
auto BufOrError = MemoryBuffer::getFileOrSTDIN (InputFilename);
106
52
if (!BufOrError)
107
53
return createFileError (InputFilename, BufOrError.getError ());
108
- auto P = json::parse (BufOrError.get ()->getBuffer ());
109
- if (!P)
110
- return P.takeError ();
111
54
112
- std::vector<DeserializableCtx> DCList;
113
- json::Path::Root R (" " );
114
- if (!fromJSON (*P, DCList, R))
115
- return R.getError ();
116
- // Nodes provides memory backing for the ContextualNodes.
117
- std::vector<std::unique_ptr<char []>> Nodes;
118
55
std::error_code EC;
119
- raw_fd_stream Out (OutputFilename, EC);
56
+ // Using a fd_ostream instead of a fd_stream. The latter would be more
57
+ // efficient as the bitstream writer supports incremental flush to it, but the
58
+ // json scenario is for test, and file size scalability doesn't really concern
59
+ // us.
60
+ raw_fd_ostream Out (OutputFilename, EC);
120
61
if (EC)
121
62
return createStringError (EC, " failed to open output" );
122
- PGOCtxProfileWriter Writer (Out);
123
- for (const auto &DC : DCList) {
124
- auto *TopList = createNode (Nodes, DC);
125
- if (!TopList)
126
- return createStringError (
127
- " Unexpected error converting internal structure to ctx profile" );
128
- Writer.write (*TopList);
129
- }
130
- if (EC)
131
- return createStringError (EC, " failed to write output" );
132
- return Error::success ();
63
+
64
+ return llvm::createCtxProfFromJSON (BufOrError.get ()->getBuffer (), Out);
133
65
}
134
66
135
67
int main (int argc, const char **argv) {
0 commit comments