LLVM рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдмрдирд╛рдирд╛ред рднрд╛рдЧ 4: JIT рдФрд░ рдЕрдиреБрдХреВрд▓рдХ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рдирд╛

рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЗ рдЕрдзреНрдпрд╛рдп 4 рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИ "рдПрд▓рдПрд▓рд╡реАрдПрдо рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдмрдирд╛рдирд╛"ред рдкрд┐рдЫрд▓реЗ рдЕрдзреНрдпрд╛рдпреЛрдВ ( 1 , 2 рдФрд░ 3 ) рдиреЗ рд╕рд░рд▓рддрдо рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдФрд░ рдЗрд╕рдореЗрдВ рдПрд▓рдПрд▓рд╡реАрдПрдо рдЖрдИрдЖрд░ рдкреАрдврд╝реА рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдХреЛ рдЬреЛрдбрд╝рд╛ред рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдореЗрдВ рджреЛ рдирдИ рддрдХрдиреАрдХреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝рд░ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рдирд╛ рдФрд░ рдЬреЗрдЖрдИрдЯреА рд╕рдВрдХрд▓рдХ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рдирд╛ред рдпреЗ рдРрдб-рдСрди рдпрд╣ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВрдЧреЗ рдХрд┐ рд╣рдорд╛рд░реА рдмрд╣реБрд░реВрдкрджрд░реНрд╢рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛, рдХреБрд╢рд▓ рдХреЛрдб рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреА рд╕рдмрд╕реЗ рд╕рд░рд▓ рддрд╣ (рдирд┐рд░рдВрддрд░ рддрд╣)


рдЕрдзреНрдпрд╛рдп 3 рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░рд╛ рдбреЗрдореЛ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдФрд░ рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд▓ рд╣реИред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдпрд╣ рд╕рд╣реА рдХреЛрдб рд╕реЗ рджреВрд░ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред IRBuilder, рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╕рд░рд▓ рдХреЛрдб рд╕рдВрдХрд▓рди рдХрд░рддреЗ рд╕рдордп рд╣рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рдЕрдиреБрдХреВрд▓рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ:

 ready> def test(x) 1+2+x; Read function definition: define double @test(double %x) { entry: %addtmp = fadd double 3.000000e+00, %x ret double %addtmp } 

рдпрд╣ рдХреЛрдб рдЗрдирдкреБрдЯ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдХреЗ рдирд┐рд░реНрдорд┐рдд рдПрдПрд╕рдЯреА рдХрд╛ рд╢рд╛рдмреНрджрд┐рдХ рдкреНрд░рддрд┐рд▓реЗрдЦрди рдирд╣реАрдВ рд╣реИред рдЕрдиреНрдпрдерд╛, рдпрд╣ рд╣реЛрдЧрд╛:

  рддреИрдпрд╛рд░> рдбрд┐рдл рдЯреЗрд╕реНрдЯ (рдПрдХреНрд╕) 1 + 2 + рдПрдХреНрд╕;
 рдлрд╝рдВрдХреНрд╢рди рдкрд░рд┐рднрд╛рд╖рд╛ рдкрдврд╝реЗрдВ:
 рдкрд░рд┐рднрд╛рд╖рд┐рдд рдбрдмрд▓ @test (рдбрдмрд▓% x) {
 рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐:
         % addtmp = fadd double 2.000000e + 00, 1.000000e + 00
         % addtmp1 = fadd рдбрдмрд▓% addtmp,% x
         рджреЛрд╣рд░рд╛% addtmp1 рдХреЛ рдкреБрдирдГрдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ
 }

рд▓рдЧрд╛рддрд╛рд░ рддрд╣ ( рдирд┐рд░рдВрддрд░ рддрд╣ ), рдЬреИрд╕рд╛ рдХрд┐ рд╣рдордиреЗ рдКрдкрд░ рджреЗрдЦрд╛, рдмрд╣реБрдд рдмрд╛рд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЕрдиреБрдХреВрд▓рди рд╣реИ: рдЗрддрдирд╛ рдХрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рдХреЗ рдХрдИ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдПрдПрд╕рдЯреА рдореЗрдВ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рддрд╣ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВред

рдПрд▓рдПрд▓рд╡реАрдПрдо рдХреЗ рд╕рд╛рде, рдЖрдкрдХреЛ рдПрдПрд╕рдЯреА рдореЗрдВ рдЗрд╕рдХреЗ рд╕рдорд░реНрдерди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдПрд▓рдПрд▓рд╡реАрдПрдо рдЖрдИрдЖрд░ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рд╕рднреА рдХреЙрд▓ LLVM IR Builder рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рддреЗ рд╣реИрдВ, рдЬреЛ рд╕реНрд╡рдпрдВ рдЬрд╛рдВрдЪрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЛ рдЧрд┐рд░рд╛рдирд╛ рд╕рдВрднрд╡ рд╣реИред рдпрд╣ рд╕рд┐рд░реНрдл рд╕реНрдерд┐рд░рд╛рдВрдХ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдирдпрд╛ рд╕реНрдерд┐рд░рд╛рдВрдХ рд▓реМрдЯрд╛рддрд╛ рд╣реИред рдПрдХ рдирд┐рд░реНрджреЗрд╢ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдПред

