Skip to content

Commit

Permalink
Modernize use of LLVM pointer types (#639)
Browse files Browse the repository at this point in the history
  • Loading branch information
elliottslaughter authored Aug 25, 2023
1 parent 389150f commit 8f43bed
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 50 deletions.
107 changes: 61 additions & 46 deletions src/tcompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,15 @@ class Types {
EnsureTypeIsComplete(&objTy);
} // otherwise it is niltype and already complete
}
static void PointsToType(Obj *ptrTy, Obj *result) {
if (ptrTy->kind("kind") == T_pointer) {
ptrTy->obj("type", result);
} else {
printf("unexpected kind = %d, %s\n", ptrTy->kind("kind"),
tkindtostr(ptrTy->kind("kind")));
assert(false);
}
}
};

// helper function to alloca at the beginning of function
Expand All @@ -736,10 +745,9 @@ static AllocaInst *CreateAlloca(IRBuilder<> *B, Type *Ty, Value *ArraySize = 0,
return TmpB.CreateAlloca(Ty, ArraySize, Name);
}

static Value *CreateConstGEP2_32(IRBuilder<> *B, Value *Ptr, unsigned Idx0,
unsigned Idx1) {
return B->CreateConstGEP2_32(Ptr->getType()->getPointerElementType(), Ptr, Idx0,
Idx1);
static Value *CreateConstGEP2_32(IRBuilder<> *B, Value *Ptr, Type *ValueType,
unsigned Idx0, unsigned Idx1) {
return B->CreateConstGEP2_32(ValueType, Ptr, Idx0, Idx1);
}

// functions that handle the details of the x86_64 ABI (this really should be handled by
Expand Down Expand Up @@ -1285,7 +1293,7 @@ struct CCallingConv {
int N = st->getNumElements();
for (int j = 0; j < N; j++) {
Type *elt_type = st->getElementType(j);
EmitEntryAggReg(B, CreateConstGEP2_32(B, dest, 0, j), elt_type, ai);
EmitEntryAggReg(B, CreateConstGEP2_32(B, dest, st, 0, j), elt_type, ai);
}
} else {
B->CreateStore(&*ai, dest);
Expand Down Expand Up @@ -1354,7 +1362,7 @@ struct CCallingConv {
Type *result_type = type;
if (info->returntype.GetNumberOfTypesInParamList() == 1) {
do {
result = CreateConstGEP2_32(B, result, 0, 0);
result = CreateConstGEP2_32(B, result, type, 0, 0);
result_type = type->getElementType(0);
} while ((type = dyn_cast<StructType>(result_type)));
}
Expand All @@ -1378,12 +1386,11 @@ struct CCallingConv {
int N = st->getNumElements();
for (int j = 0; j < N; j++) {
Type *elt_type = st->getElementType(j);
EmitCallAggReg(B, CreateConstGEP2_32(B, value, 0, j), elt_type,
EmitCallAggReg(B, CreateConstGEP2_32(B, value, st, 0, j), elt_type,
arguments);
}
} else {
arguments.push_back(
B->CreateLoad(value->getType()->getPointerElementType(), value));
arguments.push_back(B->CreateLoad(param_type, value));
}
}

Expand Down Expand Up @@ -1454,7 +1461,7 @@ struct CCallingConv {
Value *casted = B->CreateBitCast(aggregate, Ptr(type, as));
if (info.returntype.GetNumberOfTypesInParamList() == 1) {
do {
casted = CreateConstGEP2_32(B, casted, 0, 0);
casted = CreateConstGEP2_32(B, casted, type, 0, 0);
} while ((type = dyn_cast<StructType>(type->getElementType(0))));
}
if (info.returntype.GetNumberOfTypesInParamList() > 0)
Expand All @@ -1468,8 +1475,7 @@ struct CCallingConv {
} else {
assert(!"unhandled argument kind");
}
return B->CreateLoad(aggregate->getType()->getPointerElementType(),
aggregate);
return B->CreateLoad(info.returntype.type->type, aggregate);
}
}
void GatherArgumentsAggReg(Type *type, std::vector<Type *> &arguments) {
Expand Down Expand Up @@ -2158,24 +2164,28 @@ struct FunctionEmitter {
ttype.issigned = ftype->issigned;
return emitPrimitiveCast(ftype, &ttype, number);
}
Value *emitPointerArith(T_Kind kind, Value *pointer, TType *numTy, Value *number) {
Value *emitPointerArith(T_Kind kind, Obj *ptrTy, Value *pointer, TType *numTy,
Value *number) {
Obj objTy;
Types::PointsToType(ptrTy, &objTy);

number = emitIndex(numTy, 64, number);
if (kind == T_add) {
return B->CreateGEP(pointer->getType()->getPointerElementType(), pointer,
number);
return B->CreateGEP(getType(&objTy)->type, pointer, number);
} else if (kind == T_sub) {
Value *numNeg = B->CreateNeg(number);
return B->CreateGEP(pointer->getType()->getPointerElementType(), pointer,
numNeg);
return B->CreateGEP(getType(&objTy)->type, pointer, numNeg);
} else {
assert(!"unexpected pointer arith");
return NULL;
}
}
Value *emitPointerSub(TType *t, Value *a, Value *b) {
Value *emitPointerSub(Obj *ptrTy, Value *a, Value *b) {
Obj objTy;
Types::PointsToType(ptrTy, &objTy);
return B->CreatePtrDiff(
#if LLVM_VERSION >= 140
a->getType()->getPointerElementType(),
getType(&objTy)->type,
#endif
a, b);
}
Expand Down Expand Up @@ -2211,10 +2221,10 @@ struct FunctionEmitter {
Ty->EnsurePointsToCompleteType(&aot);
if (bt->type->isPointerTy()) {
assert(kind == T_sub);
return emitPointerSub(t, a, b);
return emitPointerSub(&aot, a, b);
} else {
assert(bt->type->isIntegerTy());
return emitPointerArith(kind, a, bt, b);
return emitPointerArith(kind, &aot, a, bt, b);
}
}

Expand Down Expand Up @@ -2283,8 +2293,9 @@ struct FunctionEmitter {
return 0;
}
Value *emitArrayToPointer(Obj *exp) {
TType *t = typeOfValue(exp);
Value *v = emitAddressOf(exp);
return CreateConstGEP2_32(B, v, 0, 0);
return CreateConstGEP2_32(B, v, t->type, 0, 0);
}
Type *getPrimitiveType(TType *t) {
if (t->type->isVectorTy())
Expand Down Expand Up @@ -2351,7 +2362,8 @@ struct FunctionEmitter {
bool isPointerToFunction(Type *t) {
return t->isPointerTy() && t->getPointerElementType()->isFunctionTy();
}
Value *emitStructSelect(Obj *structType, Value *structPtr, int index) {
Value *emitStructSelect(Obj *structType, Value *structPtr, int index,
Obj *entryType) {
assert(structPtr->getType()->isPointerTy());
assert(structPtr->getType()->getPointerElementType()->isStructTy());
Ty->EnsureTypeIsComplete(structType);
Expand All @@ -2364,7 +2376,8 @@ struct FunctionEmitter {

int allocindex = entry.number("allocation");

Value *addr = CreateConstGEP2_32(B, structPtr, 0, allocindex);
Value *addr = CreateConstGEP2_32(B, structPtr, getType(structType)->type, 0,
allocindex);
// in three cases the type of the value in the struct does not match the expected
// type returned
// 1. if it is a union then the llvm struct will have some buffer space to hold
Expand All @@ -2374,12 +2387,11 @@ struct FunctionEmitter {
// (Terra internal represents functions with i8* for simplicity)
// 3. if the field was an anonymous C struct, so we don't know its name
// in all cases we simply bitcast cast the resulting pointer to the expected type
Obj entryType;
entry.obj("type", &entryType);
if (entry.boolean("inunion") ||
isPointerToFunction(addr->getType()->getPointerElementType())) {
entry.obj("type", entryType);
TType *entryTType = getType(entryType);
if (entry.boolean("inunion") || isPointerToFunction(entryTType->type)) {
unsigned as = addr->getType()->getPointerAddressSpace();
Type *resultType = PointerType::get(getType(&entryType)->type, as);
Type *resultType = PointerType::get(entryTType->type, as);
addr = B->CreateBitCast(addr, resultType);
}

Expand Down Expand Up @@ -2456,7 +2468,7 @@ struct FunctionEmitter {
exp->obj("type", &type);
Ty->EnsureTypeIsComplete(&type);
Type *ttype = getType(&type)->type;
raw = B->CreateLoad(raw->getType()->getPointerElementType(), raw);
raw = B->CreateLoad(ttype, raw);
}
return raw;
}
Expand Down Expand Up @@ -2569,16 +2581,18 @@ struct FunctionEmitter {
Value *result = B->CreateExtractElement(valueExp, idxExp);
return result;
} else {
assert(aggType->type->isPointerTy());
Obj objType;
Types::PointsToType(&aggTypeO, &objType);
TType *objTType = getType(&objType);

idxExp = emitIndex(typeOfValue(&idx), 64, idxExp);
// otherwise we have a pointer access which will use a GEP instruction
std::vector<Value *> idxs;
Ty->EnsurePointsToCompleteType(&aggTypeO);
Value *result =
B->CreateGEP(valueExp->getType()->getPointerElementType(),
valueExp, idxExp);
Value *result = B->CreateGEP(objTType->type, valueExp, idxExp);
if (!exp->boolean("lvalue"))
result = B->CreateLoad(result->getType()->getPointerElementType(),
result);
result = B->CreateLoad(objTType->type, result);
return result;
}
} break;
Expand All @@ -2602,8 +2616,8 @@ struct FunctionEmitter {
}

Obj objType;
type.obj("type", &objType);
if (t->type->getPointerElementType()->isIntegerTy(8)) {
Types::PointsToType(&type, &objType);
if (getType(&objType)->type->isIntegerTy(8)) {
Obj stringvalue;
exp->obj("value", &stringvalue);
Value *str = lookupSymbol<Value>(CU->symbols, &stringvalue);
Expand Down Expand Up @@ -2684,13 +2698,14 @@ struct FunctionEmitter {
Obj value;
entry.obj("value", &value);
int idx = entry.number("index");
Value *oe = emitStructSelect(&to, output, idx);
Obj entryType;
Value *oe = emitStructSelect(&to, output, idx, &entryType);
Value *in = emitExp(
&value); // these expressions will select from the
// structvariable and perform any casts necessary
B->CreateStore(in, oe);
}
return B->CreateLoad(output->getType()->getPointerElementType(), output);
return B->CreateLoad(toT->type, output);
} break;
case T_cast: {
Obj a;
Expand Down Expand Up @@ -2739,11 +2754,11 @@ struct FunctionEmitter {
int offset = exp->number("index");

Value *v = emitAddressOf(&obj);
Value *result = emitStructSelect(&typ, v, offset);
Obj entryType;
Value *result = emitStructSelect(&typ, v, offset, &entryType);
Type *ttype = getType(&typ)->type;
if (!exp->boolean("lvalue"))
result = B->CreateLoad(result->getType()->getPointerElementType(),
result);
result = B->CreateLoad(getType(&entryType)->type, result);
return result;
} break;
case T_constructor:
Expand Down Expand Up @@ -2793,7 +2808,7 @@ struct FunctionEmitter {
Ty->EnsureTypeIsComplete(&type);
Type *ttype = getType(&type)->type;
Value *v = emitExp(&addr);
LoadInst *l = B->CreateLoad(v->getType()->getPointerElementType(), v);
LoadInst *l = B->CreateLoad(ttype, v);
if (attr.hasfield("alignment")) {
int alignment = attr.number("alignment");
l->setAlignment(Align(alignment));
Expand Down Expand Up @@ -3142,10 +3157,10 @@ struct FunctionEmitter {
std::vector<Value *> values;
emitExpressionList(expressions, true, &values);
for (size_t i = 0; i < values.size(); i++) {
Value *addr = CreateConstGEP2_32(B, result, 0, i);
Value *addr = CreateConstGEP2_32(B, result, ttype, 0, i);
B->CreateStore(values[i], addr);
}
return B->CreateLoad(result->getType()->getPointerElementType(), result);
return B->CreateLoad(ttype, result);
}
void emitStmtList(Obj *stmts) {
int NS = stmts->size();
Expand Down Expand Up @@ -3316,7 +3331,7 @@ struct FunctionEmitter {
BasicBlock *cond = createAndInsertBB("forcond");
B->CreateBr(cond);
setInsertBlock(cond);
Value *v = B->CreateLoad(vp->getType()->getPointerElementType(), vp);
Value *v = B->CreateLoad(t->type, vp);
Value *c = B->CreateOr(B->CreateAnd(emitCompare(T_lt, t, v, limitv),
emitCompare(T_gt, t, stepv, zero)),
B->CreateAnd(emitCompare(T_gt, t, v, limitv),
Expand Down
8 changes: 4 additions & 4 deletions src/tllvmutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,10 @@ struct CopyConnectedComponent : public ValueMaterializer {
} else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
GlobalVariable *newGV = dest->getGlobalVariable(GV->getName(), true);
if (!newGV || needsFreshlyNamedConstant(GV, newGV)) {
newGV = new GlobalVariable(
*dest, GV->getType()->getPointerElementType(), GV->isConstant(),
GV->getLinkage(), NULL, GV->getName(), NULL,
GlobalVariable::NotThreadLocal, GV->getType()->getAddressSpace());
newGV = new GlobalVariable(*dest, GV->getValueType(), GV->isConstant(),
GV->getLinkage(), NULL, GV->getName(), NULL,
GlobalVariable::NotThreadLocal,
GV->getType()->getAddressSpace());
newGV->copyAttributesFrom(GV);
// copyAttributesFrom does not copy comdats
newGV->setComdat(GV->getComdat());
Expand Down

0 comments on commit 8f43bed

Please sign in to comment.