슬레이트 만들기 [2.1부]

지난번 기사에서 많은 부분을 생략했다는 것을 깨달았기 때문에 오늘은 여러분을 모두 채워드리려고 왔습니다.




1부에서 언급한 큰 변경 사항 중 하나는 Wasm 사용에서 LLVM 사용으로의 전환이었는데 실수로 완전히 얼버무렸습니다. 그것에 대해 매우 죄송합니다.

그래서,
LLVM은 이 "중간 표현"을 호출하고 기계 코드로 실제 컴파일을 수행하는 의사 어셈블리 및 프로그램 모음입니다. 매우 강력한 유형이며 친숙하면서도 이질적으로 보입니다.

프로그램이 코드에서 AST를 생성할 수 있게 되면 LLVM IR을 생성하는 것이 Slate 컴파일러의 역할입니다.

https://gist.github.com/nektro/a61777bbcb818d99dddf579b031e9798

이 요지에는 우리가 작업 중인 코드와 원하는 LLVM IR 출력이 모두 포함되어 있습니다. 고맙게도 LLVM 프로젝트는 우리가 사용할 수 있는 Go 라이브러리를 제공합니다. 실제로 IR을 생성하려면 고려해야 할 사항이 많으므로 오늘은 첫 번째 부분을 다룰 것입니다.

피킹 선언 순서



코드에는 각각 호출이 있는 함수와 동일한 4개의 선언const이 있습니다. 작성된 순서대로 컴파일하는 경우를 제외하고는 문제가 되지 않습니다. 이 경우 main 에 대한 함수 개체를 생성하지만 print 에 대한 함수 개체를 찾으려고 하면 거기에 없습니다(파일의 아래쪽에 있고 아직 아직 컴파일하지 않았습니다). 안타깝다. 불행하게도 이것이 우리의 문제입니다. 왜냐하면 우리는 함수를 사용되는 순서대로 넣어야 하는 C의 동작을 복사하고 싶지 않기 때문입니다.

현재 접근 방식



먼저 두 개의 변수를 설정합니다. 첫 번째는 completed 이름을 IR 개체에 연결하는 const 맵입니다. 여기에는 완료된 선언이 포함되며 나중에 언제든지 참조할 수 있습니다.

처음에는 비어 있습니다. 둘째, 컴파일되지 않은todo 선언의 문자열 배열const도 필요합니다. 여전히 처리가 필요한 한 이름이 포함됩니다. 시작 시 모든 선언은 todo 에 배치됩니다. (이 예에서는 [main, print, write, syscall3] 입니다.)

그런 다음 todo 배열을 반복하고 각 항목의 "종속성"을 계산합니다. 이전에 구문 분석main을 하려고 했고 필요한 시점print을 기억하십니까? 그 정보는 여기에서 계산됩니다. 그 후 다음 정보를 얻습니다.

main: [print]
print: [write]
write: [syscall3]
syscall3: []


Note: write calls syscall3 because the convention is the direct call-path for x86_64 Linux, which is what this base example was made for.



-

syscall3 has no "dependencies" because the only call it makes is inline assembly and will just about be directly inserted into the binary with its arguments.



이제 계산된 종속성이 completed 지도 개체의 모든 요소인 모든 AST 개체에 대해 IR 변환을 만들고 todo에서 제거합니다.

이 예에서는 syscall3 입니다. syscall3 그런 다음 LLVM Go 라이브러리로 전송되어 completed 에 배치됩니다. 그런 다음 컴파일러는 todo가 비어 있을 때까지 이 루프를 반복하고 마지막으로 종료합니다.

향후 개선 사항



이 접근 방식은 예제가 매우 직접적이었고 가져오기나 그와 유사한 것이 없었기 때문에 효과가 있었습니다. 또한 형식이 안전하지 않습니다.

결국 이름 오버로드를 허용할지 여부에 대해 충돌하지만 print(string)가 존재하지만 print(int) 등을 호출하려고 시도하는 경우 오류를 던질 수 있기를 바랍니다.

게다가 더 작은 이진 출력의 이점을 위한 트리 쉐이킹이 좋을 것입니다. 이는 main에서 시작하여 없는 항목을 모두 구문 분석할 때까지 각 종속 항목으로 다이빙하여 달성할 수 있습니다. 그런 다음 역방향으로 작업하여 main 경로를 통해 참조되는 함수/객체만 컴파일합니다. 이것은 죽은 코드 분석을 무료로 제공하는 추가 이점이 있습니다.

마무리



나는 이것이 지난 기사보다 내부를 훨씬 더 잘 설명하기를 바라며 다음 번에는 거슬리는 전체를 제외하기 위해 최선을 다할 것입니다. 블로깅은 자체 기술이며 이를 정기적으로 수행하는 사람들에게 찬사를 보냅니다.

프로젝트는 여전히 여기https://github.com/nektro/slate에서 찾을 수 있으며 여기 DEV, Github 및 Twitter에서 모두 찾을 수 있습니다.
.

읽어주셔서 감사하고 다음에 또 뵙겠습니다❤

좋은 웹페이지 즐겨찾기