рдЦреИрд░, рдпрд╣ рдЖрд╕рд╛рди рдерд╛ :)ред рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рд╣рдо рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк рд╣рдореЗрд╢рд╛ рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╕рдордп IRBuilder рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдЗрд╕рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рд╣реЛрдиреЗ рдкрд░ "рд╕рд┐рдВрдЯреИрдХреНрдЯрд┐рдХ рдУрд╡рд░рд╣реЗрдб" рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ (рдЖрдкрдХреЛ рд╣рд░ рдЬрдЧрд╣ рд▓рдЧрд╛рддрд╛рд░ рдЬрд╛рдВрдЪ рдХреЗ рд╕рд╛рде рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рдЦрд░рд╛рдм рдирд╣реАрдВ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ), рдФрд░ рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдпрд╣ рдЙрддреНрдкрдиреНрди рдПрд▓рдПрд▓рд╡реАрдПрдо рдЖрдИрдЖрд░ рдХреА рдорд╛рддреНрд░рд╛ рдХреЛ рдХрдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ (рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдореИрдХреНрд░реЛрдкреНрд░реЛрд╕реЗрд╕рд░реЛрдВ рд╡рд╛рд▓реА рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП (рдЬреЛ рдХрдИ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ)ред

рджреВрд╕рд░реА рдУрд░, IRBuilder рдЗрд╕ рддрдереНрдп IRBuilder рд╕реАрдорд┐рдд рд╣реИ рдХрд┐ рдпрд╣ рдХреЛрдб рдХреЗ рд╕рднреА рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддрд╛ рд╣реИ "рдЬреИрд╕рд╛ рд╣реИ", рдЕрд░реНрдерд╛рдд, рдкрд╣рд▓реЗ рд╕реЗ рдирд┐рд░реНрдорд┐рдд рдХреЛрдб рдХреЗ рд╕рд╛рдеред рдпрджрд┐ рдЖрдк рдереЛрдбрд╝рд╛ рдФрд░ рдЬрдЯрд┐рд▓ рдЙрджрд╛рд╣рд░рдг рд▓реЗрддреЗ рд╣реИрдВ:

  рддреИрдпрд╛рд░> рдбреАрдИрдЯреА рдЯреЗрд╕реНрдЯ (рдПрдХреНрд╕) (1 + 2 + x) * (x + (1 + 2));
 рддреИрдпрд╛рд░> рдкрдврд╝реЗрдВ рд╕рдорд╛рд░реЛрд╣ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛:
 рдкрд░рд┐рднрд╛рд╖рд┐рдд рдбрдмрд▓ @test (рдбрдмрд▓% x) {
 рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐:
         % addtmp = fadd double 3.000000e + 00,% x
         % addtmp1 = fadd рдбрдмрд▓% x, 3.000000e + 00
         % рдорд▓реНрдЯреАрдореНрдк = fmul рдбрдмрд▓% рдПрдбрдЯрдореНрдк,% addtmp1
         рджреЛрд╣рд░рд╛ рджреЛрд╣рд░рд╛ рдорд▓реНрдЯреАрдк
 }

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХрд╛рдо рдХреЗ рдмрд╛рдПрдВ рдФрд░ рджрд╛рдПрдВ рд╣рд┐рд╕реНрд╕реЗ рд╕рдорд╛рди рдореВрд▓реНрдп рд╣реИрдВред рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ "tmp = x + 3" рдЬреИрд╕реА рдХрд┐рд╕реА рдЪреАрдЬрд╝ рдХреЗ рд▓рд┐рдП рдЪрд╛рд╣реЗрдВрдЧреЗ; рдкрд░рд┐рдгрд╛рдо = tmp * tmp; тАЭрдбрдмрд▓ рдХрдВрдкреНрдпреВрдЯрд┐рдВрдЧ рдХреЗ рдмрдЬрд╛рдптАЬ x + 3 тАЭред

рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдХреЛрдИ рднреА рд╕реНрдерд╛рдиреАрдп рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдЗрд╕рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдФрд░ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЗрд╕рдХреЗ рд▓рд┐рдП рджреЛ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ: рдирд┐рд░рд░реНрдердХ рдЕрддрд┐рд░рд┐рдХреНрдд рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдкреБрдирд░реНрд╕рдВрдпреЛрдЬрди (рд╢рд╛рдмреНрджрд┐рдХ рдкрд╣рдЪрд╛рди рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП) рдФрд░ рдЖрдо рд╕рдмрдЯреЗрдХреНрд╢рдВрд╕ ( рдХреЙрдорди рд╕рдХреНрд╕реЗрдХреНрд╕рдкреНрд░реЗрд╢рди рдПрд▓рд┐рдорд┐рдиреЗрд╢рди, рд╕реАрдПрд╕рдИ ) рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдирд╛ред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдПрд▓рдПрд▓рд╡реАрдПрдо рдЕрдиреБрдХреВрд▓рди рдХреА рдПрдХ рд╡рд┐рд╕реНрддреГрдд рд╢реНрд░реГрдВрдЦрд▓рд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдорд╛рд░реНрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдПрд▓рдПрд▓рд╡реАрдПрдо рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реЗрд╢рди рдкрд╛рд╕


рдПрд▓рдПрд▓рд╡реАрдПрдо рдХрдИ рдЕрдиреБрдХреВрд▓рди рдкрд╛рд╕ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЪреАрдЬреЗрдВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдЯреНрд░реЗрдбрдСрдл рд╣реЛрддреЗ рд╣реИрдВред рдЕрдиреНрдп рдкреНрд░рдгрд╛рд▓рд┐рдпреЛрдВ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдПрд▓рдПрд▓рд╡реАрдПрдо рдореЗрдВ рдЧрд▓рдд рд╡рд┐рдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕реНрдерд╛рди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЕрдиреБрдХреВрд▓рди рдХрд╛ рдПрдХ рд╕реЗрдЯ рд╕рднреА рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рд╣реИ рдФрд░ рд╕рднреА рдЕрд╡рд╕рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╣реИред рдПрд▓рдПрд▓рд╡реАрдПрдо рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рдПрдХ рдирд┐рд╖реНрдкрд╛рджрдХ рд╣реЛрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреВрд░реНрдг рдирд┐рд░реНрдгрдп рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХрд┐рд╕ рдХреНрд░рдо рдореЗрдВ рдФрд░ рдХрд┐рд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред

рдПрд▓рдПрд▓рд╡реАрдПрдо рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдореЗрдВ "рдореЙрдбреНрдпреВрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ" рдФрд░ "рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ" рджреЛрдиреЛрдВ рдкрд╛рд╕ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдЬреЛ рдХреЗрд╡рд▓ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдмрд╛рдХреА рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦреЗ рдмрд┐рдирд╛ред рдкреИрд╕реЗрдЬ рдФрд░ рд╡реЗ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП, рдбреЙрдХреНрдпреВрдореЗрдВрдЯ рдХреИрд╕реЗ рд▓рд┐рдЦреЗрдВ рдПрдХ рдкрд╛рд╕ рдФрд░ рдПрд▓рдПрд▓рд╡реАрдПрдо рдкрд╛рд╕ рд╕реВрдЪреА рджреЗрдЦреЗрдВ ред

рдмрд╣реБрд░реВрдкрджрд░реНрд╢рдХ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рджрд░реНрдЬ рдХрд┐рдП рдЬрд╛рдиреЗ рдХреЗ рд╕рдордп, рдПрдХ-рд╕реЗ-рдПрдХ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдЙрддреНрдкрдиреНрди рдХрд░ рд░рд╣реЗ рд╣реИрдВред рд╣рдорд╛рд░рд╛ рд▓рдХреНрд╖реНрдп рдЕрдкрдиреЗ рд╡рд░реНрддрдорд╛рди рд╕реНрд╡рд░реВрдк рдореЗрдВ рдЕрдзрд┐рдХрддрдо рдЕрдиреБрдХреВрд▓рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди, рдлрд┐рд░ рднреА рд╣рдо рдЖрд╕рд╛рди рдФрд░ рддреЗрдЬрд╝ рдХреЛрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рджрд░реНрдЬ рдХрд┐рдП рдЧрдП "рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░" рдХрдИ рдЕрдиреБрдХреВрд▓рди рдХрд╛ рдЪрдпрди рдХрд░реЗрдВрдЧреЗред рдЕрдЧрд░ рд╣рдо "рд╕реНрдЯреИрдЯрд┐рдХ рдХреИрд▓рд┐рдбреЛрд╕реНрдХреЛрдк рдХрдВрдкрд╛рдЗрд▓рд░" рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддреЗ рдереЗ, рддреЛ рд╣рдо рд▓рдЧрднрдЧ рдПрдХ рд╣реА рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рд╣рдо рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝рд░ рдХреЗ рд▓реЙрдиреНрдЪ рдореЗрдВ рджреЗрд░реА рдХрд░реЗрдВрдЧреЗ рдЬрдм рддрдХ рдХрд┐ рдкреВрд░реА рдлрд╝рд╛рдЗрд▓ рдкрд╛рд░реНрд╕ рдирд╣реАрдВ рд╣реЛ рдЬрд╛рддреАред

рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдЕрдиреБрдХреВрд▓рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛ FunctionPassManager FunctionPassManager рдЙрд╕ LLVM рдЕрдиреБрдХреВрд▓рди рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдФрд░ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдЪрд▓рд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдлрд┐рд░ рд╣рдо рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рди рдХрд╛ рдПрдХ рд╕реЗрдЯ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдХреЛрдб рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИ:

  FunctionPassManager OurFPM(TheModule); //   .     ,  //       . OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData())); //   AliasAnalysis  GVN. OurFPM.add(createBasicAliasAnalysisPass()); //   "peephole"  "bit-twiddling". OurFPM.add(createInstructionCombiningPass()); //  . OurFPM.add(createReassociatePass()); //   . OurFPM.add(createGVNPass()); //     (    ..). OurFPM.add(createCFGSimplificationPass()); OurFPM.doInitialization(); //   ,     . TheFPM = &OurFPM; //    " ". MainLoop(); 

рдпрд╣ рдХреЛрдб "OurFPM" рдирд╛рдордХ рдПрдХ FunctionPassManager рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рдмрдирд╛рддреЗ рд╕рдордп, рдореЙрдбреНрдпреВрд▓ рдХреЛ рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдкрд╛рд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдПрдХ рдмрд╛рд░ рдпрд╣ рд╣реЛ рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо LLVM рдкрд╛рд╕ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдРрдб рдХреЙрд▓ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдкрд╣рд▓рд╛ рдкрд╛рд╕ рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рд╣реИ, рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рддрд╛рдХрд┐ рдмрд╛рдж рдХреЗ рдЕрдиреБрдХреВрд▓рди рдХреЛ рдкрддрд╛ рдЪрд▓реЗ рдХрд┐ рдХрд╛рд░реНрдпрдХреНрд░рдо рдореЗрдВ рдХреМрди рд╕реЗ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред "TheExecutionEngine" рдЪрд░ JIT рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ, рдЬреЛ рд╣рдореЗрдВ рдЕрдЧрд▓реЗ рднрд╛рдЧ рдореЗрдВ рдорд┐рд▓реЗрдЧрд╛ред

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдордиреЗ 4 рдЕрдиреБрдХреВрд▓рди рдкрд╛рд╕ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдЪреБрдиреЗ рдЧрдП рдорд╛рд░реНрдЧ "рд╕рдлрд╛рдИ" рдЕрдиреБрдХреВрд▓рди рдХреЗ рдПрдХ рдХрд╛рдлреА рдорд╛рдирдХ рд╕реЗрдЯ рд╣реИрдВ рдЬреЛ рдХреЛрдб рдХреА рдПрдХ рд╡рд┐рд╕реНрддреГрдд рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИрдВред рдореИрдВ рдЧрд╣рд░рд╛рдИ рд╕реЗ рдирд╣реАрдВ рдЬрд╛рддрд╛ рдХрд┐ рд╡реЗ рдХреНрдпрд╛ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореЗрд░рд╛ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдХрд░реЛ, рд╡реЗ рдПрдХ рдЕрдЪреНрдЫреЗ рд╢реБрд░реБрдЖрддреА рдмрд┐рдВрджреБ рд╣реИрдВ :)ред

