<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=us-ascii"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
{font-family:SimSun;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
@font-face
{font-family:"\@SimSun";
panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
span.EmailStyle17
{mso-style-type:personal-compose;
font-family:"Calibri","sans-serif";
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;
font-family:"Calibri","sans-serif";}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link="#0563C1" vlink="#954F72"><div class=WordSection1><p class=MsoNormal><span style='font-family:Consolas'>Dear All,<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'>In the LLVM IR, both formal parameters in functions and actual parameters in call instruction can have a set of attributes. However, it seems that there is no consistency check between attributes of formal parameters and attributes for actual ones. For example, consider the following llvm code:<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-indent:.5in'><span style='font-family:Consolas'>%struct.example = type { i64, i64, i64, i64, double }<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'> <o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>define void @should_be_pass_by_value(%struct.example* byval align 8 %para) {<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> ……<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>}<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>define void @do_something() {<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>entry:<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> %foo = alloca %struct.example, align 8<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> call void @should_be_pass_by_value(%struct.example* %foo)<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> ret void<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>}<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'>The code demonstrate the situation where the caller omit the ‘byval’ attribute of the parameter when calling the function. In this case, the llvm compiler could actually break the code if no inline, since the caller and callee disagree on the binary prototype of the function. For instance, in x86_64 SYS V ABI, complex structs (larger than four eightbytes) passed by value are directly constructed on stack by caller and accessed by callee. If not passed by value (pass by pointer), a pointer to the struct shall be passed as an integer to the callee. As a result, the caller will be end up using the wrong prototype of the function. <o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'>To make things worse, consider the following llvm code compiled from C targeting x86_64:<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-indent:.5in'><span style='font-family:Consolas'>%struct.example = type { i64, i64, i64, i64, double }<o:p></o:p></span></p><p class=MsoNormal style='text-indent:.5in'><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-indent:.5in'><span style='font-family:Consolas'>@external_func_pass_by_value = external global void (%struct.example*)*<o:p></o:p></span></p><p class=MsoNormal style='text-indent:.5in'><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='text-indent:.5in'><span style='font-family:Consolas'>define void @do_something() {<o:p></o:p></span></p><p class=MsoNormal style='text-indent:.5in'><span style='font-family:Consolas'>entry:<o:p></o:p></span></p><p class=MsoNormal style='text-indent:.5in'><span style='font-family:Consolas'> %foo = alloca %struct.example, align 8<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'> %func_to_call = load void (%struct.example*)** @external_func_pass_by_value, align 8<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'> call void %func_to_call(%struct.example* byval align 8 %foo)<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'> ret void<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'>The corresponding C source is something like:<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>typedef struct {<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> long long a;<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> long long b;<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> long long c;<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> long long d;<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> double e;<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>}example;<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>typedef void (*pF_t)(example);<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>extern pF_t external_func_pass_by_value;<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>void do_something(void)<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>{<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> example foo;<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'> (*external_func_pass_by_value)(foo);<o:p></o:p></span></p><p class=MsoNormal style='margin-left:.5in'><span style='font-family:Consolas'>}<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'>In this case, the calling function is defined externally as a function pointer. The type of the function pointer will not expose the attributes of the parameters in the function to the current ‘Module’. There might be no effective ways to check whether the struct ‘example’ should be passed by value or not when an indirect call to the function is made. Currently the implementation of ‘FunctionType’ does not embed ‘byval’ attribute in itself. Consequently it could be troublesome that functions share the same ‘FunctionType’ differ in both C prototype and binary prototype only because of the difference in parameter attribute. <o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'>Should we put the important parameter attributes which can alter the function prototype directly into ‘FunctionType’? The subproject we are working on preforms some transformation of llvm ‘Modules’. During the transformation, both direct and indirect function calls (‘CallInst’) gets inserted. It would be much more convenient that the “important” parameter attributes can be deduced from ‘FunctionType’.<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'>Sincerely,<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'>Bo<o:p></o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-family:Consolas'><o:p> </o:p></span></p></div></body></html>