radeonsi: import all TGSI->LLVM code from gallium/radeon
Acked-by: Nicolai Hähnle <nicolai.haehnle@amd.com> Reviewed-by: Emil Velikov <emil.velikov@collabora.com> Acked-by: Edward O'Callaghan <funfunctor@folklore1984.net>
This commit is contained in:
parent
4967cacdfa
commit
5ab25bb4ba
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include "r600_asm.h"
|
||||
#ifdef HAVE_OPENCL
|
||||
#include "radeon/radeon_llvm.h"
|
||||
#include <llvm-c/Core.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -25,8 +25,4 @@ C_SOURCES := \
|
|||
|
||||
LLVM_C_FILES := \
|
||||
radeon_elf_util.c \
|
||||
radeon_elf_util.h \
|
||||
radeon_llvm_emit.c \
|
||||
radeon_llvm_emit.h \
|
||||
radeon_llvm.h \
|
||||
radeon_setup_tgsi_llvm.c
|
||||
radeon_elf_util.h
|
||||
|
|
|
@ -1,151 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors: Tom Stellard <thomas.stellard@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RADEON_LLVM_H
|
||||
#define RADEON_LLVM_H
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
#include "gallivm/lp_bld_init.h"
|
||||
#include "gallivm/lp_bld_tgsi.h"
|
||||
#include "tgsi/tgsi_parse.h"
|
||||
|
||||
#define RADEON_LLVM_MAX_INPUT_SLOTS 32
|
||||
#define RADEON_LLVM_MAX_INPUTS 32 * 4
|
||||
#define RADEON_LLVM_MAX_OUTPUTS 32 * 4
|
||||
|
||||
#define RADEON_LLVM_INITIAL_CF_DEPTH 4
|
||||
|
||||
#define RADEON_LLVM_MAX_SYSTEM_VALUES 4
|
||||
|
||||
struct radeon_llvm_flow;
|
||||
|
||||
struct radeon_llvm_context {
|
||||
struct lp_build_tgsi_soa_context soa;
|
||||
|
||||
/*=== Front end configuration ===*/
|
||||
|
||||
/* Instructions that are not described by any of the TGSI opcodes. */
|
||||
|
||||
/** This function is responsible for initilizing the inputs array and will be
|
||||
* called once for each input declared in the TGSI shader.
|
||||
*/
|
||||
void (*load_input)(struct radeon_llvm_context *,
|
||||
unsigned input_index,
|
||||
const struct tgsi_full_declaration *decl,
|
||||
LLVMValueRef out[4]);
|
||||
|
||||
void (*load_system_value)(struct radeon_llvm_context *,
|
||||
unsigned index,
|
||||
const struct tgsi_full_declaration *decl);
|
||||
|
||||
void (*declare_memory_region)(struct radeon_llvm_context *,
|
||||
const struct tgsi_full_declaration *decl);
|
||||
|
||||
/** This array contains the input values for the shader. Typically these
|
||||
* values will be in the form of a target intrinsic that will inform the
|
||||
* backend how to load the actual inputs to the shader.
|
||||
*/
|
||||
struct tgsi_full_declaration input_decls[RADEON_LLVM_MAX_INPUT_SLOTS];
|
||||
LLVMValueRef inputs[RADEON_LLVM_MAX_INPUTS];
|
||||
LLVMValueRef outputs[RADEON_LLVM_MAX_OUTPUTS][TGSI_NUM_CHANNELS];
|
||||
|
||||
/** This pointer is used to contain the temporary values.
|
||||
* The amount of temporary used in tgsi can't be bound to a max value and
|
||||
* thus we must allocate this array at runtime.
|
||||
*/
|
||||
LLVMValueRef *temps;
|
||||
unsigned temps_count;
|
||||
LLVMValueRef system_values[RADEON_LLVM_MAX_SYSTEM_VALUES];
|
||||
|
||||
/*=== Private Members ===*/
|
||||
|
||||
struct radeon_llvm_flow *flow;
|
||||
unsigned flow_depth;
|
||||
unsigned flow_depth_max;
|
||||
|
||||
struct tgsi_array_info *temp_arrays;
|
||||
LLVMValueRef *temp_array_allocas;
|
||||
|
||||
LLVMValueRef undef_alloca;
|
||||
|
||||
LLVMValueRef main_fn;
|
||||
LLVMTypeRef return_type;
|
||||
|
||||
unsigned fpmath_md_kind;
|
||||
LLVMValueRef fpmath_md_2p5_ulp;
|
||||
|
||||
struct gallivm_state gallivm;
|
||||
};
|
||||
|
||||
LLVMTypeRef tgsi2llvmtype(struct lp_build_tgsi_context *bld_base,
|
||||
enum tgsi_opcode_type type);
|
||||
|
||||
LLVMValueRef bitcast(struct lp_build_tgsi_context *bld_base,
|
||||
enum tgsi_opcode_type type, LLVMValueRef value);
|
||||
|
||||
LLVMValueRef radeon_llvm_bound_index(struct radeon_llvm_context *ctx,
|
||||
LLVMValueRef index,
|
||||
unsigned num);
|
||||
|
||||
void radeon_llvm_context_init(struct radeon_llvm_context *ctx,
|
||||
const char *triple,
|
||||
const struct tgsi_shader_info *info,
|
||||
const struct tgsi_token *tokens);
|
||||
|
||||
void radeon_llvm_create_func(struct radeon_llvm_context *ctx,
|
||||
LLVMTypeRef *return_types, unsigned num_return_elems,
|
||||
LLVMTypeRef *ParamTypes, unsigned ParamCount);
|
||||
|
||||
void radeon_llvm_dispose(struct radeon_llvm_context *ctx);
|
||||
|
||||
void radeon_llvm_finalize_module(struct radeon_llvm_context *ctx,
|
||||
bool run_verifier);
|
||||
|
||||
LLVMValueRef radeon_llvm_emit_fetch_64bit(struct lp_build_tgsi_context *bld_base,
|
||||
enum tgsi_opcode_type type,
|
||||
LLVMValueRef ptr,
|
||||
LLVMValueRef ptr2);
|
||||
|
||||
LLVMValueRef radeon_llvm_saturate(struct lp_build_tgsi_context *bld_base,
|
||||
LLVMValueRef value);
|
||||
|
||||
LLVMValueRef radeon_llvm_emit_fetch(struct lp_build_tgsi_context *bld_base,
|
||||
const struct tgsi_full_src_register *reg,
|
||||
enum tgsi_opcode_type type,
|
||||
unsigned swizzle);
|
||||
|
||||
void radeon_llvm_emit_store(struct lp_build_tgsi_context *bld_base,
|
||||
const struct tgsi_full_instruction *inst,
|
||||
const struct tgsi_opcode_info *info,
|
||||
LLVMValueRef dst[4]);
|
||||
|
||||
static inline struct radeon_llvm_context *
|
||||
radeon_llvm_context(struct lp_build_tgsi_context *bld_base)
|
||||
{
|
||||
return (struct radeon_llvm_context*)bld_base;
|
||||
}
|
||||
|
||||
#endif /* RADEON_LLVM_H */
|
|
@ -1,241 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors: Tom Stellard <thomas.stellard@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "radeon_llvm_emit.h"
|
||||
#include "radeon_elf_util.h"
|
||||
#include "c11/threads.h"
|
||||
#include "gallivm/lp_bld_misc.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include <llvm-c/Target.h>
|
||||
#include <llvm-c/TargetMachine.h>
|
||||
#include <llvm-c/Core.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CPU_STRING_LEN 30
|
||||
#define FS_STRING_LEN 30
|
||||
#define TRIPLE_STRING_LEN 7
|
||||
|
||||
/**
|
||||
* Shader types for the LLVM backend.
|
||||
*/
|
||||
enum radeon_llvm_shader_type {
|
||||
RADEON_LLVM_SHADER_PS = 0,
|
||||
RADEON_LLVM_SHADER_VS = 1,
|
||||
RADEON_LLVM_SHADER_GS = 2,
|
||||
RADEON_LLVM_SHADER_CS = 3,
|
||||
};
|
||||
|
||||
enum radeon_llvm_calling_convention {
|
||||
RADEON_LLVM_AMDGPU_VS = 87,
|
||||
RADEON_LLVM_AMDGPU_GS = 88,
|
||||
RADEON_LLVM_AMDGPU_PS = 89,
|
||||
RADEON_LLVM_AMDGPU_CS = 90,
|
||||
};
|
||||
|
||||
void radeon_llvm_add_attribute(LLVMValueRef F, const char *name, int value)
|
||||
{
|
||||
char str[16];
|
||||
|
||||
snprintf(str, sizeof(str), "%i", value);
|
||||
LLVMAddTargetDependentFunctionAttr(F, name, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the shader type we want to compile
|
||||
*
|
||||
* @param type shader type to set
|
||||
*/
|
||||
void radeon_llvm_shader_type(LLVMValueRef F, unsigned type)
|
||||
{
|
||||
enum radeon_llvm_shader_type llvm_type;
|
||||
enum radeon_llvm_calling_convention calling_conv;
|
||||
|
||||
switch (type) {
|
||||
case PIPE_SHADER_VERTEX:
|
||||
case PIPE_SHADER_TESS_CTRL:
|
||||
case PIPE_SHADER_TESS_EVAL:
|
||||
llvm_type = RADEON_LLVM_SHADER_VS;
|
||||
calling_conv = RADEON_LLVM_AMDGPU_VS;
|
||||
break;
|
||||
case PIPE_SHADER_GEOMETRY:
|
||||
llvm_type = RADEON_LLVM_SHADER_GS;
|
||||
calling_conv = RADEON_LLVM_AMDGPU_GS;
|
||||
break;
|
||||
case PIPE_SHADER_FRAGMENT:
|
||||
llvm_type = RADEON_LLVM_SHADER_PS;
|
||||
calling_conv = RADEON_LLVM_AMDGPU_PS;
|
||||
break;
|
||||
case PIPE_SHADER_COMPUTE:
|
||||
llvm_type = RADEON_LLVM_SHADER_CS;
|
||||
calling_conv = RADEON_LLVM_AMDGPU_CS;
|
||||
break;
|
||||
default:
|
||||
unreachable("Unhandle shader type");
|
||||
}
|
||||
|
||||
if (HAVE_LLVM >= 0x309)
|
||||
LLVMSetFunctionCallConv(F, calling_conv);
|
||||
else
|
||||
radeon_llvm_add_attribute(F, "ShaderType", llvm_type);
|
||||
}
|
||||
|
||||
static void init_r600_target()
|
||||
{
|
||||
gallivm_init_llvm_targets();
|
||||
#if HAVE_LLVM < 0x0307
|
||||
LLVMInitializeR600TargetInfo();
|
||||
LLVMInitializeR600Target();
|
||||
LLVMInitializeR600TargetMC();
|
||||
LLVMInitializeR600AsmPrinter();
|
||||
#else
|
||||
LLVMInitializeAMDGPUTargetInfo();
|
||||
LLVMInitializeAMDGPUTarget();
|
||||
LLVMInitializeAMDGPUTargetMC();
|
||||
LLVMInitializeAMDGPUAsmPrinter();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static once_flag init_r600_target_once_flag = ONCE_FLAG_INIT;
|
||||
|
||||
LLVMTargetRef radeon_llvm_get_r600_target(const char *triple)
|
||||
{
|
||||
LLVMTargetRef target = NULL;
|
||||
char *err_message = NULL;
|
||||
|
||||
call_once(&init_r600_target_once_flag, init_r600_target);
|
||||
|
||||
if (LLVMGetTargetFromTriple(triple, &target, &err_message)) {
|
||||
fprintf(stderr, "Cannot find target for triple %s ", triple);
|
||||
if (err_message) {
|
||||
fprintf(stderr, "%s\n", err_message);
|
||||
}
|
||||
LLVMDisposeMessage(err_message);
|
||||
return NULL;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
struct radeon_llvm_diagnostics {
|
||||
struct pipe_debug_callback *debug;
|
||||
unsigned retval;
|
||||
};
|
||||
|
||||
static void radeonDiagnosticHandler(LLVMDiagnosticInfoRef di, void *context)
|
||||
{
|
||||
struct radeon_llvm_diagnostics *diag = (struct radeon_llvm_diagnostics *)context;
|
||||
LLVMDiagnosticSeverity severity = LLVMGetDiagInfoSeverity(di);
|
||||
char *description = LLVMGetDiagInfoDescription(di);
|
||||
const char *severity_str = NULL;
|
||||
|
||||
switch (severity) {
|
||||
case LLVMDSError:
|
||||
severity_str = "error";
|
||||
break;
|
||||
case LLVMDSWarning:
|
||||
severity_str = "warning";
|
||||
break;
|
||||
case LLVMDSRemark:
|
||||
severity_str = "remark";
|
||||
break;
|
||||
case LLVMDSNote:
|
||||
severity_str = "note";
|
||||
break;
|
||||
default:
|
||||
severity_str = "unknown";
|
||||
}
|
||||
|
||||
pipe_debug_message(diag->debug, SHADER_INFO,
|
||||
"LLVM diagnostic (%s): %s", severity_str, description);
|
||||
|
||||
if (severity == LLVMDSError) {
|
||||
diag->retval = 1;
|
||||
fprintf(stderr,"LLVM triggered Diagnostic Handler: %s\n", description);
|
||||
}
|
||||
|
||||
LLVMDisposeMessage(description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an LLVM module to machine code.
|
||||
*
|
||||
* @returns 0 for success, 1 for failure
|
||||
*/
|
||||
unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary,
|
||||
LLVMTargetMachineRef tm,
|
||||
struct pipe_debug_callback *debug)
|
||||
{
|
||||
struct radeon_llvm_diagnostics diag;
|
||||
char *err;
|
||||
LLVMContextRef llvm_ctx;
|
||||
LLVMMemoryBufferRef out_buffer;
|
||||
unsigned buffer_size;
|
||||
const char *buffer_data;
|
||||
LLVMBool mem_err;
|
||||
|
||||
diag.debug = debug;
|
||||
diag.retval = 0;
|
||||
|
||||
/* Setup Diagnostic Handler*/
|
||||
llvm_ctx = LLVMGetModuleContext(M);
|
||||
|
||||
LLVMContextSetDiagnosticHandler(llvm_ctx, radeonDiagnosticHandler, &diag);
|
||||
|
||||
/* Compile IR*/
|
||||
mem_err = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err,
|
||||
&out_buffer);
|
||||
|
||||
/* Process Errors/Warnings */
|
||||
if (mem_err) {
|
||||
fprintf(stderr, "%s: %s", __FUNCTION__, err);
|
||||
pipe_debug_message(debug, SHADER_INFO,
|
||||
"LLVM emit error: %s", err);
|
||||
FREE(err);
|
||||
diag.retval = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Extract Shader Code*/
|
||||
buffer_size = LLVMGetBufferSize(out_buffer);
|
||||
buffer_data = LLVMGetBufferStart(out_buffer);
|
||||
|
||||
radeon_elf_read(buffer_data, buffer_size, binary);
|
||||
|
||||
/* Clean up */
|
||||
LLVMDisposeMemoryBuffer(out_buffer);
|
||||
|
||||
out:
|
||||
if (diag.retval != 0)
|
||||
pipe_debug_message(debug, SHADER_INFO, "LLVM compile failed");
|
||||
return diag.retval;
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors: Tom Stellard <thomas.stellard@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RADEON_LLVM_EMIT_H
|
||||
#define RADEON_LLVM_EMIT_H
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm-c/TargetMachine.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct pipe_debug_callback;
|
||||
struct radeon_shader_binary;
|
||||
|
||||
void radeon_llvm_add_attribute(LLVMValueRef F, const char *name, int value);
|
||||
void radeon_llvm_shader_type(LLVMValueRef F, unsigned type);
|
||||
|
||||
LLVMTargetRef radeon_llvm_get_r600_target(const char *triple);
|
||||
|
||||
unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary,
|
||||
LLVMTargetMachineRef tm,
|
||||
struct pipe_debug_callback *debug);
|
||||
|
||||
#endif /* RADEON_LLVM_EMIT_H */
|
|
@ -17,6 +17,7 @@ C_SOURCES := \
|
|||
si_shader.h \
|
||||
si_shader_internal.h \
|
||||
si_shader_tgsi_alu.c \
|
||||
si_shader_tgsi_setup.c \
|
||||
si_state.c \
|
||||
si_state_draw.c \
|
||||
si_state_shaders.c \
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
|
||||
#include "si_pipe.h"
|
||||
#include "si_public.h"
|
||||
#include "si_shader_internal.h"
|
||||
#include "sid.h"
|
||||
|
||||
#include "radeon/radeon_llvm_emit.h"
|
||||
#include "radeon/radeon_uvd.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_suballoc.h"
|
||||
|
|
|
@ -33,9 +33,7 @@
|
|||
#include "gallivm/lp_bld_arit.h"
|
||||
#include "gallivm/lp_bld_flow.h"
|
||||
#include "gallivm/lp_bld_misc.h"
|
||||
#include "radeon/radeon_llvm.h"
|
||||
#include "radeon/radeon_elf_util.h"
|
||||
#include "radeon/radeon_llvm_emit.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_string.h"
|
||||
#include "tgsi/tgsi_build.h"
|
||||
|
|
|
@ -27,6 +27,138 @@
|
|||
#include "si_shader.h"
|
||||
#include "gallivm/lp_bld_init.h"
|
||||
#include "gallivm/lp_bld_tgsi.h"
|
||||
#include "tgsi/tgsi_parse.h"
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm-c/TargetMachine.h>
|
||||
|
||||
struct pipe_debug_callback;
|
||||
struct radeon_shader_binary;
|
||||
|
||||
#define RADEON_LLVM_MAX_INPUT_SLOTS 32
|
||||
#define RADEON_LLVM_MAX_INPUTS 32 * 4
|
||||
#define RADEON_LLVM_MAX_OUTPUTS 32 * 4
|
||||
|
||||
#define RADEON_LLVM_INITIAL_CF_DEPTH 4
|
||||
|
||||
#define RADEON_LLVM_MAX_SYSTEM_VALUES 4
|
||||
|
||||
struct radeon_llvm_flow;
|
||||
|
||||
struct radeon_llvm_context {
|
||||
struct lp_build_tgsi_soa_context soa;
|
||||
|
||||
/*=== Front end configuration ===*/
|
||||
|
||||
/* Instructions that are not described by any of the TGSI opcodes. */
|
||||
|
||||
/** This function is responsible for initilizing the inputs array and will be
|
||||
* called once for each input declared in the TGSI shader.
|
||||
*/
|
||||
void (*load_input)(struct radeon_llvm_context *,
|
||||
unsigned input_index,
|
||||
const struct tgsi_full_declaration *decl,
|
||||
LLVMValueRef out[4]);
|
||||
|
||||
void (*load_system_value)(struct radeon_llvm_context *,
|
||||
unsigned index,
|
||||
const struct tgsi_full_declaration *decl);
|
||||
|
||||
void (*declare_memory_region)(struct radeon_llvm_context *,
|
||||
const struct tgsi_full_declaration *decl);
|
||||
|
||||
/** This array contains the input values for the shader. Typically these
|
||||
* values will be in the form of a target intrinsic that will inform the
|
||||
* backend how to load the actual inputs to the shader.
|
||||
*/
|
||||
struct tgsi_full_declaration input_decls[RADEON_LLVM_MAX_INPUT_SLOTS];
|
||||
LLVMValueRef inputs[RADEON_LLVM_MAX_INPUTS];
|
||||
LLVMValueRef outputs[RADEON_LLVM_MAX_OUTPUTS][TGSI_NUM_CHANNELS];
|
||||
|
||||
/** This pointer is used to contain the temporary values.
|
||||
* The amount of temporary used in tgsi can't be bound to a max value and
|
||||
* thus we must allocate this array at runtime.
|
||||
*/
|
||||
LLVMValueRef *temps;
|
||||
unsigned temps_count;
|
||||
LLVMValueRef system_values[RADEON_LLVM_MAX_SYSTEM_VALUES];
|
||||
|
||||
/*=== Private Members ===*/
|
||||
|
||||
struct radeon_llvm_flow *flow;
|
||||
unsigned flow_depth;
|
||||
unsigned flow_depth_max;
|
||||
|
||||
struct tgsi_array_info *temp_arrays;
|
||||
LLVMValueRef *temp_array_allocas;
|
||||
|
||||
LLVMValueRef undef_alloca;
|
||||
|
||||
LLVMValueRef main_fn;
|
||||
LLVMTypeRef return_type;
|
||||
|
||||
unsigned fpmath_md_kind;
|
||||
LLVMValueRef fpmath_md_2p5_ulp;
|
||||
|
||||
struct gallivm_state gallivm;
|
||||
};
|
||||
|
||||
static inline struct radeon_llvm_context *
|
||||
radeon_llvm_context(struct lp_build_tgsi_context *bld_base)
|
||||
{
|
||||
return (struct radeon_llvm_context*)bld_base;
|
||||
}
|
||||
|
||||
void radeon_llvm_add_attribute(LLVMValueRef F, const char *name, int value);
|
||||
void radeon_llvm_shader_type(LLVMValueRef F, unsigned type);
|
||||
|
||||
LLVMTargetRef radeon_llvm_get_r600_target(const char *triple);
|
||||
|
||||
unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary,
|
||||
LLVMTargetMachineRef tm,
|
||||
struct pipe_debug_callback *debug);
|
||||
|
||||
LLVMTypeRef tgsi2llvmtype(struct lp_build_tgsi_context *bld_base,
|
||||
enum tgsi_opcode_type type);
|
||||
|
||||
LLVMValueRef bitcast(struct lp_build_tgsi_context *bld_base,
|
||||
enum tgsi_opcode_type type, LLVMValueRef value);
|
||||
|
||||
LLVMValueRef radeon_llvm_bound_index(struct radeon_llvm_context *ctx,
|
||||
LLVMValueRef index,
|
||||
unsigned num);
|
||||
|
||||
void radeon_llvm_context_init(struct radeon_llvm_context *ctx,
|
||||
const char *triple,
|
||||
const struct tgsi_shader_info *info,
|
||||
const struct tgsi_token *tokens);
|
||||
|
||||
void radeon_llvm_create_func(struct radeon_llvm_context *ctx,
|
||||
LLVMTypeRef *return_types, unsigned num_return_elems,
|
||||
LLVMTypeRef *ParamTypes, unsigned ParamCount);
|
||||
|
||||
void radeon_llvm_dispose(struct radeon_llvm_context *ctx);
|
||||
|
||||
void radeon_llvm_finalize_module(struct radeon_llvm_context *ctx,
|
||||
bool run_verifier);
|
||||
|
||||
LLVMValueRef radeon_llvm_emit_fetch_64bit(struct lp_build_tgsi_context *bld_base,
|
||||
enum tgsi_opcode_type type,
|
||||
LLVMValueRef ptr,
|
||||
LLVMValueRef ptr2);
|
||||
|
||||
LLVMValueRef radeon_llvm_saturate(struct lp_build_tgsi_context *bld_base,
|
||||
LLVMValueRef value);
|
||||
|
||||
LLVMValueRef radeon_llvm_emit_fetch(struct lp_build_tgsi_context *bld_base,
|
||||
const struct tgsi_full_src_register *reg,
|
||||
enum tgsi_opcode_type type,
|
||||
unsigned swizzle);
|
||||
|
||||
void radeon_llvm_emit_store(struct lp_build_tgsi_context *bld_base,
|
||||
const struct tgsi_full_instruction *inst,
|
||||
const struct tgsi_opcode_info *info,
|
||||
LLVMValueRef dst[4]);
|
||||
|
||||
void si_shader_context_init_alu(struct lp_build_tgsi_context *bld_base);
|
||||
void si_prepare_cube_coords(struct lp_build_tgsi_context *bld_base,
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "gallivm/lp_bld_intr.h"
|
||||
#include "gallivm/lp_bld_gather.h"
|
||||
#include "tgsi/tgsi_parse.h"
|
||||
#include "radeon/radeon_llvm.h"
|
||||
|
||||
static void kill_if_fetch_args(struct lp_build_tgsi_context *bld_base,
|
||||
struct lp_build_emit_data *emit_data)
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2011 Advanced Micro Devices, Inc.
|
||||
* Copyright 2016 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
|
@ -14,16 +14,15 @@
|
|||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors: Tom Stellard <thomas.stellard@amd.com>
|
||||
*
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "radeon_llvm.h"
|
||||
|
||||
#include "si_shader_internal.h"
|
||||
#include "radeon/radeon_elf_util.h"
|
||||
|
||||
#include "gallivm/lp_bld_const.h"
|
||||
#include "gallivm/lp_bld_gather.h"
|
||||
|
@ -39,7 +38,6 @@
|
|||
#include "util/u_debug.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm-c/Transforms/Scalar.h>
|
||||
|
||||
/* Data for if/else/endif and bgnloop/endloop control flow structures.
|
||||
|
@ -50,6 +48,205 @@ struct radeon_llvm_flow {
|
|||
LLVMBasicBlockRef loop_entry_block;
|
||||
};
|
||||
|
||||
#define CPU_STRING_LEN 30
|
||||
#define FS_STRING_LEN 30
|
||||
#define TRIPLE_STRING_LEN 7
|
||||
|
||||
/**
|
||||
* Shader types for the LLVM backend.
|
||||
*/
|
||||
enum radeon_llvm_shader_type {
|
||||
RADEON_LLVM_SHADER_PS = 0,
|
||||
RADEON_LLVM_SHADER_VS = 1,
|
||||
RADEON_LLVM_SHADER_GS = 2,
|
||||
RADEON_LLVM_SHADER_CS = 3,
|
||||
};
|
||||
|
||||
enum radeon_llvm_calling_convention {
|
||||
RADEON_LLVM_AMDGPU_VS = 87,
|
||||
RADEON_LLVM_AMDGPU_GS = 88,
|
||||
RADEON_LLVM_AMDGPU_PS = 89,
|
||||
RADEON_LLVM_AMDGPU_CS = 90,
|
||||
};
|
||||
|
||||
void radeon_llvm_add_attribute(LLVMValueRef F, const char *name, int value)
|
||||
{
|
||||
char str[16];
|
||||
|
||||
snprintf(str, sizeof(str), "%i", value);
|
||||
LLVMAddTargetDependentFunctionAttr(F, name, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the shader type we want to compile
|
||||
*
|
||||
* @param type shader type to set
|
||||
*/
|
||||
void radeon_llvm_shader_type(LLVMValueRef F, unsigned type)
|
||||
{
|
||||
enum radeon_llvm_shader_type llvm_type;
|
||||
enum radeon_llvm_calling_convention calling_conv;
|
||||
|
||||
switch (type) {
|
||||
case PIPE_SHADER_VERTEX:
|
||||
case PIPE_SHADER_TESS_CTRL:
|
||||
case PIPE_SHADER_TESS_EVAL:
|
||||
llvm_type = RADEON_LLVM_SHADER_VS;
|
||||
calling_conv = RADEON_LLVM_AMDGPU_VS;
|
||||
break;
|
||||
case PIPE_SHADER_GEOMETRY:
|
||||
llvm_type = RADEON_LLVM_SHADER_GS;
|
||||
calling_conv = RADEON_LLVM_AMDGPU_GS;
|
||||
break;
|
||||
case PIPE_SHADER_FRAGMENT:
|
||||
llvm_type = RADEON_LLVM_SHADER_PS;
|
||||
calling_conv = RADEON_LLVM_AMDGPU_PS;
|
||||
break;
|
||||
case PIPE_SHADER_COMPUTE:
|
||||
llvm_type = RADEON_LLVM_SHADER_CS;
|
||||
calling_conv = RADEON_LLVM_AMDGPU_CS;
|
||||
break;
|
||||
default:
|
||||
unreachable("Unhandle shader type");
|
||||
}
|
||||
|
||||
if (HAVE_LLVM >= 0x309)
|
||||
LLVMSetFunctionCallConv(F, calling_conv);
|
||||
else
|
||||
radeon_llvm_add_attribute(F, "ShaderType", llvm_type);
|
||||
}
|
||||
|
||||
static void init_r600_target()
|
||||
{
|
||||
gallivm_init_llvm_targets();
|
||||
#if HAVE_LLVM < 0x0307
|
||||
LLVMInitializeR600TargetInfo();
|
||||
LLVMInitializeR600Target();
|
||||
LLVMInitializeR600TargetMC();
|
||||
LLVMInitializeR600AsmPrinter();
|
||||
#else
|
||||
LLVMInitializeAMDGPUTargetInfo();
|
||||
LLVMInitializeAMDGPUTarget();
|
||||
LLVMInitializeAMDGPUTargetMC();
|
||||
LLVMInitializeAMDGPUAsmPrinter();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static once_flag init_r600_target_once_flag = ONCE_FLAG_INIT;
|
||||
|
||||
LLVMTargetRef radeon_llvm_get_r600_target(const char *triple)
|
||||
{
|
||||
LLVMTargetRef target = NULL;
|
||||
char *err_message = NULL;
|
||||
|
||||
call_once(&init_r600_target_once_flag, init_r600_target);
|
||||
|
||||
if (LLVMGetTargetFromTriple(triple, &target, &err_message)) {
|
||||
fprintf(stderr, "Cannot find target for triple %s ", triple);
|
||||
if (err_message) {
|
||||
fprintf(stderr, "%s\n", err_message);
|
||||
}
|
||||
LLVMDisposeMessage(err_message);
|
||||
return NULL;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
struct radeon_llvm_diagnostics {
|
||||
struct pipe_debug_callback *debug;
|
||||
unsigned retval;
|
||||
};
|
||||
|
||||
static void radeonDiagnosticHandler(LLVMDiagnosticInfoRef di, void *context)
|
||||
{
|
||||
struct radeon_llvm_diagnostics *diag = (struct radeon_llvm_diagnostics *)context;
|
||||
LLVMDiagnosticSeverity severity = LLVMGetDiagInfoSeverity(di);
|
||||
char *description = LLVMGetDiagInfoDescription(di);
|
||||
const char *severity_str = NULL;
|
||||
|
||||
switch (severity) {
|
||||
case LLVMDSError:
|
||||
severity_str = "error";
|
||||
break;
|
||||
case LLVMDSWarning:
|
||||
severity_str = "warning";
|
||||
break;
|
||||
case LLVMDSRemark:
|
||||
severity_str = "remark";
|
||||
break;
|
||||
case LLVMDSNote:
|
||||
severity_str = "note";
|
||||
break;
|
||||
default:
|
||||
severity_str = "unknown";
|
||||
}
|
||||
|
||||
pipe_debug_message(diag->debug, SHADER_INFO,
|
||||
"LLVM diagnostic (%s): %s", severity_str, description);
|
||||
|
||||
if (severity == LLVMDSError) {
|
||||
diag->retval = 1;
|
||||
fprintf(stderr,"LLVM triggered Diagnostic Handler: %s\n", description);
|
||||
}
|
||||
|
||||
LLVMDisposeMessage(description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an LLVM module to machine code.
|
||||
*
|
||||
* @returns 0 for success, 1 for failure
|
||||
*/
|
||||
unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary,
|
||||
LLVMTargetMachineRef tm,
|
||||
struct pipe_debug_callback *debug)
|
||||
{
|
||||
struct radeon_llvm_diagnostics diag;
|
||||
char *err;
|
||||
LLVMContextRef llvm_ctx;
|
||||
LLVMMemoryBufferRef out_buffer;
|
||||
unsigned buffer_size;
|
||||
const char *buffer_data;
|
||||
LLVMBool mem_err;
|
||||
|
||||
diag.debug = debug;
|
||||
diag.retval = 0;
|
||||
|
||||
/* Setup Diagnostic Handler*/
|
||||
llvm_ctx = LLVMGetModuleContext(M);
|
||||
|
||||
LLVMContextSetDiagnosticHandler(llvm_ctx, radeonDiagnosticHandler, &diag);
|
||||
|
||||
/* Compile IR*/
|
||||
mem_err = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err,
|
||||
&out_buffer);
|
||||
|
||||
/* Process Errors/Warnings */
|
||||
if (mem_err) {
|
||||
fprintf(stderr, "%s: %s", __FUNCTION__, err);
|
||||
pipe_debug_message(debug, SHADER_INFO,
|
||||
"LLVM emit error: %s", err);
|
||||
FREE(err);
|
||||
diag.retval = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Extract Shader Code*/
|
||||
buffer_size = LLVMGetBufferSize(out_buffer);
|
||||
buffer_data = LLVMGetBufferStart(out_buffer);
|
||||
|
||||
radeon_elf_read(buffer_data, buffer_size, binary);
|
||||
|
||||
/* Clean up */
|
||||
LLVMDisposeMemoryBuffer(out_buffer);
|
||||
|
||||
out:
|
||||
if (diag.retval != 0)
|
||||
pipe_debug_message(debug, SHADER_INFO, "LLVM compile failed");
|
||||
return diag.retval;
|
||||
}
|
||||
|
||||
LLVMTypeRef tgsi2llvmtype(struct lp_build_tgsi_context *bld_base,
|
||||
enum tgsi_opcode_type type)
|
||||
{
|
Loading…
Reference in New Issue