PassManager рд╕реНрдерд╛рдкрдирд╛ рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдо рдЗрд╕реЗ рдЕрдкрдиреЗ рдирдП рдлрд╝рдВрдХреНрд╢рди ( FunctionAST::Codegen ) рдореЗрдВ рдЬреЗрдирд░реЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдкрд╛рд╕ рд▓реМрдЯрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ:

  if (Value *RetVal = Body->Codegen()) { //  . Builder.CreateRet(RetVal); //   ,    (). verifyFunction(*TheFunction); 
 //  . TheFPM->run(*TheFunction); 
 return TheFunction; } 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИред FunctionPassManager рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝ рдХрд░рддрд╛ рд╣реИ рдФрд░ рддреБрд░рдВрдд LLVM Function* рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ LLVM Function* рдХреА рдмреЙрдбреА рдореЗрдВ рд╕реБрдзрд╛рд░ рд╣реЛрддрд╛ рд╣реИред рдЕрдм рд╣рдорд╛рд░реЗ рдХреЛрдб рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ:

  рддреИрдпрд╛рд░> рдбреАрдИрдЯреА рдЯреЗрд╕реНрдЯ (рдПрдХреНрд╕) (1 + 2 + x) * (x + (1 + 2));
 рддреИрдпрд╛рд░> рдкрдврд╝реЗрдВ рд╕рдорд╛рд░реЛрд╣ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛:
 рдкрд░рд┐рднрд╛рд╖рд┐рдд рдбрдмрд▓ @test (рдбрдмрд▓% x) {
 рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐:
         % addtmp = fadd рдбрдмрд▓% x, 3.000000e + 00
         % рдорд▓реНрдЯреАрдореНрдк = fmul рдбрдмрд▓% рдПрдбрдЯрдореНрдк,% рдПрдбрдЯрдореНрдк
         рджреЛрд╣рд░рд╛ рджреЛрд╣рд░рд╛ рдорд▓реНрдЯреАрдк
 }

