Alex Susu via llvm-dev
2016-Oct-29 00:25 UTC
[llvm-dev] Problems with Inline ASM expressions generated in the back end
Hello. I generated in the back end by hand (in C++ code, not with TableGen) some fancy assembly code using Inline ASM expressions and if I use 2 functions in my source code (but NOT just 1 function; I will not present the functions, but each requires me to generate an Inline ASM expression) I get this error at compilation (at scheduling): BB#0: derived from LLVM BB %entry Live Ins: %R1 %R2 %vreg6<def> = COPY %R2; GPR:%vreg6 %vreg5<def> = COPY %R1; GPR:%vreg5 %vreg12<def> = VLOAD_D_WO_IMM; MSA128D:%vreg12 dbg:IfVectorize.c:39:5 INLINEASM <es: (Param1 - Param2); // MSA_I10> [sideeffect] [attdialect], <llc: /llvm/include/llvm/Support/Casting.h:237: typename llvm::cast_retty<X, Y*>::ret_type llvm::cast(Y*) [with X = llvm::ValueAsMetadata; Y = const llvm::Metadata; typename llvm::cast_retty<X, Y*>::ret_type = const llvm::ValueAsMetadata*]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. #0 0x00007f50baa5c700 llvm::sys::PrintStackTrace(llvm::raw_ostream&) /llvm/lib/Support/Unix/Signals.inc:402:0 #1 0x00007f50baa5ca9a PrintStackTraceSignalHandler(void*) /llvm/lib/Support/Unix/Signals.inc:470:0 #2 0x00007f50baa5ab55 llvm::sys::RunSignalHandlers() /llvm/lib/Support/Signals.cpp:44:0 ... #8 0x00007f50b9904c82 (/lib/x86_64-linux-gnu/libc.so.6+0x2dc82) #9 0x00007f50bc68f6e4 llvm::cast_retty<llvm::ValueAsMetadata, llvm::Metadata const*>::ret_type llvm::cast<llvm::ValueAsMetadata, llvm::Metadata const>(llvm::Metadata const*) /llvm/include/llvm/Support/Casting.h:239:0 #10 0x00007f50bc679010 WriteAsOperandInternal(llvm::raw_ostream&, llvm::Metadata const*, (anonymous namespace)::TypePrinting*, llvm::SlotTracker*, llvm::Module const*, bool) /llvm/lib/IR/AsmWriter.cpp:2045:0 #11 0x00007f50bc680e2c printMetadataImpl(llvm::raw_ostream&, llvm::Metadata const&, llvm::ModuleSlotTracker&, llvm::Module const*, bool) /llvm/lib/IR/AsmWriter.cpp:3504:0 #12 0x00007f50bc680fcc llvm::Metadata::printAsOperand(llvm::raw_ostream&, llvm::ModuleSlotTracker&, llvm::Module const*) const /llvm/lib/IR/AsmWriter.cpp:3520:0 #13 0x00007f50bd2ee8e2 llvm::MachineOperand::print(llvm::raw_ostream&, llvm::ModuleSlotTracker&, llvm::TargetRegisterInfo const*) const /llvm/lib/CodeGen/MachineInstr.cpp:449:0 #14 0x00007f50bd2f4141 llvm::MachineInstr::print(llvm::raw_ostream&, llvm::ModuleSlotTracker&, bool) const /llvm/lib/CodeGen/MachineInstr.cpp:1770:0 #15 0x00007f50bd288580 llvm::MachineBasicBlock::print(llvm::raw_ostream&, llvm::ModuleSlotTracker&, llvm::SlotIndexes const*) const /llvm/lib/CodeGen/MachineBasicBlock.cpp:295:0 #16 0x00007f50bd2da1cf llvm::MachineFunction::print(llvm::raw_ostream&, llvm::SlotIndexes const*) const /llvm/lib/CodeGen/MachineFunction.cpp:442:0 #17 0x00007f50baffedb1 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) /llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:662:0 My code that creates an inline ASM expression (in ConnexISelDAGToDAG.cpp, method Select) looks something like this: /* IMPORTANT: it seems we must malloc the char * that is passed to getTargetExternalSymbol as a reference, so we must make sure the value persists after we get out of this function. Hopefully no leak will happen either - maybe when deleting SDNode the destructor frees the char *. // This seems to be so because of this method doing creation of the SDNode, which is used also by getTargetExternalSymbol(): template <typename SDNodeT, typename... ArgTypes> SDNodeT *newSDNode(ArgTypes &&... Args) { return new (NodeAllocator.template Allocate<SDNodeT>()) SDNodeT(std::forward<ArgTypes>(Args)...); } */ char *exprStrChar = (char *)malloc(2048); strcpy(exprStrChar, "test... ..."); SDValue extSym = CurDAG->getTargetExternalSymbol( exprStrChar, MVT::i64); SDNode *extSymNode = extSym.getNode(); std::vector<SDValue> opsRes; opsRes.push_back(SDValue(vloadSpecial, 0)); opsRes.push_back(extSym); // Creating an SDNode MDNode<null> (MetaData) with a ch out port SDNode *mdNodeSDNode = CurDAG->getNode(ISD::MDNODE_SDNODE, DL, CurDAG->getVTList(MVT::Other)).getNode(); opsRes.push_back(SDValue(mdNodeSDNode, 0)); SDValue targetConstant = CurDAG->getTargetConstant(1, DL, MVT::i64); SDNode *targetConstantSDNode = targetConstant.getNode(); opsRes.push_back(SDValue(targetConstantSDNode, 0)); SDValue inlineAsm = CurDAG->getNode(ISD::INLINEASM, DL, CurDAG->getVTList(MVT::Other, MVT::Glue), opsRes); SDNode *inlineAsmNode = inlineAsm.getNode(); ... Does anyone have an idea why is this happening. Thank you very much, Alex
Alex Susu via llvm-dev
2016-Nov-10 17:05 UTC
[llvm-dev] Problems with Inline ASM expressions generated in the back end
Hello. I managed to fix this bug (at least for the tests I have). It is a bit weird - the error is at the creation of a (less-standard) MDNode like this: // Creating an SDNode MDNode<null> (MetaData) with a ch out port SDValue mdNode = CrtDAG->getNode(ISD::MDNODE_SDNODE, DL, CrtDAG->getVTList(MVT::Other) ); SDNode *mdNodeSDNode = mdNode.getNode(); This code generates an error if we generate 2 or more of these nodes in the compiled ASM module generated. Note that sometimes the error message is less complete - but the error manifests exactly when printing the MDNode, since it stops after printing the tag "[attdialect]" for the INLINEASM node. I wasn't able to understand well why this error is happening - probably it has something with the null metadata. The code that does not produce the bug (w.r.t. the above) is the following: /* Creating a NON-null-MDNode MDNodeSDNode object (has a hexadecimal value when outputing the DOT file). From http://llvm.org/docs/doxygen/html/classllvm_1_1MDNode.html: Detailed Description Metadata nodes can be uniqued, like constants, or distinct. */ MDNode *mdNode = MDNode::get(* (CrtDAG->getContext()), None); /* From http://llvm.org/docs/doxygen/html/classllvm_1_1SelectionDAG.html <<SDValue getMDNode (const MDNode *MD) Return an MDNodeSDNode which holds an MDNode.>> */ SDNode *mdNodeSDNode = CrtDAG->getMDNode(mdNode).getNode(); Best regards, Alex On 10/29/2016 3:25 AM, Alex Susu wrote:> Hello. > I generated in the back end by hand (in C++ code, not with TableGen) some fancy > assembly code using Inline ASM expressions and if I use 2 functions in my source code (but > NOT just 1 function; I will not present the functions, but each requires me to generate an > Inline ASM expression) I get this error at compilation (at scheduling): > BB#0: derived from LLVM BB %entry > Live Ins: %R1 %R2 > %vreg6<def> = COPY %R2; GPR:%vreg6 > %vreg5<def> = COPY %R1; GPR:%vreg5 > %vreg12<def> = VLOAD_D_WO_IMM; MSA128D:%vreg12 dbg:IfVectorize.c:39:5 > INLINEASM <es: (Param1 - Param2); // MSA_I10> [sideeffect] > [attdialect], <llc: /llvm/include/llvm/Support/Casting.h:237: typename llvm::cast_retty<X, > Y*>::ret_type llvm::cast(Y*) [with X = llvm::ValueAsMetadata; Y = const llvm::Metadata; > typename llvm::cast_retty<X, Y*>::ret_type = const llvm::ValueAsMetadata*]: Assertion > `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. > #0 0x00007f50baa5c700 llvm::sys::PrintStackTrace(llvm::raw_ostream&) > /llvm/lib/Support/Unix/Signals.inc:402:0 > #1 0x00007f50baa5ca9a PrintStackTraceSignalHandler(void*) > /llvm/lib/Support/Unix/Signals.inc:470:0 > #2 0x00007f50baa5ab55 llvm::sys::RunSignalHandlers() > /llvm/lib/Support/Signals.cpp:44:0 > ... > #8 0x00007f50b9904c82 (/lib/x86_64-linux-gnu/libc.so.6+0x2dc82) > #9 0x00007f50bc68f6e4 llvm::cast_retty<llvm::ValueAsMetadata, llvm::Metadata > const*>::ret_type llvm::cast<llvm::ValueAsMetadata, llvm::Metadata const>(llvm::Metadata > const*) /llvm/include/llvm/Support/Casting.h:239:0 > #10 0x00007f50bc679010 WriteAsOperandInternal(llvm::raw_ostream&, llvm::Metadata > const*, (anonymous namespace)::TypePrinting*, llvm::SlotTracker*, llvm::Module const*, > bool) /llvm/lib/IR/AsmWriter.cpp:2045:0 > #11 0x00007f50bc680e2c printMetadataImpl(llvm::raw_ostream&, llvm::Metadata > const&, llvm::ModuleSlotTracker&, llvm::Module const*, bool) > /llvm/lib/IR/AsmWriter.cpp:3504:0 > #12 0x00007f50bc680fcc llvm::Metadata::printAsOperand(llvm::raw_ostream&, > llvm::ModuleSlotTracker&, llvm::Module const*) const /llvm/lib/IR/AsmWriter.cpp:3520:0 > #13 0x00007f50bd2ee8e2 llvm::MachineOperand::print(llvm::raw_ostream&, > llvm::ModuleSlotTracker&, llvm::TargetRegisterInfo const*) const > /llvm/lib/CodeGen/MachineInstr.cpp:449:0 > #14 0x00007f50bd2f4141 llvm::MachineInstr::print(llvm::raw_ostream&, > llvm::ModuleSlotTracker&, bool) const /llvm/lib/CodeGen/MachineInstr.cpp:1770:0 > #15 0x00007f50bd288580 llvm::MachineBasicBlock::print(llvm::raw_ostream&, > llvm::ModuleSlotTracker&, llvm::SlotIndexes const*) const > /llvm/lib/CodeGen/MachineBasicBlock.cpp:295:0 > #16 0x00007f50bd2da1cf llvm::MachineFunction::print(llvm::raw_ostream&, > llvm::SlotIndexes const*) const /llvm/lib/CodeGen/MachineFunction.cpp:442:0 > #17 0x00007f50baffedb1 > llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) > /llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:662:0 > > > My code that creates an inline ASM expression (in ConnexISelDAGToDAG.cpp, method > Select) looks something like this: > /* IMPORTANT: it seems we must malloc the char * that is > passed to getTargetExternalSymbol as a reference, so > we must make sure the value persists after we get out of > this function. > Hopefully no leak will happen either - maybe when deleting > SDNode the destructor frees the char *. > > // This seems to be so because of this method doing > creation of the SDNode, which is used also by > getTargetExternalSymbol(): > template <typename SDNodeT, typename... ArgTypes> > SDNodeT *newSDNode(ArgTypes &&... Args) { > return new (NodeAllocator.template Allocate<SDNodeT>()) > SDNodeT(std::forward<ArgTypes>(Args)...); > } > */ > char *exprStrChar = (char *)malloc(2048); > strcpy(exprStrChar, "test... ..."); > SDValue extSym = CurDAG->getTargetExternalSymbol( > exprStrChar, > MVT::i64); > SDNode *extSymNode = extSym.getNode(); > > std::vector<SDValue> opsRes; > > opsRes.push_back(SDValue(vloadSpecial, 0)); > > opsRes.push_back(extSym); > > // Creating an SDNode MDNode<null> (MetaData) with a ch out port > SDNode *mdNodeSDNode = CurDAG->getNode(ISD::MDNODE_SDNODE, DL, > CurDAG->getVTList(MVT::Other)).getNode(); > > opsRes.push_back(SDValue(mdNodeSDNode, 0)); > > SDValue targetConstant = CurDAG->getTargetConstant(1, DL, MVT::i64); > SDNode *targetConstantSDNode = targetConstant.getNode(); > opsRes.push_back(SDValue(targetConstantSDNode, 0)); > > > SDValue inlineAsm = CurDAG->getNode(ISD::INLINEASM, DL, > CurDAG->getVTList(MVT::Other, MVT::Glue), > opsRes); > > SDNode *inlineAsmNode = inlineAsm.getNode(); > ... > > > > Does anyone have an idea why is this happening. > > > Thank you very much, > Alex