@@ -272,6 +272,231 @@ static ParseResult parseStoreOp(OpAsmParser &parser, OperationState &result) {
272
272
return success ();
273
273
}
274
274
275
+ // /===----------------------------------------------------------------------===//
276
+ // / Verifying/Printing/Parsing for LLVM::InvokeOp.
277
+ // /===----------------------------------------------------------------------===//
278
+
279
+ static LogicalResult verify (InvokeOp op) {
280
+ if (op.getNumResults () > 1 )
281
+ return op.emitOpError (" must have 0 or 1 result" );
282
+ if (op.getNumSuccessors () != 2 )
283
+ return op.emitOpError (" must have normal and unwind destinations" );
284
+
285
+ if (op.getSuccessor (1 )->empty ())
286
+ return op.emitError (
287
+ " must have at least one operation in unwind destination" );
288
+
289
+ // In unwind destination, first operation must be LandingpadOp
290
+ if (!isa<LandingpadOp>(op.getSuccessor (1 )->front ()))
291
+ return op.emitError (" first operation in unwind destination should be a "
292
+ " llvm.landingpad operation" );
293
+
294
+ return success ();
295
+ }
296
+
297
+ static void printInvokeOp (OpAsmPrinter &p, InvokeOp &op) {
298
+ auto callee = op.callee ();
299
+ bool isDirect = callee.hasValue ();
300
+
301
+ p << op.getOperationName () << ' ' ;
302
+
303
+ // Either function name or pointer
304
+ if (isDirect)
305
+ p.printSymbolName (callee.getValue ());
306
+ else
307
+ p << op.getOperand (0 );
308
+
309
+ p << ' (' << op.getOperands ().drop_front (isDirect ? 0 : 1 ) << ' )' ;
310
+ p << " to " ;
311
+ p.printSuccessorAndUseList (op.getOperation (), 0 );
312
+ p << " unwind " ;
313
+ p.printSuccessorAndUseList (op.getOperation (), 1 );
314
+
315
+ p.printOptionalAttrDict (op.getAttrs (), {" callee" });
316
+
317
+ SmallVector<Type, 8 > argTypes (
318
+ llvm::drop_begin (op.getOperandTypes (), isDirect ? 0 : 1 ));
319
+
320
+ p << " : "
321
+ << FunctionType::get (argTypes, op.getResultTypes (), op.getContext ());
322
+ }
323
+
324
+ // / <operation> ::= `llvm.invoke` (function-id | ssa-use) `(` ssa-use-list `)`
325
+ // / `to` bb-id (`[` ssa-use-and-type-list `]`)?
326
+ // / `unwind` bb-id (`[` ssa-use-and-type-list `]`)?
327
+ // / attribute-dict? `:` function-type
328
+ static ParseResult parseInvokeOp (OpAsmParser &parser, OperationState &result) {
329
+ SmallVector<OpAsmParser::OperandType, 8 > operands;
330
+ FunctionType funcType;
331
+ SymbolRefAttr funcAttr;
332
+ llvm::SMLoc trailingTypeLoc;
333
+ Block *normalDest, *unwindDest;
334
+ SmallVector<Value, 4 > normalOperands, unwindOperands;
335
+
336
+ // Parse an operand list that will, in practice, contain 0 or 1 operand. In
337
+ // case of an indirect call, there will be 1 operand before `(`. In case of a
338
+ // direct call, there will be no operands and the parser will stop at the
339
+ // function identifier without complaining.
340
+ if (parser.parseOperandList (operands))
341
+ return failure ();
342
+ bool isDirect = operands.empty ();
343
+
344
+ // Optionally parse a function identifier.
345
+ if (isDirect && parser.parseAttribute (funcAttr, " callee" , result.attributes ))
346
+ return failure ();
347
+
348
+ if (parser.parseOperandList (operands, OpAsmParser::Delimiter::Paren) ||
349
+ parser.parseKeyword (" to" ) ||
350
+ parser.parseSuccessorAndUseList (normalDest, normalOperands) ||
351
+ parser.parseKeyword (" unwind" ) ||
352
+ parser.parseSuccessorAndUseList (unwindDest, unwindOperands) ||
353
+ parser.parseOptionalAttrDict (result.attributes ) || parser.parseColon () ||
354
+ parser.getCurrentLocation (&trailingTypeLoc) || parser.parseType (funcType))
355
+ return failure ();
356
+
357
+ if (isDirect) {
358
+ // Make sure types match.
359
+ if (parser.resolveOperands (operands, funcType.getInputs (),
360
+ parser.getNameLoc (), result.operands ))
361
+ return failure ();
362
+ result.addTypes (funcType.getResults ());
363
+ } else {
364
+ // Construct the LLVM IR Dialect function type that the first operand
365
+ // should match.
366
+ if (funcType.getNumResults () > 1 )
367
+ return parser.emitError (trailingTypeLoc,
368
+ " expected function with 0 or 1 result" );
369
+
370
+ Builder &builder = parser.getBuilder ();
371
+ auto *llvmDialect =
372
+ builder.getContext ()->getRegisteredDialect <LLVM::LLVMDialect>();
373
+ LLVM::LLVMType llvmResultType;
374
+ if (funcType.getNumResults () == 0 ) {
375
+ llvmResultType = LLVM::LLVMType::getVoidTy (llvmDialect);
376
+ } else {
377
+ llvmResultType = funcType.getResult (0 ).dyn_cast <LLVM::LLVMType>();
378
+ if (!llvmResultType)
379
+ return parser.emitError (trailingTypeLoc,
380
+ " expected result to have LLVM type" );
381
+ }
382
+
383
+ SmallVector<LLVM::LLVMType, 8 > argTypes;
384
+ argTypes.reserve (funcType.getNumInputs ());
385
+ for (Type ty : funcType.getInputs ()) {
386
+ if (auto argType = ty.dyn_cast <LLVM::LLVMType>())
387
+ argTypes.push_back (argType);
388
+ else
389
+ return parser.emitError (trailingTypeLoc,
390
+ " expected LLVM types as inputs" );
391
+ }
392
+
393
+ auto llvmFuncType = LLVM::LLVMType::getFunctionTy (llvmResultType, argTypes,
394
+ /* isVarArg=*/ false );
395
+ auto wrappedFuncType = llvmFuncType.getPointerTo ();
396
+
397
+ auto funcArguments = llvm::makeArrayRef (operands).drop_front ();
398
+
399
+ // Make sure that the first operand (indirect callee) matches the wrapped
400
+ // LLVM IR function type, and that the types of the other call operands
401
+ // match the types of the function arguments.
402
+ if (parser.resolveOperand (operands[0 ], wrappedFuncType, result.operands ) ||
403
+ parser.resolveOperands (funcArguments, funcType.getInputs (),
404
+ parser.getNameLoc (), result.operands ))
405
+ return failure ();
406
+
407
+ result.addTypes (llvmResultType);
408
+ }
409
+ result.addSuccessor (normalDest, normalOperands);
410
+ result.addSuccessor (unwindDest, unwindOperands);
411
+ return success ();
412
+ }
413
+
414
+ // /===----------------------------------------------------------------------===//
415
+ // / Verifying/Printing/Parsing for LLVM::LandingpadOp.
416
+ // /===----------------------------------------------------------------------===//
417
+
418
+ static LogicalResult verify (LandingpadOp op) {
419
+ Value value;
420
+
421
+ if (!op.cleanup () && op.getOperands ().empty ())
422
+ return op.emitError (" landingpad instruction expects at least one clause or "
423
+ " cleanup attribute" );
424
+
425
+ for (unsigned idx = 0 , ie = op.getNumOperands (); idx < ie; idx++) {
426
+ value = op.getOperand (idx);
427
+ bool isFilter = value.getType ().cast <LLVMType>().isArrayTy ();
428
+ if (isFilter) {
429
+ // FIXME: Verify filter clauses when arrays are appropriately handled
430
+ } else {
431
+ // catch - global addresses only.
432
+ // Bitcast ops should have global addresses as their args.
433
+ if (auto bcOp = dyn_cast_or_null<BitcastOp>(value.getDefiningOp ())) {
434
+ if (auto addrOp =
435
+ dyn_cast_or_null<AddressOfOp>(bcOp.arg ().getDefiningOp ()))
436
+ continue ;
437
+ return op.emitError (" constant clauses expected" )
438
+ .attachNote (bcOp.getLoc ())
439
+ << " global addresses expected as operand to "
440
+ " bitcast used in clauses for landingpad" ;
441
+ }
442
+ // NullOp and AddressOfOp allowed
443
+ if (dyn_cast_or_null<NullOp>(value.getDefiningOp ()))
444
+ continue ;
445
+ if (dyn_cast_or_null<AddressOfOp>(value.getDefiningOp ()))
446
+ continue ;
447
+ return op.emitError (" clause #" )
448
+ << idx << " is not a known constant - null, addressof, bitcast" ;
449
+ }
450
+ }
451
+ return success ();
452
+ }
453
+
454
+ static void printLandingpadOp (OpAsmPrinter &p, LandingpadOp &op) {
455
+ p << op.getOperationName () << (op.cleanup () ? " cleanup " : " " );
456
+
457
+ // Clauses
458
+ for (auto value : op.getOperands ()) {
459
+ // Similar to llvm - if clause is an array type then it is filter
460
+ // clause else catch clause
461
+ bool isArrayTy = value.getType ().cast <LLVMType>().isArrayTy ();
462
+ p << ' (' << (isArrayTy ? " filter " : " catch " ) << value << " : "
463
+ << value.getType () << " ) " ;
464
+ }
465
+
466
+ p.printOptionalAttrDict (op.getAttrs (), {" cleanup" });
467
+
468
+ p << " : " << op.getType ();
469
+ }
470
+
471
+ // / <operation> ::= `llvm.landingpad` `cleanup`?
472
+ // / ((`catch` | `filter`) operand-type ssa-use)* attribute-dict?
473
+ static ParseResult parseLandingpadOp (OpAsmParser &parser,
474
+ OperationState &result) {
475
+ // Check for cleanup
476
+ if (succeeded (parser.parseOptionalKeyword (" cleanup" )))
477
+ result.addAttribute (" cleanup" , parser.getBuilder ().getUnitAttr ());
478
+
479
+ // Parse clauses with types
480
+ while (succeeded (parser.parseOptionalLParen ()) &&
481
+ (succeeded (parser.parseOptionalKeyword (" filter" )) ||
482
+ succeeded (parser.parseOptionalKeyword (" catch" )))) {
483
+ OpAsmParser::OperandType operand;
484
+ Type ty;
485
+ if (parser.parseOperand (operand) || parser.parseColon () ||
486
+ parser.parseType (ty) ||
487
+ parser.resolveOperand (operand, ty, result.operands ) ||
488
+ parser.parseRParen ())
489
+ return failure ();
490
+ }
491
+
492
+ Type type;
493
+ if (parser.parseColon () || parser.parseType (type))
494
+ return failure ();
495
+
496
+ result.addTypes (type);
497
+ return success ();
498
+ }
499
+
275
500
// ===----------------------------------------------------------------------===//
276
501
// Printing/parsing for LLVM::CallOp.
277
502
// ===----------------------------------------------------------------------===//
0 commit comments