diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -381,10 +381,14 @@ CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval] CST_CODE_POISON = 26, // POISON CST_CODE_DSO_LOCAL_EQUIVALENT = 27, // DSO_LOCAL_EQUIVALENT [gvty, gv] - CST_CODE_INLINEASM = 28, // INLINEASM: [sideeffect|alignstack| + CST_CODE_INLINEASM_OLD3 = 28, // INLINEASM: [sideeffect|alignstack| + // asmdialect|unwind, + // asmstr,conststr] + CST_CODE_NO_CFI_VALUE = 29, // NO_CFI [ fty, f ] + CST_CODE_INLINEASM = 30, // INLINEASM: [fnty, + // sideeffect|alignstack| // asmdialect|unwind, // asmstr,conststr] - CST_CODE_NO_CFI_VALUE = 29, // NO_CFI [ fty, f ] }; /// CastOpcodes - These are values used in the bitcode files to encode which diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2824,6 +2824,7 @@ for (unsigned i = 0; i != ConstStrSize; ++i) ConstrStr += (char)Record[3+AsmStrSize+i]; UpgradeInlineAsmString(&AsmStr); + // FIXME: support upgrading in opaque pointers mode. V = InlineAsm::get( cast(cast(CurTy)->getElementType()), AsmStr, ConstrStr, HasSideEffects, IsAlignStack); @@ -2850,6 +2851,7 @@ for (unsigned i = 0; i != ConstStrSize; ++i) ConstrStr += (char)Record[3+AsmStrSize+i]; UpgradeInlineAsmString(&AsmStr); + // FIXME: support upgrading in opaque pointers mode. V = InlineAsm::get( cast(cast(CurTy)->getElementType()), AsmStr, ConstrStr, HasSideEffects, IsAlignStack, @@ -2857,32 +2859,70 @@ break; } // This version adds support for the unwind keyword. - case bitc::CST_CODE_INLINEASM: { + case bitc::CST_CODE_INLINEASM_OLD3: { if (Record.size() < 2) return error("Invalid record"); + unsigned OpNum = 0; std::string AsmStr, ConstrStr; - bool HasSideEffects = Record[0] & 1; - bool IsAlignStack = (Record[0] >> 1) & 1; - unsigned AsmDialect = (Record[0] >> 2) & 1; - bool CanThrow = (Record[0] >> 3) & 1; - unsigned AsmStrSize = Record[1]; - if (2 + AsmStrSize >= Record.size()) + bool HasSideEffects = Record[OpNum] & 1; + bool IsAlignStack = (Record[OpNum] >> 1) & 1; + unsigned AsmDialect = (Record[OpNum] >> 2) & 1; + bool CanThrow = (Record[OpNum] >> 3) & 1; + ++OpNum; + unsigned AsmStrSize = Record[OpNum]; + ++OpNum; + if (OpNum + AsmStrSize >= Record.size()) return error("Invalid record"); - unsigned ConstStrSize = Record[2 + AsmStrSize]; + unsigned ConstStrSize = Record[OpNum + AsmStrSize]; if (3 + AsmStrSize + ConstStrSize > Record.size()) return error("Invalid record"); for (unsigned i = 0; i != AsmStrSize; ++i) - AsmStr += (char)Record[2 + i]; + AsmStr += (char)Record[OpNum + i]; + ++OpNum; for (unsigned i = 0; i != ConstStrSize; ++i) - ConstrStr += (char)Record[3 + AsmStrSize + i]; + ConstrStr += (char)Record[OpNum + AsmStrSize + i]; UpgradeInlineAsmString(&AsmStr); + // FIXME: support upgrading in opaque pointers mode. V = InlineAsm::get( cast(cast(CurTy)->getElementType()), AsmStr, ConstrStr, HasSideEffects, IsAlignStack, InlineAsm::AsmDialect(AsmDialect), CanThrow); break; } + // This version adds explicit function type. + case bitc::CST_CODE_INLINEASM: { + if (Record.size() < 3) + return error("Invalid record"); + unsigned OpNum = 0; + auto *FnTy = dyn_cast_or_null(getTypeByID(Record[OpNum])); + ++OpNum; + if (!FnTy) + return error("Invalid record"); + std::string AsmStr, ConstrStr; + bool HasSideEffects = Record[OpNum] & 1; + bool IsAlignStack = (Record[OpNum] >> 1) & 1; + unsigned AsmDialect = (Record[OpNum] >> 2) & 1; + bool CanThrow = (Record[OpNum] >> 3) & 1; + ++OpNum; + unsigned AsmStrSize = Record[OpNum]; + ++OpNum; + if (OpNum + AsmStrSize >= Record.size()) + return error("Invalid record"); + unsigned ConstStrSize = Record[OpNum + AsmStrSize]; + if (3 + AsmStrSize + ConstStrSize > Record.size()) + return error("Invalid record"); + + for (unsigned i = 0; i != AsmStrSize; ++i) + AsmStr += (char)Record[OpNum + i]; + ++OpNum; + for (unsigned i = 0; i != ConstStrSize; ++i) + ConstrStr += (char)Record[OpNum + AsmStrSize + i]; + UpgradeInlineAsmString(&AsmStr); + V = InlineAsm::get(FnTy, AsmStr, ConstrStr, HasSideEffects, IsAlignStack, + InlineAsm::AsmDialect(AsmDialect), CanThrow); + break; + } case bitc::CST_CODE_BLOCKADDRESS:{ if (Record.size() < 3) return error("Invalid record"); @@ -4779,7 +4819,7 @@ cast(Callee->getType())->getElementType()); if (!FTy) return error("Callee is not of pointer to function type"); - } else if (cast(Callee->getType())->getElementType() != FTy) + } else if (!OpTy->isOpaqueOrPointeeTypeMatches(FTy)) return error("Explicit call type does not match pointee type of " "callee operand"); if (Record.size() < FTy->getNumParams() + OpNum) diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2458,6 +2458,7 @@ } if (const InlineAsm *IA = dyn_cast(V)) { + Record.push_back(VE.getTypeID(IA->getFunctionType())); Record.push_back( unsigned(IA->hasSideEffects()) | unsigned(IA->isAlignStack()) << 1 | unsigned(IA->getDialect() & 1) << 2 | unsigned(IA->canThrow()) << 3); diff --git a/llvm/test/Bitcode/callbr.ll b/llvm/test/Bitcode/callbr.ll --- a/llvm/test/Bitcode/callbr.ll +++ b/llvm/test/Bitcode/callbr.ll @@ -1,10 +1,13 @@ -; RUN: llvm-dis < %s.bc | FileCheck %s - +; RUN: llvm-dis < %s.bc | FileCheck %s --check-prefixes=CHECK,CHECK-TYPED ; callbr.ll.bc was generated by passing this file to llvm-as. +; RUN: llvm-as < %s | llvm-dis | FileCheck %s --check-prefixes=CHECK,CHECK-TYPED +; RUN: llvm-as -opaque-pointers < %s | llvm-dis -opaque-pointers | FileCheck %s --check-prefixes=CHECK,CHECK-OPAQUE + define i32 @test_asm_goto(i32 %x){ entry: -; CHECK: callbr void asm "", "r,X"(i32 %x, i8* blockaddress(@test_asm_goto, %fail)) +; CHECK-TYPED: callbr void asm "", "r,X"(i32 %x, i8* blockaddress(@test_asm_goto, %fail)) +; CHECK-OPAQUE: callbr void asm "", "r,X"(i32 %x, ptr blockaddress(@test_asm_goto, %fail)) ; CHECK-NEXT: to label %normal [label %fail] callbr void asm "", "r,X"(i32 %x, i8* blockaddress(@test_asm_goto, %fail)) to label %normal [label %fail] normal: