3737// )
3838// )
3939//
40- // Instrumenting void* malloc(int32_t) with a user-defined tracer
41- // (trace_allocation):
40+ // Instrumenting void* malloc(int32_t) with a user-defined name
41+ // of the tracer (trace_allocation):
4242// Before:
4343// (call $malloc
4444// (local.const 32))
5858// )
5959//
6060
61- #include < set >
61+ #include < unordered_map >
6262
6363#include " asmjs/shared-constants.h"
6464#include " ir/import-utils.h"
6868
6969namespace wasm {
7070
71- struct TracedFunction {
72- Name originName;
73- Name tracerName;
74- Type params;
75- Type results;
76- };
77- bool operator <(const TracedFunction& lhs, const TracedFunction& rhs) {
78- return lhs.originName < rhs.originName ;
79- }
80-
81- static Type strToType (const std::string& strType) {
82- if (strType == " i32" ) {
83- return Type::i32 ;
84- } else if (strType == " i64" ) {
85- return Type::i64 ;
86- } else if (strType == " f32" ) {
87- return Type::f32 ;
88- } else if (strType == " f64" ) {
89- return Type::f64 ;
90- } else if (strType == " v128" ) {
91- return Type::v128;
92- } else {
93- Fatal () << " Failed to parse type '" << strType << " '" ;
94- }
95- }
71+ using TracedFunctions =
72+ std::unordered_map<Name /* originName */ , Name /* tracerName */ >;
9673
9774struct AddTraceWrappers : public WalkerPass <PostWalker<AddTraceWrappers>> {
98- AddTraceWrappers (std::set<TracedFunction> tracedFunctions)
75+ AddTraceWrappers (TracedFunctions tracedFunctions)
9976 : tracedFunctions(std::move(tracedFunctions)) {}
10077 void visitCall (Call* curr) {
10178 auto * target = getModule ()->getFunction (curr->target );
10279
103- auto iter = std::find_if (tracedFunctions.begin (),
104- tracedFunctions.end (),
105- [target](const TracedFunction& f) {
106- return f.originName == target->name ;
107- });
80+ auto iter = tracedFunctions.find (target->name );
10881 if (iter != tracedFunctions.end ()) {
109- addInstrumentation (curr, target, iter->tracerName );
82+ addInstrumentation (curr, target, iter->second );
11083 }
11184 }
11285
@@ -143,7 +116,7 @@ struct AddTraceWrappers : public WalkerPass<PostWalker<AddTraceWrappers>> {
143116 wrapperName, trackerCallParams, Type::BasicType::none)}));
144117 }
145118
146- std::set<TracedFunction> tracedFunctions;
119+ TracedFunctions tracedFunctions;
147120};
148121
149122struct TraceCalls : public Pass {
@@ -154,39 +127,55 @@ struct TraceCalls : public Pass {
154127 auto functionsDefinitions = getPassOptions ().getArgument (
155128 " trace-calls" ,
156129 " TraceCalls usage: wasm-opt "
157- " --trace-calls=FUNCTION_TO_TRACE[:TRACER_NAME][,RESULT1_TYPE]"
158- " [,PARAM1_TYPE[,PARAM2_TYPE[,...]]][;...]" );
130+ " --trace-calls=FUNCTION_TO_TRACE[:TRACER_NAME][,...]" );
159131
160132 auto tracedFunctions = parseArgument (functionsDefinitions);
161133
162134 for (const auto & tracedFunction : tracedFunctions) {
163- addImport (module , tracedFunction);
135+ auto func = module ->getFunctionOrNull (tracedFunction.first );
136+ if (!func) {
137+ std::cerr << " [TraceCalls] Function '" << tracedFunction.first
138+ << " ' not found" ;
139+ } else {
140+ addImport (module , *func, tracedFunction.second );
141+ }
164142 }
165143
166144 AddTraceWrappers (std::move (tracedFunctions)).run (getPassRunner (), module );
167145 }
168146
169147private:
170- std::set<TracedFunction> parseArgument (const std::string& arg) {
171- std::set<TracedFunction> tracedFunctions;
148+ Type getTracerParamsType (ImportInfo& info, const Function& func) {
149+ auto resultsType = func.type .getSignature ().results ;
150+ if (resultsType.isTuple ()) {
151+ Fatal () << " Failed to instrument function '" << func.name
152+ << " ': Multi-value result type is not supported" ;
153+ }
154+
155+ std::vector<Type> tracerParamTypes;
156+ if (resultsType.isConcrete ()) {
157+ tracerParamTypes.push_back (resultsType);
158+ }
159+ for (auto & op : func.type .getSignature ().params ) {
160+ tracerParamTypes.push_back (op);
161+ }
162+
163+ return Type (tracerParamTypes);
164+ }
172165
173- for (const auto & definition : String::Split (arg, " ;" )) {
174- auto parts = String::Split (definition, " ," );
175- if (parts.size () == 0 ) {
166+ TracedFunctions parseArgument (const std::string& arg) {
167+ TracedFunctions tracedFunctions;
168+
169+ for (const auto & definition : String::Split (arg, " ," )) {
170+ if (definition.empty ()) {
176171 // Empty definition, ignore.
177172 continue ;
178173 }
179174
180175 std::string originName, traceName;
181- parseFunctionName (parts[0 ], originName, traceName);
182-
183- std::vector<Type> paramsAndResults;
184- for (size_t i = 1 ; i < parts.size (); i++) {
185- paramsAndResults.push_back (strToType (parts[i]));
186- }
176+ parseFunctionName (definition, originName, traceName);
187177
188- tracedFunctions.emplace (TracedFunction{
189- Name (originName), Name (traceName), paramsAndResults, Type::none});
178+ tracedFunctions[Name (originName)] = Name (traceName);
190179 }
191180
192181 return tracedFunctions;
@@ -211,14 +200,14 @@ struct TraceCalls : public Pass {
211200 }
212201 }
213202
214- void addImport (Module* wasm, const TracedFunction & f) {
203+ void addImport (Module* wasm, const Function & f, const Name& tracerName ) {
215204 ImportInfo info (*wasm);
216205
217- if (!info.getImportedFunction (ENV, f. tracerName )) {
218- auto import =
219- Builder::makeFunction (f. tracerName , Signature (f. params , f. results ), {});
206+ if (!info.getImportedFunction (ENV, tracerName)) {
207+ auto import = Builder::makeFunction (
208+ tracerName, Signature (getTracerParamsType (info , f), Type::none ), {});
220209 import ->module = ENV;
221- import ->base = f. tracerName ;
210+ import ->base = tracerName;
222211 wasm->addFunction (std::move (import ));
223212 }
224213 }
0 commit comments