рдЬреИрд╕рд╛ рдХрд┐ рдЕрдкреЗрдХреНрд╖рд┐рдд рдерд╛, рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрддрд┐рд░рд┐рдХреНрдд рдкрд░рд┐рдгрд╛рдо рдФрд░ рдЗрд╕рдХреЗ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЕрдиреБрдХреВрд▓рд┐рдд рдХреЛрдб рд╣реИред

LLVM рдХреБрдЫ рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛ рд╕рдХрдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреБрдХреВрд▓рди рдХреА рдПрдХ рд╡рд┐рд╕реНрддреГрдд рд╢реНрд░реГрдВрдЦрд▓рд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рд╡рд┐рднрд┐рдиреНрди рд╡реЙрдХрд╡реЗ рдкрд░ рдХреБрдЫ рджрд╕реНрддрд╛рд╡реЗрдЬ рдЙрдкрд▓рдмреНрдз рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдмрд╣реБрдд рдкреВрд░рд╛ рдирд╣реАрдВ рд╣реИред рд╡рд┐рдЪрд╛рд░реЛрдВ рдХрд╛ рдПрдХ рдФрд░ рдЕрдЪреНрдЫрд╛ рд╕реНрд░реЛрдд рдЗрд╕рдХреЗ рд╕рд╛рде рдЖрдиреЗ рд╡рд╛рд▓реЗ рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рджреЗрдЦрдирд╛ рд╣реИ рдЬреЛ рдХрд┐ llvm-gcc рдпрд╛ llvm-ld рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдСрдкреНрдЯ рдЯреВрд▓ рдЖрдкрдХреЛ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдорд╛рд░реНрдЧ рдХреЗ рд╕рд╛рде рдкреНрд░рдпреЛрдЧ рдХрд░рдиреЗ рдФрд░ рдпрд╣ рджреЗрдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдХрд┐ рд╡реЗ рдХреНрдпрд╛ рдХрд░рддреЗ рд╣реИрдВред

рдЕрдм рдЬрдм рд╣рдорд╛рд░реЗ рд╕рд╛рдордиреЗ рдХреЗ рдЫреЛрд░ рд╕реЗ рдПрдХ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рдХреЛрдб рд╣реИ, рддреЛ рд╣рдо рдЗрд╕рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ!

рдПрдХ рдЬреЗрдЖрдИрдЯреА рдХрдВрдкрд╛рдЗрд▓рд░ рдЬреЛрдбрд╝рдирд╛


рдПрд▓рдПрд▓рд╡реАрдПрдо рдЖрдИрдЖрд░ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рдХреЛрдб рдХреЗ рд▓рд┐рдП рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЙрдкрдХрд░рдг рд▓рдЧрд╛рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдк рдЗрд╕рдХреЗ рд▓рд┐рдП рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реЗрд╢рди рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ (рдЬреИрд╕рд╛ рдХрд┐ рд╣рдордиреЗ рдКрдкрд░ рдХрд┐рдпрд╛ рдерд╛), рдЖрдк рдЗрд╕реЗ рдЯреЗрдХреНрд╕реНрдЯ рдпрд╛ рдмрд╛рдЗрдирд░реА рдлреЙрд░реНрдо рдореЗрдВ рдЖрдЙрдЯрдкреБрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЖрдк рдХреБрдЫ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреЛ рдХреЛрдбрд╛рдВрддрд░рдХ LLVM (.s) рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рдВрдХрд▓рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдЖрдк JIT- рдХреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрд╡реЗрджрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╕рдВрдХрд▓рдиред LLVM IR рджреГрд╢реНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдорд╣рд╛рди рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдВрдХрд▓рдХ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рднрд╛рдЧреЛрдВ рдХреЗ рдмреАрдЪ "рдПрдХрд▓" рд╣реИред

рдЗрд╕ рдЦрдВрдб рдореЗрдВ, рд╣рдо рдЕрдкрдиреЗ рджреБрднрд╛рд╖рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП JIT рд╕рдВрдХрд▓рди рд╕рдорд░реНрдерди рдЬреЛрдбрд╝реЗрдВрдЧреЗред рдХреИрд▓реАрдбреЛрд╕реНрдХреЛрдк рдХрд╛ рдореБрдЦреНрдп рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдпрд╛ рд╢реАрд░реНрд╖-рд╕реНрддрд░реАрдп рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рджрд░реНрдЬ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рддреБрд░рдВрдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, "1 + 2" рджрд░реНрдЬ рдХрд░рддреЗ рд╕рдордп, рд╣рдореЗрдВ 3 рдХреА рдЧрдгрдирд╛ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдФрд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╕рдордп, рд╣рдо рдЗрд╕реЗ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рд╕реЗ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЬреЗрдЖрдИрдЯреА рдХреЛ рдШреЛрд╖рд┐рдд рдФрд░ рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдХреЛ рдЬреЛрдбрд╝рдХрд░ рдФрд░ рдЗрд╕реЗ main рдХреЙрд▓ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:

 static ExecutionEngine *TheExecutionEngine; 
 ... int main() { .. 
  //  JIT.    . TheExecutionEngine = EngineBuilder(TheModule).create(); 
  .. } 

рдпрд╣ рдПрдХ рдЕрдореВрд░реНрдд "Execution Engine" рдмрдирд╛рддрд╛ рд╣реИ, рдЬреЛ рдПрдХ рд╕рдВрдХрд▓рдХ рдпрд╛ рдПрдХ рдПрд▓рдПрд▓рд╡реАрдПрдо рджреБрднрд╛рд╖рд┐рдпрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдПрд▓рдПрд▓рд╡реАрдПрдо рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЖрдкрдХреЗ рд▓рд┐рдП рдЬреЗрдЖрдИрдЯреА рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд╛ рдЪрдпрди рдХрд░реЗрдЧрд╛ рдпрджрд┐ рдпрд╣ рдЖрдкрдХреЗ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЗ рд▓рд┐рдП рдореМрдЬреВрдж рд╣реИ, рдЕрдиреНрдпрдерд╛ рдпрд╣ рдЗрдВрдЯрд░рдкреНрд░реЗрдЯрд░ рдкрд░ рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдПрдЧрд╛ред

