bridge: support builtin memset
Change-Id: I7321f57e0d58c0ff5c3a19f7cbf5721fabbf1263
Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/184439
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/bridge/go-llvm-builtins.cpp b/bridge/go-llvm-builtins.cpp
index 10befb0..76b4d1f 100644
--- a/bridge/go-llvm-builtins.cpp
+++ b/bridge/go-llvm-builtins.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "go-llvm.h"
#include "go-llvm-builtins.h"
#include "go-llvm-bfunction.h"
#include "go-llvm-typemanager.h"
@@ -347,7 +348,7 @@
static llvm::Value *builtinExtractReturnAddrMaker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
// __builtin_extract_return_addr(uintptr) uintptr
// extracts the actual encoded address from the address as returned
@@ -362,12 +363,29 @@
static llvm::Value *builtinUnreachableMaker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
llvm::UnreachableInst *unr = builder->CreateUnreachable();
return unr;
}
+static llvm::Value *builtinMemsetMaker(llvm::SmallVectorImpl<llvm::Value*> &args,
+ BinstructionsLIRBuilder *builder,
+ Llvm_backend *be)
+{
+ // __builtin_memset takes int32 as its second argument, whereas
+ // LLVM intrinsic memset takes an i8. We wrap the intrinsic in
+ // an expression builtin, which does a cast first.
+ assert(args.size() == 3);
+ llvm::Value *cast = builder->CreateTrunc(args[1], be->llvmInt8Type());
+ llvm::Function* fn =
+ llvm::Intrinsic::getDeclaration(&be->module(),
+ llvm::Intrinsic::memset,
+ {args[0]->getType(), args[2]->getType()});
+ // LLVM memset takes an extra isVolatile argument.
+ return builder->CreateCall(fn, {args[0], cast, args[2], builder->getFalse()});
+}
+
static llvm::AtomicOrdering llvmOrder(int o)
{
switch (o) {
@@ -389,10 +407,10 @@
static llvm::Value *atomicLoadMaker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm, int sz)
+ Llvm_backend *be, int sz)
{
assert(args.size() == 2);
- llvm::Type *t = sz == 8 ? tm->llvmInt64Type() : tm->llvmInt32Type();
+ llvm::Type *t = sz == 8 ? be->llvmInt64Type() : be->llvmInt32Type();
llvm::LoadInst *load = builder->CreateLoad(t, args[0]);
// FIXME: we assume the FE always emits constant memory order.
// in case it doesn't, conservatively use SequentiallyConsistent.
@@ -407,21 +425,21 @@
static llvm::Value *atomicLoad4Maker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
- return atomicLoadMaker(args, builder, tm, 4);
+ return atomicLoadMaker(args, builder, be, 4);
}
static llvm::Value *atomicLoad8Maker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
- return atomicLoadMaker(args, builder, tm, 8);
+ return atomicLoadMaker(args, builder, be, 8);
}
static llvm::Value *atomicStoreMaker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm, int sz)
+ Llvm_backend *be, int sz)
{
assert(args.size() == 3);
llvm::StoreInst *store = builder->CreateStore(args[1], args[0]);
@@ -437,22 +455,22 @@
static llvm::Value *atomicStore4Maker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
- return atomicStoreMaker(args, builder, tm, 4);
+ return atomicStoreMaker(args, builder, be, 4);
}
static llvm::Value *atomicStore8Maker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
- return atomicStoreMaker(args, builder, tm, 8);
+ return atomicStoreMaker(args, builder, be, 8);
}
static llvm::Value *atomicRMWMaker(llvm::AtomicRMWInst::BinOp op,
llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
assert(args.size() == 3);
// FIXME: see atomicLoadMaker.
@@ -465,41 +483,41 @@
static llvm::Value *atomicXchgMaker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
- return atomicRMWMaker(llvm::AtomicRMWInst::Xchg, args, builder, tm);
+ return atomicRMWMaker(llvm::AtomicRMWInst::Xchg, args, builder, be);
}
static llvm::Value *atomicAddMaker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
// atomicrmw returns the old content. We need to do the add.
- llvm::Value* old = atomicRMWMaker(llvm::AtomicRMWInst::Add, args, builder, tm);
+ llvm::Value* old = atomicRMWMaker(llvm::AtomicRMWInst::Add, args, builder, be);
return builder->CreateAdd(old, args[1]);
}
static llvm::Value *atomicAndMaker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
// atomicrmw returns the old content. We need to do the and.
- llvm::Value* old = atomicRMWMaker(llvm::AtomicRMWInst::And, args, builder, tm);
+ llvm::Value* old = atomicRMWMaker(llvm::AtomicRMWInst::And, args, builder, be);
return builder->CreateAnd(old, args[1]);
}
static llvm::Value *atomicOrMaker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
// atomicrmw returns the old content. We need to do the or.
- llvm::Value* old = atomicRMWMaker(llvm::AtomicRMWInst::Or, args, builder, tm);
+ llvm::Value* old = atomicRMWMaker(llvm::AtomicRMWInst::Or, args, builder, be);
return builder->CreateOr(old, args[1]);
}
static llvm::Value *atomicCasMaker(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm)
+ Llvm_backend *be)
{
assert(args.size() == 6);
// GCC __atomic_compare_exchange_n takes a pointer to the old value.
@@ -525,7 +543,7 @@
// LLVM cmpxchg instruction returns { valType, i1 }. Extract the second
// value, and cast to Go bool type (i8).
llvm::Value *ret = builder->CreateExtractValue(cas, {1});
- return builder->CreateZExt(ret, tm->llvmInt8Type());
+ return builder->CreateZExt(ret, be->llvmInt8Type());
}
void BuiltinTable::defineExprBuiltins()
@@ -554,6 +572,12 @@
}
{
+ BuiltinEntryTypeVec typeVec = {nullptr, uint8Type, int32Type, uintPtrType};
+ registerExprBuiltin("__builtin_memset", nullptr,
+ typeVec, builtinMemsetMaker);
+ }
+
+ {
BuiltinEntryTypeVec typeVec = {uint32Type, uint32PtrType, int32Type};
registerExprBuiltin("__atomic_load_4", nullptr,
typeVec, atomicLoad4Maker);
diff --git a/bridge/go-llvm-builtins.h b/bridge/go-llvm-builtins.h
index 1e5399a..fe36da1 100644
--- a/bridge/go-llvm-builtins.h
+++ b/bridge/go-llvm-builtins.h
@@ -27,7 +27,7 @@
typedef llvm::Value *(*BuiltinExprMaker)(llvm::SmallVectorImpl<llvm::Value*> &args,
BinstructionsLIRBuilder *builder,
- TypeManager *tm);
+ Llvm_backend *be);
// An entry in a table of interesting builtin functions. A given entry
// is either an intrinsic or a libcall builtin.