<div dir="ltr"><div>TL;DR: I am trying to implement a new calling convention for X86 with</div><div>an associated new return instruction.  I am getting stuck with the</div><div>error listed towards the end and not sure where I need to make a</div><div>change.  I have included the changes I have made.  Any help is appreciated.</div><div><br></div><div>(In addition to finding out how to get past this error, I also would</div><div>love a pointer on how to generate a two-byte opcode for my new</div><div>instruction, e.g., 0xF0 0x3F.  In the code below you can see that I am</div><div>currently just generating 0xF0.  Thank-you.)</div><div><br></div><div>The rest of the note is:</div><div>- Overview of changes I made to clang</div><div>- Overview of changes I made to llvm</div><div>- C file I am trying to compile</div><div>- Error I get from executing llc</div><div>- The llvm IR for the C file</div><div>- The detailed list of changes I made to llvm</div><div>- The detailed list of changes I made to clang</div><div><br></div><div>- OVERVIEW OF CHANGES I MADE TO CLANG</div><div><br></div><div>In the front-end I added a new attribute: `__attribute__</div><div>((new_interrupt))`.  I am fairly confident I touched all the places I</div><div>needed to, but all the changes I made in Attr.td, SemaDeclAttr.cpp,</div><div>SemaExpr.cpp, AttrDocs.td, and DiagnosticSemaKinds.td are listed at</div><div>the very end under 'CHANGES TO CLANG:'</div><div><br></div><div>- OVERVIEW OF CHANGES I MADE TO LLVM</div><div><br></div><div>In llvm I am sure I have either made incorrect changes or am still</div><div>missing changes I need to make.  The overview is I added new defs for</div><div>my new X86 instructions, a new calling convention, code to detect the</div><div>attribute, and some new asm and LL tokens.  Yet, when I compile:</div><div><br></div><div>- C FILE I AM TRYING TO COMPILE</div><div><br></div><div>----------------------------------------------------------------</div><div>static int myvar = 0;</div><div><br></div><div>__attribute__ ((new_interrupt)) void</div><div>incr(void)</div><div>{</div><div>  myvar++;</div><div>}</div><div>----------------------------------------------------------------</div><div><br></div><div>- ERROR I GET FROM EXECUTING LLC</div><div><br></div><div>with `build/bin/llc one.ll` I get the following error (clearly I still</div><div>have to fix or implement something else)</div><div>----------------------------------------------------------------</div><div>llc: lib/Target/X86/X86GenAsmWriter.inc:45898: void llvm::X86ATTInstPrinter::printInstruction(const llvm::MCInst*, llvm::raw_ostream&): Assertion `Bits != 0 && "Cannot print this instruction."' failed.</div><div>#0 0x00007fa28495ac59 llvm::sys::PrintStackTrace(llvm::raw_ostream&) /home/seth/research/uli/src/compiler/llvm/lib/Support/Unix/Signals.inc:398:0</div><div>#1 0x00007fa28495acea PrintStackTraceSignalHandler(void*) /home/seth/research/uli/src/compiler/llvm/lib/Support/Unix/Signals.inc:462:0</div><div>#2 0x00007fa2849590d8 llvm::sys::RunSignalHandlers() /home/seth/research/uli/src/compiler/llvm/lib/Support/Signals.cpp:49:0</div><div>#3 0x00007fa28495a5f1 SignalHandler(int) /home/seth/research/uli/src/compiler/llvm/lib/Support/Unix/Signals.inc:252:0</div><div>#4 0x00007fa2838a7cb0 (/lib/x86_64-linux-gnu/libc.so.6+0x36cb0)</div><div>#5 0x00007fa2838a7c37 gsignal /build/eglibc-SvCtMH/eglibc-2.19/signal/../nptl/sysdeps/unix/sysv/linux/raise.c:56:0</div><div>#6 0x00007fa2838ab028 abort /build/eglibc-SvCtMH/eglibc-2.19/stdlib/abort.c:91:0</div><div>#7 0x00007fa2838a0bf6 __assert_fail_base /build/eglibc-SvCtMH/eglibc-2.19/assert/assert.c:92:0</div><div>#8 0x00007fa2838a0ca2 (/lib/x86_64-linux-gnu/libc.so.6+0x2fca2)</div><div>#9 0x00007fa2836c0bb1 llvm::X86ATTInstPrinter::printInstruction(llvm::MCInst const*, llvm::raw_ostream&) /home/seth/research/uli/src/compiler/build/lib/Target/X86/X86GenAsmWriter.inc:45899:0</div><div>#10 0x00007fa2836c4f6f llvm::X86ATTInstPrinter::printInst(llvm::MCInst const*, llvm::raw_ostream&, llvm::StringRef, llvm::MCSubtargetInfo const&) /home/seth/research/uli/src/compiler/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp:95:0</div><div>#11 0x00007fa28595d7d0 llvm::MCTargetStreamer::prettyPrintAsm(llvm::MCInstPrinter&, llvm::raw_ostream&, llvm::MCInst const&, llvm::MCSubtargetInfo const&) /home/seth/research/uli/src/compiler/llvm/lib/MC/MCStreamer.cpp:832:0</div><div>#12 0x00007fa2858f6e7a (anonymous namespace)::MCAsmStreamer::EmitInstruction(llvm::MCInst const&, llvm::MCSubtargetInfo const&, bool) /home/seth/research/uli/src/compiler/llvm/lib/MC/MCAsmStreamer.cpp:1659:0</div><div>#13 0x00007fa2887208ce llvm::X86AsmPrinter::EmitAndCountInstruction(llvm::MCInst&) /home/seth/research/uli/src/compiler/llvm/lib/Target/X86/X86MCInstLower.cpp:107:0</div><div>#14 0x00007fa28872a707 llvm::X86AsmPrinter::EmitInstruction(llvm::MachineInstr const*) /home/seth/research/uli/src/compiler/llvm/lib/Target/X86/X86MCInstLower.cpp:2022:0</div><div>#15 0x00007fa2871d36db llvm::AsmPrinter::EmitFunctionBody() /home/seth/research/uli/src/compiler/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp:1044:0</div><div>#16 0x00007fa288484d17 llvm::X86AsmPrinter::runOnMachineFunction(llvm::MachineFunction&) /home/seth/research/uli/src/compiler/llvm/lib/Target/X86/X86AsmPrinter.cpp:81:0</div><div>#17 0x00007fa2868d35d3 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) /home/seth/research/uli/src/compiler/llvm/lib/CodeGen/MachineFunctionPass.cpp:62:0</div><div>#18 0x00007fa285e531f0 llvm::FPPassManager::runOnFunction(llvm::Function&) /home/seth/research/uli/src/compiler/llvm/lib/IR/LegacyPassManager.cpp:1514:0</div><div>#19 0x00007fa285e53383 llvm::FPPassManager::runOnModule(llvm::Module&) /home/seth/research/uli/src/compiler/llvm/lib/IR/LegacyPassManager.cpp:1535:0</div><div>#20 0x00007fa285e5371e (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) /home/seth/research/uli/src/compiler/llvm/lib/IR/LegacyPassManager.cpp:1591:0</div><div>#21 0x00007fa285e53e6e llvm::legacy::PassManagerImpl::run(llvm::Module&) /home/seth/research/uli/src/compiler/llvm/lib/IR/LegacyPassManager.cpp:1694:0</div><div>#22 0x00007fa285e540af llvm::legacy::PassManager::run(llvm::Module&) /home/seth/research/uli/src/compiler/llvm/lib/IR/LegacyPassManager.cpp:1726:0</div><div>#23 0x0000000000431826 compileModule(char**, llvm::LLVMContext&) /home/seth/research/uli/src/compiler/llvm/tools/llc/llc.cpp:572:0</div><div>#24 0x000000000042ffd8 main /home/seth/research/uli/src/compiler/llvm/tools/llc/llc.cpp:346:0</div><div>#25 0x00007fa283892f45 __libc_start_main /build/eglibc-SvCtMH/eglibc-2.19/csu/libc-start.c:321:0</div><div>#26 0x000000000042de99 _start (/home/seth/research/uli/src/compiler/build/bin/llc+0x42de99)</div><div>Stack dump:</div><div>0.      Program arguments: build/bin/llc one.ll </div><div>1.      Running pass 'Function Pass Manager' on module 'one.ll'.</div><div>2.      Running pass 'X86 Assembly Printer' on function '@incr'</div><div>Aborted (core dumped)</div><div>================================================================</div><div><br></div><div>- THE LLVM IR FOR THE C FILE</div><div><br></div><div>The llvm ir for the C file above is:</div><div>----------------------------------------------------------------</div><div>; ModuleID = 'one.c'</div><div>source_filename = "one.c"</div><div>target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"</div><div>target triple = "x86_64-unknown-linux-gnu"</div><div><br></div><div>@myvar = internal global i32 0, align 4</div><div><br></div><div>; Function Attrs: noinline nounwind optnone uwtable</div><div>define x86_newircc void @incr() #0 {</div><div>entry:</div><div>  %0 = load i32, i32* @myvar, align 4</div><div>  %inc = add nsw i32 %0, 1</div><div>  store i32 %inc, i32* @myvar, align 4</div><div>  ret void</div><div>}</div><div><br></div><div>attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }</div><div><br></div><div>!llvm.module.flags = !{!0}</div><div>!llvm.ident = !{!1}</div><div><br></div><div>!0 = !{i32 1, !"wchar_size", i32 4}</div><div>!1 = !{!"clang version 6.0.0 (trunk) (llvm/trunk 316096)"}</div><div>----------------------------------------------------------------</div><div><br></div><div>- THE DETAILED LIST OF CHANGES I MADE TO LLVM</div><div><br></div><div><br></div><div>================================================================</div><div>Changes to llvm:</div><div>================================================================</div><div><br></div><div>llvm/include/llvm/IR/CallingConv.h:223</div><div>---------------------------------------------------------------- in namespace CallingConv to the enum:</div><div>    /// X86_NewI - x86 new interrupt context. Callee may take</div><div>    /// multiple arguments which are accessed by the FROMNewI</div><div>    /// instructions</div><div>    X86_NewI = 97,</div><div>================================================================</div><div><br></div><div>llvm/lib/Target/X86/X86InstrInfo.td:2841</div><div>----------------------------------------------------------------</div><div>def : MnemonicAlias<"newiret",    "NewIRET",    "att">;</div><div>================================================================</div><div><br></div><div>llvm/lib/Target/X86/X86InstrControl.td:57</div><div>----------------------------------------------------------------</div><div>  // new interrupt return</div><div>  def NewIRET32   : I   <0x0F, RawFrm, (outs), (ins),</div><div>                    "newiretl", [], IIC_RET>, OpSize32;</div><div>  def NewIRET64   : I   <0x0F, RawFrm, (outs), (ins),</div><div>                    "newiretq", [], IIC_RET>, Requires<[In64BitMode]>;</div><div>----------------------------------------------------------------</div><div><br></div><div>llvm/lib/Target/X86/X86InstrControl.td:66</div><div>----------------------------------------------------------------</div><div>  let isCodeGenOnly = 1 in {</div><div>    def IRET : PseudoI<(outs), (ins i32imm:$adj), [(X86iret timm:$adj)]>;</div><div>    def NewIRET : PseudoI<(outs), (ins i32imm:$adj), [(X86newiret timm:$adj)]>;</div><div>  }</div><div>================================================================</div><div><br></div><div>llvm/lib/Target/X86/X86ISelLowering.h:132</div><div>---------------------------------------------------------------- in namespace X86ISD, enum NodeType</div><div>      /// Return from new interrupt. No operands</div><div>      NewIRET,</div><div>================================================================</div><div><br></div><div>llvm/lib/Target/X86/X86ISelLowering.cpp:2171</div><div>----------------------------------------- SDValue X86TargetLowering::LowerReturn</div><div>  if (((CallConv == CallingConv::X86_INTR)||(CallConv == CallingConv::X86_NewI)) && !Outs.empty())</div><div>    report_fatal_error("X86 (new) interrupts may not return any value");</div><div>---------------------------------------- </div><div><br></div><div>llvm/lib/Target/X86/X86ISelLowering.cpp:2358</div><div>----------------------------------------- SDValue X86TargetLowering::LowerReturn</div><div>  else if (CallConv == CallingConv::X86_NewI)</div><div>    opcode = X86ISD::NewIRET;</div><div>---------------------------------------- </div><div><br></div><div>llvm/lib/Target/X86/X86ISelLowering.cpp:3337</div><div>---------------------------------------------------------------- SDValue X86TargetLowering::LowerCall</div><div>  else if (CallConv == CallingConv::X86_NewI)</div><div>    report_fatal_error("X86 new interrupts may not be called directly");</div><div>---------------------------------------- </div><div><br></div><div>llvm/lib/Target/X86/X86ISelLowering.cpp:24539</div><div>---------------------------------------- const char *X86TargetLowering::getTargetNodeName</div><div>  case X86ISD::NewIRET:             return "X86ISD::NewIRET";</div><div>================================================================</div><div><br></div><div>llvm/lib/AsmParser/LLToken.h:152</div><div>---------------------------------------------------------------- in namespace lltok, enum kind</div><div>  kw_x86_newircc,</div><div>================================================================</div><div><br></div><div>llvm/lib/AsmParser/LLLexer.h:600</div><div>---------------------------------------------------------------- in lltok::Kind LLLexer::LexIdentifier</div><div>  KEYWORD(x86_newircc);</div><div>================================================================</div><div><br></div><div>llvm/lib/AsmParser/LLParser.cpp:1737</div><div>---------------------------------------------------------------- in bool LLParser::ParseOptionalCallingConv</div><div>  case lltok::kw_x86_newircc:        CC = CallingConv::X86_NewI; break;</div><div>================================================================</div><div><br></div><div>llvm/lib/IR/AsmWriter.cpp:373</div><div>---------------------------------------------------------------- in static void PrintCallingConv</div><div>  case CallingConv::X86_NewI:      Out << "x86_newircc"; break;</div><div>================================================================</div><div><br></div><div>- THE DETAILED LIST OF CHANGES I MADE TO CLANG</div><div><br></div><div>CHANGES TO CLANG:</div><div>================================================================</div><div><br></div><div>clang/include/clang/Basic/Attr.td</div><div>---------------------------------------------------------------- Added new def</div><div> def NewInterrupt : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {</div><div>  let Spellings = [GNU<"new_interrupt">];</div><div>  let Subjects = SubjectList<[Function]>;</div><div>  let Documentation = [NewInterruptDocs];</div><div>}</div><div>================================================================</div><div><br></div><div>clang/lib/Sema/SemaDeclAttr.cpp</div><div>---------------------------------------------------------------- Added In static void ProcessDeclAttribute</div><div>  case AttributeList::AT_NewInterrupt:</div><div>    handleNewInterruptAttr(S, D, Attr);</div><div>    break;</div><div><br></div><div>---------------------------------------------------------------- Added new function</div><div>static void handleNewInterruptAttr(Sema &S, Decl *D,</div><div>                                      const AttributeList &Attr) {</div><div>  // Semantic checks for a function with the 'interrupt' attribute.</div><div>  // a) Must be a function.</div><div>  // b) Must have the 'void' return type.</div><div><br></div><div>  if (!isFunctionOrMethod(D)) {</div><div>    S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)</div><div>        << "'new-interrupt'" << ExpectedFunctionOrMethod;</div><div>    return;</div><div>  }</div><div><br></div><div>  if (!getFunctionOrMethodResultType(D)->isVoidType()) {</div><div>    S.Diag(D->getLocation(), diag::err_new_interrupt_attribute)</div><div>        << 1;</div><div>    return;</div><div>  }</div><div>  handleSimpleAttribute<NewInterruptAttr>(S, D, Attr);</div><div>}</div><div>================================================================</div><div><br></div><div>clang/lib/CodeGen/TargetInfo.cpp</div><div>------------------------------------------- Added In void X86_32TargetCodeGenInfo::setTargetAttributes</div><div>    if (FD->hasAttr<AnyX86InterruptAttr>() || FD->hasAttr<NewInterruptAttr>()) {</div><div>      llvm::Function *Fn = cast<llvm::Function>(GV);</div><div>      Fn->setCallingConv(FD->hasAttr<AnyX86InterruptAttr>() </div><div>            ? llvm::CallingConv::X86_INTR </div><div>            : llvm::CallingConv::X86_NewI);</div><div>    }</div><div><br></div><div>------------------------------------------- Added In class X86_64TargetCodeGenInfo, void setTargetAttributes</div><div>same as above</div><div><br></div><div>------------------------------------------- Added In void WinX86_64TargetCodeGenInfo::setTargetAttributes</div><div>same as above</div><div>================================================================</div><div><br></div><div>In clang/lib/Sema/SemaExpr.cpp</div><div>---------------------------------------------------------------- Added In ExprResult Sema::BuildResolvedCallExpr</div><div>  // Functions with 'interrupt' attribute cannot be called directly.</div><div>  if (FDecl && (FDecl->hasAttr<AnyX86InterruptAttr>() || FDecl->hasAttr<NewInterruptAttr>())) {</div><div>    Diag(Fn->getExprLoc(), diag::err_anyx86_interrupt_called);</div><div>    return ExprError();</div><div>  }</div><div>================================================================</div><div><br></div><div>In clang/include/clang/Basic/DiagnosticSemaKinds.td</div><div>---------------------------------------------------------------- Added new defs</div><div>def err_new_interrupt_attribute : Error<</div><div>    "'new_interrupt' attribute only applies to functions that have a 'void' return type">;</div><div>def err_new_interrupt_called : Error<</div><div>  "new interrupt service routine cannot be called directly">;</div><div>================================================================</div><div><br></div><div>In clang/include/clang/Basic/AttrDocs.td</div><div>---------------------------------------------------------------- Added new def</div><div>def NewInterruptDocs  : Documentation {</div><div>  let Category = DocCatFunction;</div><div>  let Heading = "new interrupt (x86)";</div><div>  let Content = [{</div><div>Clang supports the GNU style ``__attribute__((new_interrupt))`` attribute on</div><div>x86 targets. This attribute may be attached to a function definition and</div><div>instructs the backend to generate appropriate function entry/exit code so that</div><div>it can be used directly as a new interrupt service routine.</div><div>  }];</div><div>}</div><div>================================================================</div><div><br></div><div><div class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><br></div><div>--------------</div><div>Seth Copen Goldstein</div><div>Carnegie Mellon University</div><div>Computer Science Dept</div><div>7111 GHC</div><div>412-268-3828</div></div></div></div></div></div>
</div>