static Type* getArgSymbolCodegenType(ArgSymbol* arg) { QualifiedType q = arg->qualType(); Type* useType = q.type(); if (q.isRef() && !q.isRefType()) useType = getOrMakeRefTypeDuringCodegen(useType); if (q.isWideRef() && !q.isWideRefType()) { Type* refType = getOrMakeRefTypeDuringCodegen(useType); useType = getOrMakeWideTypeDuringCodegen(refType); } return useType; }
GenRet ArgSymbol::codegen() { GenInfo* info = gGenInfo; FILE* outfile = info->cfile; GenRet ret; if( outfile ) { QualifiedType qt = qualType(); ret.c = '&'; ret.c += cname; ret.isLVPtr = GEN_PTR; if (qt.isRef() && !qt.isRefType()) ret.chplType = getOrMakeRefTypeDuringCodegen(typeInfo()); else if (qt.isWideRef() && !qt.isWideRefType()) { Type* refType = getOrMakeRefTypeDuringCodegen(typeInfo()); ret.chplType = getOrMakeWideTypeDuringCodegen(refType); } /* // BHARSH TODO: Is this still necessary? if (q.isRef() && !q.isRefType()) { ret.c = cname; ret.isLVPtr = GEN_PTR; } else if(q.isWideRef() && !q.isWideRefType()) { ret.c = cname; ret.isLVPtr = GEN_WIDE_PTR; } else { ret.c = '&'; ret.c += cname; ret.isLVPtr = GEN_PTR; } */ } else { #ifdef HAVE_LLVM ret = info->lvt->getValue(cname); #endif } // BHARSH TODO: Is this still necessary? //if( requiresCPtr() ) { // // Don't try to use chplType. // ret.chplType = NULL; // ret = codegenLocalDeref(ret); //} //ret.chplType = this->type; return ret; }
void VarSymbol::codegenDefC(bool global, bool isHeader) { GenInfo* info = gGenInfo; if (this->hasFlag(FLAG_EXTERN)) return; if (type == dtVoid) return; AggregateType* ct = toAggregateType(type); QualifiedType qt = qualType(); if (qt.isRef() && !qt.isRefType()) { Type* refType = getOrMakeRefTypeDuringCodegen(type); ct = toAggregateType(refType); } if (qt.isWideRef() && !qt.isWideRefType()) { Type* refType = getOrMakeRefTypeDuringCodegen(type); Type* wideType = getOrMakeWideTypeDuringCodegen(refType); ct = toAggregateType(wideType); } Type* useType = type; if (ct) useType = ct; std::string typestr = (this->hasFlag(FLAG_SUPER_CLASS) ? std::string(toAggregateType(useType)->classStructName(true)) : useType->codegen().c); // // a variable can be codegen'd as static if it is global and neither // exported nor external. // std::string str; if(fIncrementalCompilation) { bool addExtern = global && isHeader; str = (addExtern ? "extern " : "") + typestr + " " + cname; } else { bool isStatic = global && !hasFlag(FLAG_EXPORT) && !hasFlag(FLAG_EXTERN); str = (isStatic ? "static " : "") + typestr + " " + cname; } if (ct) { if (ct->isClass()) { if (isFnSymbol(defPoint->parentSymbol)) { str += " = NULL"; } } else if (ct->symbol->hasFlag(FLAG_WIDE_REF) || ct->symbol->hasFlag(FLAG_WIDE_CLASS)) { if (isFnSymbol(defPoint->parentSymbol)) { if (widePointersStruct) { // // CHPL_LOCALEID_T_INIT is #defined in the chpl-locale-model.h // file in the runtime, for the selected locale model. // str += " = {CHPL_LOCALEID_T_INIT, NULL}"; } else { str += " = ((wide_ptr_t) NULL)"; } } } } if (fGenIDS) str = idCommentTemp(this) + str; if (printCppLineno && !isHeader && !isTypeSymbol(defPoint->parentSymbol)) str = zlineToString(this) + str; info->cLocalDecls.push_back(str); }
GenRet VarSymbol::codegenVarSymbol(bool lhsInSetReference) { GenInfo* info = gGenInfo; FILE* outfile = info->cfile; GenRet ret; ret.chplType = typeInfo(); if( outfile ) { // dtString immediates don't actually codegen as immediates, we just use // them for param string functionality. if (immediate && ret.chplType != dtString) { ret.isLVPtr = GEN_VAL; if (immediate->const_kind == CONST_KIND_STRING) { ret.c += '"'; ret.c += immediate->v_string; ret.c += '"'; } else if (immediate->const_kind == NUM_KIND_BOOL) { std::string bstring = (immediate->bool_value())?"true":"false"; const char* castString = "("; switch (immediate->num_index) { case BOOL_SIZE_1: case BOOL_SIZE_SYS: case BOOL_SIZE_8: castString = "UINT8("; break; case BOOL_SIZE_16: castString = "UINT16("; break; case BOOL_SIZE_32: castString = "UINT32("; break; case BOOL_SIZE_64: castString = "UINT64("; break; default: INT_FATAL("Unexpected immediate->num_index: %d\n", immediate->num_index); } ret.c = castString + bstring + ")"; } else if (immediate->const_kind == NUM_KIND_INT) { int64_t iconst = immediate->int_value(); if (iconst == (1ll<<63)) { ret.c = "-INT64(9223372036854775807) - INT64(1)"; } else if (iconst <= -2147483648ll || iconst >= 2147483647ll) { ret.c = "INT64(" + int64_to_string(iconst) + ")"; } else { const char* castString = "("; switch (immediate->num_index) { case INT_SIZE_8: castString = "INT8("; break; case INT_SIZE_16: castString = "INT16("; break; case INT_SIZE_32: castString = "INT32("; break; case INT_SIZE_64: castString = "INT64("; break; default: INT_FATAL("Unexpected immediate->num_index: %d\n", immediate->num_index); } ret.c = castString + int64_to_string(iconst) + ")"; } } else if (immediate->const_kind == NUM_KIND_UINT) { uint64_t uconst = immediate->uint_value(); if( uconst <= (uint64_t) INT32_MAX ) { const char* castString = "("; switch (immediate->num_index) { case INT_SIZE_8: castString = "UINT8("; break; case INT_SIZE_16: castString = "UINT16("; break; case INT_SIZE_32: castString = "UINT32("; break; case INT_SIZE_64: castString = "UINT64("; break; default: INT_FATAL("Unexpected immediate->num_index: %d\n", immediate->num_index); } ret.c = castString + uint64_to_string(uconst) + ")"; } else { ret.c = "UINT64(" + uint64_to_string(uconst) + ")"; } } else { ret.c = cname; // in C, all floating point literals are (double) } } else { // not immediate // is it a constant extern? If it is, it might be for example // an enum or #define'd value, in which case taking the address // of it is simply nonsense. Therefore, we code generate // extern const symbols as GEN_VAL (ie not an lvalue). if( hasFlag(FLAG_CONST) && hasFlag(FLAG_EXTERN) ) { ret.isLVPtr = GEN_VAL; ret.c = cname; } else { QualifiedType qt = qualType(); if (lhsInSetReference) { ret.c = '&'; ret.c += cname; ret.isLVPtr = GEN_PTR; if (qt.isRef() && !qt.isRefType()) ret.chplType = getOrMakeRefTypeDuringCodegen(typeInfo()); else if (qt.isWideRef() && !qt.isWideRefType()) { Type* refType = getOrMakeRefTypeDuringCodegen(typeInfo()); ret.chplType = getOrMakeWideTypeDuringCodegen(refType); } } else { if (qt.isRef() && !qt.isRefType()) { ret.c = cname; ret.isLVPtr = GEN_PTR; } else if(qt.isWideRef() && !qt.isWideRefType()) { ret.c = cname; ret.isLVPtr = GEN_WIDE_PTR; } else { ret.c = '&'; ret.c += cname; ret.isLVPtr = GEN_PTR; } } } // Print string contents in a comment if developer mode // and savec is set. if (developer && 0 != strcmp(saveCDir, "") && immediate && ret.chplType == dtString && immediate->const_kind == CONST_KIND_STRING) { if (strstr(immediate->v_string, "/*") || strstr(immediate->v_string, "*/")) { // Don't emit comment b/c string contained comment character. } else { ret.c += " /* \""; ret.c += immediate->v_string; ret.c += "\" */"; } } } return ret; } else { #ifdef HAVE_LLVM // for LLVM // Handle extern type variables. if( hasFlag(FLAG_EXTERN) && isType() ) { // code generate the type. GenRet got = typeInfo(); return got; } // for nil, generate a void pointer of chplType dtNil // to allow LLVM pointer cast // e.g. T = ( (locale) (nil) ); // // We would just compare against dtNil, but in some cases // the code generator needs to assign e.g. // _ret:dtNil = nil if( typeInfo() == dtNil && 0 == strcmp(cname, "nil") ) { GenRet voidPtr; voidPtr.val = llvm::Constant::getNullValue(info->builder->getInt8PtrTy()); voidPtr.chplType = dtNil; return voidPtr; } if (typeInfo() == dtBool){ // since "true" and "false" are read into the LVT during ReadMacrosAction // they will generate an LLVM value of type i32 instead of i8 if (0 == strcmp(cname, "false")){ GenRet boolVal = new_UIntSymbol(0, INT_SIZE_8)->codegen(); return boolVal; } if (0 == strcmp(cname, "true")){ GenRet boolVal = new_UIntSymbol(1, INT_SIZE_8)->codegen(); return boolVal; } } if(!isImmediate()) { // check LVT for value GenRet got = info->lvt->getValue(cname); got.chplType = typeInfo(); if( got.val ) { return got; } } if(isImmediate()) { ret.isLVPtr = GEN_VAL; if(immediate->const_kind == CONST_KIND_STRING) { if(llvm::Value *value = info->module->getNamedGlobal(name)) { ret.val = value; ret.isLVPtr = GEN_PTR; return ret; } llvm::Value *constString = codegenImmediateLLVM(immediate); llvm::GlobalVariable *globalValue = llvm::cast<llvm::GlobalVariable>( info->module->getOrInsertGlobal (name, info->builder->getInt8PtrTy())); globalValue->setConstant(true); globalValue->setInitializer(llvm::cast<llvm::Constant>( info->builder->CreateConstInBoundsGEP2_32( #if HAVE_LLVM_VER >= 37 NULL, #endif constString, 0, 0))); ret.val = globalValue; ret.isLVPtr = GEN_PTR; } else { ret.val = codegenImmediateLLVM(immediate); } return ret; } if(std::string(cname) == "0") { // Chapel compiler should not make these. INT_FATAL(" zero value BOO "); return ret; } else if (std::string(cname) == "NULL") { GenRet voidPtr; voidPtr.val = llvm::Constant::getNullValue(info->builder->getInt8PtrTy()); voidPtr.chplType = typeInfo(); return voidPtr; } #endif } INT_FATAL("Could not code generate %s - " "perhaps it is a complex macro?", cname); return ret; }