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