Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gollvm: supporting i386/i686 builds (Intel) #42440

Open
advancedwebdeveloper opened this issue Nov 7, 2020 · 31 comments
Open

gollvm: supporting i386/i686 builds (Intel) #42440

advancedwebdeveloper opened this issue Nov 7, 2020 · 31 comments
Milestone

Comments

@advancedwebdeveloper
Copy link

@advancedwebdeveloper advancedwebdeveloper commented Nov 7, 2020

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):

  • running 32bit userspace apps on 32bit hardware/CPU/OS kernel, for micro-controllers (system-on-chip);
  • running 32bit containerized Go apps, on 64bit hosts (system-on-board);
  • running 32bit containerized Go apps, on 64bit hosts (system-on-chip);
  • running 32bit bare metal/in-kernel firmware (probably on 32bit system-on-chip), compiled from Golang source code
    .

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.

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 7, 2020

@thanm thanm added this to the gollvm milestone Nov 9, 2020
@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 16, 2020

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
    .

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 19, 2020

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.

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 21, 2020

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).

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 24, 2020

@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:

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 24, 2020

go-llvm-cabi-oracle_8cpp__incl

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 24, 2020

go-llvm-cabi-oracle_8h__dep__incl

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 24, 2020

go-llvm-cabi-oracle_8h__incl

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 24, 2020

classCABIOracleArgumentAnalyzer__coll__graph
classCABIOracleArgumentAnalyzer__inherit__graph
classCABIOracle__coll__graph
classCABIOracleX86__64__SysV__coll__graph
classCABIOracleX86__64__SysV__inherit__graph

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 24, 2020

I see some adoptions of EightByteInfo::determineABITypesForLLVM'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.).

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Nov 24, 2020

@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 .

@thanm
Copy link
Member

@thanm thanm commented Nov 24, 2020

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.

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Nov 29, 2020

Referencing http://llvm.org/docs/LangRef.html#parameter-attributes - specific considerations would be added later

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 3, 2020

Reminding about unresolved issue #42975

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 3, 2020

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:

  1. 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
.

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 3, 2020

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

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 3, 2020

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;

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 3, 2020

Probably related to #42440 (comment) : 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);

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Dec 3, 2020

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.

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 5, 2020

@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.

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 5, 2020

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 5, 2020

@JonChesterfield , could you elaborate regarding relic 32bit AMD's CPUs?
Which stack alignments should be considered, for old CPUs?
Why?

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 6, 2020

@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?

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 13, 2020

@kcadieux , @GreatKeeper : could you elaborate about MSVC's stack alignment, when compiling (and linking, by using Microsoft's linker) for 32bit Windows 10 (i686) ?

@advancedwebdeveloper
Copy link
Author

@advancedwebdeveloper advancedwebdeveloper commented Dec 13, 2020

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?

@phoebewang
Copy link

@phoebewang phoebewang commented Dec 16, 2020

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.

@MoringLiu
Copy link

@MoringLiu MoringLiu commented Dec 17, 2020

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
Copy link
Member

@thanm thanm commented Dec 21, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants