ldc/utils/gen_gccbuiltins.cpp
Kai Nacke cb0f2e7e6a Fix space handling for different paths.
E.g. on my machine LLVM is installed in folder C:\My Program Files\LLVM.

Fixes part of issue #1465. (PR 1466 is required for complete fix.)
2016-05-16 00:12:27 +02:00

224 lines
5.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===-- gen_gccbuiltins.cpp - GCC builtin module generator ----------------===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
//
// This tool reads the GCC builtin definitions from LLVM's Intrinsics.td for
// a given architecture and accordingly generates a ldc.gccbuiltins_<arch>
// module for using them from D code.
//
//===----------------------------------------------------------------------===//
#include "llvm/TableGen/Main.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Path.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
#include <assert.h>
#include <map>
#include <stdio.h>
#include <string.h>
#include <string>
using namespace std;
using namespace llvm;
string dtype(Record* rec, bool readOnlyMem)
{
Init* typeInit = rec->getValueInit("VT");
if(!typeInit)
return "";
string type = typeInit->getAsString();
if(type == "iPTR")
return readOnlyMem ? "const void*" : "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(vec.size() > 0 && type.size() > 0)
{
int typeSize, vecElements;
if(
sscanf(vec.c_str(), "%d", &vecElements) == 1 &&
sscanf(type.c_str() + 1, "%d", &typeSize) == 1 &&
typeSize * vecElements > 256)
{
return "";
}
}
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 =
#if LDC_LLVM_VER >= 307
propertyList->size()
#else
propertyList->getSize()
#endif
? propertyList->getElementAsRecord(0)->getName() : "";
return
prop == "IntrNoMem" ? " pure @safe" :
prop == "IntrReadArgMem" ? " pure" :
prop == "IntrReadWriteArgMem" ? " pure" : "";
}
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;
#if LDC_LLVM_VER >= 309
ListInit* propsList = rec.getValueAsListInit("IntrProperties");
#else
ListInit* propsList = rec.getValueAsListInit("Properties");
#endif
string prop =
#if LDC_LLVM_VER >= 307
propsList->size()
#else
propsList->getSize()
#endif
? propsList->getElementAsRecord(0)->getName() : "";
bool readOnlyMem = prop == "IntrReadArgMem" || prop == "IntrReadMem";
ListInit* paramsList = rec.getValueAsListInit("ParamTypes");
vector<string> params;
for(unsigned int i = 0; i <
#if LDC_LLVM_VER >= 307
paramsList->size();
#else
paramsList->getSize();
#endif
i++)
{
string t = dtype(paramsList->getElementAsRecord(i), readOnlyMem);
if(t == "")
return;
params.push_back(t);
}
ListInit* retList = rec.getValueAsListInit("RetTypes");
string ret;
#if LDC_LLVM_VER >= 307
size_t sz = retList->size();
#else
size_t sz = retList->getSize();
#endif
if(sz == 0)
ret = "void";
else if(sz == 1)
{
ret = dtype(retList->getElementAsRecord(0), false);
if(ret == "")
return;
}
else
return;
os << "pragma(LDC_intrinsic, \"" + name + "\")\n ";
os << ret + " " + builtinName + "(";
if(params.size())
os << params[0];
for(size_t i = 1; i < params.size(); i++)
os << ", " << params[i];
os << ")" + attributes(propsList) + ";\n\n";
}
std::string arch;
bool emit(raw_ostream& os, RecordKeeper& records)
{
os << "module ldc.gccbuiltins_";
os << arch;
os << "; \n\nimport core.simd;\n\nnothrow @nogc:\n\n";
#if LDC_LLVM_VER >= 306
const auto &defs = records.getDefs();
#else
map<string, Record*> defs = records.getDefs();
#endif
for (const auto& d : defs)
processRecord(os, *d.second, arch);
return false;
}
int main(int argc, char** argv)
{
if(argc != 3)
{
fprintf(stderr, "There must be exactly two command line arguments\n");
return 1;
}
#define STR(x) #x
#define XSTR(x) STR(x)
llvm::SmallString<128> file(XSTR(LLVM_INTRINSIC_TD_PATH));
sys::path::append(file, "llvm");
sys::path::append(file, "IR");
sys::path::append(file, "Intrinsics.td");
string iStr = string("-I=") + string(XSTR(LLVM_INTRINSIC_TD_PATH));
string oStr = string("-o=") + argv[1];
#undef XSTR
#undef STR
vector<char*> args2(argv, argv + 1);
args2.push_back(const_cast<char*>(file.c_str()));
args2.push_back(const_cast<char*>(iStr.c_str()));
args2.push_back(const_cast<char*>(oStr.c_str()));
cl::ParseCommandLineOptions(args2.size(), &args2[0]);
arch = argv[2];
return TableGenMain(argv[0], emit);
}