#include #include #include #include #include #include #include #if LDC_LLVM_VER < 302 #include #endif #include #include #include #include using namespace std; using namespace llvm; string dtype(Record* rec) { Init* typeInit = rec->getValueInit("VT"); if(!typeInit) return ""; string type = typeInit->getAsString(); if(type == "iPTR") return "void*"; string vec = ""; if(type[0] == 'v') { size_t i = 1; while(i != type.size() && type[i] <= '9' && type[i] >= '0') i++; vec = type.substr(1, i - 1); type = type.substr(i); } if(type == "i8") return "byte" + vec; else if(type == "i16") return "short" + vec; else if(type == "i32") return "int" + vec; else if(type == "i64") return "long" + vec; else if(type == "f32") return "float" + vec; else if(type == "f64") return "double" + vec; else return ""; } string attributes(ListInit* propertyList) { string prop = propertyList->getSize() ? propertyList->getElementAsRecord(0)->getName() : ""; return prop == "IntrNoMem" ? "nothrow pure @safe" : prop == "IntrReadArgMem" ? "nothrow pure" : prop == "IntrReadWriteArgMem" ? "nothrow pure" : "nothrow"; } void processRecord(raw_ostream& os, Record& rec, string arch) { if(!rec.getValue("GCCBuiltinName")) return; string builtinName = rec.getValueAsString("GCCBuiltinName"); string name = rec.getName(); if(name.substr(0, 4) != "int_" || name.find(arch) == string::npos) return; name = name.substr(4); replace(name.begin(), name.end(), '_', '.'); name = string("llvm.") + name; ListInit* paramsList = rec.getValueAsListInit("ParamTypes"); vector params; for(int i = 0; i < paramsList->getSize(); i++) { string t = dtype(paramsList->getElementAsRecord(i)); if(t == "") return; params.push_back(t); } ListInit* retList = rec.getValueAsListInit("RetTypes"); string ret; if(retList->getSize() == 0) ret = "void"; else if(retList->getSize() == 1) { ret = dtype(retList->getElementAsRecord(0)); if(ret == "") return; } else return; os << "pragma(intrinsic, \"" + name + "\")\n "; os << ret + " " + builtinName + "("; if(params.size()) os << params[0]; for(int i = 1; i < params.size(); i++) os << ", " << params[i]; os << ")" + attributes(rec.getValueAsListInit("Properties")) + ";\n\n"; } std::string arch; bool emit(raw_ostream& os, RecordKeeper& records) { os << "module ldc.gccbuiltins_"; os << arch; os << "; \n\nimport core.simd;\n\n"; map defs = records.getDefs(); for( map::iterator it = defs.begin(); it != defs.end(); it++) { processRecord(os, *(*it).second, arch); } return false; } #if LDC_LLVM_VER < 302 struct ActionImpl : TableGenAction { bool operator()(raw_ostream& os, RecordKeeper& records) { return emit(os, records); } }; #endif int main(int argc, char** argv) { if(argc != 3) { fprintf(stderr, "There must be exactly two command line arguments\n"); return 1; } sys::Path file(LLVM_INTRINSIC_TD_PATH); file.appendComponent("llvm"); file.appendComponent("Intrinsics.td"); string iStr = string("-I=") + string(LLVM_INTRINSIC_TD_PATH); string oStr = string("-o=") + argv[1]; vector args2(argv, argv + 1); args2.push_back(const_cast(file.c_str())); args2.push_back(const_cast(iStr.c_str())); args2.push_back(const_cast(oStr.c_str())); cl::ParseCommandLineOptions(args2.size(), &args2[0]); arch = argv[2]; #if LDC_LLVM_VER >= 302 return TableGenMain(argv[0], emit); #else ActionImpl act; return TableGenMain(argv[0], act); #endif }