1- #include " ../../include/backend_llvm.h"
2- #include < llvm/IR/IRBuilder.h>
3- #include < llvm/IR/LLVMContext.h>
4- #include < llvm/IR/Module.h>
5- #include < llvm/IR/Verifier.h>
1+ #include " ../../include/object.h"
62#include < vector>
73#include < map>
84#include < iostream>
95
10- using namespace llvm ;
6+ // Do NOT use 'using namespace llvm;' due to clash with our 'Value' type.
7+
118
129class LLVMEmitter {
13- std::unique_ptr<LLVMContext> Context;
14- std::unique_ptr<Module> ModuleOb;
15- std::unique_ptr<IRBuilder<>> Builder;
16- std::map<IRBasicBlock*, BasicBlock*> blockMap;
17- std::vector<Value*> ssaValues;
10+ std::unique_ptr<llvm:: LLVMContext> Context;
11+ std::unique_ptr<llvm:: Module> ModuleOb;
12+ std::unique_ptr<llvm:: IRBuilder<>> Builder;
13+ std::map<IRBasicBlock*, llvm:: BasicBlock*> blockMap;
14+ std::vector<llvm:: Value*> ssaValues;
1815
1916public:
2017 LLVMEmitter () {
21- Context = std::make_unique<LLVMContext>();
22- ModuleOb = std::make_unique<Module>(" ProXPL Module" , *Context);
23- Builder = std::make_unique<IRBuilder<>>(*Context);
18+ Context = std::make_unique<llvm:: LLVMContext>();
19+ ModuleOb = std::make_unique<llvm:: Module>(" ProXPL Module" , *Context);
20+ Builder = std::make_unique<llvm:: IRBuilder<>>(*Context);
2421
2522 setupRuntimeTypes ();
2623 }
2724
2825 void setupRuntimeTypes () {
29- // Declare extern "C" functions from llvm_runtime.c
30-
3126 // Value prox_rt_add(Value a, Value b);
32- FunctionType *BinOpType = FunctionType::get (
27+ llvm:: FunctionType *BinOpType = llvm:: FunctionType::get (
3328 Builder->getInt64Ty (),
3429 {Builder->getInt64Ty (), Builder->getInt64Ty ()},
3530 false
3631 );
37- Function::Create (BinOpType, Function::ExternalLinkage, " prox_rt_add" , ModuleOb.get ());
32+ llvm:: Function::Create (BinOpType, llvm:: Function::ExternalLinkage, " prox_rt_add" , ModuleOb.get ());
3833
3934 // void prox_rt_print(Value v);
40- FunctionType *PrintType = FunctionType::get (
35+ llvm:: FunctionType *PrintType = llvm:: FunctionType::get (
4136 Builder->getVoidTy (),
4237 {Builder->getInt64Ty ()},
4338 false
4439 );
45- Function::Create (PrintType, Function::ExternalLinkage, " prox_rt_print" , ModuleOb.get ());
40+ llvm:: Function::Create (PrintType, llvm:: Function::ExternalLinkage, " prox_rt_print" , ModuleOb.get ());
4641
4742 // Value prox_rt_const_string(char* chars, int length);
48- FunctionType *ConstStrType = FunctionType::get (
43+ llvm:: FunctionType *ConstStrType = llvm:: FunctionType::get (
4944 Builder->getInt64Ty (),
5045 {Builder->getInt8PtrTy (), Builder->getInt32Ty ()},
5146 false
5247 );
53- Function::Create (ConstStrType, Function::ExternalLinkage, " prox_rt_const_string" , ModuleOb.get ());
48+ llvm:: Function::Create (ConstStrType, llvm:: Function::ExternalLinkage, " prox_rt_const_string" , ModuleOb.get ());
5449 }
5550
5651 void emitModule (IRModule* module ) {
5752 for (int i = 0 ; i < module ->funcCount ; i++) {
5853 emitFunction (module ->functions [i]);
5954 }
60- ModuleOb->print (outs (), nullptr );
55+ ModuleOb->print (llvm:: outs (), nullptr );
6156 }
6257
6358 void emitFunction (IRFunction* func) {
6459 // All functions return Value (Int64)
65- FunctionType *FT = FunctionType::get (Builder->getInt64Ty (), false );
66- Function *F = Function::Create (FT, Function::ExternalLinkage, func->name , ModuleOb.get ());
60+ llvm:: FunctionType *FT = llvm:: FunctionType::get (Builder->getInt64Ty (), false );
61+ llvm:: Function *F = llvm:: Function::Create (FT, llvm:: Function::ExternalLinkage, func->name , ModuleOb.get ());
6762
6863 ssaValues.clear ();
6964 ssaValues.resize (func->nextSsaVal + 2048 , nullptr );
@@ -73,13 +68,13 @@ class LLVMEmitter {
7368 for (int i = 0 ; i < func->blockCount ; i++) {
7469 char name[64 ];
7570 sprintf (name, " block%d" , func->blocks [i]->id );
76- blockMap[func->blocks [i]] = BasicBlock::Create (*Context, name, F);
71+ blockMap[func->blocks [i]] = llvm:: BasicBlock::Create (*Context, name, F);
7772 }
7873
7974 // Pass 2: Emit instructions (except Phi operands)
8075 for (int i = 0 ; i < func->blockCount ; i++) {
8176 IRBasicBlock* irBlock = func->blocks [i];
82- BasicBlock* llvmBlock = blockMap[irBlock];
77+ llvm:: BasicBlock* llvmBlock = blockMap[irBlock];
8378 Builder->SetInsertPoint (llvmBlock);
8479
8580 IRInstruction* instr = irBlock->first ;
@@ -94,10 +89,10 @@ class LLVMEmitter {
9489 IRInstruction* instr = func->blocks [i]->first ;
9590 while (instr) {
9691 if (instr->opcode == IR_OP_PHI) {
97- PHINode* phi = cast<PHINode>(ssaValues[instr->result ]);
92+ llvm:: PHINode* phi = llvm:: cast<llvm:: PHINode>(ssaValues[instr->result ]);
9893 for (int k = 0 ; k < instr->operandCount ; k += 2 ) {
99- Value* val = getOperand (instr->operands [k]);
100- BasicBlock* incomingBB = blockMap[instr->operands [k+1 ].as .block ];
94+ llvm:: Value* val = getOperand (instr->operands [k]);
95+ llvm:: BasicBlock* incomingBB = blockMap[instr->operands [k+1 ].as .block ];
10196 if (val && incomingBB) {
10297 phi->addIncoming (val, incomingBB);
10398 }
@@ -112,40 +107,40 @@ class LLVMEmitter {
112107 Builder->SetInsertPoint (&F->back ());
113108 // Return NIL (0x7ffc000000000001)
114109 uint64_t nilVal = 0x7ffc000000000001 ;
115- Builder->CreateRet (ConstantInt::get (*Context, APInt (64 , nilVal, false )));
110+ Builder->CreateRet (llvm:: ConstantInt::get (*Context, llvm:: APInt (64 , nilVal, false )));
116111 }
117112
118113 // Verify function
119114 std::string err;
120- raw_string_ostream os (err);
121- if (verifyFunction (*F, &os)) {
115+ llvm:: raw_string_ostream os (err);
116+ if (llvm:: verifyFunction (*F, &os)) {
122117 std::cerr << " LLVM Verification Error: " << os.str () << " \n " ;
123118 }
124119 }
125120
126121 void emitInstruction (IRInstruction* instr) {
127122 switch (instr->opcode ) {
128123 case IR_OP_CONST: {
129- Value* v = nullptr ;
124+ llvm:: Value* v = nullptr ;
130125 if (IS_NUMBER (instr->operands [0 ].as .constant )) {
131126 // Just a double encoded as int64
132127 double num = AS_NUMBER (instr->operands [0 ].as .constant );
133128 uint64_t bits;
134129 memcpy (&bits, &num, sizeof (double ));
135- v = ConstantInt::get (*Context, APInt (64 , bits, false ));
130+ v = llvm:: ConstantInt::get (*Context, llvm:: APInt (64 , bits, false ));
136131 } else if (IS_STRING (instr->operands [0 ].as .constant )) {
137132 // Define global string constant
138133 ObjString* strObj = AS_STRING (instr->operands [0 ].as .constant );
139- Constant *StrConstant = ConstantDataArray::getString (*Context, strObj->chars );
140- GlobalVariable *ValidStr = new GlobalVariable (*ModuleOb, StrConstant->getType (), true ,
141- GlobalValue::PrivateLinkage, StrConstant, " .str" );
134+ llvm:: Constant *StrConstant = llvm:: ConstantDataArray::getString (*Context, strObj->chars );
135+ llvm:: GlobalVariable *ValidStr = new llvm:: GlobalVariable (*ModuleOb, StrConstant->getType (), true ,
136+ llvm:: GlobalValue::PrivateLinkage, StrConstant, " .str" );
142137
143138 // Call runtime to create ObjString
144- Function *AllocFunc = ModuleOb->getFunction (" prox_rt_const_string" );
145- Value* Zero = Builder->getInt32 (0 );
146- Value* Args[] = { Zero, Zero };
139+ llvm:: Function *AllocFunc = ModuleOb->getFunction (" prox_rt_const_string" );
140+ llvm:: Value* Zero = Builder->getInt32 (0 );
141+ llvm:: Value* Args[] = { Zero, Zero };
147142 // GEP to get pointer to char array
148- Value* StrPtr = Builder->CreateInBoundsGEP (StrConstant->getType (), ValidStr, Args);
143+ llvm:: Value* StrPtr = Builder->CreateInBoundsGEP (StrConstant->getType (), ValidStr, Args);
149144
150145 v = Builder->CreateCall (AllocFunc, {
151146 StrPtr,
@@ -156,9 +151,9 @@ class LLVMEmitter {
156151 break ;
157152 }
158153 case IR_OP_ADD: {
159- Value* L = getOperand (instr->operands [0 ]);
160- Value* R = getOperand (instr->operands [1 ]);
161- Function *AddFunc = ModuleOb->getFunction (" prox_rt_add" );
154+ llvm:: Value* L = getOperand (instr->operands [0 ]);
155+ llvm:: Value* R = getOperand (instr->operands [1 ]);
156+ llvm:: Function *AddFunc = ModuleOb->getFunction (" prox_rt_add" );
162157 if (L && R && AddFunc) ssaValues[instr->result ] = Builder->CreateCall (AddFunc, {L, R}, " addtmp" );
163158 break ;
164159 }
@@ -169,30 +164,13 @@ class LLVMEmitter {
169164 break ;
170165 }
171166 case IR_OP_JUMP_IF: {
172- Value* Cond = getOperand (instr->operands [0 ]);
173- BasicBlock* Then = blockMap[instr->operands [1 ].as .block ];
174- BasicBlock* Else = blockMap[instr->operands [2 ].as .block ];
175-
176- // Compare Cond != FALSE (simplified); really should check for non-false/non-nil
177- // For now assuming Cond is a boolean-like Value
178- // Note: In Nan-boxing, False is specific tag.
179- // We'll simplify and check if (Cond & ~TAG_MASK) != 0 for now or just check explicit False?
180- // For this iteration, let's assume we optimized bools to i1 in IR or strict checking.
181- // Actually, if everything is i64, we need to compare against encoded False.
182-
183- // Hack: Compare against 0 for testing if we used 0 for false in simple tests?
184- // But we are using full values.
185- // Let's rely on truthiness: != False && != Nil
186- // For MVP: Compare != encoded FALSE.
187-
188- // uint64_t falseVal = 0x7ffc000000000002; // TAG_FALSE = 2
189- // Value* FalseC = ConstantInt::get(*Context, APInt(64, falseVal, false));
190- // Value* isFalse = Builder->CreateICmpEQ(Cond, FalseC, "isfalse");
191- // Builder->CreateCondBr(isFalse, Else, Then); // Swap branches
167+ llvm::Value* Cond = getOperand (instr->operands [0 ]);
168+ llvm::BasicBlock* Then = blockMap[instr->operands [1 ].as .block ];
169+ llvm::BasicBlock* Else = blockMap[instr->operands [2 ].as .block ];
192170
193171 // Temporary: Treat 0 as false (legacy behavior until full type lowering)
194172 if (Cond) {
195- Value* boolCond = Builder->CreateICmpNE (Cond, ConstantInt::get (*Context, APInt (64 , 0 )), " ifcond" );
173+ llvm:: Value* boolCond = Builder->CreateICmpNE (Cond, llvm:: ConstantInt::get (*Context, llvm:: APInt (64 , 0 )), " ifcond" );
196174 Builder->CreateCondBr (boolCond, Then, Else);
197175 }
198176 break ;
@@ -202,11 +180,11 @@ class LLVMEmitter {
202180 break ;
203181 }
204182 case IR_OP_RETURN: {
205- Value* V = getOperand (instr->operands [0 ]);
183+ llvm:: Value* V = getOperand (instr->operands [0 ]);
206184 // Default return NIL
207185 if (!V) {
208186 uint64_t nilVal = 0x7ffc000000000001 ;
209- V = ConstantInt::get (*Context, APInt (64 , nilVal, false ));
187+ V = llvm:: ConstantInt::get (*Context, llvm:: APInt (64 , nilVal, false ));
210188 }
211189 Builder->CreateRet (V);
212190 break ;
@@ -216,14 +194,14 @@ class LLVMEmitter {
216194 }
217195 }
218196
219- Value* getOperand (IROperand& op) {
197+ llvm:: Value* getOperand (IROperand& op) {
220198 if (op.type == OPERAND_CONST) {
221199 if (IS_NUMBER (op.as .constant )) {
222200 // Return int64 representation of double
223201 double num = AS_NUMBER (op.as .constant );
224202 uint64_t bits;
225203 memcpy (&bits, &num, sizeof (double ));
226- return ConstantInt::get (*Context, APInt (64 , bits, false ));
204+ return llvm:: ConstantInt::get (*Context, llvm:: APInt (64 , bits, false ));
227205 }
228206 // Other constants?
229207 return nullptr ;
0 commit comments