X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Famd%2Fcommon%2Fac_llvm_helper.cpp;h=d392c0ece7f3db3901348ca9bae777b890f5dd37;hb=d9f33951df9c107e7e6b88ec7cc884f38f92c52b;hp=e022e12c7f320a5d883c6cce532ac8352f297392;hpb=fd1121e8399ef1439a6a1cec8246b970cceac7fa;p=mesa.git diff --git a/src/amd/common/ac_llvm_helper.cpp b/src/amd/common/ac_llvm_helper.cpp index e022e12c7f3..d392c0ece7f 100644 --- a/src/amd/common/ac_llvm_helper.cpp +++ b/src/amd/common/ac_llvm_helper.cpp @@ -29,8 +29,13 @@ #pragma push_macro("DEBUG") #undef DEBUG +#include + #include "ac_binary.h" #include "ac_llvm_util.h" +#include "ac_llvm_build.h" + +#include "util/macros.h" #include #include @@ -39,9 +44,6 @@ #include #include -#if HAVE_LLVM < 0x0700 -#include "llvm/Support/raw_ostream.h" -#endif void ac_add_attr_dereferenceable(LLVMValueRef val, uint64_t bytes) { @@ -112,14 +114,76 @@ ac_dispose_target_library_info(LLVMTargetLibraryInfoRef library_info) delete reinterpret_cast(library_info); } +/* Implementation of raw_pwrite_stream that works on malloc()ed memory for + * better compatibility with C code. */ +struct raw_memory_ostream : public llvm::raw_pwrite_stream { + char *buffer; + size_t written; + size_t bufsize; + + raw_memory_ostream() + { + buffer = NULL; + written = 0; + bufsize = 0; + SetUnbuffered(); + } + + ~raw_memory_ostream() + { + free(buffer); + } + + void clear() + { + written = 0; + } + + void take(char *&out_buffer, size_t &out_size) + { + out_buffer = buffer; + out_size = written; + buffer = NULL; + written = 0; + bufsize = 0; + } + + void flush() = delete; + + void write_impl(const char *ptr, size_t size) override + { + if (unlikely(written + size < written)) + abort(); + if (written + size > bufsize) { + bufsize = MAX3(1024, written + size, bufsize / 3 * 4); + buffer = (char *)realloc(buffer, bufsize); + if (!buffer) { + fprintf(stderr, "amd: out of memory allocating ELF buffer\n"); + abort(); + } + } + memcpy(buffer + written, ptr, size); + written += size; + } + + void pwrite_impl(const char *ptr, size_t size, uint64_t offset) override + { + assert(offset == (size_t)offset && + offset + size >= offset && offset + size <= written); + memcpy(buffer + offset, ptr, size); + } + + uint64_t current_pos() const override + { + return written; + } +}; + /* The LLVM compiler is represented as a pass manager containing passes for * optimizations, instruction selection, and code generation. */ struct ac_compiler_passes { - ac_compiler_passes(): ostream(code_string) {} - - llvm::SmallString<0> code_string; /* ELF shader binary */ - llvm::raw_svector_ostream ostream; /* stream for appending data to the binary */ + raw_memory_ostream ostream; /* ELF shader binary stream */ llvm::legacy::PassManager passmgr; /* list of passes */ }; @@ -132,9 +196,7 @@ struct ac_compiler_passes *ac_create_llvm_passes(LLVMTargetMachineRef tm) llvm::TargetMachine *TM = reinterpret_cast(tm); if (TM->addPassesToEmitFile(p->passmgr, p->ostream, -#if HAVE_LLVM >= 0x0700 nullptr, -#endif llvm::TargetMachine::CGFT_ObjectFile)) { fprintf(stderr, "amd: TargetMachine can't emit a file of this type!\n"); delete p; @@ -149,18 +211,12 @@ void ac_destroy_llvm_passes(struct ac_compiler_passes *p) } /* This returns false on failure. */ -bool ac_compile_module_to_binary(struct ac_compiler_passes *p, LLVMModuleRef module, - struct ac_shader_binary *binary) +bool ac_compile_module_to_elf(struct ac_compiler_passes *p, LLVMModuleRef module, + char **pelf_buffer, size_t *pelf_size) { p->passmgr.run(*llvm::unwrap(module)); - - llvm::StringRef data = p->ostream.str(); - bool success = ac_elf_read(data.data(), data.size(), binary); - p->code_string = ""; /* release the ELF shader binary */ - - if (!success) - fprintf(stderr, "amd: cannot read an ELF shader binary\n"); - return success; + p->ostream.take(*pelf_buffer, *pelf_size); + return true; } void ac_llvm_add_barrier_noop_pass(LLVMPassManagerRef passmgr) @@ -170,7 +226,63 @@ void ac_llvm_add_barrier_noop_pass(LLVMPassManagerRef passmgr) void ac_enable_global_isel(LLVMTargetMachineRef tm) { -#if HAVE_LLVM >= 0x0700 reinterpret_cast(tm)->setGlobalISel(true); -#endif +} + +LLVMValueRef ac_build_atomic_rmw(struct ac_llvm_context *ctx, LLVMAtomicRMWBinOp op, + LLVMValueRef ptr, LLVMValueRef val, + const char *sync_scope) { + llvm::AtomicRMWInst::BinOp binop; + switch (op) { + case LLVMAtomicRMWBinOpXchg: + binop = llvm::AtomicRMWInst::Xchg; + break; + case LLVMAtomicRMWBinOpAdd: + binop = llvm::AtomicRMWInst::Add; + break; + case LLVMAtomicRMWBinOpSub: + binop = llvm::AtomicRMWInst::Sub; + break; + case LLVMAtomicRMWBinOpAnd: + binop = llvm::AtomicRMWInst::And; + break; + case LLVMAtomicRMWBinOpNand: + binop = llvm::AtomicRMWInst::Nand; + break; + case LLVMAtomicRMWBinOpOr: + binop = llvm::AtomicRMWInst::Or; + break; + case LLVMAtomicRMWBinOpXor: + binop = llvm::AtomicRMWInst::Xor; + break; + case LLVMAtomicRMWBinOpMax: + binop = llvm::AtomicRMWInst::Max; + break; + case LLVMAtomicRMWBinOpMin: + binop = llvm::AtomicRMWInst::Min; + break; + case LLVMAtomicRMWBinOpUMax: + binop = llvm::AtomicRMWInst::UMax; + break; + case LLVMAtomicRMWBinOpUMin: + binop = llvm::AtomicRMWInst::UMin; + break; + default: + unreachable(!"invalid LLVMAtomicRMWBinOp"); + break; + } + unsigned SSID = llvm::unwrap(ctx->context)->getOrInsertSyncScopeID(sync_scope); + return llvm::wrap(llvm::unwrap(ctx->builder)->CreateAtomicRMW( + binop, llvm::unwrap(ptr), llvm::unwrap(val), + llvm::AtomicOrdering::SequentiallyConsistent, SSID)); +} + +LLVMValueRef ac_build_atomic_cmp_xchg(struct ac_llvm_context *ctx, LLVMValueRef ptr, + LLVMValueRef cmp, LLVMValueRef val, + const char *sync_scope) { + unsigned SSID = llvm::unwrap(ctx->context)->getOrInsertSyncScopeID(sync_scope); + return llvm::wrap(llvm::unwrap(ctx->builder)->CreateAtomicCmpXchg( + llvm::unwrap(ptr), llvm::unwrap(cmp), llvm::unwrap(val), + llvm::AtomicOrdering::SequentiallyConsistent, + llvm::AtomicOrdering::SequentiallyConsistent, SSID)); }