def generate_call_code(self, result_arg_list): return "call {output_precision} @{function_name}({arg_list})".format( output_precision=llvm_ir_format(self.output_precision), function_name=self.function_name, arg_list=", ".join([ "%s %s" % (llvm_ir_format(var_arg.precision), var_arg.get()) for var_arg in result_arg_list ]))
def get_function_common(self, fct_type, common_keyword, final=True, language=LLVM_IR_Code, arg_list=None): """ :param common_keyword: llvm-ir specialization function declaration or definition """ if arg_list: arg_format_list = ", ".join("%s %s" % (llvm_ir_format(inp.get_precision()), self.get_llvm_varname(inp.get_tag())) for inp in arg_list) else: arg_format_list = ", ".join(input_format.get_name(language=language) for input_format in fct_type.arg_list_precision) function_name = fct_type.name output_format = fct_type.output_format return "{keyword} {out_format} @{name}({arg_list})\n".format( keyword=common_keyword, out_format=llvm_ir_format(output_format), name=function_name, arg_list=arg_format_list)
def get_function_declaration(self, function_name, output_format, arg_list, final=True, language=C_Code): """ generate function declaration code """ arg_format_list = ", ".join("%s %s" % (llvm_ir_format(inp.get_precision()), self.get_llvm_varname(inp.get_tag())) for inp in arg_list) return "define %s @%s(%s)\n" % (llvm_ir_format(output_format), function_name, arg_format_list)
def llvm_not_function(precision): """ build a code generation operator for LogicalNot operation (unary) from the binary operations supported in LLVM-IR """ op = "xor" one = 1 return LLVMIrTemplateOperator("{op} {precision} {one}, {{}}".format( op=op, one=one, precision=llvm_ir_format(precision)), arity=1)
def generate_assignation(self, result_var, expression_code, final=True, precision=None): """ generate code for assignation of value <expression_code> to variable <result_var> """ final_symbol = ";\n" if final else "" format_symbol = llvm_ir_format(precision) if precision else "" return "{result} = {format_str} {expr}{final}".format( result=result_var, expr=expression_code, format_str=format_symbol, final=final_symbol )
def llvm_negation_function(precision): """ build code generation operator for Negation operation. As LLVM-IR does not have neg we must build a subtraction from 0 """ op = "fsub" if ML_FP_Format.is_fp_format(precision) else "sub" zero = "0.0" if ML_FP_Format.is_fp_format(precision) else "0" return LLVMIrTemplateOperator("{op} {precision} {zero}, {{}}".format( zero=zero, op=op, precision=llvm_ir_format(precision), ), arity=1)
def generate_expr(self, code_object, optree, folded=True, result_var=None, initial=False, __exact=None, language=None, strip_outer_parenthesis=False, force_variable_storing=False, next_block=None): """ code generation function """ # search if <optree> has already been processed if self.has_memoization(optree): return self.get_memoization(optree) result = None # implementation generation if isinstance(optree, CodeVariable): # adding LLVM variable "%" prefix if optree.name[0] != "%": optree.name = "%" + optree.name result = optree elif isinstance(optree, Variable): result = CodeVariable("%" + optree.get_tag(), optree.get_precision()) elif isinstance(optree, Constant): precision = optree.get_precision() result = generate_Constant_expr(optree) #result = CodeExpression(precision.get_gappa_cst(optree.get_value()), precision) elif isinstance(optree, BasicBlock): bb_label = self.get_bb_label(code_object, optree) code_object << (bb_label + ":") code_object.open_level(header="") for op in optree.inputs: self.generate_expr(code_object, op, folded=folded, initial=True, language=language) code_object.close_level(footer="", cr="") return None elif isinstance(optree, ConditionalBranch): cond = optree.get_input(0) if_bb = optree.get_input(1) else_bb = optree.get_input(2) if_label = self.get_bb_label(code_object, if_bb) else_label = self.get_bb_label(code_object, else_bb) cond_code = self.generate_expr( code_object, cond, folded=folded, language=language) code_object << "br i1 {cond} , label %{if_label}, label %{else_label}\n".format( cond=cond_code.get(), if_label=if_label, else_label=else_label ) # generating destination bb # self.generate_expr(code_object, if_bb, folded=folded, language=language) # self.generate_expr(code_object, else_bb, folded=folded, language=language) return None elif isinstance(optree, UnconditionalBranch): dest_bb = optree.get_input(0) code_object << "br label %{}\n".format(self.get_bb_label(code_object, dest_bb)) # generating destination bb # self.generate_expr(code_object, dest_bb, folded=folded, language=language) return None elif isinstance(optree, BasicBlockList): for bb in optree.inputs: self.generate_expr(code_object, bb, folded=folded, language=language) return None elif isinstance(optree, Statement): Log.report(Log.Error, "Statement are not supported in LLVM-IR codegen" "They must be translated to BB (e.g. through gen_basic_block pass)" "faulty node: {}", optree) elif isinstance(optree, ConditionBlock): Log.report(Log.Error, "ConditionBlock are not supported in LLVM-IR codegen" "They must be translated to BB (e.g. through gen_basic_block pass)" "faulty node: {}", optree) elif isinstance(optree, Loop): Log.report(Log.Error, "Loop are not supported in LLVM-IR codegen" "They must be translated to BB (e.g. through gen_basic_block pass)" "faulty node: {}", optree) elif isinstance(optree, PhiNode): output_var = optree.get_input(0) output_var_code = self.generate_expr( code_object, output_var, folded=folded, language=language) value_list = [] for input_var, bb_var in zip(optree.get_inputs()[1::2], optree.get_inputs()[2::2]): assert isinstance(input_var, Variable) assert isinstance(bb_var, BasicBlock) input_var = self.generate_expr( code_object, input_var, folded=folded, language=language ) bb_label = self.get_bb_label(code_object, bb_var) value_list.append("[{var}, %{bb}]".format(var=input_var.get(), bb=bb_label)) code_object << "{output_var} = phi {precision} {value_list}\n".format( output_var=output_var_code.get(), precision=llvm_ir_format(precision=output_var.get_precision()), value_list=(", ".join(value_list)) ) return None elif isinstance(optree, ReferenceAssign): output_var = optree.get_input(0) result_value = optree.get_input(1) # In LLVM it is illegal to assign a constant value, directly to a # variable so with insert a dummy add with 0 if isinstance(result_value, Constant): cst_precision = result_value.get_precision() result_value = Addition( result_value, Constant(0, precision=cst_precision), precision=cst_precision) # TODO/FIXME: fix single static assignation enforcement #output_var_code = self.generate_expr( # code_object, output_var, folded=False, language=language #) result_value_code = self.generate_expr( code_object, result_value, folded=folded, result_var="%"+output_var.get_tag(), language=language ) assert isinstance(result_value_code, CodeVariable) # code_object << self.generate_assignation(output_var_code.get(), result_value_code.get(), precision=output_var_code.precision) # debug msg generation is not supported in LLVM code genrator return None else: result = self.processor.generate_expr(self, code_object, optree, optree.inputs, folded = folded, result_var = result_var, language = self.language) # each operation is generated on a separate line # registering result into memoization table self.add_memoization(optree, result) # debug management if optree.get_debug() and not self.disable_debug: code_object << self.generate_debug_msg(optree, result) if strip_outer_parenthesis and isinstance(result, CodeExpression): result.strip_outer_parenthesis() return result
def generate_call_code(self, result_arg_list): return "{function_name} {output_precision} {arg_list}".format( output_precision=llvm_ir_format(self.output_precision), function_name=self.function_name, arg_list=", ".join([var_arg.get() for var_arg in result_arg_list]))
def llvm_extract_element_function(src_precision, index_precision): return LLVMIrTemplateOperator( "extractelement {src_format} {{}}, {index_format} {{}}".format( src_format=llvm_ir_format(src_precision), index_format=llvm_ir_format(index_precision)), arity=1)
def llvm_bitcast_function(dst_precision, src_precision): return LLVMIrTemplateOperator( "bitcast {src_format} {{}} to {dst_format}".format( src_format=llvm_ir_format(src_precision), dst_format=llvm_ir_format(dst_precision)), arity=1)