我正在執行使用LLVM的無類型編程語言來生成後端代碼。爲了跟蹤當前類型的特定變量的我使用一個結構StructTy_struct_datatype_t
其定義爲:LLVM:如何跟蹤無類型語言的運行時Value *的數據類型?
PointerTy_8 = PointerType::get(IntegerType::get(TheContext, 8), 0);
StructTy_struct_datatype_t = StructType::create(TheContext, "struct.datatype_t");
std::vector<Type *> StructTy_struct_datatype_t_fields;
StructTy_struct_datatype_t_fields.push_back(IntegerType::get(TheContext, 32));
StructTy_struct_datatype_t_fields.push_back(PointerTy_8);
// which represents the struct
typedef struct datatype_t {
int type; // holds an integer that tells me the type (1 = int, 2 = float, ...)
void* v; // holds a pointer to the actual value
} datatype_t;
然後,假設我有一個這樣
def function_add(a, b) {
return a + b;
}
我想要的功能該功能能夠接受
function_add(1, 1); // returns 2; (int)
function_add(1.0, 1.0); // returns 2.0 (float)
function_add("str1", "str2"); // returns "str1str2" (string)
處理該二進制運算即代碼。 a + b
如下
Value* L = lhs_codegen_elements.back();
Value* R = rhs_codegen_elements.back();
if (!L || !R) {
logError("L or R are undefined");
return codegen;
}
AllocaInst* lptr_datatype = (AllocaInst*)((LoadInst*)L)->getPointerOperand();
AllocaInst* rptr_datatype = (AllocaInst*)((LoadInst*)R)->getPointerOperand();
ConstantInt* const_int32_0 = ConstantInt::get(TheContext, APInt(32, StringRef("0"), 10));
ConstantInt* const_int32_1 = ConstantInt::get(TheContext, APInt(32, StringRef("1"), 10));
GetElementPtrInst* lptr_type =
GetElementPtrInst::Create(StructTy_struct_datatype_t, lptr_datatype, {const_int32_0, const_int32_0}, "type");
GetElementPtrInst* rptr_type =
GetElementPtrInst::Create(StructTy_struct_datatype_t, rptr_datatype, {const_int32_0, const_int32_0}, "type");
GetElementPtrInst* lptr_v =
GetElementPtrInst::Create(StructTy_struct_datatype_t, lptr_datatype, {const_int32_0, const_int32_1}, "v");
GetElementPtrInst* rptr_v =
GetElementPtrInst::Create(StructTy_struct_datatype_t, rptr_datatype, {const_int32_0, const_int32_1}, "v");
LoadInst* lload_inst_type = load_inst_codegen(TYPE_INT, lptr_type);
LoadInst* rload_inst_type = load_inst_codegen(TYPE_INT, rptr_type);
LoadInst* lload_inst_v = load_inst_codegen(TYPE_VOID_POINTER, lptr_v);
LoadInst* rload_inst_v = load_inst_codegen(TYPE_VOID_POINTER, rptr_v);
CmpInst* cond1 =
new ICmpInst(ICmpInst::ICMP_EQ, lload_inst_type, ConstantInt::get(TheContext, APInt(32, TYPE_DOUBLE)));
Function* function_bb = dyn_cast<Function>(bb);
BasicBlock* label_if_then_double = BasicBlock::Create(TheContext, "if.then.double", function_bb);
BasicBlock* label_if_then_long = BasicBlock::Create(TheContext, "if.then.long", function_bb);
BranchInst* branch_inst = BranchInst::Create(label_if_then_double, label_if_else, cond1, bb);
L->dump(); // %load_inst = load %struct.datatype_t, %struct.datatype_t* %alloca_datatype_v, align 8
R->dump(); // %load_inst = load %struct.datatype_t, %struct.datatype_t* %alloca_datatype_v1, align 8
L->getType()->dump(); // %struct.datatype_t = type { i32, i8* }
R->getType()->dump(); // %struct.datatype_t = type { i32, i8* }
lload_inst_type->dump(); // %load_inst = load i32, i32* %type, align 4
rload_inst_type->dump(); // %load_inst = load i32, i32* %type, align 4
lload_inst_v->dump(); // %load_inst = load i8*, i8** %v, align 8
rload_inst_v->dump(); // %load_inst = load i8*, i8** %v, align 8
if (op == '+') {
// issue: how to take the decision without knowing the type lload_inst_v holds
BinaryOperator::Create(Instruction::FAdd, lload_inst_v, rload_inst_v, "add", label_if_then_double);
// or
BinaryOperator::Create(Instruction::Add, lload_inst_v, rload_inst_v, "add", label_if_then_long);
}
所以問題是,我需要知道這是該類型lload_inst_type
和rload_inst_type
保持,這樣我就可以切換從LLVM API BinaryOperator::Create(Instruction::FAdd, ...)
的方法floats
和BinaryOperator::Create(Instruction::Add, ...)
爲ints
,例如。
但是,我剛剛意識到我無法弄清AllocaInst
,LoadInst
在生成後端時的價值(至少我不知道如何去做)。
- 如何在運行時跟蹤
Value*
的數據類型? - 我是否選擇了一種錯誤的策略來實現無類型語言?