construct_ir =
function(node, cmp, helper, types, .targetType = NULL)
{
cat("**CONSTRUCT_IR for", class(node)[1], "\n")
UseMethod("construct_ir")
}
# These two don't look as if they have been changed to R2llvm so probably never invoked.
construct_ir.BranchInst =
function(node, cmp, helper, types, .targetType = NULL) {
# Connect block to its successors.
# FIXME: Check condition on branch instruction.
helper$createBr(node$true)
}
construct_ir.ReturnInst =
function(node, cmp, helper, types, .targetType = NULL) {
# FIXME: What if retval is not a symbol?
alloc = helper$get_alloc(node$value$name)
val = helper$create_load(alloc)
helper$create_ret(val)
}
#########################################################################################################################
# Disable these methods as we migrate them all to compile() methods
if(FALSE) {
construct_ir.Phi =
function(node, cmp, helper, types, .targetType = NULL)
{
#XXXX
# Don't insert phis for shadowed globals.
# if ( any(is_global(node$read)) )
# return (NULL)
phiName = node$write$name
type = types[[node$write$name]]
numIncoming = length(node$blocks)
phi = Rllvm::createPhi(helper, type, numIncoming, id = node$write$name)
# Add the incoming. We have them in the node$blocks and in node$read
# We may not have created all of the incoming values for the phi nodes at this point
# as the order of the CFG may put put creation of the incoming after the Phi node
# into which it comes.
# So we have to make an incomplete Phi node and add its identity and what it is waiting
# for (i.e. the variable in the Assignment) and when we process that we check to see if
# we need to add it to any of the incomplete Phi nodes.
mapply(function(var, block) {
val = cmp$.phiVarInstructions[[ var$name ]]
if(is.null(val)) {
# so the intruction has not been processed yet.
# We create a dummy Value and then arrange to replace
# it with the actual instruction at the end of the module/
# routine construction. This is the purpose of
# the llvm function replaceAllUsesWith()
# This approach is what llvm uses itself when we create
# the c++ API code from a .ll file. i.e., we are copying
# that directly.
val = .Call("R_createFwdRef_for_phi", type)
cmp$.phiForwardRefs[[ var$name ]] = val
}
addIncoming(phi, val, block)
}, node$read, cmp$blocks[node$blocks])
if(node$write$name %in% names(cmp$.phiVarInstructions))
cmp$.phiVarInstructions[[ phiName ]] <- phi
else
cmp$.allocVars[[ phiName ]] <- phi
phi
}
construct_ir.Replacement =
function(node, cmp, helper, types, .targetType = NULL)
{
browser()
e = to_r(node)
var = node$write$basename
if(!( var %in% names(cmp$.params)) )
var = paste0(var, "_1")
e[[2]][[2]] = as.name(var)
return(`compile.=`(e, cmp, helper))
# idx = match(node$fn$name, names(cmp$.compilerHandlers))
# if (is.na(idx))
# compile(node, cmp, helper)
# else
# cmp$.compilerHandlers[[idx]](node, cmp, helper)
}
construct_ir.Symbol =
function(node, cmp, helper, types, .targetType = NULL)
{
v = cmp$getAlloc(node$name)
if(is.null(v)) {
v = cmp$.params[[ node$name ]]
return(v)
}
#XXX Do we only load this if it is an AllocaInst?
if(!is(v, "PHINode"))
helper$createLoad( v )
else
v
}
construct_ir.Assign =
function(node, cmp, helper, types, .targetType = NULL)
{
# For dealing with assignments that are actually for Phi nodes.
if(node$write$name %in% names(cmp$.phiVarInstructions)) {
.targetType = cmp$.types[[node$write$name]]
i = compile(node$read, cmp, helper, .targetType = .targetType)
cmp$.phiVarInstructions[[node$write$name]] = i
return(i)
}
call = asRCall(node)
call=node
return(`compile.=`(call, cmp, helper, .targetType = .targetType))
######
# Allocate memory for RHS.
type = types[[node$write$name]]
lhs = helper$createAlloc(type, id = node$write$name)
cmp$newAlloc(node$write$name, lhs)
# Store LHS into RHS.
rhs = construct_ir(node$read, cmp, helper, types, .targetType = NULL)
#Hack for now to avoid bad cast.
if(node$write$name != "._return_") {
# Check the types match
rtype = Rllvm::getType(rhs)
if(!sameType(rtype, type))
rhs = createCast(cmp, helper, type, rtype, rhs)
}
helper$createStore(rhs, lhs)
lhs
#########
}
construct_ir.Call =
function(node, cmp, helper, types, .targetType = NULL)
{
# FIXME: What if $fn is not a symbol?
idx = match(node$fn$name, names(cmp$.compilerHandlers))
if (is.na(idx))
compile.call(node, cmp, helper)
else
cmp$.compilerHandlers[[idx]](node, cmp, helper)
}
construct_ir.Integer =
function(node, cmp, helper, types, .targetType = NULL)
createIntegerConstant(node$value)
construct_ir.BrTerminator =
function(node, cmp, helper, types, .targetType = NULL)
helper$createBr(node$dest)
#??? Is this ever called?
construct_ir.RetTerminator =
function(node, cmp, helper, types, .targetType = NULL)
Rllvm::createReturn(helper$builder, Rllvm::createLoad(helper$builder, helper$alloc_table[["._return__1"]]))
construct_ir.Numeric =
function(node, cmp, helper, types, .targetType = NULL)
{
createConstant(helper, node$value)
}
} # end of if() disabling these methods.
construct_ir.default =
function(node, cmp, helper, types, .targetType = NULL)
browser()
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.