llvm.org GIT mirror llvm / c4de3de
For PR1297: Implement code generation for overloaded intrinsic functions. The basic difference is that "actual" argument types must be provided when constructing intrinsic names and types. Also, for recognition, only the prefix is examined. If it matches, the suffix is assumed to match. The suffix is checked by the Verifier, however. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35539 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Spencer 13 years ago
3 changed file(s) with 35 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
2323 class CodeGenTarget;
2424
2525 struct CodeGenIntrinsic {
26 Record *TheDef; // The actual record defining this instruction.
26 Record *TheDef; // The actual record defining this intrinsic.
2727 std::string Name; // The name of the LLVM function "llvm.bswap.i32"
2828 std::string EnumName; // The name of the enum "bswap_i32"
2929 std::string GCCBuiltinName;// Name of the corresponding GCC builtin, or "".
4848 NoMem, ReadArgMem, ReadMem, WriteArgMem, WriteMem
4949 } ModRef;
5050
51 // This is set to true if the intrinsic is overloaded by its argument
52 // types.
53 bool isOverloaded;
54
5155 CodeGenIntrinsic(Record *R, CodeGenTarget *CGT);
5256 };
5357
4242 case MVT::i32: return "MVT::i32";
4343 case MVT::i64: return "MVT::i64";
4444 case MVT::i128: return "MVT::i128";
45 case MVT::iAny: return "MVT::iAny";
4546 case MVT::f32: return "MVT::f32";
4647 case MVT::f64: return "MVT::f64";
4748 case MVT::f80: return "MVT::f80";
7374 case MVT::i32: return "MVT::i32";
7475 case MVT::i64: return "MVT::i64";
7576 case MVT::i128: return "MVT::i128";
77 case MVT::iAny: return "MVT::iAny";
7678 case MVT::f32: return "MVT::f32";
7779 case MVT::f64: return "MVT::f64";
7880 case MVT::f80: return "MVT::f80";
569571 TheDef = R;
570572 std::string DefName = R->getName();
571573 ModRef = WriteMem;
574 isOverloaded = false;
572575
573576 if (DefName.size() <= 4 ||
574577 std::string(DefName.begin(), DefName.begin()+4) != "int_")
609612 Record *TyEl = TypeList->getElementAsRecord(i);
610613 assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
611614 ArgTypes.push_back(TyEl->getValueAsString("TypeVal"));
612
613 if (CGT)
614 ArgVTs.push_back(getValueType(TyEl->getValueAsDef("VT"), CGT));
615 MVT::ValueType VT = getValueType(TyEl->getValueAsDef("VT"), CGT);
616 isOverloaded |= VT == MVT::iAny;
617 ArgVTs.push_back(VT);
615618 ArgTypeDefs.push_back(TyEl);
616619 }
617620 if (ArgTypes.size() == 0)
618621 throw "Intrinsic '"+DefName+"' needs at least a type for the ret value!";
622
619623
620624 // Parse the intrinsic properties.
621625 ListInit *PropList = R->getValueAsListInit("Properties");
7373 EmitFnNameRecognizer(const std::vector &Ints,
7474 std::ostream &OS) {
7575 // Build a function name -> intrinsic name mapping.
76 std::mapstd::string> IntMapping;
76 std::mapunsigned> IntMapping;
7777 for (unsigned i = 0, e = Ints.size(); i != e; ++i)
78 IntMapping[Ints[i].Name] = Ints[i].EnumName;
78 IntMapping[Ints[i].Name] = i;
7979
8080 OS << "// Function name -> enum value recognizer code.\n";
8181 OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
8383 OS << " default:\n";
8484 // Emit the intrinsics in sorted order.
8585 char LastChar = 0;
86 for (std::mapstd::string>::iterator I = IntMapping.begin(),
86 for (std::mapunsigned>::iterator I = IntMapping.begin(),
8787 E = IntMapping.end(); I != E; ++I) {
8888 if (I->first[5] != LastChar) {
8989 LastChar = I->first[5];
9191 OS << " case '" << LastChar << "':\n";
9292 }
9393
94 OS << " if (Len == " << I->first.size()
95 << " && !memcmp(Name, \"" << I->first << "\", Len)) return Intrinsic::"
96 << I->second << ";\n";
94 // For overloaded intrinsics, only the prefix needs to match
95 if (Ints[I->second].isOverloaded)
96 OS << " if (Len >= " << I->first.size()
97 << " && !memcmp(Name, \"" << I->first << "\", " << I->first.size()
98 << ")) return Intrinsic::" << Ints[I->second].EnumName << ";\n";
99 else
100 OS << " if (Len == " << I->first.size()
101 << " && !memcmp(Name, \"" << I->first << "\", Len)) return Intrinsic::"
102 << Ints[I->second].EnumName << ";\n";
97103 }
98104 OS << " }\n";
99105 OS << " // The 'llvm.' namespace is reserved!\n";
129135 return false;
130136 }
131137
132 static void EmitTypeGenerate(std::ostream &OS, Record *ArgType) {
138 static void EmitTypeGenerate(std::ostream &OS, Record *ArgType, unsigned ArgNo){
133139 if (ArgType->isSubClassOf("LLVMIntegerType")) {
134 OS << "IntegerType::get(" << ArgType->getValueAsInt("Width") << ")";
140 unsigned BitWidth = ArgType->getValueAsInt("Width");
141 if (BitWidth == 0)
142 OS << "Tys[" << ArgNo << "]";
143 else
144 OS << "IntegerType::get(" << BitWidth << ")";
135145 } else if (ArgType->isSubClassOf("LLVMVectorType")) {
136146 OS << "VectorType::get(";
137 EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"));
147 EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
138148 OS << ", " << ArgType->getValueAsInt("NumElts") << ")";
139149 } else if (ArgType->isSubClassOf("LLVMPointerType")) {
140150 OS << "PointerType::get(";
141 EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"));
151 EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
142152 OS << ")";
143153 } else if (ArgType->isSubClassOf("LLVMEmptyStructType")) {
144154 OS << "StructType::get(std::vector())";
193203 }
194204
195205 const std::vector &ArgTypes = I->first;
196 OS << " VerifyIntrinsicPrototype(IF, ";
206 OS << " VerifyIntrinsicPrototype(ID, IF, ";
197207 bool VarArg = false;
198208 for (unsigned j = 0; j != ArgTypes.size(); ++j) {
199209 VarArg = EmitTypeVerify(OS, ArgTypes[j]);
245255 }
246256
247257 OS << " ResultTy = ";
248 EmitTypeGenerate(OS, ArgTypes[0]);
258 EmitTypeGenerate(OS, ArgTypes[0], 0);
249259 OS << ";\n";
250260
251261 for (unsigned j = 1; j != N; ++j) {
252262 OS << " ArgTys.push_back(";
253 EmitTypeGenerate(OS, ArgTypes[j]);
263 EmitTypeGenerate(OS, ArgTypes[j], j);
254264 OS << ");\n";
255265 }
256266