ExecutionEngine рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, JIT рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИред рд╡рд┐рднрд┐рдиреНрди рдЙрдкрдпреЛрдЧреА рдПрдкреАрдЖрдИ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕рд░рд▓рддрдо "getPointerToFunction(F)" рд╡рд┐рдзрд┐ рд╣реИред рдпрд╣ рд╡рд┐рдзрд┐ JIT, рдирд┐рд░реНрджрд┐рд╖реНрдЯ LLVM рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддреА рд╣реИ рдФрд░ рдЙрддреНрдкрдиреНрди рдорд╢реАрди рдХреЛрдб рдХреЗ рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди рдкреЙрдЗрдВрдЯрд░ рд▓реМрдЯрд╛рддреА рд╣реИред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдо рдЙрд╕ рдХреЛрдб рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╢реАрд░реНрд╖-рд╕реНрддрд░реАрдп рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдкрд╛рд░ рдХрд░рддрд╛ рд╣реИ:

 static void HandleTopLevelExpression() { //      . if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { LF->dump(); //  . 
 // JIT-,   . void *FPtr = TheExecutionEngine->getPointerToFunction(LF); //     ( ,  double), //       . double (*FP)() = (double (*)())(intptr_t)FPtr; fprintf(stderr, "Evaluated to %f\n", FP()); 
  } 

рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рд╣рдо рдПрдХ рд╕реНрд╡рд╛рдпрддреНрдд рдЕрдирд╛рдо LLVM рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд░реВрдк рдореЗрдВ рд╢реАрд░реНрд╖-рд╕реНрддрд░реАрдп рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдХреЛрдИ рддрд░реНрдХ рдирд╣реАрдВ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдВрдЦреНрдпрд╛ рджреЗрддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рд╣рдо рдПрдХ рджреЗрд╢реА рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдкрд░ LLVM JIT рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЖрдк рдмрд╕ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕реАрдзреЗ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдЬреЗрдЖрдИрдЯреА-рд╕рдВрдХрд▓рд┐рдд рдХреЛрдб рдФрд░ рдорд╢реАрди рдХреЛрдб рдХреЗ рдмреАрдЪ рдХреЛрдИ рдЕрдВрддрд░ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдЖрдкрдХреЗ рдЖрд╡реЗрджрди рдореЗрдВ рд╕рд╛рдВрдЦреНрдпрд┐рдХреАрдп рд░реВрдк рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИред

рдЗрди рджреЛ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рд╕рд╛рде, рд╣рдо рдЕрдм рдмрд╣реБрд░реВрдкрджрд░реНрд╢рдХ рдХреЛ рдХрд╛рдо рдХрд░рддреЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ!

  рддреИрдпрд╛рд░> 4 + 5;
 рдкрд░рд┐рднрд╛рд╖рд┐рдд рдбрдмрд▓ @ "" () {
 рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐:
         рджреЛрд╣рд░рд╛ рджреЛрд╣рд░рд╛ 9.000000e + 00
 }

 9.000000 рдкрд░ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд┐рдпрд╛ рдЧрдпрд╛

рдорд╣рд╛рди, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдбрдВрдк рдПрдХ "рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХреЛрдИ рддрд░реНрдХ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдПрдХ рджреЛрд╣рд░рд╛ рд░рд┐рдЯрд░реНрди рджреЗрддрд╛ рд╣реИ", рдЬрд┐рд╕реЗ рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдЙрдЪреНрдЪ-рд╕реНрддрд░реАрдп рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рд╕рдВрд╢реНрд▓реЗрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рдХреЗрд╡рд▓ рдмреБрдирд┐рдпрд╛рджреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рд╣реИ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣рдо рдФрд░ рдЕрдзрд┐рдХ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИрдВ?

  рддреИрдпрд╛рд░> def testfunc (xy) x + y * 2;
 рдлрд╝рдВрдХреНрд╢рди рдкрд░рд┐рднрд╛рд╖рд╛ рдкрдврд╝реЗрдВ:
 рдбрдмрд▓ @testfunc рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ (рдбрдмрд▓% x, рдбрдмрд▓% y) {
 рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐:
         % рдорд▓реНрдЯреАрдореНрдк = fmul рдбрдмрд▓% y, 2.000000e + 00
         % addtmp = fadd рдбрдмрд▓% рдорд▓реНрдЯреАрдореНрдк,% x
         рджреЛрд╣рд░рд╛% addtmp
 }

рддреИрдпрд╛рд░> testfunc (4, 10);
 рдкрд░рд┐рднрд╛рд╖рд┐рдд рдбрдмрд▓ @ "" () {
 рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐:
         % calltmp = рдХреЙрд▓ рдбрдмрд▓ @testfunc (рдбрдмрд▓ 4.000000e + 00, рдбрдмрд▓ 1.000000e + 01)
         рджреЛрд╣рд░реЗ% рдХреЙрд▓рдЯреИрдВрдк рдХреЛ рдкреБрдирдГрдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ
 }

 24.000000 рдкрд░ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд┐рдпрд╛ рдЧрдпрд╛

