<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'><div>On the IA64 matter, it appears the bundle is the lower 5 bits.</div><div>And the bundles 6, 7, 14, 15, 1A, 1B, 1E, 1F are invalid.</div><div>It appears IA64 can be little or big endian, but the instructions</div><div>are always little endian.</div><div>Therefore a 64bit value of -1 would seem invalid and ok for a marker,</div><div>but 0 is less clear -- might still be invalid.</div><div><br></div><div><br></div><div> - Jay</div><br><br><br><div><hr id="stopSpelling">From: jay.krell@cornell.edu<br>To: m3devel@elegosoft.com<br>Date: Sun, 30 Aug 2015 07:45:21 +0000<br>Subject: [M3devel] Target.Aligned_procedures and closure markers?<br><br>
<style><!--
.ExternalClass .ecxhmmessage P {
padding:0px;
}
.ExternalClass body.ecxhmmessage {
font-size:12pt;
font-family:Calibri;
}
--></style>
<div dir="ltr"><div><span style="font-size:12pt;">The agenda remains seeing if Target variables can be made constants.</span></div><div><br></div><div>The discussion in this case is more complicated and some facts are unclear.</div><div><br></div><div><br></div><div>Background:</div><div><br></div><div><br></div><div>Nested functions are a problem.</div><div>In particular, if you can take their address.</div><div>Taking the address of a nested function presents a problem.</div><div><span style="font-size:12pt;">You are presented with two or three solutions.</span></div><div><br></div><div><br></div><div> - runtime code gen</div><div> - either on the stack</div><div><br></div><div> - or somewhere more expensive, possibly with garbage collection</div><div><br></div><div> - possibly "templated" instead of "arbitrary"; the meaning</div><div> of this is a lot to explain -- related to libffi and mremap, which</div><div> isn't entirely portable, but is e.g. portable to Windows </div><div><br></div><div><br></div><div> - or instead of runtime codegen, altering how function pointers are</div><div><span style="font-size:12pt;"> called; you can only do this from Modula-3 code, not e.g. C or C++.</span></div><div><br></div><div><br></div><div>The solution Modula-3 has taken is to alter how funtion pointers are called.</div><div>The sequence is roughly:</div><div> Check if it is a "regular" function pointer or a "closure".</div><div> If it is a "regular" function pointer, just call it.</div><div> If it is a "closure", it contains a function pointer and a "static link".</div><div> Call the function pointer, passing the static link.</div><div><br></div><div><br></div><div> To tell if it is "regular" function pointer or a "closure", roughly</div><div> what is done is the data at the function pointer is read and compared</div><div> against a marker value. If it equals the marker value, it is a closure.</div><div><br></div><div><br></div><div> The size of the marker is the size of an integer or pointer (4 or 8 bytes).</div><div> The value of the marker checked for is 0 or -1, I'd have to check.</div><div> The alignment of the pointer might be a factor. In particular, on most</div><div> architectures, all instructions have a certain alignment. If the pointer has</div><div> less alignment, it can't be an instruction. Or maybe on those architectures,</div><div> the bytes are read one at a time to avoid alignment faults. </div><div><br></div><div><br></div><div> In particular, as far as I know, the following:</div><div> x86/amd64: no alignment of instructions, but functions maybe, but Modula-3 assumes functions aren't aligned </div><div><br></div><div><span style="font-size:12pt;"> ppc32/ppc64/alpha32/alpha64/mips32/mipa64/sparc32/sparc64/arm64/hppa32/hppa64 -- instructions are all</span></div><div> 4 bytes and 4 byte aligned, so functions are at least also as much</div><div><br></div><div> arm32 -- instructions are 2 or 4 bytes; if they are 2 bytes, then the instruction</div><div> pointer is actually odd as well, and the low bit is removed to really find the instructions</div><div> That is -- instruction pointer is either odd or 4-aligned, never 2-aligned.</div><div><br></div><div> ia64 -- instructions come in bundles of 3, they are 41 bits each, with a 5 bit "template" in each</div><div> bundle, for a total of 128 bits per bundle, likely always 128-bit-aligned</div><div><br></div><div><br></div><div> I could use confirmation on much of this.</div><div><br></div><div><br></div><div> I find the use of a marker value a little dubious. It'd be good to research if there is one</div><div> value that works on all.</div><div><br></div><div><br></div><div> I find the choice of a marker size to be pointer-sized dubious on most platforms.</div><div> In particular, most 64bit platforms have a 32bit instruction size, so using more than 32 bits</div><div> for the marker value doesn't buy much. If the marker value is actually a legal instruction,</div><div> then checking for two in a row reduces the odds of a false positive. </div><div><br></div><div><br></div><div> However, given that the closure is a marker and two pointers, it isn't like you are going</div><div> to pack the second and third 64bit field right up against a 32bit field. You'd want padding for alignmet.</div><div><br></div><div><br></div><div> If we are aiming for all out target-specificity, I'd suggest marker size be a target aspect,</div><div> and set it to 4 bytes for ppc64/mips64/sparc64/alpha64/arm64/hppa64.</div><div><br></div><div><br></div><div> However, I want less target-variation not more.</div><div><br></div><div><br></div><div> Here are some my lingering questions:</div><div> - Is the marker value actually invalid code on every platform? Does its value need to be target-specific?</div><div> - Is a 64bit marker value actually sufficient on IA64?</div><div> The way to help here, I think, is to ensure that a 64bit marker,</div><div> not a 128bit marker, contains the "template", and an invalid "template".</div><div> - Barring the previous, a solution might be to use a 128 bit marker on all platforms.</div><div><br></div><div><br></div><div> i believe all of these function pointers are rare.</div><div> I hope/believe the object method calls do not check for closures -- though actually</div><div> that is related to a useful language construct, that I doubt we have.</div><div><br></div><div><br></div><div> The simplest solution is likely:</div><div> - ignore IA64, or research it further </div><div> - keep marker size at integer</div><div> - for the C backend, assume no alignment of function pointers -- give up</div><div> any of the optimization, esp. x86/amd64.</div><div><br></div><div><br></div><div> For other than the C backend, maybe dial back marker size to 4 bytes for mips64/sparc64/alpha64/arm64/hppa64.</div><div> While I don't like target-specificity, notice this wouldn't check linux vs. bsd vs. solaris, etc. It isn't a cross produce thing.</div><div><br></div><div><br></div><div>Thoughts?</div><div><br></div><div><br></div><div> - Jay</div><br> </div>
<br>_______________________________________________
M3devel mailing list
M3devel@elegosoft.com
https://mail.elegosoft.com/cgi-bin/mailman/listinfo/m3devel</div> </div></body>
</html>