@@ -252,6 +252,7 @@ bool InlineAsmLowering::lowerInlineAsm(
252
252
TLI->ParseConstraints (DL, TRI, Call);
253
253
254
254
ExtraFlags ExtraInfo (Call);
255
+ unsigned ArgNo = 0 ; // ArgNo - The argument of the CallInst.
255
256
unsigned ResNo = 0 ; // ResNo - The result number of the next output.
256
257
for (auto &T : TargetConstraints) {
257
258
ConstraintOperands.push_back (GISelAsmOperandInfo (T));
@@ -261,9 +262,32 @@ bool InlineAsmLowering::lowerInlineAsm(
261
262
if (OpInfo.Type == InlineAsm::isInput ||
262
263
(OpInfo.Type == InlineAsm::isOutput && OpInfo.isIndirect )) {
263
264
264
- LLVM_DEBUG (dbgs () << " Input operands and indirect output operands are "
265
- " not supported yet\n " );
266
- return false ;
265
+ OpInfo.CallOperandVal = const_cast <Value *>(Call.getArgOperand (ArgNo++));
266
+
267
+ if (const auto *BB = dyn_cast<BasicBlock>(OpInfo.CallOperandVal )) {
268
+ LLVM_DEBUG (dbgs () << " Basic block input operands not supported yet\n " );
269
+ return false ;
270
+ }
271
+
272
+ Type *OpTy = OpInfo.CallOperandVal ->getType ();
273
+
274
+ // If this is an indirect operand, the operand is a pointer to the
275
+ // accessed type.
276
+ if (OpInfo.isIndirect ) {
277
+ PointerType *PtrTy = dyn_cast<PointerType>(OpTy);
278
+ if (!PtrTy)
279
+ report_fatal_error (" Indirect operand for inline asm not a pointer!" );
280
+ OpTy = PtrTy->getElementType ();
281
+ }
282
+
283
+ // FIXME: Support aggregate input operands
284
+ if (!OpTy->isSingleValueType ()) {
285
+ LLVM_DEBUG (
286
+ dbgs () << " Aggregate input operands are not supported yet\n " );
287
+ return false ;
288
+ }
289
+
290
+ OpInfo.ConstraintVT = TLI->getValueType (DL, OpTy, true ).getSimpleVT ();
267
291
268
292
} else if (OpInfo.Type == InlineAsm::isOutput && !OpInfo.isIndirect ) {
269
293
assert (!Call.getType ()->isVoidTy () && " Bad inline asm!" );
@@ -363,8 +387,97 @@ bool InlineAsmLowering::lowerInlineAsm(
363
387
}
364
388
365
389
break ;
366
- case InlineAsm::isInput:
367
- return false ;
390
+ case InlineAsm::isInput: {
391
+ if (OpInfo.isMatchingInputConstraint ()) {
392
+ LLVM_DEBUG (dbgs () << " Tied input operands not supported yet\n " );
393
+ return false ;
394
+ }
395
+
396
+ if (OpInfo.ConstraintType == TargetLowering::C_Other &&
397
+ OpInfo.isIndirect ) {
398
+ LLVM_DEBUG (dbgs () << " Indirect input operands with unknown constraint "
399
+ " not supported yet\n " );
400
+ return false ;
401
+ }
402
+
403
+ if (OpInfo.ConstraintType == TargetLowering::C_Immediate ||
404
+ OpInfo.ConstraintType == TargetLowering::C_Other) {
405
+
406
+ std::vector<MachineOperand> Ops;
407
+ if (!lowerAsmOperandForConstraint (OpInfo.CallOperandVal ,
408
+ OpInfo.ConstraintCode , Ops,
409
+ MIRBuilder)) {
410
+ LLVM_DEBUG (dbgs () << " Don't support constraint: "
411
+ << OpInfo.ConstraintCode << " yet\n " );
412
+ return false ;
413
+ }
414
+
415
+ assert (Ops.size () > 0 &&
416
+ " Expected constraint to be lowered to at least one operand" );
417
+
418
+ // Add information to the INLINEASM node to know about this input.
419
+ unsigned OpFlags =
420
+ InlineAsm::getFlagWord (InlineAsm::Kind_Imm, Ops.size ());
421
+ Inst.addImm (OpFlags);
422
+ Inst.add (Ops);
423
+ break ;
424
+ }
425
+
426
+ if (OpInfo.ConstraintType == TargetLowering::C_Memory) {
427
+ assert (OpInfo.isIndirect && " Operand must be indirect to be a mem!" );
428
+
429
+ unsigned ConstraintID =
430
+ TLI->getInlineAsmMemConstraint (OpInfo.ConstraintCode );
431
+ unsigned OpFlags = InlineAsm::getFlagWord (InlineAsm::Kind_Mem, 1 );
432
+ OpFlags = InlineAsm::getFlagWordForMem (OpFlags, ConstraintID);
433
+ Inst.addImm (OpFlags);
434
+ ArrayRef<Register> SourceRegs =
435
+ GetOrCreateVRegs (*OpInfo.CallOperandVal );
436
+ assert (
437
+ SourceRegs.size () == 1 &&
438
+ " Expected the memory input to fit into a single virtual register" );
439
+ Inst.addReg (SourceRegs[0 ]);
440
+ break ;
441
+ }
442
+
443
+ assert ((OpInfo.ConstraintType == TargetLowering::C_RegisterClass ||
444
+ OpInfo.ConstraintType == TargetLowering::C_Register) &&
445
+ " Unknown constraint type!" );
446
+
447
+ if (OpInfo.isIndirect ) {
448
+ LLVM_DEBUG (dbgs () << " Can't handle indirect register inputs yet "
449
+ " for constraint '"
450
+ << OpInfo.ConstraintCode << " '\n " );
451
+ return false ;
452
+ }
453
+
454
+ // Copy the input into the appropriate registers.
455
+ if (OpInfo.Regs .empty ()) {
456
+ LLVM_DEBUG (
457
+ dbgs ()
458
+ << " Couldn't allocate input register for register constraint\n " );
459
+ return false ;
460
+ }
461
+
462
+ unsigned NumRegs = OpInfo.Regs .size ();
463
+ ArrayRef<Register> SourceRegs = GetOrCreateVRegs (*OpInfo.CallOperandVal );
464
+ assert (NumRegs == SourceRegs.size () &&
465
+ " Expected the number of input registers to match the number of "
466
+ " source registers" );
467
+
468
+ if (NumRegs > 1 ) {
469
+ LLVM_DEBUG (dbgs () << " Input operands with multiple input registers are "
470
+ " not supported yet\n " );
471
+ return false ;
472
+ }
473
+
474
+ unsigned Flag = InlineAsm::getFlagWord (InlineAsm::Kind_RegUse, NumRegs);
475
+ Inst.addImm (Flag);
476
+ MIRBuilder.buildCopy (OpInfo.Regs [0 ], SourceRegs[0 ]);
477
+ Inst.addReg (OpInfo.Regs [0 ]);
478
+ break ;
479
+ }
480
+
368
481
case InlineAsm::isClobber: {
369
482
370
483
unsigned NumRegs = OpInfo.Regs .size ();
@@ -441,3 +554,27 @@ bool InlineAsmLowering::lowerInlineAsm(
441
554
442
555
return true ;
443
556
}
557
+
558
+ bool InlineAsmLowering::lowerAsmOperandForConstraint (
559
+ Value *Val, StringRef Constraint, std::vector<MachineOperand> &Ops,
560
+ MachineIRBuilder &MIRBuilder) const {
561
+ if (Constraint.size () > 1 )
562
+ return false ;
563
+
564
+ char ConstraintLetter = Constraint[0 ];
565
+ switch (ConstraintLetter) {
566
+ default :
567
+ return false ;
568
+ case ' i' : // Simple Integer or Relocatable Constant
569
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(Val)) {
570
+ assert (CI->getBitWidth () <= 64 &&
571
+ " expected immediate to fit into 64-bits" );
572
+ // Boolean constants should be zero-extended, others are sign-extended
573
+ bool IsBool = CI->getBitWidth () == 1 ;
574
+ int64_t ExtVal = IsBool ? CI->getZExtValue () : CI->getSExtValue ();
575
+ Ops.push_back (MachineOperand::CreateImm (ExtVal));
576
+ return true ;
577
+ }
578
+ return false ;
579
+ }
580
+ }
0 commit comments