рдЗрд╕рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдХрд╕реНрдЯрдо рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдПрдХ рд╕реВрдХреНрд╖реНрдо рдмрд┐рдВрджреБ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдо JIT рдХреЛ рдПрдХ рдЕрдирд╛рдо рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдХреЙрд▓ testfunc , рдЬреЛ testfunc рдХреЙрд▓ testfunc , рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдХрднреА рднреА рдЯреЗрд╕реНрдЯрдлрдВрдХ рдкрд░ рдХреЙрд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рднреА рдЧреИрд░-рдЕрдирд╛рдо рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП JIT рдХреЛ getPointerToFunction() рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ getPointerToFunction() рд╕реЗ рд▓реМрдЯрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдПрдХ рдЕрдирд╛рдо рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдЬреЗрдЖрдИрдЯреА рдХрдИ рдЕрдиреНрдп рдЪреАрдЬреЛрдВ рдХреЗ рд▓рд┐рдП рдФрд░ рдЕрдзрд┐рдХ рдЙрдиреНрдирдд рдЗрдВрдЯрд░рдлреЗрд╕ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ рдорд╢реАрди рдХреЛ рдлреНрд░реА-рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдирд╛, рдЙрдиреНрд╣реЗрдВ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреБрдирд░реНрдореВрд▓реНрдпрд╛рдВрдХрди рдХрд╛рд░реНрдп рдЖрджрд┐ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕ рд╕рд░рд▓ рдХреЛрдб рдХреА рд╕рд╣рд╛рдпрддрд╛ рд╕реЗ, рд╣рдореЗрдВ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд░реВрдк рд╕реЗ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рд╕реБрд╡рд┐рдзрд╛рдПрдБ рдорд┐рд▓рддреА рд╣реИрдВ - рд╣рдо рдЗрд╕реЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░реЗрдВрдЧреЗ (рдореИрдВрдиреЗ рдЕрдирд╛рдо рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдбрдВрдк рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рд╣реИ рддрд╛рдХрд┐ рдЖрдк рдХреЗрд╡рд▓ рд╡рд┐рдЪрд╛рд░ рджреЗрдЦ рд╕рдХреЗрдВ :):

  рддреИрдпрд╛рд░> рдмрд╛рд╣рд░реА рдкрд╛рдк (рдПрдХреНрд╕);
 рдмрд╛рд╣рд░реА рдкрдврд╝реЗрдВ: 
 рдбрдмрд▓ @sin (рдбрдмрд▓) рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ

рддреИрдпрд╛рд░> рдмрд╛рд╣рд░реА рдХреЙрд╢рди (x);
 рдмрд╛рд╣рд░реА рдкрдврд╝реЗрдВ: 
 рдбрдмрд▓ @cos (рдбрдмрд▓) рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ

рддреИрдпрд╛рд░> рдкрд╛рдк (1.0);
 0.841471 рдореЗрдВ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд┐рдпрд╛ рдЧрдпрд╛

рддреИрдпрд╛рд░> рдбреАрдУ рдлреВ (рдПрдХреНрд╕) рдкрд╛рдк (рдПрдХреНрд╕) * рдкрд╛рдк (рдПрдХреНрд╕) + рдХреЙрд╕ (рдПрдХреНрд╕) * рдХреЙрд╕ (рдПрдХреНрд╕);
 рдлрд╝рдВрдХреНрд╢рди рдкрд░рд┐рднрд╛рд╖рд╛ рдкрдврд╝реЗрдВ:
 рдкрд░рд┐рднрд╛рд╖рд┐рдд рдбрдмрд▓ @foo (рдбрдмрд▓% x) {
 рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐:
         % calltmp = рдХреЙрд▓ рдбрдмрд▓ @ рдПрд╕рд┐рди (рдбрдмрд▓% x)
         % рдорд▓реНрдЯреАрдореНрдк = fmul рдбрдмрд▓% рдХреЙрд▓рдЯреИрдВрдк,% рдХреЙрд▓рдЯреИрдВрдк
         % calltmp2 = call double @cos (рдбрдмрд▓% x)
         % multmp4 = fmul рдбрдмрд▓% calltmp2,% calltmp2
         % addtmp = fadd рдбрдмрд▓% рдорд▓реНрдЯреАрдореНрдк,% рдорд▓реНрдЯреАрдореНрдк 4
         рджреЛрд╣рд░рд╛% addtmp
 }

рддреИрдпрд╛рд░> рдлреВ (4.0);
 1.000000 рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд┐рдпрд╛ рдЧрдпрд╛

рд╡рд╛рд╣, JIT рдиреЗ sin рдФрд░ cos рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ рд╕реАрдЦрд╛? рдЬрд╡рд╛рдм рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд░реВрдк рд╕реЗ рд╕рд░рд▓ рд╣реИ: рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдЬреЗрдЖрдИрдЯреА рдиреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдкрд░ рдкрд╣реБрдВрдЪ рдЧрдпрд╛ред рдЙрдиреНрд╣реЛрдВрдиреЗ рдорд╣рд╕реВрд╕ рдХрд┐рдпрд╛ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЕрднреА рддрдХ JIT рджреНрд╡рд╛рд░рд╛ рд╕рдВрдХрд▓рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдореВрд▓реНрдпрд╛рдВрдХрди рдХреЗ рд▓рд┐рдП рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рдПрдХ рдорд╛рдирдХ рд╕реЗрдЯ рдХрд╣рд╛ рдЬрд╛рддрд╛ рдерд╛ред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЗрд╕рдХреЗ рд╢рд░реАрд░ рдХреЛ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП JIT "dlsym("sin")" рд▓рд┐рдП рдПрдХ рдХреЙрд▓ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрдЧрд╛ред рдЪреВрдВрдХрд┐ "sin" рдЬреЗрдЖрдИрдЯреА рдкрддрд╛ рд╕реНрдерд╛рди рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рд╕реАрдзреЗ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред

LLVM JIT рдпрд╣ рдмрддрд╛рддреА рд╣реИ рдХрд┐ рдПрдХ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреИрд╕реЗ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕реЗ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдЗрдВрдЯрд░рдлреЗрд╕ ( ExecutionEngine.h рдлрд╝рд╛рдЗрд▓ рджреЗрдЦреЗрдВ) рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдЖрдкрдХреЛ IR рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдФрд░ рдкрддреЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рд╕реНрдкрд╖реНрдЯ рдорд╛рдирдЪрд┐рддреНрд░рдг рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЖрдк рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХреЗ рдирд╛рдореЛрдВ рдХреЛ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдлрд╝реНрд▓рд╛рдИ рдкрд░ рд╣рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЬрдм рд╡реЗ рдкрд╣рд▓реА рдмрд╛рд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЖрд▓рд╕реА JIT рд╕рдВрдХрд▓рди рдХреА рднреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред

рдЗрд╕рдХреЗ рджрд┐рд▓рдЪрд╕реНрдк рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдпрд╣ рд╣реИ рдХрд┐ рдЕрдм рд╣рдо рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП рдордирдорд╛рдирд╛ C ++ рдХреЛрдб рд▓рд┐рдЦрдХрд░ рднрд╛рд╖рд╛ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рд╣рдо рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:

 /// putchard -        0. extern "C" double putchard(double X) { putchar((char)X); return 0; } 

