[llvm-commits] [llvm] r156905 - in /llvm/trunk: lib/VMCore/Function.cpp utils/TableGen/IntrinsicEmitter.cpp
Chris Lattner
sabre at nondot.org
Tue May 15 23:34:44 PDT 2012
Author: lattner
Date: Wed May 16 01:34:44 2012
New Revision: 156905
URL: http://llvm.org/viewvc/llvm-project?rev=156905&view=rev
Log:
Significantly reduce the compiled size of Functions.cpp by turning a big blob of tblgen
generated code (for Intrinsic::getType) into a table. This handles common cases right now,
but I plan to extend it to handle all cases and merge in type verification logic as well
in follow-on patches.
Modified:
llvm/trunk/lib/VMCore/Function.cpp
llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp
Modified: llvm/trunk/lib/VMCore/Function.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Function.cpp?rev=156905&r1=156904&r2=156905&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/Function.cpp (original)
+++ llvm/trunk/lib/VMCore/Function.cpp Wed May 16 01:34:44 2012
@@ -29,7 +29,6 @@
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
-
// Explicit instantiations of SymbolTableListTraits since some of the methods
// are not in the public header file...
template class llvm::SymbolTableListTraits<Argument, Function>;
@@ -358,17 +357,57 @@
return Result;
}
+#define GET_INTRINSTIC_GENERATOR_GLOBAL
+#include "llvm/Intrinsics.gen"
+#undef GET_INTRINSTIC_GENERATOR_GLOBAL
+
+static Type *DecodeFixedType(unsigned &TableVal, LLVMContext &Context) {
+ unsigned Nibble = TableVal & 0xF;
+ TableVal >>= 4;
+
+ switch ((IIT_Info)Nibble) {
+ case IIT_Done: return Type::getVoidTy(Context);
+ case IIT_I1: return Type::getInt1Ty(Context);
+ case IIT_I8: return Type::getInt8Ty(Context);
+ case IIT_I16: return Type::getInt16Ty(Context);
+ case IIT_I32: return Type::getInt32Ty(Context);
+ case IIT_I64: return Type::getInt64Ty(Context);
+ case IIT_F32: return Type::getFloatTy(Context);
+ case IIT_F64: return Type::getDoubleTy(Context);
+ case IIT_V2: return VectorType::get(DecodeFixedType(TableVal, Context), 2);
+ case IIT_V4: return VectorType::get(DecodeFixedType(TableVal, Context), 4);
+ case IIT_V8: return VectorType::get(DecodeFixedType(TableVal, Context), 8);
+ case IIT_V16: return VectorType::get(DecodeFixedType(TableVal, Context), 16);
+ case IIT_MMX: return Type::getX86_MMXTy(Context);
+ case IIT_PTR: return PointerType::get(DecodeFixedType(TableVal, Context),0);
+ case IIT_ARG: assert(0 && "Unimp!");
+ }
+ llvm_unreachable("unhandled");
+}
+
+
FunctionType *Intrinsic::getType(LLVMContext &Context,
- ID id, ArrayRef<Type*> Tys) {
- Type *ResultTy = NULL;
+ ID id, ArrayRef<Type*> Tys) {
+ Type *ResultTy = 0;
SmallVector<Type*, 8> ArgTys;
- bool IsVarArg = false;
+
+ // Check to see if the intrinsic's type was expressible by the table.
+ unsigned TableVal = IIT_Table[id-1];
+ if (TableVal != ~0U) {
+ ResultTy = DecodeFixedType(TableVal, Context);
+
+ while (TableVal)
+ ArgTys.push_back(DecodeFixedType(TableVal, Context));
+
+ return FunctionType::get(ResultTy, ArgTys, false);
+ }
+
#define GET_INTRINSIC_GENERATOR
#include "llvm/Intrinsics.gen"
#undef GET_INTRINSIC_GENERATOR
- return FunctionType::get(ResultTy, ArgTys, IsVarArg);
+ return FunctionType::get(ResultTy, ArgTys, false);
}
bool Intrinsic::isOverloaded(ID id) {
@@ -440,4 +479,3 @@
return false;
}
-// vim: sw=2 ai
Modified: llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp?rev=156905&r1=156904&r2=156905&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp Wed May 16 01:34:44 2012
@@ -174,109 +174,6 @@
OS << "#endif\n\n";
}
-static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
- if (EVT(VT).isInteger()) {
- unsigned BitWidth = EVT(VT).getSizeInBits();
- OS << "IntegerType::get(Context, " << BitWidth << ")";
- } else if (VT == MVT::Other) {
- // MVT::OtherVT is used to mean the empty struct type here.
- OS << "StructType::get(Context)";
- } else if (VT == MVT::f16) {
- OS << "Type::getHalfTy(Context)";
- } else if (VT == MVT::f32) {
- OS << "Type::getFloatTy(Context)";
- } else if (VT == MVT::f64) {
- OS << "Type::getDoubleTy(Context)";
- } else if (VT == MVT::f80) {
- OS << "Type::getX86_FP80Ty(Context)";
- } else if (VT == MVT::f128) {
- OS << "Type::getFP128Ty(Context)";
- } else if (VT == MVT::ppcf128) {
- OS << "Type::getPPC_FP128Ty(Context)";
- } else if (VT == MVT::isVoid) {
- OS << "Type::getVoidTy(Context)";
- } else if (VT == MVT::Metadata) {
- OS << "Type::getMetadataTy(Context)";
- } else if (VT == MVT::x86mmx) {
- OS << "Type::getX86_MMXTy(Context)";
- } else {
- assert(false && "Unsupported ValueType!");
- }
-}
-
-static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
- unsigned &ArgNo);
-
-static void EmitTypeGenerate(raw_ostream &OS,
- const std::vector<Record*> &ArgTypes,
- unsigned &ArgNo) {
- if (ArgTypes.empty())
- return EmitTypeForValueType(OS, MVT::isVoid);
-
- if (ArgTypes.size() == 1)
- return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
-
- OS << "StructType::get(";
-
- for (std::vector<Record*>::const_iterator
- I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
- EmitTypeGenerate(OS, *I, ArgNo);
- OS << ", ";
- }
-
- OS << " NULL)";
-}
-
-static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
- unsigned &ArgNo) {
- MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
-
- if (ArgType->isSubClassOf("LLVMMatchType")) {
- unsigned Number = ArgType->getValueAsInt("Number");
- assert(Number < ArgNo && "Invalid matching number!");
- if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
- OS << "VectorType::getExtendedElementVectorType"
- << "(cast<VectorType>(Tys[" << Number << "]))";
- else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
- OS << "VectorType::getTruncatedElementVectorType"
- << "(cast<VectorType>(Tys[" << Number << "]))";
- else
- OS << "Tys[" << Number << "]";
- } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
- // NOTE: The ArgNo variable here is not the absolute argument number, it is
- // the index of the "arbitrary" type in the Tys array passed to the
- // Intrinsic::getDeclaration function. Consequently, we only want to
- // increment it when we actually hit an overloaded type. Getting this wrong
- // leads to very subtle bugs!
- OS << "Tys[" << ArgNo++ << "]";
- } else if (EVT(VT).isVector()) {
- EVT VVT = VT;
- OS << "VectorType::get(";
- EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
- OS << ", " << VVT.getVectorNumElements() << ")";
- } else if (VT == MVT::iPTR) {
- OS << "PointerType::getUnqual(";
- EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
- OS << ")";
- } else if (VT == MVT::iPTRAny) {
- // Make sure the user has passed us an argument type to overload. If not,
- // treat it as an ordinary (not overloaded) intrinsic.
- OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo
- << "] : PointerType::getUnqual(";
- EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
- OS << ")";
- ++ArgNo;
- } else if (VT == MVT::isVoid) {
- if (ArgNo == 0)
- OS << "Type::getVoidTy(Context)";
- else
- // MVT::isVoid is used to mean varargs here.
- OS << "...";
- } else {
- EmitTypeForValueType(OS, VT);
- }
-}
-
/// RecordListComparator - Provide a deterministic comparator for lists of
/// records.
namespace {
@@ -411,22 +308,322 @@
OS << "#endif\n\n";
}
+static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
+ if (EVT(VT).isInteger()) {
+ unsigned BitWidth = EVT(VT).getSizeInBits();
+ OS << "IntegerType::get(Context, " << BitWidth << ")";
+ } else if (VT == MVT::Other) {
+ // MVT::OtherVT is used to mean the empty struct type here.
+ OS << "StructType::get(Context)";
+ } else if (VT == MVT::f16) {
+ OS << "Type::getHalfTy(Context)";
+ } else if (VT == MVT::f32) {
+ OS << "Type::getFloatTy(Context)";
+ } else if (VT == MVT::f64) {
+ OS << "Type::getDoubleTy(Context)";
+ } else if (VT == MVT::f80) {
+ OS << "Type::getX86_FP80Ty(Context)";
+ } else if (VT == MVT::f128) {
+ OS << "Type::getFP128Ty(Context)";
+ } else if (VT == MVT::ppcf128) {
+ OS << "Type::getPPC_FP128Ty(Context)";
+ } else if (VT == MVT::isVoid) {
+ OS << "Type::getVoidTy(Context)";
+ } else if (VT == MVT::Metadata) {
+ OS << "Type::getMetadataTy(Context)";
+ } else if (VT == MVT::x86mmx) {
+ OS << "Type::getX86_MMXTy(Context)";
+ } else {
+ assert(false && "Unsupported ValueType!");
+ }
+}
+
+static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
+ unsigned &ArgNo);
+
+static void EmitTypeGenerate(raw_ostream &OS,
+ const std::vector<Record*> &ArgTypes,
+ unsigned &ArgNo) {
+ if (ArgTypes.empty())
+ return EmitTypeForValueType(OS, MVT::isVoid);
+
+ if (ArgTypes.size() == 1)
+ return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
+
+ OS << "StructType::get(";
+
+ for (std::vector<Record*>::const_iterator
+ I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
+ EmitTypeGenerate(OS, *I, ArgNo);
+ OS << ", ";
+ }
+
+ OS << " NULL)";
+}
+
+static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
+ unsigned &ArgNo) {
+ MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
+
+ if (ArgType->isSubClassOf("LLVMMatchType")) {
+ unsigned Number = ArgType->getValueAsInt("Number");
+ assert(Number < ArgNo && "Invalid matching number!");
+ if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+ OS << "VectorType::getExtendedElementVectorType"
+ << "(cast<VectorType>(Tys[" << Number << "]))";
+ else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+ OS << "VectorType::getTruncatedElementVectorType"
+ << "(cast<VectorType>(Tys[" << Number << "]))";
+ else
+ OS << "Tys[" << Number << "]";
+ } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
+ // NOTE: The ArgNo variable here is not the absolute argument number, it is
+ // the index of the "arbitrary" type in the Tys array passed to the
+ // Intrinsic::getDeclaration function. Consequently, we only want to
+ // increment it when we actually hit an overloaded type. Getting this wrong
+ // leads to very subtle bugs!
+ OS << "Tys[" << ArgNo++ << "]";
+ } else if (EVT(VT).isVector()) {
+ EVT VVT = VT;
+ OS << "VectorType::get(";
+ EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
+ OS << ", " << VVT.getVectorNumElements() << ")";
+ } else if (VT == MVT::iPTR) {
+ OS << "PointerType::getUnqual(";
+ EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
+ OS << ")";
+ } else if (VT == MVT::iPTRAny) {
+ // Make sure the user has passed us an argument type to overload. If not,
+ // treat it as an ordinary (not overloaded) intrinsic.
+ OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo
+ << "] : PointerType::getUnqual(";
+ EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
+ OS << ")";
+ ++ArgNo;
+ } else if (VT == MVT::isVoid) {
+ assert(ArgNo == 0);
+ OS << "Type::getVoidTy(Context)";
+ } else {
+ EmitTypeForValueType(OS, VT);
+ }
+}
+
+
+// NOTE: This must be kept in synch with the version emitted to the .gen file!
+enum IIT_Info {
+ IIT_Done = 0,
+ IIT_I1 = 1,
+ IIT_I8 = 2,
+ IIT_I16 = 3,
+ IIT_I32 = 4,
+ IIT_I64 = 5,
+ IIT_F32 = 6,
+ IIT_F64 = 7,
+ IIT_V2 = 8,
+ IIT_V4 = 9,
+ IIT_V8 = 10,
+ IIT_V16 = 11,
+ IIT_MMX = 12,
+ IIT_PTR = 13,
+ IIT_ARG = 14
+};
+
+static void EncodeFixedValueType(MVT::SimpleValueType VT,
+ SmallVectorImpl<unsigned> &Sig) {
+ if (EVT(VT).isInteger()) {
+ unsigned BitWidth = EVT(VT).getSizeInBits();
+ switch (BitWidth) {
+ default: return Sig.push_back(~0U);
+ case 1: return Sig.push_back(IIT_I1);
+ case 8: return Sig.push_back(IIT_I8);
+ case 16: return Sig.push_back(IIT_I16);
+ case 32: return Sig.push_back(IIT_I32);
+ case 64: return Sig.push_back(IIT_I64);
+ }
+ }
+
+/* } else if (VT == MVT::Other) {
+ // MVT::OtherVT is used to mean the empty struct type here.
+ OS << "StructType::get(Context)";
+ } else if (VT == MVT::f16) {
+ OS << "Type::getHalfTy(Context)";*/
+ if (VT == MVT::f32)
+ return Sig.push_back(IIT_F32);
+ if (VT == MVT::f64)
+ return Sig.push_back(IIT_F64);
+ //if (VT == MVT::f80) {
+ // OS << "Type::getX86_FP80Ty(Context)";
+ //if (VT == MVT::f128) {
+ // OS << "Type::getFP128Ty(Context)";
+ // if (VT == MVT::ppcf128) {
+ // OS << "Type::getPPC_FP128Ty(Context)";
+ //if (VT == MVT::Metadata) {
+ // OS << "Type::getMetadataTy(Context)";
+ if (VT == MVT::x86mmx)
+ return Sig.push_back(IIT_MMX);
+
+ assert(VT != MVT::isVoid);
+ Sig.push_back(~0U);
+}
+
+
+static void EncodeFixedType(Record *R, SmallVectorImpl<unsigned> &Sig) {
+
+ if (R->isSubClassOf("LLVMMatchType")) {
+ return Sig.push_back(~0U);
+/*
+ unsigned Number = ArgType->getValueAsInt("Number");
+ assert(Number < ArgNo && "Invalid matching number!");
+ if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+ OS << "VectorType::getExtendedElementVectorType"
+ << "(cast<VectorType>(Tys[" << Number << "]))";
+ else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+ OS << "VectorType::getTruncatedElementVectorType"
+ << "(cast<VectorType>(Tys[" << Number << "]))";
+ else
+ OS << "Tys[" << Number << "]";
+ */
+ }
+
+ MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
+
+ if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
+ return Sig.push_back(~0U);
+ /*
+ // NOTE: The ArgNo variable here is not the absolute argument number, it is
+ // the index of the "arbitrary" type in the Tys array passed to the
+ // Intrinsic::getDeclaration function. Consequently, we only want to
+ // increment it when we actually hit an overloaded type. Getting this wrong
+ // leads to very subtle bugs!
+ OS << "Tys[" << ArgNo++ << "]";
+ */
+ }
+
+ if (EVT(VT).isVector()) {
+ EVT VVT = VT;
+ switch (VVT.getVectorNumElements()) {
+ default: Sig.push_back(~0U); return;
+ case 2: Sig.push_back(IIT_V2); break;
+ case 4: Sig.push_back(IIT_V4); break;
+ case 8: Sig.push_back(IIT_V8); break;
+ case 16: Sig.push_back(IIT_V16); break;
+ }
+
+ return EncodeFixedValueType(VVT.getVectorElementType().
+ getSimpleVT().SimpleTy, Sig);
+ }
+
+ if (VT == MVT::iPTR) {
+ Sig.push_back(IIT_PTR);
+ return EncodeFixedType(R->getValueAsDef("ElTy"), Sig);
+ }
+
+ /*if (VT == MVT::iPTRAny) {
+ // Make sure the user has passed us an argument type to overload. If not,
+ // treat it as an ordinary (not overloaded) intrinsic.
+ OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo
+ << "] : PointerType::getUnqual(";
+ EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
+ OS << ")";
+ ++ArgNo;
+ }*/
+
+ assert(VT != MVT::isVoid);
+ EncodeFixedValueType(VT, Sig);
+}
+
+/// ComputeFixedEncoding - If we can encode the type signature for this
+/// intrinsic into 32 bits, return it. If not, return ~0U.
+static unsigned ComputeFixedEncoding(const CodeGenIntrinsic &Int) {
+ if (Int.IS.RetVTs.size() >= 2) return ~0U;
+
+ SmallVector<unsigned, 8> TypeSig;
+ if (Int.IS.RetVTs.empty())
+ TypeSig.push_back(IIT_Done);
+ else if (Int.IS.RetVTs.size() == 1 &&
+ Int.IS.RetVTs[0] == MVT::isVoid)
+ TypeSig.push_back(IIT_Done);
+ else
+ EncodeFixedType(Int.IS.RetTypeDefs[0], TypeSig);
+
+ for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i)
+ EncodeFixedType(Int.IS.ParamTypeDefs[i], TypeSig);
+
+ // Can only encode 8 nibbles into a 32-bit word.
+ if (TypeSig.size() > 8) return ~0U;
+
+ unsigned Result = 0;
+ for (unsigned i = 0, e = TypeSig.size(); i != e; ++i) {
+ // If we had an unencodable argument, bail out.
+ if (TypeSig[i] == ~0U)
+ return ~0U;
+ Result = (Result << 4) | TypeSig[e-i-1];
+ }
+
+ return Result;
+}
+
void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS) {
- OS << "// Code for generating Intrinsic function declarations.\n";
- OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
- OS << " switch (id) {\n";
- OS << " default: llvm_unreachable(\"Invalid intrinsic!\");\n";
+ OS << "// Global intrinsic function declaration type table.\n";
+ OS << "#ifdef GET_INTRINSTIC_GENERATOR_GLOBAL\n";
+ // NOTE: These enums must be kept in sync with the ones above!
+ OS << "enum IIT_Info {\n";
+ OS << " IIT_Done = 0,\n";
+ OS << " IIT_I1 = 1,\n";
+ OS << " IIT_I8 = 2,\n";
+ OS << " IIT_I16 = 3,\n";
+ OS << " IIT_I32 = 4,\n";
+ OS << " IIT_I64 = 5,\n";
+ OS << " IIT_F32 = 6,\n";
+ OS << " IIT_F64 = 7,\n";
+ OS << " IIT_V2 = 8,\n";
+ OS << " IIT_V4 = 9,\n";
+ OS << " IIT_V8 = 10,\n";
+ OS << " IIT_V16 = 11,\n";
+ OS << " IIT_MMX = 12,\n";
+ OS << " IIT_PTR = 13,\n";
+ OS << " IIT_ARG = 14\n";
+ // 15 is unassigned so far.
+ OS << "};\n\n";
+
// Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
// types.
typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
MapTy UniqueArgInfos;
+
+ // If we can compute a 32-bit fixed encoding for this intrinsic, do so and
+ // capture it in this vector, otherwise store a ~0U.
+ std::vector<unsigned> FixedEncodings;
// Compute the unique argument type info.
- for (unsigned i = 0, e = Ints.size(); i != e; ++i)
- UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
- Ints[i].IS.ParamTypeDefs)].push_back(i);
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ FixedEncodings.push_back(ComputeFixedEncoding(Ints[i]));
+
+ // If we didn't compute a compact encoding, emit a long-form variant.
+ if (FixedEncodings.back() == ~0U)
+ UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
+ Ints[i].IS.ParamTypeDefs)].push_back(i);
+ }
+
+ OS << "static const unsigned IIT_Table[] = {\n ";
+
+ for (unsigned i = 0, e = FixedEncodings.size(); i != e; ++i) {
+ if ((i & 7) == 7)
+ OS << "\n ";
+ if (FixedEncodings[i] == ~0U)
+ OS << "~0U, ";
+ else
+ OS << "0x" << utohexstr(FixedEncodings[i]) << ", ";
+ }
+
+ OS << "0\n};\n\n#endif\n\n"; // End of GET_INTRINSTIC_GENERATOR_GLOBAL
+
+ OS << "// Code for generating Intrinsic function declarations.\n";
+ OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
+ OS << " switch (id) {\n";
+ OS << " default: llvm_unreachable(\"Invalid intrinsic!\");\n";
// Loop through the array, emitting one generator for each batch.
std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
@@ -442,13 +639,6 @@
const std::vector<Record*> &ParamTys = ArgTypes.second;
unsigned N = ParamTys.size();
-
- if (N > 1 &&
- getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
- OS << " IsVarArg = true;\n";
- --N;
- }
-
unsigned ArgNo = 0;
OS << " ResultTy = ";
EmitTypeGenerate(OS, RetTys, ArgNo);
More information about the llvm-commits
mailing list