blob: bf31d3837bdd415ece184229f0c67b4c891ced5f [file] [log] [blame]
//===-- go-llvm-builtins.h - decls for 'BuiltinTable' class ---------------===//
//
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
//===----------------------------------------------------------------------===//
//
// Defines BuiltinTable and related classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVMGOFRONTEND_GO_LLVM_BUILTINTABLE_H
#define LLVMGOFRONTEND_GO_LLVM_BUILTINTABLE_H
#include <unordered_map>
#include "go-llvm-irbuilders.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
class Bfunction;
class Btype;
class TypeManager;
typedef std::vector<Btype*> BuiltinEntryTypeVec;
typedef llvm::Value *(*BuiltinExprMaker)(llvm::SmallVector<llvm::Value*, 16> args,
BinstructionsLIRBuilder *builder);
// An entry in a table of interesting builtin functions. A given entry
// is either an intrinsic or a libcall builtin.
//
// Intrinsic functions can be generic or target-dependent; they are
// predefined by LLVM, described in various tables (ex:
// .../include/llvm/IR/Intrinsics.td). Intrinsics can be polymorphic
// (for example, accepting an arg of any float type).
//
// Libcall builtins can also be generic or target-dependent; they
// are identified via enums defined in .../Analysis/TargetLibraryInfo.def).
// These functions are not polymorphic.
//
// Inlined builtins are intrinsics handled by the bridge (instead
// of LLVM). A call to it will turn into an inlined expresssion
// (an LLVM Value and perhaps a sequence of instructions) at
// materialization.
class BuiltinEntry {
public:
enum BuiltinFlavor { IntrinsicBuiltin, LibcallBuiltin, InlinedBuiltin };
static const auto NotInTargetLib = llvm::LibFunc::NumLibFuncs;
BuiltinFlavor flavor() const { return flavor_; }
const std::string &name() const { return name_; }
const std::string &libname() const { return libname_; }
llvm::Intrinsic::ID intrinsicId() const { return intrinsicId_; }
llvm::LibFunc libfunc() const { return libfunc_; }
const BuiltinEntryTypeVec &types() const { return types_; }
Bfunction *bfunction() const { return bfunction_; }
void setBfunction(Bfunction *bfunc);
BuiltinExprMaker exprMaker() const { return exprMaker_; }
BuiltinEntry(llvm::Intrinsic::ID intrinsicId,
const std::string &name,
const std::string &libname,
const BuiltinEntryTypeVec &ovltypes)
: name_(name), libname_(libname), flavor_(IntrinsicBuiltin),
intrinsicId_(intrinsicId), libfunc_(NotInTargetLib),
bfunction_(nullptr), types_(ovltypes), exprMaker_(nullptr) { }
BuiltinEntry(llvm::LibFunc libfunc,
const std::string &name,
const std::string &libname,
const BuiltinEntryTypeVec &paramtypes)
: name_(name), libname_(libname), flavor_(LibcallBuiltin),
intrinsicId_(), libfunc_(libfunc), bfunction_(nullptr),
types_(paramtypes), exprMaker_(nullptr) { }
BuiltinEntry(const std::string &name,
const std::string &libname,
const BuiltinEntryTypeVec &paramtypes,
BuiltinExprMaker exprMaker)
: name_(name), libname_(libname), flavor_(InlinedBuiltin),
intrinsicId_(), libfunc_(NotInTargetLib), bfunction_(nullptr),
types_(paramtypes), exprMaker_(exprMaker) { }
~BuiltinEntry();
private:
std::string name_;
std::string libname_;
BuiltinFlavor flavor_;
llvm::Intrinsic::ID intrinsicId_;
llvm::LibFunc libfunc_;
Bfunction *bfunction_;
BuiltinEntryTypeVec types_;
BuiltinExprMaker exprMaker_;
};
// This table contains entries for the builtin functions that may
// be useful/needed for a go backend. The intent here is to generate
// info about the functions at the point where this object is created,
// then create the actual LLVM function lazily at the point where
// there is a need to call the function.
//
// Note: there is support in the table for creating "long double"
// versions of things like the trig builtins, but the CABI machinery
// does not yet handle "long double" (nor does this type exist in Go),
// so it is currently stubbed out (via the "addLongDouble" param below).
class BuiltinTable {
public:
BuiltinTable(TypeManager *tman, bool addLongDouble);
~BuiltinTable() { }
void defineAllBuiltins();
BuiltinEntry *lookup(const std::string &name);
private:
void defineSyncFetchAndAddBuiltins();
void defineIntrinsicBuiltins();
void defineTrigBuiltins();
void defineExprBuiltins();
void defineLibcallBuiltin(const char *libname, const char *name,
unsigned libfuncID, ...);
void defineLibcallBuiltin(const char *libname, const char *name,
BuiltinEntryTypeVec &types,
unsigned libfuncID);
void defineIntrinsicBuiltin(const char *name, const char *libname,
unsigned intrinsicID, ...);
void registerIntrinsicBuiltin(const char *name,
const char *libname,
llvm::Intrinsic::ID intrinsicId,
const BuiltinEntryTypeVec &overloadTypes);
void registerLibCallBuiltin(const char *name,
const char *libname,
llvm::LibFunc libfunc,
const BuiltinEntryTypeVec &paramTypes);
void registerExprBuiltin(const char *name,
const char *libname,
const BuiltinEntryTypeVec &paramTypes,
BuiltinExprMaker exprMaker);
private:
TypeManager *tman_;
std::unordered_map<std::string, unsigned> tab_;
std::vector<BuiltinEntry> entries_;
bool addLongDouble_;
};
#endif // LLVMGOFRONTEND_GO_LLVM_BUILTINTABLE_H