рдЕрдм рд╣рдо рдЗрд╕ рдХреЛрдб рдХреА рддрд░рд╣ рдХреБрдЫ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрдВрд╕реЛрд▓ рдХреЗ рд▓рд┐рдП рд╕рд░рд▓ рдЖрдЙрдЯрдкреБрдЯ рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: "extern putchard(); putchard(120);" рдЬреЛ рдХрдВрд╕реЛрд▓ рдореЗрдВ рд▓реЛрдЕрд░рдХреЗрд╕ 'x' рдХреЛ рдкреНрд░рд┐рдВрдЯ рдХрд░рддрд╛ рд╣реИ (120 'x' рдХреЗ рд▓рд┐рдП ASCII рдХреЛрдб рд╣реИ)ред рдлрд╝рд╛рдЗрд▓ I / O, рдХрдВрд╕реЛрд▓ рдЗрдирдкреБрдЯ рдФрд░ рдХрдИ рдЕрдиреНрдп рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Kaleidoscope рдореЗрдВ рд╕рдорд╛рди рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдпрд╣ JIT рдФрд░ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝рд░ рдкрд░ рдЕрдзреНрдпрд╛рдп рдХрд╛ рд╕рдорд╛рдкрди рдХрд░рддрд╛ рд╣реИред рдлрд┐рд▓рд╣рд╛рд▓, рд╣рдо JIT- рд╕рдВрдХрд▓рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдЧреИрд░-рдЯреНрдпреВрд░рд┐рдВрдЧ-рдкреВрд░реНрдг рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛-рдЙрдиреНрдореБрдЦ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреЗ рдХреЛрдб рдХрд╛ рдЕрдиреБрдХреВрд▓рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рд╡рд╛рд╣ рдирд┐рдпрдВрддреНрд░рдг рдХреЗ рд╕рд╛рде рдЕрдкрдиреА рднрд╛рд╖рд╛ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рд░рд╛рд╕реНрддреЗ рдореЗрдВ рдХреБрдЫ рджрд┐рд▓рдЪрд╕реНрдк рдПрд▓рдПрд▓рд╡реАрдПрдо рдЖрдИрдЖрд░ рдореБрджреНрджреЛрдВ рдХреЛ рд╕рдВрдмреЛрдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВред

рдкреВрд░реНрдг рдХреЛрдб рд╕реВрдЪреА


рдФрд░ рдЕрдм, рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣, рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреА рдПрдХ рдкреВрд░реА рд╕реВрдЪреА, рдЬрд┐рд╕реЗ рдЖрдк рдЗрд╕ рддрд░рд╣ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:

#
g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
#
./toy

рд▓рд┐рдирдХреНрд╕ рдкрд░ рд╕рдВрдХрд▓рди рдХрд░рддреЗ рд╕рдордп, -rdynamic рд╡рд┐рдХрд▓реНрдк рдЬреЛрдбрд╝реЗрдВред рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд░рдирдЯрд╛рдЗрдо рдкрд░ рдмрд╛рд╣рд░реА рдлрд╝рдВрдХреНрд╢рди рдареАрдХ рд╕реЗ рд╕рдХреНрд╖рдо рд╣реИрдВред

