22
33#include < cassert>
44#include < string>
5- #include < utility>
65
76#include " lib/Dialect/Debug/IR/DebugOps.h"
87#include " lib/Dialect/LWE/IR/LWETypes.h"
@@ -63,9 +62,39 @@ FailureOr<Type> getPrivateKeyType(func::FuncOp op) {
6362 return lwePrivateKeyType;
6463}
6564
65+ void populateDebugFuncCache (ModuleOp module ,
66+ llvm::DenseMap<Type, func::FuncOp>& typeToDebugFunc,
67+ llvm::DenseSet<StringRef>& debugFuncNames) {
68+ for (auto funcOp : module .getOps <func::FuncOp>()) {
69+ if (!funcOp.isExternal ()) continue ;
70+ if (!funcOp.getName ().starts_with (" __heir_debug_" )) continue ;
71+ if (funcOp.getArgumentTypes ().size () != 2 ) continue ;
72+ if (!funcOp.getResultTypes ().empty ()) continue ;
73+
74+ typeToDebugFunc[funcOp.getFunctionType ()] = funcOp;
75+ debugFuncNames.insert (funcOp.getName ());
76+ }
77+ }
78+
79+ static bool isAlreadyDebugged (Value value,
80+ const llvm::DenseSet<StringRef>& debugFuncNames) {
81+ for (auto & use : value.getUses ()) {
82+ Operation* user = use.getOwner ();
83+ if (isa<debug::ValidateOp>(user)) {
84+ return true ;
85+ }
86+ if (auto callOp = dyn_cast<func::CallOp>(user)) {
87+ if (debugFuncNames.contains (callOp.getCallee ())) {
88+ return true ;
89+ }
90+ }
91+ }
92+ return false ;
93+ }
94+
6695func::FuncOp getOrCreateExternalDebugFunc (
67- ModuleOp module , Type lwePrivateKeyType , Type valueType ,
68- llvm::DenseMap<Type, func::FuncOp>& typeToDebugFunc) {
96+ ModuleOp module , SymbolTable& symbolTable , Type lwePrivateKeyType ,
97+ Type valueType, llvm::DenseMap<Type, func::FuncOp>& typeToDebugFunc) {
6998 auto * context = module .getContext ();
7099 auto debugFuncType =
71100 FunctionType::get (context, {lwePrivateKeyType, valueType}, {});
@@ -75,28 +104,29 @@ func::FuncOp getOrCreateExternalDebugFunc(
75104 return it->second ;
76105 }
77106
78- int counter = typeToDebugFunc.size ();
79- std::string funcName = " __heir_debug_" + std::to_string (counter);
107+ unsigned uniquingCounter = typeToDebugFunc.size ();
108+ SmallString<128 > funcName = SymbolTable::generateSymbolName<128 >(
109+ " __heir_debug" ,
110+ [&](StringRef name) { return symbolTable.lookup (name) != nullptr ; },
111+ uniquingCounter);
80112
81- // Assert that this name is not already in use.
82- assert (!module .lookupSymbol <func::FuncOp>(funcName) &&
83- " Symbol already exists" );
84-
85- ImplicitLocOpBuilder b =
86- ImplicitLocOpBuilder::atBlockBegin (module .getLoc (), module .getBody ());
87- auto funcOp = func::FuncOp::create (b, funcName, debugFuncType);
113+ auto funcOp = func::FuncOp::create (module .getLoc (), funcName, debugFuncType);
88114 // required for external func call
89115 funcOp.setPrivate ();
90116
117+ symbolTable.insert (funcOp, module .getBody ()->begin ());
118+
91119 typeToDebugFunc[debugFuncType] = funcOp;
92120 return funcOp;
93121}
94122
95- void insertValidationOps (func::FuncOp op) {
123+ void insertValidationOps (func::FuncOp op,
124+ const llvm::DenseSet<StringRef>& debugFuncNames) {
96125 int count = 0 ;
97126 auto insertValidate = [&](Value value, OpBuilder& b) {
98127 Type valueType = value.getType ();
99128 if (isa<LWECiphertextType>(getElementTypeOrSelf (valueType))) {
129+ if (isAlreadyDebugged (value, debugFuncNames)) return ;
100130 debug::ValidateOp::create (b, value.getLoc (), value,
101131 " heir_debug_" + std::to_string (count++),
102132 nullptr );
@@ -121,8 +151,8 @@ void insertValidationOps(func::FuncOp op) {
121151}
122152
123153LogicalResult lowerValidationOps (
124- func::FuncOp op, Value privateKey, int messageSize ,
125- llvm::DenseMap<Type, func::FuncOp>& typeToDebugFunc) {
154+ func::FuncOp op, SymbolTable& symbolTable, Value privateKey ,
155+ int messageSize, llvm::DenseMap<Type, func::FuncOp>& typeToDebugFunc) {
126156 auto module = op->getParentOfType <ModuleOp>();
127157 Type lwePrivateKeyType = privateKey.getType ();
128158
@@ -141,10 +171,10 @@ LogicalResult lowerValidationOps(
141171 attrs.push_back (b.getNamedAttr (
142172 " message.size" , b.getStringAttr (std::to_string (messageSize))));
143173
144- auto debugFunc = getOrCreateExternalDebugFunc (module , lwePrivateKeyType,
145- valueType, typeToDebugFunc);
146- auto callOp =
147- b. create <func::CallOp>(debugFunc, ArrayRef<Value>{privateKey, value});
174+ auto debugFunc = getOrCreateExternalDebugFunc (
175+ module , symbolTable, lwePrivateKeyType, valueType, typeToDebugFunc);
176+ auto callOp = func::CallOp::create (b, b. getLoc (), debugFunc,
177+ ArrayRef<Value>{privateKey, value});
148178 callOp->setDialectAttrs (attrs);
149179
150180 validateOp.erase ();
@@ -166,6 +196,10 @@ struct AddDebugPort : impl::AddDebugPortBase<AddDebugPort> {
166196 ModuleOp module = cast<ModuleOp>(getOperation ());
167197 SymbolTable symbolTable (module );
168198
199+ llvm::DenseMap<Type, func::FuncOp> typeToDebugFunc;
200+ llvm::DenseSet<StringRef> debugFuncNames;
201+ populateDebugFuncCache (module , typeToDebugFunc, debugFuncNames);
202+
169203 SmallVector<func::FuncOp, 16 > worklist;
170204 llvm::DenseMap<func::FuncOp, Type> funcToKeyType;
171205 if (failed (identifyInitialTargets (module , symbolTable, funcToKeyType,
@@ -183,7 +217,7 @@ struct AddDebugPort : impl::AddDebugPortBase<AddDebugPort> {
183217
184218 if (insertDebugAfterEveryOp) {
185219 for (auto & [func, _] : funcToKeyType) {
186- insertValidationOps (func);
220+ insertValidationOps (func, debugFuncNames );
187221 }
188222 }
189223
@@ -198,8 +232,8 @@ struct AddDebugPort : impl::AddDebugPortBase<AddDebugPort> {
198232 return ;
199233 }
200234
201- llvm::DenseMap<Type, func::FuncOp> typeToDebugFunc;
202- if ( failed ( lowerAllValidationOps ( module , funcToKeyType, typeToDebugFunc))) {
235+ if ( failed ( lowerAllValidationOps ( module , symbolTable, funcToKeyType,
236+ typeToDebugFunc))) {
203237 signalPassFailure ();
204238 return ;
205239 }
@@ -229,18 +263,21 @@ struct AddDebugPort : impl::AddDebugPortBase<AddDebugPort> {
229263 }
230264
231265 if (entryFunc) {
232- auto type = getPrivateKeyType (entryFunc);
233- if (succeeded (type)) {
266+ bool shouldProcess =
267+ containsAnyOperations<debug::ValidateOp>(entryFunc) ||
268+ insertDebugAfterEveryOp;
269+
270+ if (shouldProcess) {
271+ auto type = getPrivateKeyType (entryFunc);
272+ if (failed (type)) {
273+ entryFunc.emitError (
274+ " Cannot infer LWE private key type for entry function" );
275+ return failure ();
276+ }
234277 funcToKeyType[entryFunc] = *type;
235278 worklist.push_back (entryFunc);
236- return success ();
237- }
238-
239- if (containsAnyOperations<debug::ValidateOp>(entryFunc)) {
240- entryFunc.emitError (
241- " Cannot infer LWE private key type for entry function" );
242- return failure ();
243279 }
280+ return success ();
244281 }
245282
246283 for (auto funcOp : module .getOps <func::FuncOp>()) {
@@ -404,7 +441,8 @@ struct AddDebugPort : impl::AddDebugPortBase<AddDebugPort> {
404441 // / \param typePairToInt Map to track generated debug function names.
405442 // / \return success() if successful, failure() otherwise.
406443 LogicalResult lowerAllValidationOps (
407- ModuleOp module , const llvm::DenseMap<func::FuncOp, Type>& funcToKeyType,
444+ ModuleOp module , SymbolTable& symbolTable,
445+ const llvm::DenseMap<func::FuncOp, Type>& funcToKeyType,
408446 llvm::DenseMap<Type, func::FuncOp>& typeToDebugFunc) {
409447 for (auto funcOp : module .getOps <func::FuncOp>()) {
410448 if (funcOp.isExternal ()) continue ;
@@ -428,8 +466,8 @@ struct AddDebugPort : impl::AddDebugPortBase<AddDebugPort> {
428466 }
429467
430468 if (privateKey) {
431- if (failed (lowerValidationOps (funcOp, privateKey, messageSize ,
432- typeToDebugFunc))) {
469+ if (failed (lowerValidationOps (funcOp, symbolTable, privateKey ,
470+ messageSize, typeToDebugFunc))) {
433471 funcOp.emitError (" failed to lower validation ops" );
434472 return failure ();
435473 }
0 commit comments