Open advancedwebdeveloper opened 3 years ago
I am attaching the specification, System V Application Binary Interface
My first patch, submitted for a review is https://go-review.googlesource.com/c/gollvm/+/270219 . This one is related to CMake's configuration files:
AutoGenGo.cmake mostly contain the constants, which are valid for "yonah" ;
GoVars.cmake contains some basic support for the arch. dependent rules (at least CMake's generator wouldn't crash) and some Linux system folder naming conventions (would affect installation prefix, for sure) ;
LibbacktraceUtils.cmake defines stuff for building libbacktrace dependency;
LibffiUtils.cmake defined stuff for building libffi dependency .
My next patch would cover driver/ArchCpusAttrs.h
https://go-review.googlesource.com/c/gollvm/+/271457
Since it is required to perform pre-checks of supported CPU features (in my case - I have a relic Intel Celeron M440), which is resolved by Clang (common code for any LLVM related projects, for these checks - so both llvm-goc and pre-installed Clang would both act similar, on a specific hardware) - I used the following tool:
include "llvm/ADT/StringRef.h"
include "llvm/ADT/StringMap.h"
include "llvm/MC/SubtargetFeature.h"
include "llvm/Support/Host.h"
using namespace llvm; SubtargetFeatures Features1;
int main (int argc, char **argv) { sys::getHostCPUName(); StringMap
HostFeatures; if (sys::getHostCPUFeatures(HostFeatures)) for (auto &F : HostFeatures) Features1.AddFeature(F.first(), F.second); printf("test %s", Features1.getString().c_str()); printf("\nsomething else\n"); return 0; }
. Many thanks to @topperc for guiding me threw this.
I see that CPU instructions are defined in the following files: https://github.com/llvm/llvm-project/blob/756f5978410809530150f5e1cd425e85ad94d1cd/llvm/lib/Target/X86/X86InstrFormats.td https://github.com/llvm/llvm-project/blob/756f5978410809530150f5e1cd425e85ad94d1cd/llvm/lib/Target/X86/X86InstrInfo.td https://github.com/llvm/llvm-project/blob/756f5978410809530150f5e1cd425e85ad94d1cd/llvm/lib/Target/X86/X86.td https://llvm.org/doxygen/X86TargetParser_8cpp_source.html . ABI specific stuff could be found here: https://clang.llvm.org/doxygen/CodeGen_2TargetInfo_8cpp_source.html available calling conventions https://github.com/llvm/llvm-project/blob/a022b1ccd8d849dd59a8e7b76c0406cc80dee0f0/llvm/include/llvm/IR/CallingConv.h .
I missed a file, where library path should be handled: https://go.googlesource.com/gollvm/+/refs/heads/master/driver/Driver.cpp#70 I think I will submit the change within one of my future patches (yet to be submitted, as for now).
@thanm, @cherrymui: I don't understand why CABIOracle contains "Oracle" in it's naming. What does Oracle corp. has to do with you naming convention?
Attaching some diagrams, as a rude summary:
I see some adoptions of EightByteInfo::determineABITypesFor[LLVM's calling convention]() function.
Looks like EightByteInfo class has a constructor, which initializes private variable typeManager_ with the same of the second passed argument (of type *TypeManager). Correct me/elaborate, if I have an improper understanding/vision of the API. It's not currently cleat whether the switch (cconv) is a good location to define the logic of handling 32bit and 64bit calling conventions (calling conventions for 32bit variation of a specific arch. has pretty diverse ABI handling, compared to how it is done for 64bit variation of that arch.).
@advancedwebdeveloper "oracle" happens to be the name of a company but it is also an English word. It also has a well established meaning specific to computer programming: https://en.wikipedia.org/wiki/Oracle_machine .
Ian is correct. "Oracle" is being used in the non-commercial sense (as in "Oracle of Delphi"), e.g. some entity that you ask questions of.
Referencing http://llvm.org/docs/LangRef.html#parameter-attributes - specific considerations would be added later
Reminding about unresolved issue https://github.com/golang/go/issues/42975
You are referencing System V x86_64 ABI spec. , on https://go.googlesource.com/gollvm/+/refs/heads/master/bridge/go-llvm-cabi-oracle.cpp#61 . It looks like that's https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf#page=22 :
The classification of aggregate (structures and arrays) and union types works as follows:
- If the size of an object is larger than eight eightbytes, or it contains un-aligned fields, it has class MEMORY12.
In the same time - I am able to extract the following statements, from i386 ABI spec. http://www.sco.com/developers/devspecs/abi386-4.pdf#page=29 :
The Intel386 architecture does not require all data access to be properly aligned. But I suspect that it would be aligned by LLVM/Clang, in some way.
Unsure if the following contains any useful statements, for elaborating this:
For example, double-precision values occupy 1 doubleword (8-bytes), and their natural alignment is a word boundary, meaning their addresses are multiples of 4 .
I am able to extract the following, from i386 ABI spec., on http://www.sco.com/developers/devspecs/abi386-4.pdf#page=36 :
The stack is word aligned. Although the architecture does not require any alignment of the stack, software convention and the operating system requires that the stack be aligned on a word boundary.
And by taking
the term word refers to a 32-bit object
into an account, on http://www.sco.com/developers/devspecs/abi386-4.pdf#page=27 - that would be 32/8=4 bytes
So if it differs from what happens on x86_64 - the struct EightByteRegion should not be compiled on i686. And there have to be another structured type, for the similar purpose.
Probably that i686 oriented struct should contain such functions: void determineABITypesForC(); void determineABITypesForC(); It's constructor should contain
case llvm::CallingConv::C: determineABITypesForC(); break;
Probably related to https://github.com/golang/go/issues/42440#issuecomment-735389706 : we could provide such functions:
CABIOracleC::CABIOracleC(TypeManager typeManager): CABIOracleArgumentAnalyzer(typeManager) ; CABIParamDisp CABIOracleC::classifyArgType(Btype btype); CABIParamInfo CABIOracleC::analyzeABIParam(Btype *paramType, ABIState &state); bool CABIOracleC::canPassDirectly(unsigned regsInt, unsigned regsSSE, ABIState &state);
Stack alignment on 32-bit x86 has become quite complex. Search for "stack" in https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gcc/x86-Options.html#x86-Options.
@marmolejo , please elaborate regarding 32bit soft-CPU implementation and consideration for stack alignments. There where some relic i386/i686 ASIC CPUs produced, in the past - so not all options have sense. I was curious if future re-implementations of i686 compatible soft-CPUs could could assume specific alignments.
CC @MicroCoreLabs @alfikpl
@JonChesterfield , could you elaborate regarding relic 32bit AMD's CPUs? Which stack alignments should be considered, for old CPUs? Why?
@tve , I remember that you tried to build Go applications for a retired/relic VIA's CPU (eons ago). Did you try to perform any specific optimizations, by using stack alignment?
@kcadieux , @GreatKeeper : could you elaborate about MSVC's stack alignment, when compiling (and linking, by using Microsoft's linker) for 32bit Windows 10 (i686) ?
Citation from https://reviews.llvm.org/D60748 :
Please also exclude FreeBSD from these changes, since we care a lot about backwards compatibility, and specifically about alignment requirements. (We have run into many issues in our ports collection where upstream assumes everything is 16-byte aligned on i386, which is NOT ABI compliant.)
I didn't new about about that, btw. @emaste , @kostikbel : could you explain more?
@pcordes , found your old post here . Could you explain more about Clang vs GCC behavior?
Currently, Clang always aligns to 4 bytes on i386 standard calling conversion. This is not strictly following psABI/gcc. Chen had a new patch https://reviews.llvm.org/D78564 to fix the problem after D60748 abandoned. But it hasn't been accepted.
D78564 is trying to fix the wrong alignment when the parameters are unnamed parameters(Only for m128, m256 and m512). From what I know, When clang uses the stack to pass struct, it will always be aligned to 4 bytes, except m128, m256 and m512, no matter the parameter is named or unnamed. I have described the rule of __m128/256/512 in that D78564 . This is totally different from gcc. For example:
struct __attribute__((aligned(64))) X {
int x;
};
gcc will align to 64 byte but clang will align to 4 byte.
For D78564, when the parameter is unnamed, the callee will always assume that the alignment of the unnamed parameter is align to 4 byte. For common struct there is no problem. But for __m128/256/512, caller will align these parameters to 16/32/64 bytes, the callee will get wrong result.
@thanm, could you provide an extended explanation of 16 bytes sizing?
https://go.googlesource.com/gollvm/+/refs/heads/master/bridge/go-llvm-cabi-oracle.cpp#156 https://go.googlesource.com/gollvm/+/refs/heads/master/bridge/go-llvm-cabi-oracle.cpp#374 https://go.googlesource.com/gollvm/+/refs/heads/master/bridge/go-llvm-cabi-oracle.cpp#447 https://go.googlesource.com/gollvm/+/refs/heads/master/bridge/go-llvm-cabi-oracle.cpp#809 https://go.googlesource.com/gollvm/+/refs/heads/master/bridge/go-llvm-cabi-oracle.cpp#856 https://go.googlesource.com/gollvm/+/refs/heads/master/bridge/go-llvm-cabi-oracle.cpp#996 https://go.googlesource.com/gollvm/+/refs/heads/master/bridge/go-llvm-cabi-oracle.cpp#1047 https://go.googlesource.com/gollvm/+/refs/heads/master/bridge/go-llvm-cabi-oracle.cpp#1134
Which of those are ABI specific (System V x86_64, not related to the current i686 issue)? Which are specific to https://tour.golang.org/basics/11 (int16)? Specific to LLVM itself?
could you provide an extended explanation of 16 bytes sizing?
Mailing list is a better place for questions of this sort. Happy to respond on golang-dev.
I am creating this issue for a future patch (and others should be expected, for the same purpose), observable on/threw Gerrit. It would be referenced (a bit) later.
This is about compiling & running 32bit userspace Go applications on (under?) 32bit CPU/hardware/OS kernel (system-on-board). Something for 32bit AMD's CPUs would be a good cause for a separate Github issue.
This is not covering the following (corresponding options/use cases should be covered within separate Github issues):
This issue covers few OS-compiler combinations (at once). I will update this summary once there would be a demand to extend the scope. GCC, Clang compilers on Linux. MSVC compiler on Windows. Not sure what to assume on MacOS (I heard that they have a hybrid 32bit/64bit kernel - but I am not an expert). GCC, Clang on FreeBSD.