рдФрд░ рдпрд╣рд╛рдБ рдХреЛрдб рд╣реА рд╣реИ:

 #include "llvm/DerivedTypes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/JIT.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Analysis/Passes.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Support/IRBuilder.h" #include <cstdio> #include <string> #include <map> #include <vector> using namespace llvm; //===----------------------------------------------------------------------===// // Lexer ( ) //===----------------------------------------------------------------------===// //     [0-255],   , //       enum Token { tok_eof = -1, //  ( ) tok_def = -2, tok_extern = -3, //  ( : , ) tok_identifier = -4, tok_number = -5 }; static std::string IdentifierStr; // ,  tok_identifier static double NumVal; // ,  tok_number /// gettok -       . static int gettok() { static int LastChar = ' '; //  . while (isspace(LastChar)) LastChar = getchar(); if (isalpha(LastChar)) { // : [a-zA-Z][a-zA-Z0-9]* IdentifierStr = LastChar; while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; if (IdentifierStr == "def") return tok_def; if (IdentifierStr == "extern") return tok_extern; return tok_identifier; } if (isdigit(LastChar) || LastChar == '.') { // : [0-9.]+ std::string NumStr; do { NumStr += LastChar; LastChar = getchar(); } while (isdigit(LastChar) || LastChar == '.'); NumVal = strtod(NumStr.c_str(), 0); return tok_number; } if (LastChar == '#') { //     do LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); if (LastChar != EOF) return gettok(); } //   . if (LastChar == EOF) return tok_eof; //         ASCII int ThisChar = LastChar; LastChar = getchar(); return ThisChar; } //===----------------------------------------------------------------------===// // Abstract Syntax Tree (     ) //===----------------------------------------------------------------------===// /// ExprAST -      . class ExprAST { public: virtual ~ExprAST() {} virtual Value *Codegen() = 0; }; /// NumberExprAST -       (, "1.0"). class NumberExprAST : public ExprAST { double Val; public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); }; /// VariableExprAST -      (, "a"). class VariableExprAST : public ExprAST { std::string Name; public: VariableExprAST(const std::string &name) : Name(name) {} virtual Value *Codegen(); }; /// BinaryExprAST -      . class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; public: BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST -      . class CallExprAST : public ExprAST { std::string Callee; std::vector<ExprAST*> Args; public: CallExprAST(const std::string &callee, std::vector<ExprAST*> &args) : Callee(callee), Args(args) {} virtual Value *Codegen(); }; /// PrototypeAST -    ""  , ///        (,  , ///    ). class PrototypeAST { std::string Name; std::vector<std::string> Args; public: PrototypeAST(const std::string &name, const std::vector<std::string> &args) : Name(name), Args(args) {} Function *Codegen(); }; /// FunctionAST -     class FunctionAST { PrototypeAST *Proto; ExprAST *Body; public: FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} Function *Codegen(); }; //===----------------------------------------------------------------------===// // Parser (   ) //===----------------------------------------------------------------------===// /// CurTok/getNextToken -    . CurTok -   /// ,  . getNextToken     ///     CurTok. static int CurTok; static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence -      static std::map<char, int> BinopPrecedence; /// GetTokPrecedence -     . static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; // ,     . int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; return TokPrec; } /// Error* -       . ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } static ExprAST *ParseExpression(); /// identifierexpr /// ::= identifier /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; getNextToken(); //  . if (CurTok != '(') //  . return new VariableExprAST(IdName); //  . getNextToken(); //  ( std::vector<ExprAST*> Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); if (!Arg) return 0; Args.push_back(Arg); if (CurTok == ')') break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); getNextToken(); } } //  ')'. getNextToken(); return new CallExprAST(IdName, Args); } /// numberexpr ::= number static ExprAST *ParseNumberExpr() { ExprAST *Result = new NumberExprAST(NumVal); getNextToken(); //   return Result; } /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { getNextToken(); //  (. ExprAST *V = ParseExpression(); if (!V) return 0; if (CurTok != ')') return Error("expected ')'"); getNextToken(); //  ). return V; } /// primary /// ::= identifierexpr /// ::= numberexpr /// ::= parenexpr static ExprAST *ParsePrimary() { switch (CurTok) { default: return Error("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: return ParseNumberExpr(); case '(': return ParseParenExpr(); } } /// binoprhs /// ::= ('+' primary)* static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { //    ,    while (1) { int TokPrec = GetTokPrecedence(); //           , //  ,    if (TokPrec < ExprPrec) return LHS; // ,  ,    . int BinOp = CurTok; getNextToken(); // eat binop //       ExprAST *RHS = ParsePrimary(); if (!RHS) return 0; //  BinOp   RHS  ,    RHS, //      RHS  LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { RHS = ParseBinOpRHS(TokPrec+1, RHS); if (RHS == 0) return 0; } //  LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } } /// expression /// ::= primary binoprhs /// static ExprAST *ParseExpression() { ExprAST *LHS = ParsePrimary(); if (!LHS) return 0; return ParseBinOpRHS(0, LHS); } /// prototype /// ::= id '(' id* ')' static PrototypeAST *ParsePrototype() { if (CurTok != tok_identifier) return ErrorP("Expected function name in prototype"); std::string FnName = IdentifierStr; getNextToken(); if (CurTok != '(') return ErrorP("Expected '(' in prototype"); //    . std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); //  . getNextToken(); //  ')'. return new PrototypeAST(FnName, ArgNames); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { getNextToken(); //  def. PrototypeAST *Proto = ParsePrototype(); if (Proto == 0) return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); return 0; } /// toplevelexpr ::= expression static FunctionAST *ParseTopLevelExpr() { if (ExprAST *E = ParseExpression()) { //   . PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>()); return new FunctionAST(Proto, E); } return 0; } /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { getNextToken(); //  extern. return ParsePrototype(); } //===----------------------------------------------------------------------===// // Code Generation () //===----------------------------------------------------------------------===// static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); static std::map<std::string, Value*> NamedValues; static FunctionPassManager *TheFPM; Value *ErrorV(const char *Str) { Error(Str); return 0; } Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); } Value *VariableExprAST::Codegen() { //      . Value *V = NamedValues[Name]; return V ? V : ErrorV("Unknown variable name"); } Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); if (L == 0 || R == 0) return 0; switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); case '*': return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); //   0  1   0.0  1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); default: return ErrorV("invalid binary operator"); } } Value *CallExprAST::Codegen() { //      . Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); //    . if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); std::vector<Value*> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); if (ArgsV.back() == 0) return 0; } return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp"); } Function *PrototypeAST::Codegen() { //   : double(double,double)  .. std::vector<const Type*> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); //   (F)     ,     'Name'. //     ,      . if (F->getName() != Name) { //   ,      . F->eraseFromParent(); F = TheModule->getFunction(Name); //   (F)   , . if (!F->empty()) { ErrorF("redefinition of function"); return 0; } //   (F)    , . if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } //     . unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); //      . NamedValues[Args[Idx]] = AI; } return F; } Function *FunctionAST::Codegen() { NamedValues.clear(); Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; //      . BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); if (Value *RetVal = Body->Codegen()) { //  . Builder.CreateRet(RetVal); //   ,    (). verifyFunction(*TheFunction); //  . TheFPM->run(*TheFunction); return TheFunction; } //  ,   . TheFunction->eraseFromParent(); return 0; } //===----------------------------------------------------------------------===// // Top-Level parsing (  )   JIT //===----------------------------------------------------------------------===// static ExecutionEngine *TheExecutionEngine; static void HandleDefinition() { if (FunctionAST *F = ParseDefinition()) { if (Function *LF = F->Codegen()) { fprintf(stderr, "Read function definition:"); LF->dump(); } } else { //      . getNextToken(); } } static void HandleExtern() { if (PrototypeAST *P = ParseExtern()) { if (Function *F = P->Codegen()) { fprintf(stderr, "Read extern: "); F->dump(); } } else { //      . getNextToken(); } } static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { // JIT-,   . void *FPtr = TheExecutionEngine->getPointerToFunction(LF); //     ( ,  double), //       . double (*FP)() = (double (*)())(intptr_t)FPtr; fprintf(stderr, "Evaluated to %f\n", FP()); } } else { //      . getNextToken(); } } /// top ::= definition | external | expression | ';' static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { case tok_eof: return; case ';': getNextToken(); break; //     . case tok_def: HandleDefinition(); break; case tok_extern: HandleExtern(); break; default: HandleTopLevelExpression(); break; } } } //===----------------------------------------------------------------------===// // "" ,     //   ("extern")   . //===----------------------------------------------------------------------===// /// putchard -        0. extern "C" double putchard(double X) { putchar((char)X); return 0; } //===----------------------------------------------------------------------===// // Main driver code (  ) //===----------------------------------------------------------------------===// int main() { InitializeNativeTarget(); LLVMContext &Context = getGlobalContext(); //    . // 1 -  . BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; BinopPrecedence['*'] = 40; //  . fprintf(stderr, "ready> "); getNextToken(); //  ,     . TheModule = new Module("my cool jit", Context); //  JIT.     . std::string ErrStr; TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } FunctionPassManager OurFPM(TheModule); //   .     ,  //       . OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData())); //   AliasAnalysis  GVN. OurFPM.add(createBasicAliasAnalysisPass()); //   "peephole"  "bit-twiddling". OurFPM.add(createInstructionCombiningPass()); //  . OurFPM.add(createReassociatePass()); //   . OurFPM.add(createGVNPass()); //     (    ..). OurFPM.add(createCFGSimplificationPass()); OurFPM.doInitialization(); //   ,     . TheFPM = &OurFPM; //    " ". MainLoop(); TheFPM = 0; //   . TheModule->dump(); return 0; } 


PS , :

Source: https://habr.com/ru/post/In120516/


All Articles