2 * Copyright 2014 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
15 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18 * USE OR OTHER DEALINGS IN THE SOFTWARE.
20 * The above copyright notice and this permission notice (including the
21 * next paragraph) shall be included in all copies or substantial portions
26 /* based on Marek's patch to lp_bld_misc.cpp */
28 // Workaround http://llvm.org/PR23628
29 #pragma push_macro("DEBUG")
32 #include "ac_binary.h"
33 #include "ac_llvm_util.h"
35 #include <llvm-c/Core.h>
36 #include <llvm/Target/TargetMachine.h>
37 #include <llvm/IR/IRBuilder.h>
38 #include <llvm/Analysis/TargetLibraryInfo.h>
39 #include <llvm/Transforms/IPO.h>
41 #include <llvm/IR/LegacyPassManager.h>
43 void ac_add_attr_dereferenceable(LLVMValueRef val
, uint64_t bytes
)
45 llvm::Argument
*A
= llvm::unwrap
<llvm::Argument
>(val
);
46 A
->addAttr(llvm::Attribute::getWithDereferenceableBytes(A
->getContext(), bytes
));
49 bool ac_is_sgpr_param(LLVMValueRef arg
)
51 llvm::Argument
*A
= llvm::unwrap
<llvm::Argument
>(arg
);
52 llvm::AttributeList AS
= A
->getParent()->getAttributes();
53 unsigned ArgNo
= A
->getArgNo();
54 return AS
.hasAttribute(ArgNo
+ 1, llvm::Attribute::InReg
);
57 LLVMValueRef
ac_llvm_get_called_value(LLVMValueRef call
)
59 return LLVMGetCalledValue(call
);
62 bool ac_llvm_is_function(LLVMValueRef v
)
64 return LLVMGetValueKind(v
) == LLVMFunctionValueKind
;
67 LLVMModuleRef
ac_create_module(LLVMTargetMachineRef tm
, LLVMContextRef ctx
)
69 llvm::TargetMachine
*TM
= reinterpret_cast<llvm::TargetMachine
*>(tm
);
70 LLVMModuleRef module
= LLVMModuleCreateWithNameInContext("mesa-shader", ctx
);
72 llvm::unwrap(module
)->setTargetTriple(TM
->getTargetTriple().getTriple());
73 llvm::unwrap(module
)->setDataLayout(TM
->createDataLayout());
77 LLVMBuilderRef
ac_create_builder(LLVMContextRef ctx
,
78 enum ac_float_mode float_mode
)
80 LLVMBuilderRef builder
= LLVMCreateBuilderInContext(ctx
);
82 llvm::FastMathFlags flags
;
85 case AC_FLOAT_MODE_DEFAULT
:
87 case AC_FLOAT_MODE_NO_SIGNED_ZEROS_FP_MATH
:
88 flags
.setNoSignedZeros();
89 llvm::unwrap(builder
)->setFastMathFlags(flags
);
91 case AC_FLOAT_MODE_UNSAFE_FP_MATH
:
93 llvm::unwrap(builder
)->setFastMathFlags(flags
);
100 LLVMTargetLibraryInfoRef
101 ac_create_target_library_info(const char *triple
)
103 return reinterpret_cast<LLVMTargetLibraryInfoRef
>(new llvm::TargetLibraryInfoImpl(llvm::Triple(triple
)));
107 ac_dispose_target_library_info(LLVMTargetLibraryInfoRef library_info
)
109 delete reinterpret_cast<llvm::TargetLibraryInfoImpl
*>(library_info
);
112 /* The LLVM compiler is represented as a pass manager containing passes for
113 * optimizations, instruction selection, and code generation.
115 struct ac_compiler_passes
{
116 ac_compiler_passes(): ostream(code_string
) {}
118 llvm::SmallString
<0> code_string
; /* ELF shader binary */
119 llvm::raw_svector_ostream ostream
; /* stream for appending data to the binary */
120 llvm::legacy::PassManager passmgr
; /* list of passes */
123 struct ac_compiler_passes
*ac_create_llvm_passes(LLVMTargetMachineRef tm
)
125 struct ac_compiler_passes
*p
= new ac_compiler_passes();
129 llvm::TargetMachine
*TM
= reinterpret_cast<llvm::TargetMachine
*>(tm
);
131 if (TM
->addPassesToEmitFile(p
->passmgr
, p
->ostream
,
133 llvm::TargetMachine::CGFT_ObjectFile
)) {
134 fprintf(stderr
, "amd: TargetMachine can't emit a file of this type!\n");
141 void ac_destroy_llvm_passes(struct ac_compiler_passes
*p
)
146 /* This returns false on failure. */
147 bool ac_compile_module_to_binary(struct ac_compiler_passes
*p
, LLVMModuleRef module
,
148 struct ac_shader_binary
*binary
)
150 p
->passmgr
.run(*llvm::unwrap(module
));
152 llvm::StringRef data
= p
->ostream
.str();
153 bool success
= ac_elf_read(data
.data(), data
.size(), binary
);
154 p
->code_string
= ""; /* release the ELF shader binary */
157 fprintf(stderr
, "amd: cannot read an ELF shader binary\n");
161 void ac_llvm_add_barrier_noop_pass(LLVMPassManagerRef passmgr
)
163 llvm::unwrap(passmgr
)->add(llvm::createBarrierNoopPass());
166 void ac_enable_global_isel(LLVMTargetMachineRef tm
)
168 reinterpret_cast<llvm::TargetMachine
*>(tm
)->setGlobalISel(true);